Add list and iterators to opp

This commit is contained in:
drmortalwombat 2023-08-16 16:16:04 +02:00
parent 82dff88ba8
commit b7daafcac8
12 changed files with 602 additions and 106 deletions

View File

@ -35,6 +35,17 @@ void sort(T s, T e)
}
}
template<class II, class OI>
OI copy(II first, II last, OI result)
{
while (first != last)
{
*result = *first;
++result; ++first;
}
return result;
}
}
#endif

View File

@ -9,6 +9,8 @@ class array
protected:
T _data[n];
public:
typedef T element_type;
int size(void) const
{
return n;

137
include/opp/iterator.h Normal file
View File

@ -0,0 +1,137 @@
#ifndef OPP_ITERATOR_H
#define OPP_ITERATOR_H
namespace opp
{
template <class CT>
class back_insert_iterator
{
protected:
CT * co;
public:
back_insert_iterator (CT & c) : co(&c) {}
back_insert_iterator & operator= (const CT::element_type & t)
{
co->push_back(t);
return *this;
}
back_insert_iterator & operator= (CT::element_type && t)
{
co->push_back(t);
return *this;
}
back_insert_iterator & operator* (void)
{
return *this;
}
back_insert_iterator & operator++ (void)
{
return *this;
}
back_insert_iterator operator++ (int)
{
return *this;
}
};
template <class CT>
class front_insert_iterator
{
protected:
CT * co;
public:
front_insert_iterator (CT & c) : co(&c) {}
front_insert_iterator & operator= (const CT::element_type & t)
{
co->push_front(t);
return *this;
}
front_insert_iterator & operator= (CT::element_type && t)
{
co->push_front(t);
return *this;
}
front_insert_iterator & operator* (void)
{
return *this;
}
front_insert_iterator & operator++ (void)
{
return *this;
}
front_insert_iterator operator++ (int)
{
return *this;
}
};
template <class CT>
class insert_iterator
{
protected:
CT * co;
CT::iterator_type ci;
public:
insert_iterator (CT & c, const CT::iterator_type & i) : co(&c), ci(i) {}
insert_iterator & operator= (const CT::element_type & t)
{
ci = co->insert(ci, t); ++ci;
return *this;
}
insert_iterator & operator= (CT::element_type && t)
{
ci = co->insert(ci, t); ++ci;
return *this;
}
insert_iterator & operator* (void)
{
return *this;
}
insert_iterator & operator++ (void)
{
return *this;
}
insert_iterator operator++ (int)
{
return *this;
}
};
template <class CT>
front_insert_iterator<CT> front_inserter (CT & c)
{
return front_insert_iterator<CT>(c);
}
template <class CT>
back_insert_iterator<CT> back_inserter (CT & c)
{
return back_insert_iterator<CT>(c);
}
template <class CT, class CI>
insert_iterator<CT> inserter (CT & c, const CI & i)
{
return insert_iterator<CT>(c, i);
}
}

286
include/opp/list.h Normal file
View File

@ -0,0 +1,286 @@
#ifndef OPP_LIST
#define OPP_LIST
namespace opp
{
template <class T>
class listnode
{
public:
listnode * succ, * pred;
T data;
listnode()
{
succ = this;
pred = this;
}
listnode(const T & t) : data(t) {}
listnode(T && t) : data(t) {}
};
template <class T>
class list_iterator
{
public:
listnode<T> * node;
public:
list_iterator(void) : node(nullptr) {}
list_iterator(listnode<T> * n) : node(n) {}
list_iterator(const list_iterator & li) : node(li.node) {}
list_iterator & operator=(const list_iterator & li)
{
node = li.node;
return *this;
}
T & operator*()
{
return node->data;
}
list_iterator & operator++(void)
{
node = node->succ;
return *this;
}
list_iterator operator++(int)
{
listnode<T> * n = node;
node = node->succ;
return list_iterator(n);
}
list_iterator & operator+=(int n)
{
while (n--)
node = node->succ;
return *this;
}
list_iterator & operator--(void)
{
node = node->pred;
return *this;
}
list_iterator operator++(int)
{
listnode<T> * n = node;
node = node->pred;
return list_iterator(n);
}
list_iterator & operator-=(int n)
{
while (n--)
node = node->pred;
return *this;
}
bool operator==(const list_iterator & li)
{
return node == li.node;
}
bool operator!=(const list_iterator & li)
{
return node != li.node;
}
};
template <class T>
class list
{
private:
listnode<T> node;
public:
typedef T element_type;
typedef list_iterator<T> iterator_type;
list(void)
{}
~list(void)
{
listnode<T> * n = node.succ;
while (n != &node)
{
listnode<T> * m = n->succ;
delete n;
n = m;
}
}
list_iterator<T> begin(void)
{
return list_iterator<T>(node.succ);
}
list_iterator<T> end(void)
{
return list_iterator<T>(&node);
}
T & front(void)
{
return node.succ->data;
}
const T & front(void) const
{
return node.succ->data;
}
T & back(void)
{
return node.pred->data;
}
const T & back(void) const
{
return node.pred->data;
}
list_iterator<T> erase(list_iterator<T> it);
list_iterator<T> erase(list_iterator<T> first, list_iterator<T> last);
void pop_front(void);
void pop_back(void);
void push_front(const T & t);
void push_front(T && t);
void push_back(const T & t);
void push_back(T && t);
list_iterator<T> insert(list_iterator<T> it, const T & t);
list_iterator<T> insert(list_iterator<T> it, T && t);
};
template <class T>
void list<T>::pop_front(void)
{
listnode<T> * n = node.succ;
node.succ = n->succ;
n->succ->pred = &node;
delete n;
}
template <class T>
void list<T>::pop_back(void)
{
listnode<T> * n = node.pred;
node.pred = n->pred;
n->pred->succ = &node;
delete n;
}
template <class T>
void list<T>::push_front(const T & t)
{
listnode<T> * n = new listnode<T>(t);
n->pred = &node;
n->succ = node.succ;
node.succ->pred = n;
node.succ = n;
}
template <class T>
void list<T>::push_front(T && t)
{
listnode<T> * n = new listnode<T>(t);
n->pred = &node;
n->succ = node.succ;
node.succ->pred = n;
node.succ = n;
}
template <class T>
void list<T>::push_back(const T & t)
{
listnode<T> * n = new listnode<T>(t);
n->succ = &node;
n->pred = node.pred;
node.pred->succ = n;
node.pred = n;
}
template <class T>
void list<T>::push_back(T && t)
{
listnode<T> * n = new listnode<T>(t);
n->succ = &node;
n->pred = node.pred;
node.pred->succ = n;
node.pred = n;
}
template <class T>
list_iterator<T> list<T>::erase(list_iterator<T> it)
{
listnode<T> * n = it.node;
listnode<T> * s = n->succ;
n->succ->pred = n->pred;
n->pred->succ = n->succ;
delete n;
return list_iterator<T>(s);
}
template <class T>
list_iterator<T> list<T>::erase(list_iterator<T> first, list_iterator<T> last)
{
listnode<T> * n = first.node;
listnode<T> * s = last.node;
n->pred->succ = s;
s->pred = n->pred;
while (n != s)
{
listnode<T> * m = n->succ;
delete n;
n = m;
}
return list_iterator<T>(s);
}
template <class T>
list_iterator<T> list<T>::insert(list_iterator<T> it, const T & t)
{
listnode<T> * n = new listnode<T>(t);
n->succ = it.node;
n->pred = it.node->pred;
it.node->pred->succ = n;
it.node->pred = n;
return list_iterator<T>(n);
}
template <class T>
list_iterator<T> list<T>::insert(list_iterator<T> it, T && t)
{
listnode<T> * n = new listnode<T>(t);
n->succ = it.node;
n->pred = it.node->pred;
it.node->pred->succ = n;
it.node->pred = n;
return list_iterator<T>(n);
}
}
#endif

View File

@ -1,6 +1,7 @@
#include "string.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
namespace opp {

View File

@ -13,6 +13,8 @@ protected:
T * _data;
int _size, _capacity;
public:
typedef T element_type;
vector(void) : _data(nullptr), _size(0), _capacity(0) {}
vector(int n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
{

View File

@ -203,7 +203,7 @@ void Expression::Dump(int ident) const
printf("INDEX");
break;
case EX_QUALIFY:
printf("QUALIFY");
printf("QUALIFY<%s>", mDecValue->mIdent->mString);
break;
case EX_CALL:
printf("CALL");
@ -991,7 +991,9 @@ const Ident* Declaration::MangleIdent(void)
Declaration* dec = mParams;
while (dec)
{
mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString);
const Ident* id = dec->mBase->MangleIdent();
if (id)
mMangleIdent = mMangleIdent->Mangle(id->mString);
dec = dec->mNext;
if (dec)
mMangleIdent = mMangleIdent->Mangle(",");
@ -1663,20 +1665,29 @@ bool Declaration::IsSame(const Declaration* dec) const
bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tdec) const
{
uint64 dflags = dec->mFlags;
if (dec->mType == DT_TYPE_TEMPLATE)
{
dec = tdec->mScope->Lookup(dec->mIdent);
dflags |= dec->mFlags;
}
if (this == dec)
return true;
if (mType != dec->mType)
return false;
if (dec->mType == DT_TYPE_STRUCT && dec->mTemplate)
return true;
if (mSize != dec->mSize)
return false;
if (mStripe != dec->mStripe)
return false;
if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)))
if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dflags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)))
return false;
if (mType == DT_TYPE_INTEGER)

