mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +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 we have chained methods, make sure we implement the chain members if the chain head is implemented and reified
|
||||||
if (typeInst->mTypeDef->mIsCombinedPartial)
|
if (typeInst->mTypeDef->mIsCombinedPartial)
|
||||||
{
|
{
|
||||||
|
typeInst->mTypeDef->PopulateMemberSets();
|
||||||
|
|
||||||
bool hasUnimpChainMembers = false;
|
bool hasUnimpChainMembers = false;
|
||||||
|
|
||||||
impChainHeadMethods.Clear();
|
impChainHeadMethods.Clear();
|
||||||
|
@ -5342,6 +5344,35 @@ void BfCompiler::PopulateReified()
|
||||||
if (!methodInstance->IsReifiedAndImplemented())
|
if (!methodInstance->IsReifiedAndImplemented())
|
||||||
hasUnimpChainMembers = true;
|
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()))
|
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()) &&
|
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;
|
auto declType = methodInst->mMethodDef->mDeclaringType;
|
||||||
BF_ASSERT(methodInst->GetOwner()->mTypeDef->mIsCombinedPartial);
|
BF_ASSERT(methodInst->GetOwner()->mTypeDef->mIsCombinedPartial);
|
||||||
|
@ -2098,7 +2099,10 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
|
||||||
|
|
||||||
if ((methodDef->mIsStatic) || (doExplicitThis))
|
if ((methodDef->mIsStatic) || (doExplicitThis))
|
||||||
attrib += 2;
|
attrib += 2;
|
||||||
attrib += (methodDef->mIsVirtual ? 4 : 0);
|
|
||||||
|
if ((methodDef->mIsVirtual) && (!methodDef->mIsOverride))
|
||||||
|
attrib += 4;
|
||||||
|
|
||||||
name += attrib;
|
name += attrib;
|
||||||
|
|
||||||
auto bfSystem = methodInst->GetOwner()->mModule->mSystem;
|
auto bfSystem = methodInst->GetOwner()->mModule->mSystem;
|
||||||
|
|
|
@ -21517,12 +21517,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
methodInstance->mChainType = BfMethodChainType_ChainMember;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
||||||
|
@ -21539,7 +21533,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
}
|
}
|
||||||
else
|
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()))
|
(!checkMethod->mDeclaringType->IsExtension()))
|
||||||
{
|
{
|
||||||
foundHiddenMethod = true;
|
foundHiddenMethod = true;
|
||||||
|
@ -21764,6 +21764,9 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
||||||
auto propertyDeclaration = methodDef->GetPropertyDeclaration();
|
auto propertyDeclaration = methodDef->GetPropertyDeclaration();
|
||||||
auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
|
auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
|
||||||
|
|
||||||
|
if (methodInstance->mIsInnerOverride)
|
||||||
|
return false;
|
||||||
|
|
||||||
BfAstNode* declaringNode = methodDeclaration;
|
BfAstNode* declaringNode = methodDeclaration;
|
||||||
if (propertyMethodDeclaration != NULL)
|
if (propertyMethodDeclaration != NULL)
|
||||||
declaringNode = propertyMethodDeclaration->mNameNode;
|
declaringNode = propertyMethodDeclaration->mNameNode;
|
||||||
|
@ -22128,30 +22131,11 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (methodOverriden != NULL)
|
if (methodOverriden != NULL)
|
||||||
{
|
{
|
||||||
auto prevProtection = methodOverriden->mMethodDef->mProtection;
|
CheckOverridenMethod(methodInstance, methodOverriden);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22369,6 +22353,33 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
||||||
return usedMethod;
|
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)
|
bool BfModule::SlotInterfaceMethod(BfMethodInstance* methodInstance)
|
||||||
{
|
{
|
||||||
auto typeInstance = mCurTypeInstance;
|
auto typeInstance = mCurTypeInstance;
|
||||||
|
|
|
@ -1851,6 +1851,7 @@ public:
|
||||||
void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance);
|
void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance);
|
||||||
void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse);
|
void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse);
|
||||||
bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL);
|
bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL);
|
||||||
|
void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden);
|
||||||
bool SlotInterfaceMethod(BfMethodInstance* methodInstance);
|
bool SlotInterfaceMethod(BfMethodInstance* methodInstance);
|
||||||
void SetMethodDependency(BfMethodInstance* methodInstance);
|
void SetMethodDependency(BfMethodInstance* methodInstance);
|
||||||
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
|
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
|
||||||
|
|
|
@ -787,6 +787,11 @@ bool BfMethodInstance::HasThis()
|
||||||
return (!mMethodInstanceGroup->mOwner->IsValuelessType());
|
return (!mMethodInstanceGroup->mOwner->IsValuelessType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfMethodInstance::IsVirtual()
|
||||||
|
{
|
||||||
|
return mMethodDef->mIsVirtual && !mIsInnerOverride;
|
||||||
|
}
|
||||||
|
|
||||||
BfType* BfMethodInstance::GetThisType()
|
BfType* BfMethodInstance::GetThisType()
|
||||||
{
|
{
|
||||||
BF_ASSERT(!mMethodDef->mIsStatic);
|
BF_ASSERT(!mMethodDef->mIsStatic);
|
||||||
|
|
|
@ -816,6 +816,7 @@ public:
|
||||||
bool mIsIntrinsic:1;
|
bool mIsIntrinsic:1;
|
||||||
bool mHasMethodRefType:1;
|
bool mHasMethodRefType:1;
|
||||||
bool mDisallowCalling:1;
|
bool mDisallowCalling:1;
|
||||||
|
bool mIsInnerOverride:1;
|
||||||
BfMethodChainType mChainType;
|
BfMethodChainType mChainType;
|
||||||
BfCallingConvention mCallingConvention;
|
BfCallingConvention mCallingConvention;
|
||||||
BfMethodInstanceGroup* mMethodInstanceGroup;
|
BfMethodInstanceGroup* mMethodInstanceGroup;
|
||||||
|
@ -851,6 +852,7 @@ public:
|
||||||
mIsIntrinsic = false;
|
mIsIntrinsic = false;
|
||||||
mHasMethodRefType = false;
|
mHasMethodRefType = false;
|
||||||
mDisallowCalling = false;
|
mDisallowCalling = false;
|
||||||
|
mIsInnerOverride = false;
|
||||||
mChainType = BfMethodChainType_None;
|
mChainType = BfMethodChainType_None;
|
||||||
mCallingConvention = BfCallingConvention_Unspecified;
|
mCallingConvention = BfCallingConvention_Unspecified;
|
||||||
mMethodInstanceGroup = NULL;
|
mMethodInstanceGroup = NULL;
|
||||||
|
@ -882,6 +884,7 @@ public:
|
||||||
bool IsOrInUnspecializedVariation();
|
bool IsOrInUnspecializedVariation();
|
||||||
bool HasExternConstraints();
|
bool HasExternConstraints();
|
||||||
bool HasThis();
|
bool HasThis();
|
||||||
|
bool IsVirtual();
|
||||||
BfType* GetThisType();
|
BfType* GetThisType();
|
||||||
int GetThisIdx();
|
int GetThisIdx();
|
||||||
bool HasExplicitThis();
|
bool HasExplicitThis();
|
||||||
|
|
|
@ -133,9 +133,13 @@ class LibClassA
|
||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extern int GetVal4();
|
||||||
|
|
||||||
public static LibClassA Create()
|
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;
|
return mB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetVal4()
|
||||||
|
{
|
||||||
|
return 29;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue