ソースを参照

Fixes for type initializer blocks

Brian Fiete 4 年 前
コミット
34dcd47dd5

+ 14 - 4
IDEHelper/Compiler/BfModule.cpp

@@ -14952,6 +14952,8 @@ void BfModule::EmitDtorBody()
 	{
 	{
 		if (methodDeclaration != NULL)
 		if (methodDeclaration != NULL)
 			UpdateSrcPos(methodDeclaration);
 			UpdateSrcPos(methodDeclaration);
+		else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
+			UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
 		else if (typeDef->mTypeDeclaration != NULL)
 		else if (typeDef->mTypeDeclaration != NULL)
 			UpdateSrcPos(typeDef->mTypeDeclaration);
 			UpdateSrcPos(typeDef->mTypeDeclaration);
 		if ((methodDeclaration != NULL) && (methodDeclaration->mFatArrowToken != NULL))
 		if ((methodDeclaration != NULL) && (methodDeclaration->mFatArrowToken != NULL))
@@ -15594,6 +15596,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
 		baseCtorNode = methodDef->mBody;
 		baseCtorNode = methodDef->mBody;
 	else if (ctorDeclaration != NULL)
 	else if (ctorDeclaration != NULL)
 		baseCtorNode = ctorDeclaration;
 		baseCtorNode = ctorDeclaration;
+	else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
+		baseCtorNode = methodDef->mDeclaringType->GetRefNode();
 	else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 	else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 		baseCtorNode = mCurTypeInstance->mTypeDef->mTypeDeclaration->mNameNode;
 		baseCtorNode = mCurTypeInstance->mTypeDef->mTypeDeclaration->mNameNode;
 	else if ((mCurTypeInstance->mBaseType != NULL) && (mCurTypeInstance->mBaseType->mTypeDef->mTypeDeclaration != NULL))
 	else if ((mCurTypeInstance->mBaseType != NULL) && (mCurTypeInstance->mBaseType->mTypeDef->mTypeDeclaration != NULL))
@@ -15604,7 +15608,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 	bool calledCtorNoBody = false;
 	bool calledCtorNoBody = false;
 	
 	
 	if ((!mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType == BfMethodType_Ctor) && (!hadThisInitializer))
 	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 (mCurTypeInstance->mTypeDef->mHasCtorNoBody)
 		if (mCurTypeInstance->mTypeDef->mHasCtorNoBody)
 		{
 		{
@@ -17572,7 +17576,9 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 	if (methodDef->mBody != NULL)
 	if (methodDef->mBody != NULL)
 		UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
 		UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
 	else if (methodDeclaration != NULL)		
 	else if (methodDeclaration != NULL)		
-		UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);	
+		UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);
+	else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
+		UpdateSrcPos(methodDef->mDeclaringType->GetRefNode(), BfSrcPosFlag_NoSetDebugLoc);
 	else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 	else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 		UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);		
 		UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);		
 		
 		
@@ -17799,6 +17805,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 			UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);
 			UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);
 		else if (methodDef->mBody != NULL)
 		else if (methodDef->mBody != NULL)
 			UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
 			UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
+		else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
+			UpdateSrcPos(methodDef->mDeclaringType->GetRefNode(), BfSrcPosFlag_NoSetDebugLoc);
 		else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 		else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 			UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);		
 			UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);		
 	}
 	}
@@ -17956,7 +17964,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 		// We want to be able to step into delegate invokes -- we actually step over them
 		// We want to be able to step into delegate invokes -- we actually step over them
 		if (methodDef->mName != "Invoke")
 		if (methodDef->mName != "Invoke")
 		{
 		{
-			UpdateSrcPos(typeDef->mTypeDeclaration);
+			UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
 			mBfIRBuilder->DbgCreateAnnotation(diFunction, "StepOver", GetConstValue32(1));
 			mBfIRBuilder->DbgCreateAnnotation(diFunction, "StepOver", GetConstValue32(1));
 		}
 		}
 	}
 	}
@@ -18133,8 +18141,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 					
 					
 		if (methodDef->mBody != NULL)	
 		if (methodDef->mBody != NULL)	
 			UpdateSrcPos(methodDef->mBody);	
 			UpdateSrcPos(methodDef->mBody);	
+		else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
+			UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
 		else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
 		else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
-			UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration);			
+			UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration);
 		
 		
 		localIdx = 0;
 		localIdx = 0;
 		argIdx = 0;
 		argIdx = 0;

+ 9 - 7
IDEHelper/Compiler/BfSystem.cpp

@@ -2916,15 +2916,18 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
 	bool hasCtorNoBody = false;
 	bool hasCtorNoBody = false;
 	
 	
 	bool primaryHasFieldInitializers = false;
 	bool primaryHasFieldInitializers = false;
