Fix pointers in constexpr

This commit is contained in:
drmortalwombat 2023-09-20 14:19:56 +02:00
parent e20c098ab1
commit a0409002b6
16 changed files with 1216 additions and 306 deletions

View File

@ -18,6 +18,9 @@ rem @echo off
@call :test opp_streamtest.cpp
@if %errorlevel% neq 0 goto :error
@call :test opp_pairtest.cpp
@if %errorlevel% neq 0 goto :error
@call :test operatoroverload.cpp
@if %errorlevel% neq 0 goto :error

28
autotest/opp_pairtest.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <assert.h>
#include <opp/vector.h>
#include <opp/utility.h>
#include <opp/iostream.h>
using namespace opp;
int main(void)
{
vector<pair<int, int> > vii;
for(int i=0; i<100; i++)
vii.push_back(make_pair(i, i * i));
int sum1 = 0;
long sum2 = 0;
for(const auto & v : vii)
{
sum1 += v.first;
sum2 += v.second;
}
assert(sum1 == 4950);
assert(sum2 == 328350l);
return 0;
}

View File

@ -1,14 +0,0 @@
#ifndef OPP_MOVE_H
#define OPP_MOVE_H
namespace opp {
template <class T>
T && move(T & m)
{
return (T &&)m;
}
}
#endif

34
include/opp/utility.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef OPP_UTILITY_H
#define OPP_UTILITY_H
namespace opp {
template <class T>
T && move(T & m)
{
return (T &&)m;
}
template<class T1, class T2>
struct pair
{
T1 first;
T2 second;
pair(T1 && t1, T2 && t2)
: first(t1), second(t2)
{}
};
template<class T1, class T2>
constexpr pair<T1, T2> make_pair(T1 && t1, T2 && t2)
{
return pair<T1, T2>(t1, t2);
}
}
#endif

View File

@ -2,7 +2,7 @@
#define OPP_VECTOR_H
#include <stdlib.h>
#include <opp/move.h>
#include <opp/utility.h>
namespace opp {

View File

@ -37,6 +37,7 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec)
switch (dec->mType)
{
case DT_CONST_INTEGER:
case DT_CONST_ADDRESS:
PutIntAt(dec->mInteger, offset, dec->mBase);
break;
case DT_CONST_FLOAT:
@ -46,6 +47,10 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec)
for (Declaration* pdec = dec->mParams; pdec; pdec = pdec->mNext)
PutConst(pdec->mOffset, pdec);
break;
case DT_CONST_DATA:
for (int i = 0; i < dec->mBase->mSize; i++)
PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration);
break;
}
}
@ -116,8 +121,8 @@ ConstexprInterpreter::Value::Value(Value* value)
{
}
ConstexprInterpreter::Value::Value(Value* value, Declaration* type, int offset)
: mLocation(value->mLocation),
ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset)
: mLocation(location),
mDecType(type),
mBaseValue(value), mOffset(offset),
mDataSize(0), mData(mShortData)
@ -331,7 +336,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declar
{
const ValueItem* dp = GetAddr() + at;
return Value(dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)));
return Value(mLocation, dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)));
}
void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type)
@ -448,10 +453,13 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
dec->mSize = type->mSize;
dec->mSection = dataSection;
dec->mOffset = offset;
Declaration* ldec = nullptr;
while (type)
{
for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext)
{
Declaration * cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection);
Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection);
cdec->mOffset = mdec->mOffset;
if (ldec)
@ -460,7 +468,12 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
dec->mParams = cdec;
ldec = cdec;
}
if (type->mBase)
type = type->mBase->mBase;
else
type = nullptr;
}
break;
}
@ -486,6 +499,46 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
}
break;
}
case DT_TYPE_POINTER:
{
Value vp = GetPtrAt(offset, type);
if (vp.mBaseValue)
{
dec = new Declaration(mLocation, DT_CONST_POINTER);
dec->mBase = type;
dec->mSize = type->mSize;
Declaration* target;
if (vp.mBaseValue->mDecType->mType == DT_TYPE_ARRAY)
{
target = new Declaration(mLocation, DT_CONST_DATA);
target->mSize = vp.mBaseValue->mDataSize;
target->mBase = vp.mBaseValue->mDecType;
target->mSection = dataSection;
uint8* buffer = new uint8[target->mSize];
for (int i = 0; i < target->mSize; i++)
buffer[i] = uint8(vp.mBaseValue->GetIntAt(i, TheUnsignedCharTypeDeclaration));
target->mData = buffer;
}
else
target = vp.mBaseValue->GetConst(0, vp.mBaseValue->mDecType, dataSection);
dec->mValue = new Expression(mLocation, EX_CONSTANT);
dec->mValue->mDecType = target->mBase;
dec->mValue->mDecValue = target;
}
else
{
dec = new Declaration(mLocation, DT_CONST_ADDRESS);
dec->mBase = type;
dec->mFlags = 0;
dec->mSize = type->mSize;
dec->mInteger = vp.mOffset;
}
break;
}
}
@ -511,7 +564,8 @@ ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* er
ConstexprInterpreter::~ConstexprInterpreter(void)
{
for (int i = 0; i < mTemps.Size(); i++)
delete mTemps[i];
}
ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size)
@ -541,13 +595,30 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
Declaration* dec = exp->mLeft->mDecType->mParams;
int pos = 0;
if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT)
{
mResult = Value(exp->mLocation, mProcType->mBase);
mParams[0] = Value(&mResult);
pos = 2;
}
while (pex && pex->mType == EX_LIST)
{
if (dec)
pos = dec->mVarIndex;
if (pex->mLeft->mType == EX_CONSTANT)
{
if (pex->mLeft->mDecType->mType == DT_TYPE_ARRAY)
{
Value * tmp = new Value(pex->mLeft);
mTemps.Push(tmp);
mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecType->BuildArrayPointer());
mParams[pos].PutPtr(Value(tmp));
}
else
mParams[pos] = Value(pex->mLeft);
}
else if (pex->mLeft->mType == EX_VARIABLE && (pex->mLeft->mDecValue->mFlags & DTF_CONST))
{
mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase);
@ -566,7 +637,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
pos = dec->mVarIndex;
if (pex->mType == EX_CONSTANT)
{
if (pex->mDecType->mType == DT_TYPE_ARRAY)
{
Value* tmp = new Value(pex);
mTemps.Push(tmp);
mParams[pos] = Value(pex->mLocation, pex->mDecType->BuildArrayPointer());
mParams[pos].PutPtr(Value(tmp));
}
else
mParams[pos] = Value(pex);
}
else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST))
{
mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase);
@ -619,6 +700,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalBinary(Expression * exp, c
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
}
}
else if (exp->mDecType->mType == DT_TYPE_POINTER)
{
Value vlp = vl.GetPtr();
vlp.mOffset += int(vr.GetInt() * vl.mDecType->mBase->mSize);
v.PutPtr(vlp);
}
else
{
switch (exp->mToken)
@ -880,6 +967,13 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
Declaration* dec = exp->mLeft->mDecType->mParams;
int pos = 0;
if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT)
{
mResult = Value(exp->mLocation, mProcType->mBase);
mParams[0] = Value(&mResult);
pos = 2;
}
while (pex && pex->mType == EX_LIST)
{
if (dec)
@ -1096,7 +1190,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
{
Value v = Eval(exp->mLeft);
if (v.mBaseValue)
return Value(v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset);
return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset);
}
case EX_INDEX:
@ -1107,15 +1201,26 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
if (v.mDecType->mType == DT_TYPE_ARRAY)
{
if (v.mBaseValue)
return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
}
else if (v.mDecType->mType == DT_TYPE_POINTER)
{
Value p = v.GetPtr();
return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
}
}
case EX_RESULT:
if (mParams[0].mBaseValue)
return mParams[0];
else
return Value(&mParams[0]);
case EX_CONSTRUCT:
if (exp->mLeft->mLeft)
Eval(exp->mLeft->mLeft);
return Eval(exp->mRight);
case EX_VOID:
return Value(exp->mLocation);
@ -1162,6 +1267,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
case EX_PREINCDEC:
case EX_QUALIFY:
case EX_INDEX:
case EX_RESULT:
Eval(exp);
return FLOW_NEXT;

View File

@ -29,7 +29,7 @@ protected:
Value(const Location& location, Declaration* dec, int count);
Value(const Value& value);
Value(Value&& value);
Value(Value * value, Declaration * type, int offset);
Value(const Location& location, Value * value, Declaration * type, int offset);
Value(Value* value);
Value(const Location& location, const uint8 * data, Declaration* type);
Value(const Location& location, const ValueItem* data, Declaration* type);
@ -101,6 +101,7 @@ protected:
GrowingArray<Value> mParams, mLocals;
ExpandingArray<Expression*> mDestructStack;
ExpandingArray<Value *> * mHeap;
ExpandingArray<Value*> mTemps;
Errors * mErrors;
Value mResult;

View File

@ -303,6 +303,9 @@ void Expression::Dump(int ident) const
case EX_PACK:
printf("PACK");
break;
case EX_PACK_TYPE:
printf("PACK_TYPE");
break;
}
printf("\n");
@ -355,6 +358,16 @@ bool Expression::IsRValue(void) const
return true;
}
bool Expression::IsConstRef(void) const
{
if (mDecType->mType == DT_TYPE_RVALUEREF || mDecType->mType == DT_TYPE_REFERENCE)
return true;
else if (mType == EX_VARIABLE || mType == EX_QUALIFY || mType == EX_INDEX || mType == EX_PREFIX && mToken == TK_MUL)
return true;
else
return false;
}
bool Expression::IsLValue(void) const
{
if (mDecType->mFlags & DTF_CONST)
@ -996,7 +1009,7 @@ Declaration* Declaration::DeduceAuto(Declaration * dec)
if (dec->mType == DT_TYPE_ARRAY)
dec = dec->mBase->BuildPointer(mLocation);
if (mFlags & DTF_CONST)
if ((IsReference() ? mBase->mFlags : mFlags) & DTF_CONST)
dec = dec->ToConstType();
else
dec = dec->ToMutableType();
@ -1133,7 +1146,7 @@ const Ident* Declaration::MangleIdent(void)
}
else if (mType == DT_PACK_TYPE)
{
Declaration* dec = mBase;
Declaration* dec = mParams;
while (dec)
{
const Ident* id = dec->MangleIdent();
@ -1288,7 +1301,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
tpdec->mIdent = pdec->mBase->mBase->mIdent;
else
tpdec->mIdent = pdec->mBase->mIdent;
tpdec->mBase = phead;
tpdec->mParams = phead;
mScope->Insert(tpdec->mIdent, tpdec);
}
else
@ -1434,25 +1447,66 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
Declaration *ftdec = tdec->mTemplate;
while (ftdec)
{
if (ftdec->mBase->IsConstSame(fdec))
if (ftdec->mBase->mQualIdent == fdec->mQualIdent)
{
Declaration* fpdec = ftdec->mParams;
Declaration* tpdec = tdec->mTemplate->mParams;
while (fpdec)
while (fpdec && tpdec)
{
if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE)
{
Declaration * pdec = mScope->Insert(tpdec->mIdent, fpdec->mBase);
Declaration * pdec = mScope->Insert(tpdec->mBase->mIdent, fpdec->mBase);
if (pdec && !pdec->IsSame(fpdec->mBase))
return false;
}
else if (tpdec->mBase->mType == DT_PACK_TEMPLATE)
{
Declaration* tppack;
if (fpdec->mType == DT_PACK_TEMPLATE)
tppack = fpdec->mBase;
else
{
tppack = new Declaration(fpdec->mLocation, DT_PACK_TYPE);
Declaration* ppdec = nullptr;
while (fpdec)
{
if (fpdec->mType == DT_PACK_TEMPLATE)
{
if (ppdec)
ppdec->mNext = fpdec->mBase->mParams;
else
tppack->mParams = fpdec->mBase->mParams;
break;
}
Declaration* ndec = fpdec->mBase->Clone();
if (ppdec)
ppdec->mNext = ndec;
else
tppack->mParams = ndec;
ppdec = ndec;
fpdec = fpdec->mNext;
}
}
Declaration* pdec = mScope->Insert(tpdec->mBase->mIdent, tppack);
if (pdec && !pdec->IsSame(fpdec->mBase))
return false;
return true;
}
fpdec = fpdec->mNext;
tpdec = tpdec->mNext;
}
return true;
return !fpdec && !tpdec;
}
ftdec = ftdec->mNext;
@ -1604,6 +1658,7 @@ Declaration* Declaration::ToConstType(void)
ndec->mQualIdent = mQualIdent;
ndec->mTemplate = mTemplate;
ndec->mDestructor = mDestructor;
ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor;
@ -1636,6 +1691,7 @@ Declaration* Declaration::ToMutableType(void)
ndec->mQualIdent = mQualIdent;
ndec->mTemplate = mTemplate;
ndec->mDestructor = mDestructor;
ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor;
@ -1659,6 +1715,8 @@ bool Declaration::IsSameTemplate(const Declaration* dec) const
if (mType == DT_CONST_FUNCTION)
return mBase->IsSame(dec->mBase);
else if (mType == DT_TYPE_STRUCT)
return true;
return false;
}
@ -1673,7 +1731,7 @@ bool Declaration::IsSubType(const Declaration* dec) const
if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
{
if (dec->mType == DT_TYPE_POINTER)
if (dec->mType == DT_TYPE_POINTER || dec->mType == DT_TYPE_ARRAY)
return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase);
}
@ -1906,7 +1964,7 @@ bool Declaration::IsSameParams(const Declaration* dec) const
}
else if (mType == DT_PACK_TYPE && dec->mType == DT_PACK_TYPE)
{
Declaration* ld = mBase, * rd = dec->mBase;
Declaration* ld = mParams, * rd = dec->mParams;
while (ld && rd)
{
if (!ld->IsSame(rd))

View File

@ -222,7 +222,8 @@ enum ExpressionType
EX_CONSTRUCT,
EX_CLEANUP,
EX_RESULT,
EX_PACK
EX_PACK,
EX_PACK_TYPE,
};
class Expression
@ -247,6 +248,7 @@ public:
bool IsSame(const Expression* exp) const;
bool IsRValue(void) const;
bool IsLValue(void) const;
bool IsConstRef(void) const;
void Dump(int ident) const;
};

