1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Added extern method override support in extensions

This commit is contained in:
Brian Fiete 2020-10-23 11:48:37 -07:00
parent 1e020dc14e
commit 101fde1a4b
8 changed files with 99 additions and 35 deletions

View file

@ -5319,6 +5319,8 @@ void BfCompiler::PopulateReified()
// If we have chained methods, make sure we implement the chain members if the chain head is implemented and reified
if (typeInst->mTypeDef->mIsCombinedPartial)
{
typeInst->mTypeDef->PopulateMemberSets();
bool hasUnimpChainMembers = false;
impChainHeadMethods.Clear();
@ -5342,6 +5344,35 @@ void BfCompiler::PopulateReified()
if (!methodInstance->IsReifiedAndImplemented())
hasUnimpChainMembers = true;
}
else if (methodInstance->mIsInnerOverride)
{
if (!methodInstance->IsReifiedAndImplemented())
{
bool forceMethod = false;
BfMemberSetEntry* memberSetEntry;
if (typeInst->mTypeDef->mMethodSet.TryGetWith((StringImpl&)methodInstance->mMethodDef->mName, &memberSetEntry))
{
BfMethodDef* checkMethodDef = (BfMethodDef*)memberSetEntry->mMemberDef;
while (checkMethodDef != NULL)
{
auto& checkMethodInstanceGroup = typeInst->mMethodInstanceGroups[checkMethodDef->mIdx];
auto checkMethodInstance = checkMethodInstanceGroup.mDefault;
if (checkMethodInstance == NULL)
continue;
if ((checkMethodDef->mIsExtern) && (checkMethodInstance->IsReifiedAndImplemented()))
forceMethod = true;
checkMethodDef = checkMethodDef->mNextWithSameName;
}
}
if (forceMethod)
{
typeInst->mModule->GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, BfTypeVector(),
(BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass));
}
}
}
}
if ((hasUnimpChainMembers) && (!impChainHeadMethods.IsEmpty()))

View file

