Fix duplicate member cons/destructor if class included from multiple cpp

This commit is contained in:
drmortalwombat 2023-08-13 11:00:02 +02:00
parent 9d6691cf91
commit 61f8b68c2f
8 changed files with 178 additions and 21 deletions

11
include/opp/move.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef OPP_MOVE_H
#define OPP_MOVE_H
template <class T>
void move(T & dst, T & src)
{
dst = src;
}
#endif

View File

@ -1346,6 +1346,9 @@ bool Compiler::WriteDbjFile(const char* filename)
case DT_TYPE_REFERENCE: 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)); 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; 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: 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); fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"enum\",\"members\": [\n", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize);

View File

@ -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 bool Expression::IsSame(const Expression* exp) const
{ {
if (!exp || mType != exp->mType) if (!exp || mType != exp->mType)
@ -868,6 +899,32 @@ Declaration* Declaration::BuildReference(const Location& loc)
return pdec; 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) Declaration* Declaration::Last(void)
{ {
mPrev = nullptr; mPrev = nullptr;
@ -904,6 +961,10 @@ const Ident* Declaration::MangleIdent(void)
{ {
mMangleIdent = mBase->MangleIdent()->PreMangle("&"); mMangleIdent = mBase->MangleIdent()->PreMangle("&");
} }
else if (mType == DT_TYPE_RVALUEREF)
{
mMangleIdent = mBase->MangleIdent()->PreMangle("&&");
}
else if (mType == DT_TYPE_POINTER) else if (mType == DT_TYPE_POINTER)
{ {
mMangleIdent = mBase->MangleIdent()->PreMangle("*"); mMangleIdent = mBase->MangleIdent()->PreMangle("*");
@ -1065,6 +1126,13 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
else else
return ResolveTemplate(fdec, tdec->mBase); 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) else if (tdec->mType == DT_TYPE_POINTER)
{ {
if (fdec->mType == DT_TYPE_POINTER) if (fdec->mType == DT_TYPE_POINTER)

View File

@ -20,6 +20,7 @@ enum DecType
DT_TYPE_ENUM, DT_TYPE_ENUM,
DT_TYPE_POINTER, DT_TYPE_POINTER,
DT_TYPE_REFERENCE, DT_TYPE_REFERENCE,
DT_TYPE_RVALUEREF,
DT_TYPE_ARRAY, DT_TYPE_ARRAY,
DT_TYPE_STRUCT, DT_TYPE_STRUCT,
DT_TYPE_UNION, 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_PRIVATE = (1ULL << 26);
static const uint64 DTF_PROTECTED = (1ULL << 27); static const uint64 DTF_PROTECTED = (1ULL << 27);
static const uint64 DTF_VIRTUAL = (1ULL << 28); 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_VARIABLE = (1ULL << 32);
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
@ -235,6 +238,8 @@ public:
bool HasSideEffects(void) const; bool HasSideEffects(void) const;
bool IsSame(const Expression* exp) const; bool IsSame(const Expression* exp) const;
bool IsRValue(void) const;
bool IsLValue(void) const;
void Dump(int ident) const; void Dump(int ident) const;
}; };
@ -296,6 +301,10 @@ public:
Declaration* BuildReference(const Location& loc); Declaration* BuildReference(const Location& loc);
Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstPointer(const Location& loc);
Declaration* BuildConstReference(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 CanResolveTemplate(Expression* pexp, Declaration* tdec);
bool ResolveTemplate(Declaration* fdec, Declaration * tdec); bool ResolveTemplate(Declaration* fdec, Declaration * tdec);

View File

@ -30,6 +30,7 @@ enum ErrorID
EWARN_NULL_POINTER_DEREFERENCED, EWARN_NULL_POINTER_DEREFERENCED,
EWARN_DESTRUCTOR_MISMATCH, EWARN_DESTRUCTOR_MISMATCH,
EWARN_NUMERIC_0_USED_AS_NULLPTR, EWARN_NUMERIC_0_USED_AS_NULLPTR,
EWARN_FLOAT_TO_INT,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,

View File

@ -802,7 +802,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
RegisterCall(procDec, pdec->mBase->mCopyConstructor); 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; ldec->mBase->mFlags |= DTF_STACKCALL;
if (pdec) if (pdec)

View File

@ -140,6 +140,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
} }
else if (v.mType->mType == DT_TYPE_FLOAT && type->IsIntegerType()) 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); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR);
cins->mOperator = IA_FLOAT2INT; cins->mOperator = IA_FLOAT2INT;
cins->mSrc[0].mType = IT_FLOAT; cins->mSrc[0].mType = IT_FLOAT;
@ -155,6 +157,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
v.mType = type; v.mType = type;
return v; 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) else if (v.mType->mSize < type->mSize)
{ {
if (v.mType->mSize == 1 && type->mSize == 2) if (v.mType->mSize == 1 && type->mSize == 2)

View File

@ -825,6 +825,34 @@ Declaration* Parser::ParsePostfixDeclaration(void)
ndec->mBase = dec; ndec->mBase = dec;
return ndec; 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) else if (mScanner->mToken == TK_OPEN_PARENTHESIS)
{ {
mScanner->NextToken(); mScanner->NextToken();
@ -1543,6 +1571,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp)
void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) 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); Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE);
pthisexp->mDecType = pthis; pthisexp->mDecType = pthis;
pthisexp->mDecValue = cfunc->mBase->mParams; 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_DEFINED)
{ {
if (pthis->mBase->mDestructor->mFlags & DTF_COMPLETED)
return;
pthis->mBase->mDestructor->mFlags |= DTF_COMPLETED;
Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE);
pthisexp->mDecType = pthis; pthisexp->mDecType = pthis;
pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams;
@ -2870,7 +2907,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
{ {
Expression* lexp = nullptr, * rexp = nullptr; 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); lexp = AddFunctionCallRefReturned(exp->mLeft);
@ -2921,7 +2958,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
rexp = ConcatExpression(rexp, dexp); 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); lexp = AddFunctionCallRefReturned(exp->mLeft);
@ -2990,7 +3027,8 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
rexp = ConcatExpression(rexp, AddFunctionCallRefReturned(pex)); 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 // Returning a value object for pass as reference
// add a temporary variable // add a temporary variable
@ -3042,7 +3080,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
rexp = ConcatExpression(rexp, dexp); 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 // 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) 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; Declaration* dtype = exp->mDecType;
if (dtype->mType == DT_TYPE_REFERENCE) if (dtype->mType == DT_TYPE_REFERENCE || dtype->mType == DT_TYPE_RVALUEREF)
dtype = dtype->mBase; dtype = dtype->mBase;
if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION) if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION)
@ -4940,10 +4978,16 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
dist += 0; dist += 0;
else if (ptype->IsSubType(etype)) else if (ptype->IsSubType(etype))
dist += 256; 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 else
return NOOVERLOAD; return NOOVERLOAD;
} }
@ -4976,9 +5020,9 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) bool Parser::CanCoerceExpression(Expression* exp, Declaration* type)
{ {
Declaration* tdec = exp->mDecType; Declaration* tdec = exp->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE) while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF)
tdec = tdec->mBase; tdec = tdec->mBase;
while (type->mType == DT_TYPE_REFERENCE) while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF)
type = type->mBase; type = type->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
@ -5015,9 +5059,9 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type)
Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
{ {
Declaration* tdec = exp->mDecType; Declaration* tdec = exp->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE) while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF)
tdec = tdec->mBase; tdec = tdec->mBase;
while (type->mType == DT_TYPE_REFERENCE) while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF)
type = type->mBase; type = type->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
@ -5223,7 +5267,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
if (ibest == NOOVERLOAD) if (ibest == NOOVERLOAD)
{ {
#if _DEBUG #if _DEBUG
int d = OverloadDistance(exp->mLeft->mDecValue->mBase, exp->mRight); int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight);
#endif #endif
mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); 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); nexp->mRight = ParseExpression(false);
ConsumeToken(TK_CLOSE_BRACKET); 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); nexp = CheckOperatorOverload(nexp);
} }
@ -5307,7 +5351,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
tdec->mBase = exp->mDecType; tdec->mBase = exp->mDecType;
tdec->mVarIndex = mLocalIndex++; tdec->mVarIndex = mLocalIndex++;
tdec->mSize = exp->mDecType->mSize; tdec->mSize = exp->mDecType->mSize;
tdec->mFlags |= DTF_DEFINED; tdec->mFlags |= DTF_DEFINED | DTF_TEMPORARY;
Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE);
vexp->mDecType = exp->mDecType; vexp->mDecType = exp->mDecType;
@ -5365,13 +5409,28 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
exp = nexp; exp = nexp;
} }
else else if (pexp)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST);
nexp->mDecType = exp->mDecType; nexp->mDecType = exp->mDecType;
nexp->mLeft = pexp; nexp->mLeft = pexp;
exp = nexp->ConstantFold(mErrors); 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 else
@ -6270,7 +6329,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
else if (exp->mType == EX_INDEX) else if (exp->mType == EX_INDEX)
{ {
Declaration* tdec = exp->mLeft->mDecType; 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; tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
@ -6486,7 +6545,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
} }
Declaration* tdec = exp->mLeft->mDecType; 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; tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
@ -6546,7 +6605,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
if (opident) if (opident)
{ {
Declaration* tdec = exp->mLeft->mDecType; 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; tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
@ -6585,7 +6644,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
{ {
const Ident* opident = Ident::Unique("operator!"); const Ident* opident = Ident::Unique("operator!");
Declaration* tdec = exp->mLeft->mDecType; 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; tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)