-	bool anyHasFieldInitializers = false;
+	bool anyHasInitializers = false;
 
 
 	// For methods that require chaining, make sure the primary def has a definition
 	// For methods that require chaining, make sure the primary def has a definition
 	for (auto partialTypeDef : nextRevision->mPartials)
 	for (auto partialTypeDef : nextRevision->mPartials)
 	{	
 	{	
 		bool isExtension = partialTypeDef->mTypeDeclaration != nextRevision->mTypeDeclaration;
 		bool isExtension = partialTypeDef->mTypeDeclaration != nextRevision->mTypeDeclaration;
 
 
+		bool hasInitializers = false;
 		for (auto methodDef : partialTypeDef->mMethods)
 		for (auto methodDef : partialTypeDef->mMethods)
-		{			
+		{
+			if (methodDef->mMethodType == BfMethodType_Init)
+				hasInitializers = true;
 			auto& hasMethods = allHasMethods[isExtension ? 1 : 0][methodDef->mIsStatic ? 1 : 0];
 			auto& hasMethods = allHasMethods[isExtension ? 1 : 0][methodDef->mIsStatic ? 1 : 0];
 			if (methodDef->mMethodType == BfMethodType_Ctor)
 			if (methodDef->mMethodType == BfMethodType_Ctor)
 			{
 			{
@@ -2946,16 +2949,15 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
 			}
 			}
 		}
 		}
 
 
-		bool hasFieldInitializers = false;
 		for (auto fieldDef : partialTypeDef->mFields)
 		for (auto fieldDef : partialTypeDef->mFields)
 		{
 		{
 			if ((!fieldDef->mIsStatic) && (fieldDef->mFieldDeclaration->mInitializer != NULL))
 			if ((!fieldDef->mIsStatic) && (fieldDef->mFieldDeclaration->mInitializer != NULL))
-				hasFieldInitializers = true;
+				hasInitializers = true;
 		}
 		}
 
 
-		if (hasFieldInitializers)
+		if (hasInitializers)
 		{
 		{
-			anyHasFieldInitializers = true;			
+			anyHasInitializers = true;			
 			if (!isExtension)
 			if (!isExtension)
 				primaryHasFieldInitializers = true;				
 				primaryHasFieldInitializers = true;				
 			nextRevision->mHasCtorNoBody = true;
 			nextRevision->mHasCtorNoBody = true;
@@ -2965,7 +2967,7 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
 		}
 		}
 	}
 	}
 
 
-	if ((anyHasFieldInitializers) && (!primaryHasFieldInitializers))
+	if ((anyHasInitializers) && (!primaryHasFieldInitializers))
 	{
 	{
 		nextRevision->mHasCtorNoBody = true;
 		nextRevision->mHasCtorNoBody = true;
 		auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, "");
 		auto methodDef = BfDefBuilder::AddMethod(nextRevision, BfMethodType_CtorNoBody, BfProtection_Protected, false, "");

+ 16 - 0
IDEHelper/Tests/LibA/src/LibA0.bf

@@ -87,6 +87,22 @@ namespace LibA
 			return lhs == rhs;
 			return lhs == rhs;
 		}
 		}
 	}
 	}
+
+	class LibA3
+	{
+		public int mA = 3;
+		public static LibA3 sLibA3 = new LibA3() ~ delete _;
+
+		public this()
+		{
+			mA++;
+		}
+	}
+
+	class LibA4
+	{
+		public int mA;
+	}
 }
 }
 
 
 class LibClassA
 class LibClassA

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

@@ -49,6 +49,27 @@ extension LibClassA
 	}
 	}
 }
 }
 
 
+namespace LibA
+{
+	extension LibA3
+	{
+		public int mB = 7;
+
+		this
+		{
+			mA += 10;
+		}
+	}
+
+	extension LibA4
+	{
+		this
+		{
+			mA += 10;
+		}
+	}
+}
+
 static
 static
 {
 {
 	public static int Overload0(int16 a)
 	public static int Overload0(int16 a)

+ 17 - 0
IDEHelper/Tests/src/Extensions.bf

@@ -55,6 +55,17 @@ extension LibClassA
 	}
 	}
 }
 }
 
 
+namespace LibA
+{
+	extension LibA3
+	{
+		this
+		{
+			mA += 100;
+		}
+	}
+}
+
 namespace Tests
 namespace Tests
 {
 {
 	class Extensions
 	class Extensions
@@ -267,6 +278,12 @@ namespace Tests
 			Test.Assert(ca.mA == 107);
 			Test.Assert(ca.mA == 107);
 			delete ca;
 			delete ca;
 			Test.Assert(LibClassA.sMagic == 7771);
 			Test.Assert(LibClassA.sMagic == 7771);
+
+			LibA.LibA3 la3 = scope .();
+			Test.Assert(la3.mA == 114);
+			Test.Assert(la3.mB == 7);
+			LibA.LibA4 la4 = scope .();
+			Test.Assert(la4.mA == 10);
 		}
 		}
 
 
 		[Test]
 		[Test]

+ 21 - 0
IDEHelper/Tests/src/Objects.bf

@@ -1,9 +1,23 @@
+using System;
+
 namespace Tests
 namespace Tests
 {
 {
 	class Objects
 	class Objects
 	{
 	{
 		class ClassA
 		class ClassA
 		{
 		{
+			public int mA = 1;
+
+			this
+			{
+				mA *= 11;
+			}
+
+			public this()
+			{
+				mA += 100;
+			}
+
 			public virtual void MethodA()
 			public virtual void MethodA()
 			{
 			{
 
 
@@ -17,5 +31,12 @@ namespace Tests
 				 base.MethodA();
 				 base.MethodA();
 			}
 			}
 		}
 		}
+
+		[Test]
+		public static void TestBasics()
+		{
+			ClassA ca = scope .();
+			Test.Assert(ca.mA == 111);
+		}
 	}
 	}
 }
 }