From 80426d974c9b435b32fa5bff29b16e1a68ffeb41 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 13 Aug 2023 20:53:39 +0200 Subject: [PATCH] Add RValue Reference --- include/opp/move.h | 5 +- include/opp/string.cpp | 18 ++++++ include/opp/string.h | 2 + include/opp/vector.h | 19 +++++-- oscar64/Declaration.cpp | 101 +++++++++++++++++++++++++++++++-- oscar64/Declaration.h | 4 ++ oscar64/InterCode.cpp | 5 +- oscar64/InterCodeGenerator.cpp | 43 ++++++++------ oscar64/Parser.cpp | 26 ++++++++- 9 files changed, 189 insertions(+), 34 deletions(-) diff --git a/include/opp/move.h b/include/opp/move.h index bdf4950..759781a 100644 --- a/include/opp/move.h +++ b/include/opp/move.h @@ -1,11 +1,10 @@ #ifndef OPP_MOVE_H #define OPP_MOVE_H - template -void move(T & dst, T & src) +T && move(T & m) { - dst = src; + return (T &&)m; } #endif diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 72f134c..0c5821d 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -31,6 +31,12 @@ string::string(const string & s) cstr = nullptr; } +string::string(string && s) + : cstr(s.cstr) +{ + s.cstr = nullptr; +} + string::string(const char * s) { if (s) @@ -104,6 +110,18 @@ string & string::operator=(const string & s) return *this; } +string & string::operator=(string && s) +{ + if (cstr != s.cstr) + { + free(cstr); + cstr = s.cstr; + s.cstr = nullptr; + } + + return *this; +} + string & string::operator=(const char * s) { free(cstr); diff --git a/include/opp/string.h b/include/opp/string.h index 747c120..856edf6 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -9,6 +9,7 @@ private: public: string(void); string(const string & s); + string(string && s); string(const char * s); string(const char * s, char size); string(char c); @@ -17,6 +18,7 @@ public: unsigned size(void) const; string & operator=(const string & s); + string & operator=(string && s); string & operator=(const char * s); string & operator+=(const string & s); diff --git a/include/opp/vector.h b/include/opp/vector.h index d20f405..98f9e12 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -2,6 +2,7 @@ #define OPP_VECTOR_H #include +#include template class vector @@ -101,6 +102,8 @@ public: void push_back(const T & t); + void push_back(T && t); + void pop_back(void) { _size--; @@ -121,7 +124,7 @@ void vector::reserve(int n) T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) { - new (d + i)T(_data[i]); + new (d + i)T(move(_data[i])); _data[i].~T(); } free(_data); @@ -160,7 +163,7 @@ void vector::shrink_to_fit(void) T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) { - new (d + i)T(_data[i]); + new (d + i)T(move(_data[i])); _data[i].~T(); } free(_data); @@ -176,6 +179,14 @@ void vector::push_back(const T & t) new (_data + _size++)T(t); } +template +void vector::push_back(T && t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + new (_data + _size++)T(t); +} + template void vector::insert(int at, const T & t) { @@ -183,7 +194,7 @@ void vector::insert(int at, const T & t) reserve(_size + 1 + (_size >> 1)); new (_data + _size)T; for(int i=_size; i>at; i--) - _data[i] = _data[i - 1]; + _data[i] = move(_data[i - 1]); _data[at] = t; } @@ -192,7 +203,7 @@ void vector::erase(int at, int n) { _size -= n; for(int i=at; i<_size; i++) - _data[i] = _data[i + n]; + _data[i] = move(_data[i + n]); _data[_size].~T(); } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index c957ea4..36a0980 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -919,7 +919,7 @@ Declaration* Declaration::BuildConstRValueRef(const Location& loc) DecType Declaration::ValueType(void) const { - if (mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF) + if (IsReference()) return mBase->mType; else return mType; @@ -1334,7 +1334,7 @@ bool Declaration::IsSubType(const Declaration* dec) const if (this == dec) return true; - if (mType == DT_TYPE_REFERENCE && dec->mType == DT_TYPE_REFERENCE) + if (IsReference() && dec->IsReference()) return mBase->IsSubType(dec->mBase); if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) @@ -1510,6 +1510,26 @@ bool Declaration::IsConstSame(const Declaration* dec) const return false; } +bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration* tdec) const +{ + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) + { + // Skip this pointer for now + Declaration* ld = mParams->mNext, * rd = dec->mParams; + while (ld && rd) + { + if (!ld->mBase->IsTemplateSame(rd->mBase, tdec)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } + else + return false; +} + bool Declaration::IsSameParams(const Declaration* dec) const { if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) @@ -1587,7 +1607,7 @@ bool Declaration::IsSame(const Declaration* dec) const else return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); } - else if (mType == DT_TYPE_REFERENCE) + else if (IsReference()) return mBase->IsSame(dec->mBase); else if (mType == DT_TYPE_STRUCT) return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); @@ -1616,6 +1636,72 @@ bool Declaration::IsSame(const Declaration* dec) const return false; } +bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tdec) const +{ + if (dec->mType == DT_TYPE_TEMPLATE) + dec = tdec->mScope->Lookup(dec->mIdent); + + if (this == dec) + return true; + + if (mType != dec->mType) + return false; + 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))) + return false; + + if (mType == DT_TYPE_INTEGER) + return true; + else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) + return true; + else if (mType == DT_TYPE_ENUM) + return mIdent == dec->mIdent; + else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) + { + if (mBase->mType == DT_TYPE_STRUCT && dec->mBase->mType == DT_TYPE_STRUCT && mBase->mStripe == dec->mBase->mStripe) + { + if (mBase->mQualIdent == dec->mBase->mQualIdent && + (mBase->mFlags & (DTF_CONST | DTF_VOLATILE)) == (dec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE))) + return true; + else + return false; + } + else + return this->Stride() == dec->Stride() && mBase->IsTemplateSame(dec->mBase, tdec); + } + else if (IsReference()) + return mBase->IsTemplateSame(dec->mBase, tdec); + else if (mType == DT_TYPE_STRUCT) + return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); + else if (mType == DT_TYPE_FUNCTION) + { + if (!mBase->IsTemplateSame(dec->mBase, tdec)) + return false; + Declaration* dl = mParams, * dr = dec->mParams; + while (dl && dr) + { + if (!dl->mBase->IsTemplateSame(dr->mBase, tdec)) + return false; + dl = dl->mNext; + dr = dr->mNext; + } + + if (dl || dr) + return false; + + if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC)) + return false; + + return true; + } + + return false; +} + bool Declaration::IsSameValue(const Declaration* dec) const { if (mType != dec->mType || mSize != dec->mSize) @@ -1638,9 +1724,9 @@ bool Declaration::IsSameValue(const Declaration* dec) const bool Declaration::CanAssign(const Declaration* fromType) const { - if (fromType->mType == DT_TYPE_REFERENCE) + if (fromType->IsReference()) return this->CanAssign(fromType->mBase); - if (mType == DT_TYPE_REFERENCE) + if (IsReference()) return mBase->IsSubType(fromType); if (this->IsSame(fromType)) @@ -1695,6 +1781,11 @@ bool Declaration::IsNumericType(void) const } +bool Declaration::IsReference(void) const +{ + return mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF; +} + bool Declaration::IsSimpleType(void) const { return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM || mType == DT_TYPE_POINTER; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 1f1a9b0..d26e15d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -283,9 +283,13 @@ public: bool IsSameParams(const Declaration* dec) const; bool IsSameMutable(const Declaration* dec) const; + bool IsTemplateSame(const Declaration* dec, const Declaration* tdec) const; + bool IsTemplateSameParams(const Declaration* dec, const Declaration* tdec) const; + bool IsIntegerType(void) const; bool IsNumericType(void) const; bool IsSimpleType(void) const; + bool IsReference(void) const; void SetDefined(void); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6811f5f..cd03c94 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4532,7 +4532,8 @@ void InterCodeBasicBlock::Append(InterInstruction * code) assert(code->mConst.mVarIndex < mProc->mModule->mGlobalVars.Size()); assert(mProc->mModule->mGlobalVars[code->mConst.mVarIndex]); } - + if (code->mDst.mTemp >= 0) + assert(code->mDst.mType != IT_NONE); for (int i = 0; i < code->mNumOperands; i++) assert(code->mSrc[i].mType != IT_NONE); @@ -16748,7 +16749,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "join"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index a7fda9a..c887e95 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -34,13 +34,14 @@ static inline InterType InterTypeOf(const Declaration* dec) case DT_TYPE_FUNCTION: case DT_TYPE_ARRAY: case DT_TYPE_REFERENCE: + case DT_TYPE_RVALUEREF: return IT_POINTER; } } InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) { - if (v.mType && v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType && v.mType->IsReference()) { v.mType = v.mType->mBase; v.mReference++; @@ -81,9 +82,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { int stemp = v.mTemp; - if (type->mType == DT_TYPE_REFERENCE) + if (type->IsReference()) { - if (v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType->IsReference()) { if (!type->mBase->IsSubType(v.mType->mBase)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference"); @@ -960,7 +961,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vdec->mVarIndex = nindex; vdec->mBase = pdec->mBase; - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) ains->mConst.mOperandSize = 2; else ains->mConst.mOperandSize = pdec->mSize; @@ -992,7 +993,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); - if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) + if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); @@ -1026,7 +1027,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro { if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); - else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) + else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -1054,7 +1055,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) wins->mSrc[1].mOperandSize = 2; else wins->mSrc[1].mOperandSize = pdec->mSize; @@ -1124,7 +1125,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Append(ins); ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); - if (rdec->mBase->mType != DT_TYPE_REFERENCE) + if (!rdec->mBase->IsReference()) rv = Dereference(proc, exp, block, rv); return rv; } @@ -1728,7 +1729,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!(dec->mBase->mFlags & DTF_DEFINED)) mErrors->Error(dec->mLocation, EERR_VARIABLE_TYPE, "Undefined variable type"); - if (exp->mDecType->mType == DT_TYPE_REFERENCE) + if (exp->mDecType->IsReference()) return ExValue(exp->mDecType->mBase, ins->mDst.mTemp, ref + 1); else return ExValue(exp->mDecType, ins->mDst.mTemp, ref); @@ -1743,7 +1744,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper, &vl); } - else if (exp->mType == EX_INITIALIZATION && exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_REFERENCE) + else if (exp->mType == EX_INITIALIZATION && exp->mLeft->mDecType && exp->mLeft->mDecType->IsReference()) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -1776,7 +1777,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } - if (vl.mType->mType == DT_TYPE_REFERENCE) + if (vl.mType->IsReference()) { vr = Dereference(proc, exp, block, vr, 1); vl = Dereference(proc, exp, block, vl, 2); @@ -3172,7 +3173,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(ptype ? ptype : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL && texp->mDecType->mType != DT_TYPE_REFERENCE) + if (pdec && pdec->mBase->IsReference() && texp->mType == EX_CALL && !texp->mDecType->IsReference()) { mErrors->Error(texp->mLocation, EERR_MISSING_TEMP, "Missing temporary variable"); #if 0 @@ -3202,7 +3203,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, nullptr); - if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) + if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); @@ -3244,7 +3245,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); vr = CoerceType(proc, texp, block, vr, pdec->mBase); } - else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) + else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -3272,7 +3273,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) { wins->mSrc[1].mOperandSize = 2; wins->mSrc[0].mType = IT_POINTER; @@ -3359,7 +3360,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(ftype->mBase, vins->mDst.mTemp, 1); } - else if (ftype->mBase->mType == DT_TYPE_REFERENCE) + else if (ftype->mBase->IsReference()) return ExValue(ftype->mBase->mBase, cins->mDst.mTemp, 1); else return ExValue(ftype->mBase, cins->mDst.mTemp); @@ -3468,7 +3469,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RETURN); if (exp->mLeft) { - if (procType->mBase->mType == DT_TYPE_REFERENCE) + if (procType->mBase->IsReference()) { vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -4128,6 +4129,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (exp->mDecType->mType == DT_TYPE_VOID) { } + else if (exp->mDecType->IsReference() && exp->mDecType->mBase->IsConstSame(vr.mType)) + { + if (vr.mReference == 0) + mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an L value"); + + vr = Dereference(proc, exp, block, vr, 1); + return ExValue(exp->mDecType, vr.mTemp); + } else { vr = Dereference(proc, exp, block, vr); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index cde99e8..6c4686e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2035,7 +2035,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) adec->mOffset = 0; adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); adec->mBase->mSize = 2; - adec->mBase->mBase = pthis->mBase; + adec->mBase->mBase = pthis->mBase->ToConstType(); adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; adec->mSize = adec->mBase->mSize; adec->mIdent = adec->mQualIdent = Ident::Unique("_"); @@ -4733,7 +4733,10 @@ Expression* Parser::ParseQualify(Expression* exp) { if (mflags & DTF_PROTECTED) { - if (!mThisPointer || mThisPointer->mBase->IsConstSame(dtype)) + Declaration* tp = mThisPointer; + if (tp && tp->mType == DT_ARGUMENT) + tp = tp->mBase; + if (!(tp && tp->mBase->IsConstSame(dtype))) mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); } @@ -4952,6 +4955,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 512; else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { + if (ex->IsLValue()) + dist += 2; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 4; + else + return NOOVERLOAD; + int ncast = 0; Declaration* ext = ex->mDecType; while (ext && !ext->IsConstSame(ptype->mBase)) @@ -7379,6 +7389,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp if (!(mdec->mFlags & DTF_DEFINED)) { Declaration* mpdec = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) + mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) { p->ParseTemplateExpansion(mpdec->mTemplate, tdec); @@ -7411,6 +7423,8 @@ void Parser::CompleteTemplateExpansion(Declaration* tmpld) while (mdec) { Declaration* mpdec = mScope->Lookup(mdec->mQualIdent); + while (mpdec && !mpdec->IsSameParams(mdec->mParams)) + mpdec = mpdec->mNext; if (mpdec && mpdec->mType == DT_TEMPLATE) { ParseTemplateExpansion(mpdec, tmpld); @@ -7561,7 +7575,13 @@ void Parser::ParseTemplateDeclaration(void) tdec->mQualIdent = tdec->mBase->mQualIdent; tdec->mScope->mName = tdec->mQualIdent; - mScope->Insert(tdec->mQualIdent, tdec->mBase); + Declaration * pdec = mScope->Insert(tdec->mQualIdent, tdec->mBase); + if (pdec) + { + tdec->mBase->mNext = pdec->mNext; + pdec->mNext = tdec->mBase; + } + mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); }