View File

@ -24,10 +24,10 @@ enum DecType
DT_TYPE_ARRAY,
DT_TYPE_STRUCT,
DT_TYPE_UNION,
DT_TYPE_TEMPLATE,
DT_TYPE_FUNCTION,
DT_TYPE_ASSEMBLER,
DT_TYPE_AUTO,
DT_TYPE_TEMPLATE,
DT_TYPE_CONST,
DT_TYPE_VOLATILE,

View File

@ -47,7 +47,7 @@ const Ident* Ident::Unique(const char* str)
const Ident* Ident::PreMangle(const char* str) const
{
char buffer[100];
char buffer[200];
strcpy_s(buffer, str);
strcat_s(buffer, mString);
return Unique(buffer);
@ -55,7 +55,7 @@ const Ident* Ident::PreMangle(const char* str) const
const Ident* Ident::Mangle(const char* str) const
{
char buffer[100];
char buffer[200];
strcpy_s(buffer, mString);
strcat_s(buffer, str);
return Unique(buffer);

View File

@ -1152,7 +1152,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
block->Append(ins);
ExValue rv(rdec->mBase, ins->mDst.mTemp, 1);
if (!rdec->mBase->IsReference())
if (!rdec->mBase->IsReference() && rdec->mBase->mType != DT_TYPE_STRUCT)
rv = Dereference(proc, exp, block, rv);
return rv;
}
@ -3274,6 +3274,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
}
else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference()))
vr = Dereference(proc, texp, block, vr, 1);
else if (vr.mType->IsReference() && !(pdec && pdec->mBase->IsReference()))
{
vr.mReference++;
vr = Dereference(proc, texp, block, vr);
}
else
vr = Dereference(proc, texp, block, vr);
@ -4706,7 +4711,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE, dec->mAlignment));
#if 0
if (proc->mIdent && !strcmp(proc->mIdent->mString, "join"))
if (proc->mIdent && !strcmp(proc->mIdent->mString, "opp::insert_iterator<struct opp::list<i16>>::+insert_iterator"))
exp->Dump(0);
#endif
#if 0