View File

@ -557,7 +557,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
while (pdec)
{
pdec->mVarIndex += vi;
if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mBase->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST))
if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST))
{
pdec->mBase = pdec->mBase->mBase;
pdec->mSize = pdec->mBase->mSize;
@ -884,6 +884,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF)))
ldec->mBase->mFlags |= DTF_STACKCALL;
RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference()));
if (pdec)
pdec = pdec->mNext;
@ -892,7 +894,6 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
else
rex = nullptr;
}
RegisterProc(Analyze(exp->mRight, procDec, false));
}
break;
case EX_LIST:
@ -901,7 +902,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_RETURN:
if (exp->mLeft)
{
RegisterProc(Analyze(exp->mLeft, procDec, false));
RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference()));
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
{
if (procDec->mBase->mBase->mMoveConstructor)
@ -1031,8 +1032,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
procDec->mComplexity += exp->mDecType->mSize * 10;
ldec = Analyze(exp->mLeft, procDec, false);
RegisterProc(Analyze(exp->mRight->mLeft, procDec, false));
RegisterProc(Analyze(exp->mRight->mRight, procDec, false));
RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs));
RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs));
break;
}

View File

@ -3679,6 +3679,34 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray&
}
}
}
else if (mCode == IC_SELECT)
{
if (mDst.mType == IT_POINTER)
{
if (mSrc[1].mTemp < 0)
{
if (mSrc[1].mMemory == IM_LOCAL)
{
requiredVars += mSrc[1].mVarIndex;
}
else if (mSrc[1].mMemory == paramMemory)
{
requiredParams += mSrc[1].mVarIndex;
}
}
if (mSrc[2].mTemp < 0)
{
if (mSrc[2].mMemory == IM_LOCAL)
{
requiredVars += mSrc[2].mVarIndex;
}
else if (mSrc[2].mMemory == paramMemory)
{
requiredParams += mSrc[2].mVarIndex;
}
}
}
}
else if (mCode == IC_CONSTANT)
{
if (mConst.mType == IT_POINTER)
@ -3809,6 +3837,22 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock*
}
}
}
else if (mCode == IC_SELECT)
{
if (mDst.mType == IT_POINTER)
{
if (mSrc[1].mTemp < 0)
{
if (mSrc[1].mMemory == IM_GLOBAL && mSrc[1].mVarIndex >= 0)
requiredVars += mSrc[1].mVarIndex;
}
if (mSrc[2].mTemp < 0)
{
if (mSrc[2].mMemory == IM_GLOBAL && mSrc[2].mVarIndex >= 0)
requiredVars += mSrc[2].mVarIndex;
}
}
}
else if (mCode == IC_COPY || mCode == IC_STRCPY)
{
requiredVars.Fill();
@ -5241,12 +5285,11 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
break;
case IC_SELECT:
for(int i=0; i<3; i++)
for (int i = 0; i < 3; i++)
{
if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT)
if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT && ins->mSrc[i].mType != IT_POINTER)
{
ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst;
ins->mSrc[i].mType = ins->mDst.mType;
ins->mSrc[i].mTemp = -1;
}
}
@ -16376,6 +16419,8 @@ void InterCodeProcedure::ResetVisited(void)
int InterCodeProcedure::AddTemporary(InterType type)
{
assert(type != IT_NONE);
int temp = mTemporaries.Size();
mTemporaries.Push(type);
return temp;
@ -17179,7 +17224,7 @@ void InterCodeProcedure::Close(void)
{
GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "bv");
CheckFunc = !strcmp(mIdent->mString, "main");
mEntryBlock = mBlocks[0];

View File

@ -63,6 +63,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure*
ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2;
ins->mSrc[0].mStride = v.mReference == 1 ? v.mType->mStripe : 1;
if (ins->mDst.mType == IT_NONE)
{
mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Not a simple type");
return v;
}
if (v.mReference == 1 && v.mType->mType == DT_TYPE_ENUM)
{
ins->mDst.mRange.LimitMin(v.mType->mMinValue);
@ -1641,6 +1647,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
break;
case EX_PACK:
case EX_PACK_TYPE:
mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage");
return ExValue(TheVoidTypeDeclaration);
@ -2032,8 +2039,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB)))
{
if (!vl.mType->CanAssign(vr.mType))
{
vl.mType->CanAssign(vr.mType);
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
}
}
if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST))
mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot assign to const type");
@ -3754,10 +3764,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{
vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
if (vr.mType->IsReference())
{
vr.mReference++;
vr.mType = vr.mType->mBase;
}
vr = Dereference(proc, exp, block, vr, 1);
vr = CoerceType(proc, exp, block, vr, procType->mBase);
if (vr.mReference == 0)
mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Returning value as reference");
ins->mSrc[0].mType = IT_POINTER;
ins->mSrc[0].mTemp = vr.mTemp;
ins->mSrc[0].mMemory = IM_INDIRECT;
@ -3765,6 +3784,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (inlineMapper)
{
if (inlineMapper->mResultExp)
{
if (inlineMapper->mResultExp->mType->IsReference())
{
ins->mSrc[1].mType = IT_POINTER;
ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp;
@ -3774,10 +3795,18 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mNumOperands = 2;
}
else
{
//bool moving = exp->mLeft->IsRValue() || exp->mLeft->mType == EX_VARIABLE && !(exp->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE;
CopyStruct(proc, exp, block, *(inlineMapper->mResultExp), vr, inlineMapper, false);
ins->mCode = IC_NONE;
}
}
else
{
InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mType = IT_POINTER;
ains->mConst.mOperandSize = procType->mBase->mSize;
ains->mConst.mIntConst = 0;
@ -4007,7 +4036,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{
InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mType = IT_POINTER;
ains->mConst.mOperandSize = procType->mBase->mSize;
ains->mConst.mIntConst = 0;
@ -4148,14 +4177,24 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vc = Dereference(proc, exp, block, vc);
int ttemp;
int ttemp, tref = 0;
InterType ttype, stypel, styper;
stypel = InterTypeOf(vl.mType);
styper = InterTypeOf(vr.mType);
Declaration* dtype;
if (stypel == IT_POINTER || styper == IT_POINTER)
Declaration* dtype = exp->mDecType;
if (dtype->IsReference())
{
vl = Dereference(proc, exp, block, vl, 1);
vr = Dereference(proc, exp, block, vr, 1);
tref = 1;
dtype = dtype->mBase;
ttype = IT_POINTER;
}
else if (stypel == IT_POINTER || styper == IT_POINTER)
{
if (vl.mType->mType == DT_TYPE_ARRAY)
vl = Dereference(proc, exp, block, vl, 1);
@ -4224,7 +4263,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sins->mDst.mTemp = ttemp;
block->Append(sins);
return ExValue(dtype, ttemp);
return ExValue(dtype, ttemp, tref);
}
else
#endif

View File

@ -595,6 +595,16 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
AddDefaultConstructors(pthis);
if (pthis->mBase->mConst)
{
pthis->mBase->mConst->mDestructor = pthis->mBase->mDestructor;
pthis->mBase->mConst->mDefaultConstructor = pthis->mBase->mDefaultConstructor;
pthis->mBase->mConst->mCopyConstructor = pthis->mBase->mCopyConstructor;
pthis->mBase->mConst->mMoveConstructor = pthis->mBase->mMoveConstructor;
pthis->mBase->mConst->mVectorConstructor = pthis->mBase->mVectorConstructor;
pthis->mBase->mConst->mVectorCopyConstructor = pthis->mBase->mVectorCopyConstructor;
}
// Lookup constructors, have same name as class
Declaration* cdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+"), SLEVEL_SCOPE);
while (cdec)
@ -753,24 +763,26 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl
case TK_IDENT:
pident = mScanner->mTokenIdent;
mScanner->NextToken();
if (mTemplateScope)
dec = mTemplateScope->Lookup(mScanner->mTokenIdent);
{
dec = mTemplateScope->Lookup(pident);
if (dec && mScanner->mToken == TK_LESS_THAN && !dec->mTemplate)
dec = nullptr;
}
if (!dec)
{
dec = mScope->Lookup(mScanner->mTokenIdent);
dec = mScope->Lookup(pident);
if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS)
dec = mScope->mParent->Lookup(mScanner->mTokenIdent);
mScanner->NextToken();
dec = mScope->mParent->Lookup(pident);
dec = ParseBaseTypeQualify(qualified, dec, pident);
if (dec && dec->mTemplate)
dec = ParseTemplateExpansion(dec->mTemplate, nullptr);
}
else
mScanner->NextToken();
dec = ParseBaseTypeQualify(qualified, dec, pident);
@ -1191,7 +1203,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec)
atdec = atdec->mBase;
if (atdec->mType == DT_PACK_TYPE)
{
atdec = atdec->mBase;
atdec = atdec->mParams;
Declaration* apdec = adec;
while (atdec)
@ -1827,8 +1839,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp)
nexp->mDecType = vexp->mDecType;
nexp->mLeft = vexp;
ConsumeToken(TK_OPEN_PARENTHESIS);
if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS))
{
nexp->mRight = ParseRExpression();
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
return nexp;
}
@ -2043,6 +2058,9 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
scope->Insert(pdec->mIdent, pdec);
pdec = pdec->mNext;
}
if (cfunc->mBase->mParamPack)
mScope->Insert(cfunc->mBase->mParamPack->mIdent, cfunc->mBase->mParamPack);
Declaration* othis = mThisPointer;
mThisPointer = pthis;
@ -2165,6 +2183,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
if (!(bcdec->mBase->mCopyConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
inlineCopy = false;
}
if (bcdec->mBase->mMoveConstructor)
{
simpleMove = false;
if (!(bcdec->mBase->mMoveConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
inlineCopy = false;
}
if (bcdec->mBase->mCopyAssignment)
simpleAssignment = false;
bcdec = bcdec->mNext;
@ -2202,6 +2226,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
simpleCopy = false;
if (bdec->mCopyAssignment)
simpleAssignment = false;
if (bdec->mMoveConstructor)
simpleMove = false;
}
if (dec->mValue)
simpleConstructor = false;
@ -3242,16 +3268,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
// Returning a value object for pass by address
// add a temporary variable
int nindex = mLocalIndex++;
//int nindex = mLocalIndex++;
Declaration* rtdec = exp->mLeft->mDecType;
Declaration* vdec = AllocTempVar(rtdec);
#if 0
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
vdec->mVarIndex = nindex;
vdec->mBase = rtdec;
vdec->mSize = rtdec->mSize;
#endif
Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE);
vexp->mDecType = rtdec;
vexp->mDecValue = vdec;
@ -3293,16 +3321,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
// Returning a value object for pass by address
// add a temporary variable
int nindex = mLocalIndex++;
// int nindex = mLocalIndex++;
Declaration* rtdec = exp->mLeft->mDecType;
Declaration* vdec = AllocTempVar(rtdec);
#if 0
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
vdec->mVarIndex = nindex;
vdec->mBase = rtdec;
vdec->mSize = rtdec->mSize;
#endif
Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE);
vexp->mDecType = rtdec;
vexp->mDecValue = vdec;
@ -3361,16 +3391,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
// Returning a value object for pass as reference
// add a temporary variable
Declaration* vdec = AllocTempVar(pex->mDecType);
#if 0
int nindex = mLocalIndex++;
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
vdec->mVarIndex = nindex;
vdec->mBase = pdec->mBase->mBase;
vdec->mSize = pdec->mBase->mBase->mSize;
vdec->mBase = pex->mDecType;
vdec->mSize = pex->mDecType->mSize;
#endif
Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE);
vexp->mDecType = pdec->mBase->mBase;
vexp->mDecType = pex->mDecType;
vexp->mDecValue = vdec;
Expression* cexp = new Expression(pex->mLocation, pex->mType);
@ -3450,6 +3482,28 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
pex->mDecType = vdec->mBase;
}
}
else if ((pdec->mBase->mType == DT_TYPE_REFERENCE && !pex->IsConstRef()) || (pdec->mBase->mType == DT_TYPE_RVALUEREF && !pex->IsLValue()))
{
Declaration* vdec = AllocTempVar(pex->mDecType);
Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE);
vexp->mDecType = pex->mDecType;
vexp->mDecValue = vdec;
Expression* cexp = new Expression(pex->mLocation, pex->mType);
cexp->mDecType = pex->mDecType;
cexp->mDecValue = pex->mDecValue;
cexp->mLeft = pex->mLeft;
cexp->mRight = pex->mRight;
cexp->mToken = pex->mToken;
pex->mType = EX_INITIALIZATION;
pex->mToken = TK_ASSIGN;
pex->mLeft = vexp;
pex->mRight = cexp;
pex->mDecValue = nullptr;
pex->mDecType = vdec->mBase;
}
pdec = pdec->mNext;
}
@ -3753,7 +3807,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
if (ctdec->mParams)
mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter");
PrependThisArgument(ctdec, pthis);
Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
bthis->mFlags |= DTF_CONST | DTF_DEFINED;
if (ConsumeTokenIf(TK_CONST))
bthis->mBase = pthis->mBase->ToConstType();
else
bthis->mBase = pthis->mBase;
bthis->mSize = 2;
PrependThisArgument(ctdec, bthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
@ -4995,6 +5057,21 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
}
break;
case TK_CONST:
if (lhs)
exp = ParseDeclarationExpression(nullptr);
else
{
mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = ParseBaseTypeDeclaration(DTF_CONST, true);
while (ConsumeTokenIf(TK_MUL))
exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation);
while (ConsumeTokenIf(TK_BINARY_AND))
exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation);
}
break;
case TK_VOLATILE:
case TK_STRUCT:
case TK_CLASS:
@ -5314,6 +5391,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
exp->mDecValue = dec;
exp->mDecType = dec->mBase;
}
else if (dec->mType == DT_PACK_TYPE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = dec;
}
else if (dec->mType <= DT_TYPE_FUNCTION)
{
if (lhs)
@ -5335,6 +5418,11 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
exp->mDecValue = dec;
exp->mDecType = TheSignedIntTypeDeclaration;
}
else if (dec->mType == DT_PACK_TEMPLATE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecType = dec;
}
else if (dec->mType == DT_ELEMENT)
{
mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent);
@ -5411,6 +5499,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST);
nexp->mDecType = exp->mDecType;
nexp->mLeft = ParsePrefixExpression(false);
nexp = CheckOperatorOverload(nexp);
exp = nexp->ConstantFold(mErrors, mDataSection);
}
}
@ -5514,6 +5603,7 @@ Expression* Parser::ParseQualify(Expression* exp)
uint64 mflags = 0;
Declaration* mdec = nullptr;
const Ident* ident = nullptr;
bool destructor = false;
if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_BINARY_NOT)
{
@ -5529,6 +5619,7 @@ Expression* Parser::ParseQualify(Expression* exp)
}
ident = ident->PreMangle("~");
destructor = true;
}
else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
@ -5628,6 +5719,12 @@ Expression* Parser::ParseQualify(Expression* exp)
exp = nexp;
}
}
else if (destructor)
{
mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS);
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
else
{
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent);
@ -5808,6 +5905,12 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
else
return NOOVERLOAD;
if (ptype->mBase->mTemplate)
{
dist += 16;
}
else
{
int ncast = 0;
Declaration* ext = ex->mDecType;
while (ext && !ext->IsConstSame(ptype->mBase))
@ -5826,6 +5929,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
else
return NOOVERLOAD;
}
}
else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase))
dist += 2;
else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype))
@ -5912,7 +6016,7 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type)
{
if (!type->IsConstSame(tdec))
{
Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+"));
Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr;
if (fcons)
{
while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec)))
@ -6148,7 +6252,12 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
if (ibest == NOOVERLOAD)
{
#if _DEBUG
fdec = exp->mLeft->mDecValue;
while (fdec)
{
int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight);
fdec = fdec->mNext;
}
#endif
mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent);
}
@ -6301,6 +6410,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST);
nexp->mDecType = exp->mDecType;
nexp->mLeft = pexp;
nexp = CheckOperatorOverload(nexp);
exp = nexp->ConstantFold(mErrors, mDataSection);
}
else
@ -6639,19 +6749,32 @@ Expression* Parser::ParseNewOperator(void)
if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor)
{
Declaration* mdec = dec->mDefaultConstructor;
Expression* pexp = nullptr;
bool plist = false;
if (ConsumeTokenIf(TK_OPEN_PARENTHESIS))
{
if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS))
{
plist = true;
pexp = ParseListExpression(false);
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
}
if (dec->mType == DT_TYPE_STRUCT)
mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+"));
{
mdec = dec->mScope ? dec->mScope->Lookup(dec->mIdent->PreMangle("+")) : nullptr;
if (pexp && pexp->mType != EX_LIST)
{
if (pexp->mDecType->IsSame(dec))
mdec = dec->mCopyConstructor;
else if (pexp->mDecType->mType == DT_TYPE_REFERENCE && pexp->mDecType->mBase->IsSame(dec))
mdec = dec->mCopyConstructor;
else if (pexp->mDecType->mType == DT_TYPE_RVALUEREF && pexp->mDecType->mBase->IsSame(dec))
mdec = dec->mMoveConstructor;
}
}
else
mdec = nullptr;
}
}
if (mdec)
{
@ -6670,19 +6793,10 @@ Expression* Parser::ParseNewOperator(void)
iexp->mRight = nexp;
iexp->mDecType = nexp->mDecType;
Expression* pexp = vexp;
if (plist)
{
pexp = ParseListExpression(false);
ConsumeToken(TK_CLOSE_PARENTHESIS);
Expression* lexp = new Expression(mScanner->mLocation, EX_LIST);
lexp->mLeft = vexp;
lexp->mRight = pexp;
pexp = lexp;
}
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec;
@ -6718,12 +6832,7 @@ Expression* Parser::ParseNewOperator(void)
nexp->mRight = coexp;
nexp->mDecType = coexp->mDecType;
}
else if (plist && !mdec)
{
Expression * pexp = ParseListExpression(false);
ConsumeToken(TK_CLOSE_PARENTHESIS);
if (pexp && pexp->mType != EX_LIST)
else if (pexp && pexp->mType != EX_LIST)
{
Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX);
dexp->mToken = TK_MUL;
@ -6736,14 +6845,12 @@ Expression* Parser::ParseNewOperator(void)
iexp->mRight = pexp;
iexp->mDecType = nexp->mDecType;
nexp = iexp;
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
nexp->mToken = TK_BINARY_AND;
nexp->mDecType = nexp->mDecType;
nexp->mLeft = iexp;
}
else
mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent);
}
else if (plist)
else if (pexp)
{
mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent);
}
@ -7880,6 +7987,56 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
}
}
}
else if (exp->mType == EX_TYPECAST)
{
Declaration* tdec = exp->mLeft->mDecType;
if (exp->mLeft->mDecType)
{
while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("(cast)"));
while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType))
mdec = mdec->mNext;
while (!mdec && tdec->mBase && tdec->mBase->mBase)
{
tdec = tdec->mBase->mBase;
mdec = tdec->mScope->Lookup(Ident::Unique("(cast)"));
while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType))
mdec = mdec->mNext;
}
if (mdec)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_CALL);
nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = mdec->mBase;
nexp->mLeft->mDecValue = mdec;
nexp->mDecType = mdec->mBase;
nexp->mRight = exp->mRight;
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = tdec;
texp->mDecType->mSize = 2;
nexp->mRight = texp->ConstantFold(mErrors, mDataSection);
nexp = ResolveOverloadCall(nexp);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp;
}
}
}
}
else if (exp->mType == EX_LOGICAL_NOT)
{
const Ident* opident = Ident::Unique("operator!");
@ -8133,6 +8290,30 @@ Expression* Parser::ParseFunction(Declaration * dec)
return exp;
}
void Parser::SkipStatement(void)
{
if (ConsumeTokenIf(TK_OPEN_BRACE))
{
int cnt = 1;
while (cnt > 0)
{
if (ConsumeTokenIf(TK_OPEN_BRACE))
cnt++;
else if (ConsumeTokenIf(TK_CLOSE_BRACE))
cnt--;
else
mScanner->NextToken();
}
}
else
{
while (!ConsumeTokenIf(TK_SEMICOLON))
{
mScanner->NextToken();
}
}
}
Expression* Parser::ParseStatement(void)
{
Expression* exp = nullptr;
@ -8202,7 +8383,32 @@ Expression* Parser::ParseStatement(void)
case TK_IF:
{
mScanner->NextToken();
bool constExp = ConsumeTokenIf(TK_CONSTEXPR);
if (ConsumeTokenIf(TK_CONSTEXPR))
{
exp = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration)->ConstantFold(mErrors, mDataSection);
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
{
if (exp->mDecValue->mInteger)
{
exp = ParseStatement();
if (ConsumeTokenIf(TK_ELSE))
SkipStatement();
}
else
{
SkipStatement();
if (ConsumeTokenIf(TK_ELSE))
exp = ParseStatement();
else
exp = new Expression(mScanner->mLocation, EX_VOID);
}
}
else
mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Condition is not constant");
}
else
{
exp = new Expression(mScanner->mLocation, EX_IF);
exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration);
exp->mRight = new Expression(mScanner->mLocation, EX_ELSE);
@ -8214,22 +8420,8 @@ Expression* Parser::ParseStatement(void)
}
else
exp->mRight->mRight = nullptr;
}
if (constExp)
{
Expression * cexp = exp->mLeft->ConstantFold(mErrors, mDataSection);
if (cexp->mType == EX_CONSTANT && cexp->mDecValue->mType == DT_CONST_INTEGER)
{
if (cexp->mDecValue->mInteger)
exp = exp->mRight->mLeft;
else if (exp->mRight->mRight)
exp = exp->mRight->mRight;
else
exp = new Expression(mScanner->mLocation, EX_VOID);
}
else
mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Condition is not constant");
}
} break;
case TK_WHILE:
{
@ -8663,9 +8855,10 @@ Expression* Parser::ParseStatement(void)
exp->mLeft = ParseRExpression();
if (mFunctionType && mFunctionType->mBase)
{
if (mFunctionType->mBase->mType == DT_TYPE_AUTO)
if (mFunctionType->mBase->mType == DT_TYPE_AUTO || mFunctionType->mBase->IsReference() && mFunctionType->mBase->mBase->mType == DT_TYPE_AUTO)
{
mFunctionType->mBase = exp->mLeft->mDecType;
mFunctionType->mBase = mFunctionType->mBase->DeduceAuto(exp->mLeft->mDecType);
;
if (mFunctionType->mBase->mType == DT_TYPE_STRUCT)
{
// Make room for value struct return
@ -8835,11 +9028,323 @@ Expression* Parser::ParseSwitchStatement(void)
return sexp;
}
int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec)
{
Declaration* ptdec = tdec->mParams;
Declaration* psdec = spec->mParams;
int cost = 0;
if (tdec->mParser)
cost = 100000;
while (ptdec && psdec)
{
if (ptdec->mType == DT_CONST_TEMPLATE && psdec->mType == DT_CONST_TEMPLATE)
{
if (ptdec->mBase)
{
if (ptdec->mBase->mInteger != psdec->mBase->mInteger)
return NOOVERLOAD;
}
else
cost += 100;
}
else if (ptdec->mType == DT_TYPE_TEMPLATE && psdec->mType == DT_TYPE_TEMPLATE)
{
if (ptdec->mBase)
{
if (!ptdec->mBase->IsSame(psdec->mBase))
return NOOVERLOAD;
}
else
cost += 100;
}
else if (ptdec->mType == DT_PACK_TEMPLATE && psdec->mType == DT_PACK_TEMPLATE)
{
if (ptdec->mBase)
{
Declaration* tvp = ptdec->mBase->mParams;
Declaration* svp = psdec->mBase->mParams;
while (tvp && svp && tvp->IsSame(svp))
{
tvp = tvp->mNext;
svp = svp->mNext;
}
if (tvp || svp)
return NOOVERLOAD;
}
else if (psdec->mBase)
{
Declaration* dec = psdec->mBase->mParams;
while (dec)
{
cost += 200;
dec = dec->mNext;
}
}
}
else if (ptdec->mType == DT_PACK_TEMPLATE)
{
if (ptdec->mBase)
{
ptdec = ptdec->mBase->mParams;
continue;
}
else
{
while (psdec)
{
cost += 200;
psdec = psdec->mNext;
}
return cost;
}
}
else
return NOOVERLOAD;
ptdec = ptdec->mNext;
psdec = psdec->mNext;
}
if (ptdec && ptdec->mType == DT_PACK_TEMPLATE)
{
if (ptdec->mBase)
{
if (ptdec->mBase->mParams)
return NOOVERLOAD;
}
else
cost += 50;
}
else if (ptdec || psdec)
return NOOVERLOAD;
return cost;
}
Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd)
{
Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
#if 1
if (expd)
{
if (tmpld->mBase->mType == DT_TEMPLATE)
{
Parser* p = tmpld->mBase->mParser->Clone();
p->mScanner->Replay(tmpld->mBase->mTokens);
tdec = tmpld->mBase->Clone();
tdec->mScope->mName = expd->mScope->mName;
tdec->mScope->mParent = expd->mScope;
p->ParseTemplateDeclarationBody(tdec, nullptr);
return tdec;
}
Declaration* ppdec = nullptr;
Declaration* dec = expd->mParams;
while (dec)
{
Declaration* epdec = dec->Clone();
if (ppdec)
ppdec->mNext = epdec;
else
tdec->mParams = epdec;
ppdec = epdec;
dec = dec->mNext;
}
}
else
{
ConsumeToken(TK_LESS_THAN);
Declaration* ppdec = nullptr;
if (!ConsumeTokenIf(TK_GREATER_THAN))
{
do
{
Expression* exp = ParseShiftExpression(false);
Declaration* pdec = nullptr;
if (exp->mType == EX_TYPE)
{
pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE);
pdec->mBase = exp->mDecType;
}
else if (exp->mType == EX_PACK_TYPE)
{
ConsumeToken(TK_ELLIPSIS);
if (exp->mDecType->mType == DT_PACK_TYPE)
{
Declaration* ptdec = exp->mDecType->mParams;
while (ptdec)
{
pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE);
pdec->mBase = ptdec;
if (pdec)
{
if (ppdec)
ppdec->mNext = pdec;
else
tdec->mParams = pdec;
ppdec = pdec;
}
ptdec = ptdec->mNext;
}
continue;
}
else
{
pdec = new Declaration(exp->mLocation, DT_PACK_TEMPLATE);
pdec->mBase = exp->mDecType;
}
}
else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION)
{
pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE);
pdec->mBase = exp->mDecValue;
}
else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
{
pdec = new Declaration(exp->mLocation, DT_CONST_TEMPLATE);
pdec->mBase = exp->mDecValue;
}
else
mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Template specification expected");
if (pdec)
{
if (ppdec)
ppdec->mNext = pdec;
else
tdec->mParams = pdec;
ppdec = pdec;
}
} while (ConsumeTokenIf(TK_COMMA));
ConsumeToken(TK_GREATER_THAN);
}
}
while (!tmpld->mTokens)
tmpld = tmpld->mNext;
Declaration* epdec = tdec->mParams;
while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE && epdec->mBase->mType != DT_PACK_TEMPLATE)
epdec = epdec->mNext;
if (epdec)
{
// Partial template specification
Declaration* bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType);
tdec->mBase = bdec;
bdec->mTemplate = tdec;
bdec->mBase = tmpld->mBase->mBase;
tdec->mNext = tmpld;
bdec->mIdent = tdec->MangleIdent();
return bdec;
}
Declaration* pthis = tmpld->mClass;
int mindist = NOOVERLOAD;
Declaration* etdec = nullptr;
Declaration* dec = tmpld;
while (dec)
{
int dist = ExpansionDistance(dec, tdec);
if (dist < mindist)
{
mindist = dist;
etdec = dec;
}
dec = dec->mNext;
}
if (mindist == 0)
return etdec->mBase;
else if (mindist == NOOVERLOAD)
mErrors->Error(tdec->mLocation, EERR_TEMPLATE_PARAMS, "No matching template parameters");
else
tmpld = etdec;
dec = tdec->mParams;
Declaration * pdec = tmpld->mParams;
Declaration * ppdec = nullptr;
while (pdec)
{
if (pdec->mType == DT_PACK_TEMPLATE)
{
if (!dec)
{
Declaration* packd = new Declaration(tdec->mLocation, DT_PACK_TEMPLATE);
packd->mBase = new Declaration(tdec->mLocation, DT_PACK_TYPE);
if (ppdec)
ppdec->mNext = packd;
else
tdec->mParams = packd;
dec = packd;
}
else if (dec->mType != DT_PACK_TEMPLATE)
{
Declaration* packd = new Declaration(dec->mLocation, DT_PACK_TEMPLATE);
packd->mBase = new Declaration(dec->mLocation, DT_PACK_TYPE);
if (ppdec)
ppdec->mNext = packd;
else
tdec->mParams = packd;
ppdec = nullptr;
while (dec)
{
Declaration* ndec = dec->mBase->Clone();
if (ppdec)
ppdec->mNext = ndec;
else
packd->mBase->mParams = ndec;
ppdec = ndec;
dec = dec->mNext;
}
dec = packd;
}
}
if (dec)
{
dec->mIdent = pdec->mIdent;
tdec->mScope->Insert(dec->mIdent, dec->mBase);
ppdec = dec;
dec = dec->mNext;
}
pdec = pdec->mNext;
}
#else
if (expd)
{
if (tmpld->mBase->mType == DT_TEMPLATE)
@ -8971,28 +9476,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
Declaration* etdec = tmpld->mNext;
while (etdec && !etdec->IsSameParams(tdec))
etdec = etdec->mNext;
if (etdec)
{
return etdec->mBase;
}
else
{
Declaration* epdec = tdec->mParams;
while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE)
epdec = epdec->mNext;
if (epdec)
{
// Partial template specification
Declaration * bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType);
tdec->mBase = bdec;
bdec->mTemplate = tdec;
bdec->mBase = tmpld->mBase->mBase;
tdec->mNext = tmpld;
bdec->mIdent = tdec->MangleIdent();
return bdec;
}
#endif
Parser* p = tmpld->mParser->Clone();
@ -9076,7 +9560,6 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
}
return tdec->mBase;
}
}
void Parser::CompleteTemplateExpansion(Declaration* tmpld)
@ -9121,7 +9604,7 @@ Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec)
{
Declaration* tdec = new Declaration(fdec->mLocation, DT_TEMPLATE);
tdec->mParser = this->Clone();
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
tdec->mScope = new DeclarationScope(mTemplateScope, SLEVEL_TEMPLATE);
Declaration* ppdec = nullptr;
int ntp = 0;
@ -9221,6 +9704,8 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis)
Declaration* ppdec = nullptr;
ConsumeToken(TK_LESS_THAN);
if (mScanner->mToken != TK_GREATER_THAN)
{
for (;;)
{
Declaration* pdec = nullptr;
@ -9276,6 +9761,7 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis)
if (!ConsumeTokenIf(TK_COMMA))
break;
}
}
ConsumeToken(TK_GREATER_THAN);
@ -9295,7 +9781,7 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis)
void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthis)
{
mScanner->BeginRecord();
if (mScanner->mToken == TK_CLASS)
if (mScanner->mToken == TK_CLASS || mScanner->mToken == TK_STRUCT)
{
// Class template
Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT);
@ -9404,7 +9890,24 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi
tdec->mScope->mName = tdec->mQualIdent;
if (tdec->mQualIdent == mScope->Mangle(tdec->mIdent))
mScope->Insert(tdec->mIdent, tdec->mBase);
{
Declaration* pdec = mScope->Insert(tdec->mIdent, tdec->mBase);
if (pdec)
{
Declaration* ppdec = pdec;
while (pdec && !pdec->IsSameTemplate(tdec->mBase))
{
ppdec = pdec;
pdec = pdec->mNext;
}
if (pdec && pdec->mTemplate)
{
tdec->mNext = pdec->mTemplate->mNext;
pdec->mTemplate->mNext = tdec;
}
}
}
Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase);
if (pdec)

View File

@ -91,6 +91,7 @@ protected:
Declaration* ParseQualIdent(void);
void SkipStatement(void);
Expression* ParseStatement(void);
Expression* ParseSwitchStatement(void);
@ -109,6 +110,7 @@ protected:
void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis);
Declaration* FunctionAutoParamsToTemplate(Declaration* fdec);
int ExpansionDistance(Declaration* tdec, Declaration* spec);
Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd);
void CompleteTemplateExpansion(Declaration* tmpld);

View File

@ -148,6 +148,7 @@ const char* TokenNames[] =
"'#repeat'",
"'#until'",
"'#embed'",
"'#for'",
"'##'",
"'namespace'",
@ -596,6 +597,84 @@ void Scanner::NextPreToken(void)
mPreprocessor->CloseSource();
}
}
else if (mToken == TK_PREP_FOR)
{
NextRawToken();
if (mToken == TK_OPEN_PARENTHESIS)
{
NextRawToken();
Macro* macro = new Macro(Ident::Unique("@for"), nullptr);
if (mToken == TK_IDENT)
{
const Ident* loopindex = mTokenIdent;
NextRawToken();
if (mToken == TK_COMMA)
{
mPreprocessorMode = true;
NextToken();
int64 loopCount = PrepParseConditional();
mPreprocessorMode = false;
if (mToken == TK_CLOSE_PARENTHESIS)
{
int slen = mOffset;
bool quote = false;
while (mLine[slen] && (quote || mLine[slen] != '/' || mLine[slen + 1] != '/'))
{
if (mLine[slen] == '"')
quote = !quote;
slen++;
}
macro->SetString(mLine + mOffset, slen - mOffset);
mOffset = slen;
while (mLine[mOffset])
mOffset++;
if (loopCount > 0)
{
MacroExpansion* ex = new MacroExpansion();
MacroDict* scope = mDefineArguments;
mDefineArguments = new MacroDict();
Macro* arg = new Macro(loopindex, scope);
mDefineArguments->Insert(arg);
arg->SetString("0");
ex->mLine = mLine;
ex->mOffset = mOffset;
ex->mLink = mMacroExpansion;
ex->mChar = mTokenChar;
ex->mLoopCount = 0;
ex->mLoopIndex = arg;
ex->mLoopLimit = loopCount;
mMacroExpansion = ex;
mMacroExpansionDepth++;
if (mMacroExpansionDepth > 1024)
mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent);
mLine = macro->mString;
mOffset = 0;
NextChar();
}
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "')' expected in defined parameter list");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "',' expected");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'loop index variable expected");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'('(' expected");
}
else if (mToken == TK_PREP_DEFINE)
{
NextRawToken();
@ -1313,6 +1392,8 @@ void Scanner::NextRawToken(void)
mToken = TK_PREP_UNTIL;
else if (!strcmp(tkprep, "embed"))
mToken = TK_PREP_EMBED;
else if (!strcmp(tkprep, "for"))
mToken = TK_PREP_FOR;
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", tkprep);
}
@ -1912,6 +1993,19 @@ bool Scanner::NextChar(void)
{
if (mMacroExpansion)
{
if (mMacroExpansion->mLoopIndex)
{
mMacroExpansion->mLoopCount++;
if (mMacroExpansion->mLoopCount < mMacroExpansion->mLoopLimit)
{
char buffer[20];
sprintf_s(buffer, "%d", int(mMacroExpansion->mLoopCount));
mMacroExpansion->mLoopIndex->SetString(buffer);
mOffset = 0;
continue;
}
}
MacroExpansion* mac = mMacroExpansion->mLink;
// delete mDefineArguments;

View File

@ -146,6 +146,7 @@ enum Token
TK_PREP_REPEAT,
TK_PREP_UNTIL,
TK_PREP_EMBED,
TK_PREP_FOR,
TK_PREP_CONCAT,
@ -284,7 +285,14 @@ protected:
const char * mLine;
int mOffset;
char mChar;
Macro * mLoopIndex;
int64 mLoopCount, mLoopLimit;
MacroDict* mDefinedArguments;
MacroExpansion(void)
: mLink(nullptr), mLine(nullptr), mOffset(0), mChar(0), mLoopIndex(nullptr), mLoopCount(0), mLoopLimit(0), mDefinedArguments(nullptr)
{}
} * mMacroExpansion;
int mMacroExpansionDepth;