@ -2020,7 +2020,8 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
}
if ((methodInst->mMethodDef->mDeclaringType->mPartialIdx != -1) && (methodInst->mMethodDef->mDeclaringType->IsExtension()) &&
(!methodInst->mIsForeignMethodDef) && (!methodInst->mMethodDef->mIsExtern))
(!methodInst->mIsForeignMethodDef) && (!methodInst->mMethodDef->mIsExtern) &&
((!methodInst->mMethodDef->mIsOverride) || (methodDef->mName == BF_METHODNAME_MARKMEMBERS) || (methodDef->mMethodType == BfMethodType_Dtor)))
{
auto declType = methodInst->mMethodDef->mDeclaringType;
BF_ASSERT(methodInst->GetOwner()->mTypeDef->mIsCombinedPartial);
@ -2098,7 +2099,10 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
if ((methodDef->mIsStatic) || (doExplicitThis))
attrib += 2;
attrib += (methodDef->mIsVirtual ? 4 : 0);
if ((methodDef->mIsVirtual) && (!methodDef->mIsOverride))
attrib += 4;
name += attrib;
auto bfSystem = methodInst->GetOwner()->mModule->mSystem;

View file

@ -21517,12 +21517,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
methodInstance->mChainType = BfMethodChainType_ChainMember;
}
}
else if ((checkMethod->mBody == NULL) && (methodDef->mBody != NULL) &&
(checkMethod->mDeclaringType != methodDef->mDeclaringType))
{
// We're allowed to override an empty-bodied method
checkMethodInstance->mChainType = BfMethodChainType_ChainSkip;
}
else
{
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
@ -21539,7 +21533,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
}
else
{
if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
if ((methodDef->mIsOverride) && (checkMethod->mIsExtern))
{
silentlyAllow = true;
methodInstance->mIsInnerOverride = true;
CheckOverridenMethod(methodInstance, checkMethodInstance);
}
else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
(!checkMethod->mDeclaringType->IsExtension()))
{
foundHiddenMethod = true;
@ -21764,6 +21764,9 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
auto propertyDeclaration = methodDef->GetPropertyDeclaration();
auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
if (methodInstance->mIsInnerOverride)
return false;
BfAstNode* declaringNode = methodDeclaration;
if (propertyMethodDeclaration != NULL)
declaringNode = propertyMethodDeclaration->mNameNode;
@ -22128,30 +22131,11 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
}
}
if (methodOverriden != NULL)
{
auto prevProtection = methodOverriden->mMethodDef->mProtection;
if ((methodDef->mProtection != prevProtection) && (methodDef->mMethodType != BfMethodType_Dtor))
{
const char* protectionNames[] = {"hidden", "private", "internal", "protected", "public"};
BfAstNode* protectionRefNode = NULL;
if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
{
protectionRefNode = propertyMethodDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mNameNode;
}
else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
{
protectionRefNode = methodDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = methodDeclaration->mNameNode;
}
if (protectionRefNode != NULL)
Fail(StrFormat("Cannot change access modifiers when overriding '%s' inherited member", protectionNames[(int)prevProtection]), protectionRefNode, true);
}
CheckOverridenMethod(methodInstance, methodOverriden);
}
}
}
@ -22369,6 +22353,33 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
return usedMethod;
}
void BfModule::CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden)
{
auto methodDef = methodInstance->mMethodDef;
auto prevProtection = methodOverriden->mMethodDef->mProtection;
if ((methodDef->mProtection != prevProtection) && (methodDef->mMethodType != BfMethodType_Dtor))
{
const char* protectionNames[] = { "hidden", "private", "internal", "protected", "public" };
BfAstNode* protectionRefNode = NULL;
if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
{
protectionRefNode = propertyMethodDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mNameNode;
}
else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
{
protectionRefNode = methodDeclaration->mProtectionSpecifier;
if (protectionRefNode == NULL)
protectionRefNode = methodDeclaration->mNameNode;
}
if (protectionRefNode != NULL)
Fail(StrFormat("Cannot change access modifiers when overriding '%s' inherited member", protectionNames[(int)prevProtection]), protectionRefNode, true);
}
}
bool BfModule::SlotInterfaceMethod(BfMethodInstance* methodInstance)
{
auto typeInstance = mCurTypeInstance;

View file

@ -1851,6 +1851,7 @@ public:
void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance);
void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse);
bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL);
void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden);
bool SlotInterfaceMethod(BfMethodInstance* methodInstance);
void SetMethodDependency(BfMethodInstance* methodInstance);
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);

View file

@ -787,6 +787,11 @@ bool BfMethodInstance::HasThis()
return (!mMethodInstanceGroup->mOwner->IsValuelessType());
}
bool BfMethodInstance::IsVirtual()
{
return mMethodDef->mIsVirtual && !mIsInnerOverride;
}
BfType* BfMethodInstance::GetThisType()
{
BF_ASSERT(!mMethodDef->mIsStatic);

View file

@ -816,6 +816,7 @@ public:
bool mIsIntrinsic:1;
bool mHasMethodRefType:1;
bool mDisallowCalling:1;
bool mIsInnerOverride:1;
BfMethodChainType mChainType;
BfCallingConvention mCallingConvention;
BfMethodInstanceGroup* mMethodInstanceGroup;
@ -851,6 +852,7 @@ public:
mIsIntrinsic = false;
mHasMethodRefType = false;
mDisallowCalling = false;
mIsInnerOverride = false;
mChainType = BfMethodChainType_None;
mCallingConvention = BfCallingConvention_Unspecified;
mMethodInstanceGroup = NULL;
@ -882,6 +884,7 @@ public:
bool IsOrInUnspecializedVariation();
bool HasExternConstraints();
bool HasThis();
bool IsVirtual();
BfType* GetThisType();
int GetThisIdx();
bool HasExplicitThis();

View file

@ -133,9 +133,13 @@ class LibClassA
return 30;
}
public extern int GetVal4();
public static LibClassA Create()
{
return new LibClassA();
LibClassA ca = new LibClassA();
Test.Assert(ca.GetVal4() == 29);
return ca;
}
}

View file

@ -42,6 +42,11 @@ extension LibClassA
{
return mB;
}
public override int GetVal4()
{
return 29;
}
}
static