View File

@ -29989,7 +29989,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
}
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
}
else if (j > i && !(mIns[i + 0].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mExitRequiredRegs[mIns[i + 1].mAddress])
else if (j > i && !(mIns[i + 0].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mExitRequiredRegs[mIns[i + 1].mAddress] && !ReferencesZeroPage(mIns[i + 0].mAddress, 0, i))
{
int j = mIns.Size() - 1;

View File

@ -263,81 +263,83 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
else
{
Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis);
mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED);
mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent);
int offset = dec->mSize;
if (dt == DT_TYPE_UNION)
offset = 0;
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
if (mdec)
{
if (mdec->mBase->mFlags & DTF_VIRTUAL)
needVTable = true;
mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED);
mdec->mType = DT_CONST_FUNCTION;
mdec->mSection = mCodeSection;
mdec->mFlags |= DTF_GLOBAL;
mdec->mBase->mFlags |= DTF_FUNC_THIS;
mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent);
if (mCompilerOptions & COPT_NATIVE)
mdec->mFlags |= DTF_NATIVE;
int offset = dec->mSize;
if (dt == DT_TYPE_UNION)
offset = 0;
AddMemberFunction(dec, mdec);
}
else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON)
{
ConsumeToken(TK_SEMICOLON);
// anon element
}
else
{
while (mdec)
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
{
if (!(mdec->mBase->mFlags & DTF_DEFINED))
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration");
if (mdec->mBase->mFlags & DTF_VIRTUAL)
needVTable = true;
if (mdec->mType != DT_VARIABLE)
{
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected");
break;
}
mdec->mType = DT_CONST_FUNCTION;
mdec->mSection = mCodeSection;
mdec->mFlags |= DTF_GLOBAL;
mdec->mBase->mFlags |= DTF_FUNC_THIS;
mdec->mType = DT_ELEMENT;
mdec->mOffset = offset;
if (mCompilerOptions & COPT_NATIVE)
mdec->mFlags |= DTF_NATIVE;
offset += mdec->mBase->mSize;
if (offset > dec->mSize)
dec->mSize = offset;
if (dec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
if (dec->mConst)
{
Declaration* cmdec = mdec->Clone();
cmdec->mBase = mdec->mBase->ToConstType();
dec->mConst->mScope->Insert(cmdec->mIdent, cmdec);
dec->mConst->mSize = dec->mSize;
}
if (mlast)
mlast->mNext = mdec;
else
dec->mParams = mdec;
mlast = mdec;
mdec = mdec->mNext;
AddMemberFunction(dec, mdec);
}
else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON)
{
ConsumeToken(TK_SEMICOLON);
// anon element
}
if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken();
else
{
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected");
break;
while (mdec)
{
if (!(mdec->mBase->mFlags & DTF_DEFINED))
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration");
if (mdec->mType != DT_VARIABLE)
{
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected");
break;
}
mdec->mType = DT_ELEMENT;
mdec->mOffset = offset;
offset += mdec->mBase->mSize;
if (offset > dec->mSize)
dec->mSize = offset;
if (dec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
if (dec->mConst)
{
Declaration* cmdec = mdec->Clone();
cmdec->mBase = mdec->mBase->ToConstType();
dec->mConst->mScope->Insert(cmdec->mIdent, cmdec);
dec->mConst->mSize = dec->mSize;
}
if (mlast)
mlast->mNext = mdec;
else
dec->mParams = mdec;
mlast = mdec;
mdec = mdec->mNext;
}
if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken();
else
{
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected");
break;
}
}
}
}
@ -606,52 +608,55 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
if (dec && dec->mTemplate)
dec = ParseTemplateExpansion(dec->mTemplate, nullptr);
}
else
mScanner->NextToken();
while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON))
while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON))
{
if (ExpectToken(TK_IDENT))
{
if (ExpectToken(TK_IDENT))
{
pident = mScanner->mTokenIdent;
dec = dec->mScope->Lookup(mScanner->mTokenIdent);
mScanner->NextToken();
}
pident = mScanner->mTokenIdent;
dec = dec->mScope->Lookup(mScanner->mTokenIdent);
mScanner->NextToken();
}
}
if (dec && dec->mType <= DT_TYPE_FUNCTION)
if (dec && dec->mType <= DT_TYPE_FUNCTION)
{
if ((flags & ~dec->mFlags) == DTF_CONST)
dec = dec->ToConstType();
else if (dec->IsSimpleType() && (flags & ~dec->mFlags))
{
if (dec->IsSimpleType() && (flags & ~dec->mFlags))
Declaration* ndec = new Declaration(dec->mLocation, dec->mType);
ndec->mFlags = dec->mFlags | flags;
ndec->mSize = dec->mSize;
ndec->mBase = dec->mBase;
dec = ndec;
}
else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags))
{
if ((flags & ~dec->mFlags) == DTF_CONST)
dec = dec->ToConstType();
else
{
Declaration* ndec = new Declaration(dec->mLocation, dec->mType);
ndec->mFlags = dec->mFlags | flags;
ndec->mSize = dec->mSize;
ndec->mBase = dec->mBase;
ndec->mScope = dec->mScope;
ndec->mParams = dec->mParams;
ndec->mIdent = dec->mIdent;
ndec->mQualIdent = dec->mQualIdent;
dec = ndec;
}
else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags))
{
if ((flags & ~dec->mFlags) == DTF_CONST)
dec = dec->ToConstType();
else
{
Declaration* ndec = new Declaration(dec->mLocation, dec->mType);
ndec->mFlags = dec->mFlags | flags;
ndec->mSize = dec->mSize;
ndec->mBase = dec->mBase;
ndec->mScope = dec->mScope;
ndec->mParams = dec->mParams;
ndec->mIdent = dec->mIdent;
ndec->mQualIdent = dec->mQualIdent;
dec = ndec;
}
}
}
else if (!dec)
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident);
else
mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent);
}
else if (!dec)
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident);
else
mScanner->NextToken();
mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent);
break;
case TK_ENUM:
@ -989,7 +994,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec)
}
else
{
if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY)
if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY && !adec->mBase->mTemplate)
mErrors->Error(adec->mLocation, EERR_UNDEFINED_OBJECT, "Type of argument not defined");
adec->mType = DT_ARGUMENT;
@ -2173,6 +2178,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
else
{
mexp = new Expression(mScanner->mLocation, EX_INITIALIZATION);
mexp->mToken = TK_ASSIGN;
mexp->mLeft = lexp;
mexp->mRight = rexp;
mexp->mDecType = lexp->mDecType;
@ -5397,6 +5403,12 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
{
Expression * pexp = nullptr;
if (exp->mDecType->mTemplate)
{
mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "Missing template parameters", exp->mDecType->mQualIdent);
exp->mDecType = TheConstVoidTypeDeclaration;
}
mScanner->NextToken();
if (mScanner->mToken != TK_CLOSE_PARENTHESIS)
{
@ -6012,6 +6024,10 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
return nexp->mLeft;
nexp->mDecType = nexp->mLeft->mDecType->mBase;
}
else if ((mCompilerOptions & COPT_CPLUSPLUS) && nexp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
{
nexp->mDecType = nexp->mLeft->mDecType;
}
else
{
mErrors->Error(nexp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Pointer or array type expected");
@ -7370,10 +7386,16 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
{
tdec->mParams = expd->mParams;
Declaration* dec = tdec->mParams;
Declaration* xdec = tmpld->mParams;
while (dec)
{
tdec->mScope->Insert(dec->mIdent, dec->mBase);
if (dec->mBase->mType == DT_TYPE_TEMPLATE)
{
printf("oopsi");
}
tdec->mScope->Insert(xdec->mIdent, dec->mBase);
dec = dec->mNext;
xdec = xdec->mNext;
}
}
else
@ -7433,6 +7455,21 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
}
else
{
Declaration* epdec = tdec->mParams;
while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE)
epdec = epdec->mNext;
if (epdec)
{
// Partial template specification
Declaration * bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT);
tdec->mBase = bdec;
bdec->mTemplate = tdec;
bdec->mBase = tmpld->mBase;
return bdec;
}
Parser* p = tmpld->mParser;
p->mScanner->Replay(tmpld->mTokens);
@ -7614,6 +7651,9 @@ void Parser::ParseTemplateDeclaration(void)
if (adec->mBase->mType == DT_TYPE_FUNCTION)
{
if (ConsumeTokenIf(TK_CONST))
adec->mBase->mFlags |= DTF_CONST;
adec->mType = DT_CONST_FUNCTION;
adec->mSection = mCodeSection;
@ -7642,6 +7682,7 @@ void Parser::ParseTemplateDeclaration(void)
mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template expected");
adec->mType = DT_TYPE_VOID;
tdec->mBase = adec;
adec->mIdent = adec->mQualIdent = Ident::Unique("_");
adec->mTemplate = tdec;
}
}