1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Fixed extension initializers and dtors. [NoExtension]. Extension warning

This commit is contained in:
Brian Fiete 2020-10-22 11:33:13 -07:00
parent 6e71cbc765
commit b6db69d2b0
15 changed files with 235 additions and 64 deletions

View file

@ -149,6 +149,12 @@ namespace System
} }
[AttributeUsage(.MemberAccess)]
public struct NoExtensionAttribute : Attribute
{
}
[AttributeUsage(.Block)] [AttributeUsage(.Block)]
public struct IgnoreErrorsAttribute : Attribute public struct IgnoreErrorsAttribute : Attribute
{ {

View file

@ -2949,7 +2949,7 @@ public:
BfTokenNode* mThisToken; BfTokenNode* mThisToken;
BfTokenNode* mInitializerColonToken; BfTokenNode* mInitializerColonToken;
BfInvocationExpression* mInitializer; BfExpression* mInitializer;
}; BF_AST_DECL(BfConstructorDeclaration, BfMethodDeclaration); }; BF_AST_DECL(BfConstructorDeclaration, BfMethodDeclaration);

View file

@ -395,6 +395,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mActionTypeDef = NULL; mActionTypeDef = NULL;
mEnumTypeDef = NULL; mEnumTypeDef = NULL;
mFriendAttributeTypeDef = NULL; mFriendAttributeTypeDef = NULL;
mNoExtensionAttributeTypeDef = NULL;
mCheckedAttributeTypeDef = NULL; mCheckedAttributeTypeDef = NULL;
mUncheckedAttributeTypeDef = NULL; mUncheckedAttributeTypeDef = NULL;
mFunctionTypeDef = NULL; mFunctionTypeDef = NULL;
@ -6516,6 +6517,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mActionTypeDef = _GetRequiredType("System.Action"); mActionTypeDef = _GetRequiredType("System.Action");
mEnumTypeDef = _GetRequiredType("System.Enum"); mEnumTypeDef = _GetRequiredType("System.Enum");
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute"); mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");
mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute"); mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute"); mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute");
mResultTypeDef = _GetRequiredType("System.Result", 1); mResultTypeDef = _GetRequiredType("System.Result", 1);

View file

@ -394,6 +394,7 @@ public:
BfTypeDef* mDisableChecksAttributeTypeDef; BfTypeDef* mDisableChecksAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef; BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef; BfTypeDef* mFriendAttributeTypeDef;
BfTypeDef* mNoExtensionAttributeTypeDef;
BfTypeDef* mCheckedAttributeTypeDef; BfTypeDef* mCheckedAttributeTypeDef;
BfTypeDef* mUncheckedAttributeTypeDef; BfTypeDef* mUncheckedAttributeTypeDef;
BfTypeDef* mStaticInitAfterAttributeTypeDef; BfTypeDef* mStaticInitAfterAttributeTypeDef;

View file

@ -2008,8 +2008,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if (mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias) if (mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias)
needsDefaultCtor = false; needsDefaultCtor = false;
if (mCurTypeDef->mTypeCode == BfTypeCode_Extension)
needsDefaultCtor = false;
if ((needsDefaultCtor) && (!hasDefaultCtor)) if ((needsDefaultCtor) && ((!hasDefaultCtor)))
{ {
BfProtection prot = hasCtor ? BfProtection_Hidden : BfProtection_Public; BfProtection prot = hasCtor ? BfProtection_Hidden : BfProtection_Public;
if (mCurTypeDef->mName == mSystem->mEmptyAtom) if (mCurTypeDef->mName == mSystem->mEmptyAtom)

View file

@ -2167,6 +2167,13 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
// if (checkMethod->mName != mMethodName) // if (checkMethod->mName != mMethodName)
// continue; // continue;
if ((checkMethod->mDeclaringType->IsExtension()) && (mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) &&
(mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoExtensionAttributeTypeDef)))
{
mModule->mAttributeState->mUsed = true;
continue;
}
if (!isDelegate) if (!isDelegate)
{ {
if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) || if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||
@ -6408,6 +6415,13 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
if (checkMethod->mIsStatic) if (checkMethod->mIsStatic)
continue; continue;
if ((checkMethod->mDeclaringType->IsExtension()) && (mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) &&
(mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoExtensionAttributeTypeDef)))
{
mModule->mAttributeState->mUsed = true;
continue;
}
if (!mModule->IsInSpecializedSection()) if (!mModule->IsInSpecializedSection())
{ {
if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) || if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||

View file

@ -14596,10 +14596,24 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
auto methodDef = mCurMethodInstance->mMethodDef; auto methodDef = mCurMethodInstance->mMethodDef;
BF_ASSERT((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend)); BF_ASSERT((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend));
auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration; auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration;
BfTypeInstance* targetType = NULL;
if (ctorDeclaration->mInitializer != NULL) BfCustomAttributes* customAttributes = NULL;
defer(delete customAttributes);
BfInvocationExpression* ctorInvocation = NULL;
if (ctorDeclaration != NULL)
{ {
auto targetToken = BfNodeDynCast<BfTokenNode>(ctorDeclaration->mInitializer->mTarget); ctorInvocation = BfNodeDynCast<BfInvocationExpression>(ctorDeclaration->mInitializer);
if (auto attributedExpr = BfNodeDynCast<BfAttributedExpression>(ctorDeclaration->mInitializer))
{
ctorInvocation = BfNodeDynCast<BfInvocationExpression>(attributedExpr->mExpression);
customAttributes = GetCustomAttributes(attributedExpr->mAttributes, BfAttributeTargets_MemberAccess);
}
}
BfTypeInstance* targetType = NULL;
if (ctorInvocation != NULL)
{
auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType; targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
} }
else else
@ -14614,9 +14628,9 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
BfResolvedArgs argValues; BfResolvedArgs argValues;
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
{ {
argValues.Init(&ctorDeclaration->mInitializer->mArguments); argValues.Init(&ctorInvocation->mArguments);
} }
// //
@ -14670,7 +14684,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
{ {
// Do it again, but without mIgnoreWrites set // Do it again, but without mIgnoreWrites set
BfResolvedArgs argValues; BfResolvedArgs argValues;
argValues.Init(&ctorDeclaration->mInitializer->mArguments); argValues.Init(&ctorInvocation->mArguments);
exprEvaluator.ResolveArgValues(argValues, BfResolveArgFlag_DeferParamEval); exprEvaluator.ResolveArgValues(argValues, BfResolveArgFlag_DeferParamEval);
BfFunctionBindResult bindResult; BfFunctionBindResult bindResult;
@ -15445,13 +15459,31 @@ void BfModule::EmitCtorBody(bool& skipBody)
auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration; auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration;
auto typeDef = mCurTypeInstance->mTypeDef; auto typeDef = mCurTypeInstance->mTypeDef;
BfCustomAttributes* customAttributes = NULL;
defer(delete customAttributes);
BfInvocationExpression* ctorInvocation = NULL;
BfAttributeState attributeState;
attributeState.mTarget = BfAttributeTargets_MemberAccess;
if (ctorDeclaration != NULL)
{
ctorInvocation = BfNodeDynCast<BfInvocationExpression>(ctorDeclaration->mInitializer);
if (auto attributedExpr = BfNodeDynCast<BfAttributedExpression>(ctorDeclaration->mInitializer))
{
ctorInvocation = BfNodeDynCast<BfInvocationExpression>(attributedExpr->mExpression);
attributeState.mCustomAttributes = GetCustomAttributes(attributedExpr->mAttributes, attributeState.mTarget);
}
}
SetAndRestoreValue<BfAttributeState*> prevAttributeState(mAttributeState, &attributeState);
// Prologue // Prologue
mBfIRBuilder->ClearDebugLocation(); mBfIRBuilder->ClearDebugLocation();
bool hadThisInitializer = false; bool hadThisInitializer = false;
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
{ {
auto targetToken = BfNodeDynCast<BfTokenNode>(ctorDeclaration->mInitializer->mTarget); auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
auto targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType; auto targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
if (targetToken->GetToken() == BfToken_This) if (targetToken->GetToken() == BfToken_This)
{ {
@ -15480,8 +15512,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
} }
BfAstNode* baseCtorNode = NULL; BfAstNode* baseCtorNode = NULL;
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL) && (ctorDeclaration->mInitializer->mTarget != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL) && (ctorInvocation->mTarget != NULL))
baseCtorNode = ctorDeclaration->mInitializer->mTarget; baseCtorNode = ctorInvocation->mTarget;
else if (methodDef->mBody != NULL) else if (methodDef->mBody != NULL)
baseCtorNode = methodDef->mBody; baseCtorNode = methodDef->mBody;
else if (ctorDeclaration != NULL) else if (ctorDeclaration != NULL)
@ -15493,10 +15525,12 @@ void BfModule::EmitCtorBody(bool& skipBody)
else else
baseCtorNode = mContext->mBfObjectType->mTypeDef->mTypeDeclaration; baseCtorNode = mContext->mBfObjectType->mTypeDef->mTypeDeclaration;
if ((!mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType == BfMethodType_Ctor)) bool calledCtorNoBody = false;
if ((!mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType == BfMethodType_Ctor) && (!hadThisInitializer))
{ {
// Call the root type's default ctor (with no body) to initialize its fields and call the chained ctors // Call the root type's default ctor (with no body) to initialize its fields and call the chained ctors
if (methodDef->mDeclaringType->mTypeCode == BfTypeCode_Extension) if (mCurTypeInstance->mTypeDef->mHasCtorNoBody)
{ {
BfMethodDef* defaultCtor = NULL; BfMethodDef* defaultCtor = NULL;
@ -15520,6 +15554,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
SizedArray<BfIRValue, 1> irArgs; SizedArray<BfIRValue, 1> irArgs;
exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs); exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
calledCtorNoBody = true;
} }
} }
} }
@ -15533,7 +15569,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
{ {
// Field initializers occur in CtorNoBody methods for extensions // Field initializers occur in CtorNoBody methods for extensions
} }
else if (!hadThisInitializer) else if ((!hadThisInitializer) && (!calledCtorNoBody))
{ {
// If we had a 'this' initializer, that other ctor will have initialized our fields // If we had a 'this' initializer, that other ctor will have initialized our fields
@ -15711,9 +15747,9 @@ void BfModule::EmitCtorBody(bool& skipBody)
if (methodDef->mBody == NULL) if (methodDef->mBody == NULL)
SetIllegalSrcPos(); SetIllegalSrcPos();
} }
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
{ {
auto targetToken = BfNodeDynCast<BfTokenNode>(ctorDeclaration->mInitializer->mTarget); auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType; targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
} }
else if ((mCurTypeInstance->mBaseType != NULL) && (!mCurTypeInstance->IsUnspecializedType())) else if ((mCurTypeInstance->mBaseType != NULL) && (!mCurTypeInstance->IsUnspecializedType()))
@ -15801,9 +15837,9 @@ void BfModule::EmitCtorBody(bool& skipBody)
mCurMethodState->mCurAppendAlign = methodInstance->mAppendAllocAlign; mCurMethodState->mCurAppendAlign = methodInstance->mAppendAllocAlign;
} }
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL) && (ctorDeclaration->mInitializer->mArguments.size() == 1) && (targetType != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL) && (ctorInvocation->mArguments.size() == 1) && (targetType != NULL))
{ {
if (auto tokenNode = BfNodeDynCast<BfUninitializedExpression>(ctorDeclaration->mInitializer->mArguments[0])) if (auto tokenNode = BfNodeDynCast<BfUninitializedExpression>(ctorInvocation->mArguments[0]))
{ {
if (targetType == mCurTypeInstance) if (targetType == mCurTypeInstance)
{ {
@ -15829,9 +15865,9 @@ void BfModule::EmitCtorBody(bool& skipBody)
auto autoComplete = mCompiler->GetAutoComplete(); auto autoComplete = mCompiler->GetAutoComplete();
auto wasCapturingMethodInfo = (autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo); auto wasCapturingMethodInfo = (autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo);
if ((autoComplete != NULL) && (ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL)) if ((autoComplete != NULL) && (ctorDeclaration != NULL) && (ctorInvocation != NULL))
{ {
auto invocationExpr = ctorDeclaration->mInitializer; auto invocationExpr = ctorInvocation;
autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas); autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);
} }
@ -15839,9 +15875,9 @@ void BfModule::EmitCtorBody(bool& skipBody)
auto target = Cast(targetRefNode, GetThis(), targetThisType); auto target = Cast(targetRefNode, GetThis(), targetThisType);
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
BfResolvedArgs argValues; BfResolvedArgs argValues;
if ((ctorDeclaration != NULL) && (ctorDeclaration->mInitializer != NULL)) if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
{ {
argValues.Init(&ctorDeclaration->mInitializer->mArguments); argValues.Init(&ctorInvocation->mArguments);
if (gDebugStuff) if (gDebugStuff)
{ {
OutputDebugStrF("Expr: %@ %d\n", argValues.mArguments->mVals, argValues.mArguments->mSize); OutputDebugStrF("Expr: %@ %d\n", argValues.mArguments->mVals, argValues.mArguments->mSize);
@ -21367,6 +21403,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
Fail("Interfaces cannot contain constructors", methodDeclaration); Fail("Interfaces cannot contain constructors", methodDeclaration);
} }
bool foundHiddenMethod = false;
// Don't compare specialized generic methods against normal methods // Don't compare specialized generic methods against normal methods
if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) && if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) &&
(!methodDef->mIsLocalMethod)) (!methodDef->mIsLocalMethod))
@ -21437,6 +21475,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
continue; continue;
bool silentlyAllow = false; bool silentlyAllow = false;
bool extensionWarn = false;
if (checkMethod->mDeclaringType != methodDef->mDeclaringType) if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
{ {
if (typeInstance->IsInterface()) if (typeInstance->IsInterface())
@ -21445,7 +21484,21 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
silentlyAllow = true; silentlyAllow = true;
} }
else else
{
if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
(!checkMethod->mDeclaringType->IsExtension()))
{
foundHiddenMethod = true;
if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic))
silentlyAllow = true; silentlyAllow = true;
else if (methodDef->mIsNew)
silentlyAllow = true;
else
extensionWarn = true;
}
else
silentlyAllow = true;
}
} }
if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse)) if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
@ -21456,7 +21509,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator)) if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
{ {
auto refNode = methodDef->GetRefNode(); auto refNode = methodDef->GetRefNode();
auto bfError = Fail("Method already declared with the same parameter types", refNode, true); BfError* bfError;
if (extensionWarn)
bfError = Warn(BfWarning_CS0114_MethodHidesInherited,
StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.",
checkMethod->mDeclaringType->mProject->mName.c_str()), refNode);
else
bfError = Fail("Method already declared with the same parameter types", refNode, true);
if (bfError != NULL) if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode()); mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
} }
@ -21473,7 +21532,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
(!methodInstance->mIsForeignMethodDef) && (typeInstance->mBaseType != NULL) && (!methodInstance->mIsForeignMethodDef) && (typeInstance->mBaseType != NULL) &&
(methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mMethodDeclaration != NULL)) (methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mMethodDeclaration != NULL))
{ {
bool foundHiddenMethod = false;
auto baseType = typeInstance->mBaseType; auto baseType = typeInstance->mBaseType;
while (baseType != NULL) while (baseType != NULL)
{ {
@ -21624,11 +21682,6 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
if (mCurTypeInstance->IsUnspecializedTypeVariation()) if (mCurTypeInstance->IsUnspecializedTypeVariation())
return false; return false;
if ((mCurTypeInstance->mTypeDef->mName->ToString() == "Zornk") && (methodInstance->mMethodDef->mName == "GCMarkMembers"))
{
NOP;
}
auto _AddVirtualDecl = [&](BfMethodInstance* declMethodInstance) auto _AddVirtualDecl = [&](BfMethodInstance* declMethodInstance)
{ {
if (!mCompiler->mOptions.mAllowHotSwapping) if (!mCompiler->mOptions.mAllowHotSwapping)
@ -21956,13 +22009,17 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
{ {
methodInstance->mVirtualTableIdx = virtualMethodMatchIdx; methodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
bool preferRootDefinition = (methodDef->mName == BF_METHODNAME_MARKMEMBERS) || (methodDef->mMethodType == BfMethodType_Dtor);
BfMethodInstance* setMethodInstance = methodInstance;
bool doOverride = false;
auto& overridenRef = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod; auto& overridenRef = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod;
if (overridenRef.mKind != BfMethodRefKind_AmbiguousRef) if (overridenRef.mKind != BfMethodRefKind_AmbiguousRef)
{ {
methodOverriden = overridenRef; methodOverriden = overridenRef;
BfMethodInstance* setMethodInstance = methodInstance; doOverride = true;
bool doOverride = true;
if (methodOverriden->GetOwner() == methodInstance->GetOwner()) if (methodOverriden->GetOwner() == methodInstance->GetOwner())
{ {
bool isBetter = false; bool isBetter = false;
@ -21990,7 +22047,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
if ((isBetter) && (methodInstance->GetOwner() == methodOverriden->GetOwner())) if ((isBetter) && (methodInstance->GetOwner() == methodOverriden->GetOwner()))
{ {
if (methodDef->mName == BF_METHODNAME_MARKMEMBERS) if (preferRootDefinition)
{ {
// Leave the master GCMarkMember // Leave the master GCMarkMember
isBetter = false; isBetter = false;
@ -22001,6 +22058,12 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
doOverride = isBetter; doOverride = isBetter;
} }
} }
}
else if ((preferRootDefinition) && (!methodDef->mDeclaringType->IsExtension()))
{
methodOverriden = overridenRef;
doOverride = true;
}
if (doOverride) if (doOverride)
{ {
@ -22010,7 +22073,6 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod = setMethodInstance; typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod = setMethodInstance;
} }
} }
}
if (methodOverriden != NULL) if (methodOverriden != NULL)
{ {

View file

@ -9147,8 +9147,23 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
MEMBER_SET(ctorDecl, mInitializerColonToken, endToken); MEMBER_SET(ctorDecl, mInitializerColonToken, endToken);
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
BfAstNode* invokeAfter = ctorDecl;
auto nextNode = mVisitorPos.GetNext(); auto nextNode = mVisitorPos.GetNext();
endToken = ExpectTokenAfter(ctorDecl, BfToken_This, BfToken_Base);
BfAttributeDirective* attributeDirective = NULL;
if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
{
if (nextToken->mToken == BfToken_LBracket)
{
mVisitorPos.MoveNext();
attributeDirective = CreateAttributeDirective(nextToken);
nextNode = mVisitorPos.GetNext();
if (attributeDirective != NULL)
invokeAfter = attributeDirective;
}
}
endToken = ExpectTokenAfter(invokeAfter, BfToken_This, BfToken_Base);
if (endToken != NULL) if (endToken != NULL)
{ {
auto invocationExpr = CreateInvocationExpression(endToken); auto invocationExpr = CreateInvocationExpression(endToken);
@ -9162,6 +9177,18 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
// In process of typing - just eat identifier so we don't error out on whole method // In process of typing - just eat identifier so we don't error out on whole method
MoveNode(identifierAfter, ctorDecl); MoveNode(identifierAfter, ctorDecl);
} }
if (attributeDirective != NULL)
{
BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
ReplaceNode(attributeDirective, attribExpr);
attribExpr->mAttributes = attributeDirective;
if (ctorDecl->mInitializer != NULL)
{
MEMBER_SET(attribExpr, mExpression, ctorDecl->mInitializer);
}
MEMBER_SET(ctorDecl, mInitializer, attribExpr);
}
} }
endToken = NULL; endToken = NULL;

View file

@ -2640,6 +2640,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mIsConcrete = nextTypeDef->mIsConcrete; typeDef->mIsConcrete = nextTypeDef->mIsConcrete;
typeDef->mIsStatic = nextTypeDef->mIsStatic; typeDef->mIsStatic = nextTypeDef->mIsStatic;
typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor;
typeDef->mHasCtorNoBody = nextTypeDef->mHasCtorNoBody;
typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods; typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods;
typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods; typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods;
typeDef->mIsOpaque = nextTypeDef->mIsOpaque; typeDef->mIsOpaque = nextTypeDef->mIsOpaque;
@ -2744,6 +2745,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mIsConcrete = partialTypeDef->mIsConcrete; typeDef->mIsConcrete = partialTypeDef->mIsConcrete;
typeDef->mIsStatic = partialTypeDef->mIsStatic; typeDef->mIsStatic = partialTypeDef->mIsStatic;
typeDef->mHasAppendCtor = partialTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor = partialTypeDef->mHasAppendCtor;
typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody;
typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods; typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods;
typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods; typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods;
@ -2956,6 +2958,7 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
anyHasFieldInitializers = true; anyHasFieldInitializers = true;
if (!isExtension) if (!isExtension)
primaryHasFieldInitializers = true; primaryHasFieldInitializers = true;
nextRevision->mHasCtorNoBody = true;
auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, ""); auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, "");
methodDef->mDeclaringType = partialTypeDef; methodDef->mDeclaringType = partialTypeDef;
methodDef->mIsMutating = true; methodDef->mIsMutating = true;
@ -2964,6 +2967,7 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
if ((anyHasFieldInitializers) && (!primaryHasFieldInitializers)) if ((anyHasFieldInitializers) && (!primaryHasFieldInitializers))
{ {
nextRevision->mHasCtorNoBody = true;
auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, ""); auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, "");
methodDef->mDeclaringType = primaryDef; methodDef->mDeclaringType = primaryDef;
methodDef->mIsMutating = true; methodDef->mIsMutating = true;
@ -2991,6 +2995,7 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
if ((allHasMethods[0][0].mDtor == 0) && (allHasMethods[1][0].mDtor > 1)) if ((allHasMethods[0][0].mDtor == 0) && (allHasMethods[1][0].mDtor > 1))
{ {
nextRevision->mDtorDef = NULL;
auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_Dtor, BfProtection_Public, false, ""); auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_Dtor, BfProtection_Public, false, "");
methodDef->mDeclaringType = primaryDef; methodDef->mDeclaringType = primaryDef;
} }

View file

@ -919,6 +919,7 @@ public:
bool mIsConcrete; bool mIsConcrete;
bool mIsStatic; bool mIsStatic;
bool mHasAppendCtor; bool mHasAppendCtor;
bool mHasCtorNoBody;
bool mHasExtensionMethods; bool mHasExtensionMethods;
bool mHasOverrideMethods; bool mHasOverrideMethods;
bool mIsOpaque; bool mIsOpaque;
@ -956,6 +957,7 @@ public:
mIsClosure = false; mIsClosure = false;
mIsStatic = false; mIsStatic = false;
mHasAppendCtor = false; mHasAppendCtor = false;
mHasCtorNoBody = false;
mHasExtensionMethods = false; mHasExtensionMethods = false;
mHasOverrideMethods = false; mHasOverrideMethods = false;
mIsOpaque = false; mIsOpaque = false;

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Diagnostics;
namespace LibA namespace LibA
{ {
@ -90,11 +91,18 @@ namespace LibA
class LibClassA class LibClassA
{ {
public int32 mA = GetVal(7, "LibA.LibClassA.mA"); public int32 mA = GetVal(7, 10, "LibA.LibClassA.mA");
public static int32 sMagic = 1;
public static this()
{
sMagic += 10;
}
public this() public this()
{ {
PrintF("LibA.LibClassA()\n"); Debug.WriteLine("LibA.LibClassA()\n");
mA += 100; mA += 100;
} }
@ -103,9 +111,15 @@ class LibClassA
mA += a; mA += a;
} }
public static int32 GetVal(int32 val, String str) public ~this()
{ {
PrintF("GetVal: %s\n", str.CStr()); sMagic += 20;
}
public static int32 GetVal(int32 val, int32 magic, String str)
{
Debug.WriteLine("GetVal: {}", str);
sMagic += magic;
return val; return val;
} }
@ -118,6 +132,11 @@ class LibClassA
{ {
return 30; return 30;
} }
public static LibClassA Create()
{
return new LibClassA();
}
} }
class LibClassB class LibClassB

View file

@ -14,15 +14,25 @@ namespace LibB
extension LibClassA extension LibClassA
{ {
public int32 mB = GetVal(8, "LibB.LibClassA.mB"); public int32 mB = GetVal(8, 100, "LibB.LibClassA.mB");
public this() public static this()
{
sMagic += 100;
}
public ~this()
{
sMagic += 200;
}
public new this() : [NoExtension]this()
{ {
PrintF("LibB.LibClassA()\n"); PrintF("LibB.LibClassA()\n");
mB += 100; mB += 100;
} }
public this(int32 a) public new this(int32 a)
{ {
PrintF("LibB.LibClassA(int32)\n"); PrintF("LibB.LibClassA(int32)\n");
mB += 1000; mB += 1000;

View file

@ -12,7 +12,17 @@ namespace LibC
extension LibClassA extension LibClassA
{ {
public int32 mB = GetVal(13, "LibC.LibClassA.mB"); public int32 mB = GetVal(13, 1000, "LibC.LibClassA.mB");
public static this()
{
sMagic += 1000;
}
public ~this()
{
sMagic += 2000;
}
public this(int8 i8) public this(int8 i8)
{ {

View file

@ -2,15 +2,15 @@ using System;
extension LibClassA extension LibClassA
{ {
public int32 mC = GetVal(9, "TestsB.LibClassA.mC"); public int32 mC = GetVal(9, 10000, "TestsB.LibClassA.mC");
public this() public new this()
{ {
PrintF("TestB.LibClassA()\n"); PrintF("TestB.LibClassA()\n");
mB += 10000; mB += 10000;
} }
public int GetVal2() public new int GetVal2()
{ {
return 11; return 11;
} }

View file

@ -227,21 +227,32 @@ namespace Tests
[Test] [Test]
public static void TestSharedData() public static void TestSharedData()
{ {
Test.Assert(LibClassA.sMagic == 1111);
LibClassA ca = scope LibClassA(); LibClassA ca = scope LibClassA();
Test.Assert(ca.mA == 7); Test.Assert(LibClassA.sMagic == 2221);
Test.Assert(ca.mA == 107);
Test.Assert(ca.LibB_GetB() == 108); Test.Assert(ca.LibB_GetB() == 108);
Test.Assert(ca.LibC_GetB() == 13); Test.Assert(ca.LibC_GetB() == 13);
Test.Assert(ca.GetVal2() == 9); Test.Assert(ca.GetVal2() == 9);
ca = scope LibClassA(12345); ca = scope LibClassA(12345);
Test.Assert(LibClassA.sMagic == 3331);
Test.Assert(ca.mA == 7); Test.Assert(ca.mA == 7);
Test.Assert(ca.LibB_GetB() == 1008); Test.Assert(ca.LibB_GetB() == 1008);
Test.Assert(ca.LibC_GetB() == 13); Test.Assert(ca.LibC_GetB() == 13);
ca = scope LibClassA((int8)2); ca = scope LibClassA((int8)2);
Test.Assert(LibClassA.sMagic == 4441);
Test.Assert(ca.mA == 7); Test.Assert(ca.mA == 7);
Test.Assert(ca.LibB_GetB() == 8); Test.Assert(ca.LibB_GetB() == 8);
Test.Assert(ca.LibC_GetB() == 30013); Test.Assert(ca.LibC_GetB() == 30013);
ca = LibClassA.Create();
Test.Assert(LibClassA.sMagic == 5551);
Test.Assert(ca.mA == 107);
delete ca;
Test.Assert(LibClassA.sMagic == 7771);
} }
[Test] [Test]