浏览代码

Added extern method override support in extensions

Brian Fiete 4 年之前
父节点
当前提交
101fde1a4b

+ 31 - 0
IDEHelper/Compiler/BfCompiler.cpp

@@ -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()))

+ 7 - 3
IDEHelper/Compiler/BfMangler.cpp

@@ -2018,9 +2018,10 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
 		else
 			AddStr(mangleContext, name, methodDef->mName);		
 	}
-		
+	
 	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;

+ 41 - 30
IDEHelper/Compiler/BfModule.cpp

@@ -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,10 +21764,13 @@ 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;
-		
+	
 	BfMethodInstance* methodOverriden = NULL;
 	bool usedMethod = false;
 
@@ -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;

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -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);

+ 5 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -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);

+ 4 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -816,6 +816,7 @@ public:
 	bool mIsIntrinsic:1;
 	bool mHasMethodRefType:1;
 	bool mDisallowCalling:1;		
+	bool mIsInnerOverride:1;
 	BfMethodChainType mChainType;
 	BfCallingConvention mCallingConvention;
 	BfMethodInstanceGroup* mMethodInstanceGroup;
@@ -850,7 +851,8 @@ public:
 		mAlwaysInline = false;
 		mIsIntrinsic = false;
 		mHasMethodRefType = false;
-		mDisallowCalling = 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();

+ 5 - 1
IDEHelper/Tests/LibA/src/LibA0.bf

@@ -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;
 	}
 }
 

+ 5 - 0
IDEHelper/Tests/LibB/src/LibB0.bf

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