From 61f8b68c2fec39e05e7cef11a87162d45d07587a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 13 Aug 2023 11:00:02 +0200 Subject: [PATCH] Fix duplicate member cons/destructor if class included from multiple cpp --- include/opp/move.h | 11 ++++ oscar64/Compiler.cpp | 3 ++ oscar64/Declaration.cpp | 68 +++++++++++++++++++++++ oscar64/Declaration.h | 9 ++++ oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 6 +++ oscar64/Parser.cpp | 99 +++++++++++++++++++++++++++------- 8 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 include/opp/move.h diff --git a/include/opp/move.h b/include/opp/move.h new file mode 100644 index 0000000..bdf4950 --- /dev/null +++ b/include/opp/move.h @@ -0,0 +1,11 @@ +#ifndef OPP_MOVE_H +#define OPP_MOVE_H + + +template +void move(T & dst, T & src) +{ + dst = src; +} + +#endif diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 08e9b58..7bf5ee2 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -1346,6 +1346,9 @@ bool Compiler::WriteDbjFile(const char* filename) case DT_TYPE_REFERENCE: fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"ref\", eid: %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); break; + case DT_TYPE_RVALUEREF: + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"rref\", eid: %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); + break; case DT_TYPE_ENUM: { fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"enum\",\"members\": [\n", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 23b8254..c957ea4 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -328,6 +328,37 @@ bool Expression::HasSideEffects(void) const } } +bool Expression::IsRValue(void) const +{ + if (mDecType->mType == DT_TYPE_RVALUEREF) + return true; + else if (mDecType->mType == DT_TYPE_REFERENCE) + return false; + else if (mType == EX_VARIABLE) + { + if (mDecValue->mFlags & DTF_TEMPORARY) + return true; + else + return false; + } + else if (mType == EX_QUALIFY || mType == EX_INDEX || mType == EX_ASSIGNMENT || mType == EX_CONSTANT || mType == EX_PREFIX && mToken == TK_MUL) + return false; + else + return true; +} + +bool Expression::IsLValue(void) const +{ + if (mDecType->mFlags & DTF_CONST) + return false; + else 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::IsSame(const Expression* exp) const { if (!exp || mType != exp->mType) @@ -868,6 +899,32 @@ Declaration* Declaration::BuildReference(const Location& loc) return pdec; } +Declaration* Declaration::BuildRValueRef(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + return pdec; +} + +Declaration* Declaration::BuildConstRValueRef(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED | DTF_CONST; + pdec->mSize = 2; + return pdec; +} + +DecType Declaration::ValueType(void) const +{ + if (mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF) + return mBase->mType; + else + return mType; +} + Declaration* Declaration::Last(void) { mPrev = nullptr; @@ -904,6 +961,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mBase->MangleIdent()->PreMangle("&"); } + else if (mType == DT_TYPE_RVALUEREF) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("&&"); + } else if (mType == DT_TYPE_POINTER) { mMangleIdent = mBase->MangleIdent()->PreMangle("*"); @@ -1065,6 +1126,13 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) else return ResolveTemplate(fdec, tdec->mBase); } + else if (tdec->mType == DT_TYPE_RVALUEREF) + { + if (fdec->mType == DT_TYPE_RVALUEREF) + return ResolveTemplate(fdec->mBase, tdec->mBase); + else + return ResolveTemplate(fdec, tdec->mBase); + } else if (tdec->mType == DT_TYPE_POINTER) { if (fdec->mType == DT_TYPE_POINTER) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index a18439b..1f1a9b0 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -20,6 +20,7 @@ enum DecType DT_TYPE_ENUM, DT_TYPE_POINTER, DT_TYPE_REFERENCE, + DT_TYPE_RVALUEREF, DT_TYPE_ARRAY, DT_TYPE_STRUCT, DT_TYPE_UNION, @@ -90,6 +91,8 @@ static const uint64 DTF_DYNSTACK = (1ULL << 25); static const uint64 DTF_PRIVATE = (1ULL << 26); static const uint64 DTF_PROTECTED = (1ULL << 27); static const uint64 DTF_VIRTUAL = (1ULL << 28); +static const uint64 DTF_TEMPORARY = (1ULL << 29); +static const uint64 DTF_COMPLETED = (1ULL << 30); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); @@ -235,6 +238,8 @@ public: bool HasSideEffects(void) const; bool IsSame(const Expression* exp) const; + bool IsRValue(void) const; + bool IsLValue(void) const; void Dump(int ident) const; }; @@ -296,6 +301,10 @@ public: Declaration* BuildReference(const Location& loc); Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstReference(const Location& loc); + Declaration* BuildRValueRef(const Location& loc); + Declaration* BuildConstRValueRef(const Location& loc); + + DecType ValueType(void) const; bool CanResolveTemplate(Expression* pexp, Declaration* tdec); bool ResolveTemplate(Declaration* fdec, Declaration * tdec); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 23b5678..95c32f1 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -30,6 +30,7 @@ enum ErrorID EWARN_NULL_POINTER_DEREFERENCED, EWARN_DESTRUCTOR_MISMATCH, EWARN_NUMERIC_0_USED_AS_NULLPTR, + EWARN_FLOAT_TO_INT, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index d9113fe..479330f 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -802,7 +802,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo RegisterCall(procDec, pdec->mBase->mCopyConstructor); } - if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE)) + if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF))) ldec->mBase->mFlags |= DTF_STACKCALL; if (pdec) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index cf1c62f..a7fda9a 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -140,6 +140,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else if (v.mType->mType == DT_TYPE_FLOAT && type->IsIntegerType()) { + mErrors->Error(exp->mLocation, EWARN_FLOAT_TO_INT, "Float to int conversion, potential loss of precision"); + InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); cins->mOperator = IA_FLOAT2INT; cins->mSrc[0].mType = IT_FLOAT; @@ -155,6 +157,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p v.mType = type; return v; } + else if (type->mType == DT_TYPE_POINTER && v.mType->IsNumericType() && (mCompilerOptions & COPT_CPLUSPLUS)) + { + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer"); + } else if (v.mType->mSize < type->mSize) { if (v.mType->mSize == 1 && type->mSize == 2) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c3e50f9..cde99e8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -825,6 +825,34 @@ Declaration* Parser::ParsePostfixDeclaration(void) ndec->mBase = dec; return ndec; } + else if (mScanner->mToken == TK_LOGICAL_AND && (mCompilerOptions & COPT_CPLUSPLUS)) + { + mScanner->NextToken(); + + Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_RVALUEREF); + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + + for (;;) + { + if (mScanner->mToken == TK_CONST) + { + ndec->mFlags |= DTF_CONST; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_VOLATILE) + { + ndec->mFlags |= DTF_VOLATILE; + mScanner->NextToken(); + } + else + break; + } + + Declaration* dec = ParsePostfixDeclaration(); + ndec->mBase = dec; + return ndec; + } else if (mScanner->mToken == TK_OPEN_PARENTHESIS) { mScanner->NextToken(); @@ -1543,6 +1571,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) { + if (cfunc->mFlags & DTF_COMPLETED) + return; + + cfunc->mFlags |= DTF_COMPLETED; + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); pthisexp->mDecType = pthis; pthisexp->mDecValue = cfunc->mBase->mParams; @@ -2688,6 +2721,10 @@ void Parser::AppendMemberDestructor(Declaration* pthis) { if (pthis->mBase->mDestructor->mFlags & DTF_DEFINED) { + if (pthis->mBase->mDestructor->mFlags & DTF_COMPLETED) + return; + pthis->mBase->mDestructor->mFlags |= DTF_COMPLETED; + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); pthisexp->mDecType = pthis; pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; @@ -2870,7 +2907,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) { Expression* lexp = nullptr, * rexp = nullptr; - if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) + if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE && exp->mLeft->mDecType->mType != DT_TYPE_RVALUEREF) { lexp = AddFunctionCallRefReturned(exp->mLeft); @@ -2921,7 +2958,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } - else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) + else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE && exp->mLeft->mDecType->mType != DT_TYPE_RVALUEREF) { lexp = AddFunctionCallRefReturned(exp->mLeft); @@ -2990,7 +3027,8 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, AddFunctionCallRefReturned(pex)); - if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mType == EX_CALL) + if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && + (pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_RVALUEREF) && pex->mType == EX_CALL) { // Returning a value object for pass as reference // add a temporary variable @@ -3042,7 +3080,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } - else if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mType == EX_CONSTANT) + else if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && pex->mType == EX_CONSTANT) { // A simple constant is passed by const ref if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER) @@ -4653,7 +4691,7 @@ Expression* Parser::ParseQualify(Expression* exp) { Declaration* dtype = exp->mDecType; - if (dtype->mType == DT_TYPE_REFERENCE) + if (dtype->mType == DT_TYPE_REFERENCE || dtype->mType == DT_TYPE_RVALUEREF) dtype = dtype->mBase; if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION) @@ -4940,10 +4978,16 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 0; else if (ptype->IsSubType(etype)) dist += 256; - else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype)) + else if (ptype->mType == DT_TYPE_RVALUEREF && ptype->mBase->IsSameMutable(etype) && ex->IsRValue()) { - if (ex->mType == EX_VARIABLE) - dist += 1; + dist += 1; + } + else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSameMutable(etype)) + { + if (ex->IsLValue()) + dist += 2; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 4; else return NOOVERLOAD; } @@ -4976,9 +5020,9 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) { Declaration* tdec = exp->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; - while (type->mType == DT_TYPE_REFERENCE) + while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF) type = type->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -5015,9 +5059,9 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) { Declaration* tdec = exp->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; - while (type->mType == DT_TYPE_REFERENCE) + while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF) type = type->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -5223,7 +5267,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) if (ibest == NOOVERLOAD) { #if _DEBUG - int d = OverloadDistance(exp->mLeft->mDecValue->mBase, exp->mRight); + int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); #endif mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); } @@ -5262,7 +5306,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mRight = ParseExpression(false); ConsumeToken(TK_CLOSE_BRACKET); - if (exp->mDecType->mType == DT_TYPE_STRUCT || exp->mDecType->mType == DT_TYPE_REFERENCE && exp->mDecType->mBase->mType == DT_TYPE_STRUCT) + if (exp->mDecType->ValueType() == DT_TYPE_STRUCT) { nexp = CheckOperatorOverload(nexp); } @@ -5307,7 +5351,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) tdec->mBase = exp->mDecType; tdec->mVarIndex = mLocalIndex++; tdec->mSize = exp->mDecType->mSize; - tdec->mFlags |= DTF_DEFINED; + tdec->mFlags |= DTF_DEFINED | DTF_TEMPORARY; Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); vexp->mDecType = exp->mDecType; @@ -5365,13 +5409,28 @@ Expression* Parser::ParsePostfixExpression(bool lhs) exp = nexp; } - else + else if (pexp) { Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = pexp; exp = nexp->ConstantFold(mErrors); } + else + { + Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + + tdec->mBase = exp->mDecType; + tdec->mVarIndex = mLocalIndex++; + tdec->mSize = exp->mDecType->mSize; + tdec->mFlags |= DTF_DEFINED | DTF_TEMPORARY; + + Expression* nexp = new Expression(mScanner->mLocation, EX_VARIABLE); + nexp->mDecType = exp->mDecType; + nexp->mDecValue = tdec; + + exp = nexp; + } } } else @@ -6270,7 +6329,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) else if (exp->mType == EX_INDEX) { Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6486,7 +6545,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6546,7 +6605,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6585,7 +6644,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) { const Ident* opident = Ident::Unique("operator!"); Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT)