1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 20:42:21 +02:00

Fixed erroneous 'this' ctor assignment detection in struct extensions

This commit is contained in:
Brian Fiete 2022-02-13 07:41:31 -05:00
parent b341b6d3b4
commit fd4ec25e7b
4 changed files with 89 additions and 42 deletions

View file

@ -2262,47 +2262,65 @@ void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
{
for (auto& fieldInstance : checkTypeInstance->mFieldInstances)
{
if (fieldInstance.mMergedDataIdx != -1)
{
int checkMask = 1 << fieldInstance.mMergedDataIdx;
if ((localVar->mUnassignedFieldFlags & checkMask) != 0)
{
auto fieldDef = fieldInstance.GetFieldDef();
if (auto propertyDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
{
String propName;
if (propertyDeclaration->mNameNode != NULL)
propertyDeclaration->mNameNode->ToString(propName);
if (fieldInstance.mMergedDataIdx == -1)
continue;
if (checkTypeInstance == mCurTypeInstance)
{
Fail(StrFormat("Auto-implemented property '%s' must be fully assigned before control is returned to the caller",
propName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
else
{
Fail(StrFormat("Auto-implemented property '%s.%s' must be fully assigned before control is returned to the caller",
TypeToString(checkTypeInstance).c_str(),
propName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
int checkMask = 1 << fieldInstance.mMergedDataIdx;
if ((localVar->mUnassignedFieldFlags & checkMask) != 0)
{
auto fieldDef = fieldInstance.GetFieldDef();
if (mCurMethodInstance->mMethodDef->mDeclaringType->mIsPartial)
{
if (mCurMethodInstance->mMethodDef->mDeclaringType != fieldInstance.GetFieldDef()->mDeclaringType)
{
// This extension is only responsible for its own fields
foundFields = true;
continue;
}
if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mInitializer != NULL))
{
// This initializer was handled in CtorNoBody
foundFields = true;
continue;
}
}
if (auto propertyDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
{
String propName;
if (propertyDeclaration->mNameNode != NULL)
propertyDeclaration->mNameNode->ToString(propName);
if (checkTypeInstance == mCurTypeInstance)
{
Fail(StrFormat("Auto-implemented property '%s' must be fully assigned before control is returned to the caller",
propName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
else
{
if (checkTypeInstance == mCurTypeInstance)
{
Fail(StrFormat("Field '%s' must be fully assigned before control is returned to the caller",
fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
else
{
Fail(StrFormat("Field '%s.%s' must be fully assigned before control is returned to the caller",
TypeToString(checkTypeInstance).c_str(),
fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
Fail(StrFormat("Auto-implemented property '%s.%s' must be fully assigned before control is returned to the caller",
TypeToString(checkTypeInstance).c_str(),
propName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
}
else
{
if (checkTypeInstance == mCurTypeInstance)
{
Fail(StrFormat("Field '%s' must be fully assigned before control is returned to the caller",
fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
else
{
Fail(StrFormat("Field '%s.%s' must be fully assigned before control is returned to the caller",
TypeToString(checkTypeInstance).c_str(),
fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
}
}
foundFields = true;
}
foundFields = true;
}
}
checkTypeInstance = checkTypeInstance->mBaseType;
@ -10087,8 +10105,10 @@ void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool al
}
}
BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, const BfAllocTarget& allocTarget, bool callDtor)
BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, const BfAllocTarget& allocTarget, BfCastFlags castFlags)
{
bool callDtor = (castFlags & BfCastFlags_NoBoxDtor) == 0;
if (mBfIRBuilder->mIgnoreWrites)
{
if (toType == mContext->mBfObjectType)
@ -10160,7 +10180,7 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
loadedVal = mBfIRBuilder->CreateLoad(nullableValueAddr);
}
auto boxedVal = BoxValue(srcNode, BfTypedValue(loadedVal, fromStructTypeInstance->GetUnderlyingType()), resultType, allocTarget, callDtor);
auto boxedVal = BoxValue(srcNode, BfTypedValue(loadedVal, fromStructTypeInstance->GetUnderlyingType()), resultType, allocTarget, callDtor ? BfCastFlags_None : BfCastFlags_NoBoxDtor);
RestoreScopeState();
if (!boxedVal)
return BfTypedValue();
@ -17067,7 +17087,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
}
// Zero out memory for default ctor
if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()))
if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (methodInstance->mChainType != BfMethodChainType_ChainMember))
{
if (mCurTypeInstance->IsTypedPrimitive())
{
@ -17075,7 +17095,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
mBfIRBuilder->CreateStore(GetDefaultValue(mCurTypeInstance), thisRef);
}
else if (mCurTypeInstance->mInstSize > 0)
{
{
BfIRValue fillValue = GetConstValue8(0);
BfIRValue sizeValue = GetConstValue(mCurTypeInstance->mInstSize);
auto thisRef = mCurMethodState->mLocals[0]->mValue;

View file

@ -1626,7 +1626,7 @@ public:
void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
bool CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting);
BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true);
BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, BfCastFlags castFlags = BfCastFlags_None);
BfIRValue CastToFunction(BfAstNode* srcNode, const BfTypedValue& targetValue, BfMethodInstance* methodInstance, BfType* toType, BfCastFlags castFlags = BfCastFlags_None, BfIRValue irFunc = BfIRValue());
BfIRValue CastToValue(BfAstNode* srcNode, BfTypedValue val, BfType* toType, BfCastFlags castFlags = BfCastFlags_None, BfCastResultFlags* resultFlags = NULL);
BfTypedValue Cast(BfAstNode* srcNode, const BfTypedValue& val, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);

View file

@ -11906,7 +11906,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
// Null -> ObjectInst|IFace|ptr
if ((typedVal.mType->IsNull()) &&
((toType->IsObjectOrInterface()) || (toType->IsPointer() || (toType->IsFunction()))))
((toType->IsObjectOrInterface()) || (toType->IsPointer() || (toType->IsFunction()) || (toType->IsAllocType()))))
{
return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
}
@ -13274,7 +13274,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
}
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, ignoreWrites);
auto value = BoxValue(srcNode, typedVal, toType, scopeData, (castFlags & BfCastFlags_NoBoxDtor) == 0);
auto value = BoxValue(srcNode, typedVal, toType, scopeData, castFlags);
if (value)
return value.mValue;
}