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:
parent
1e020dc14e
commit
101fde1a4b
8 changed files with 99 additions and 35 deletions
|
@ -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()))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,11 @@ extension LibClassA
|
|||
{
|
||||
return mB;
|
||||
}
|
||||
|
||||
public override int GetVal4()
|
||||
{
|
||||
return 29;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue