Kaynağa Gözat

[corlib] ModuleBuilder pseudo-token lookup needs to use references insteads of logical equality comparer.

Fixes #58291
Marek Safar 8 yıl önce
ebeveyn
işleme
ebfae1efa8

+ 6 - 0
mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs

@@ -125,5 +125,11 @@ namespace MonoTests.EvaluatorTest
 			object res = Evaluator.Evaluate ("attr.GetType().Name;");
 			Assert.AreEqual ("A", res);
 		}
+
+		[Test]
+		public void EnumType ()
+		{
+			Evaluator.Run ("public class TestClass { private TestEnum _te; public string Get() { return _te.ToString(); } } public enum TestEnum { First, Second }");
+		}
 	}
 }

+ 21 - 17
mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs

@@ -709,8 +709,7 @@ namespace System.Reflection.Emit {
 		static int typespec_tokengen =  0x1bffffff;
 		static int memberref_tokengen =  0x0affffff;
 		static int methoddef_tokengen =  0x06ffffff;
-		Dictionary<MemberInfo, int> inst_tokens = new Dictionary<MemberInfo, int> ();
-		Dictionary<MemberInfo, int> inst_tokens_open = new Dictionary<MemberInfo, int> ();
+		Dictionary<MemberInfo, int> inst_tokens, inst_tokens_open;
 
 		//
 		// Assign a pseudo token to the various TypeBuilderInst objects, so the runtime
@@ -720,16 +719,20 @@ namespace System.Reflection.Emit {
 		// still encounter these objects, it will resolve them by calling their
 		// RuntimeResolve () methods.
 		//
-		int GetPseudoToken (MemberInfo member, bool create_open_instance) {
+		int GetPseudoToken (MemberInfo member, bool create_open_instance)
+		{
 			int token;
-
-			if (create_open_instance) {
-				if (inst_tokens_open.TryGetValue (member, out token))
-					return token;
-			} else {
-				if (inst_tokens.TryGetValue (member, out token))
-					return token;
+			var dict = create_open_instance ? inst_tokens_open : inst_tokens;
+			if (dict == null) {
+				dict = new Dictionary<MemberInfo, int> (ReferenceEqualityComparer<MemberInfo>.Instance);
+				if (create_open_instance)
+					inst_tokens_open = dict;
+				else
+					inst_tokens = dict;
+			} else if (dict.TryGetValue (member, out token)) {
+				return token;
 			}
+
 			// Count backwards to avoid collisions with the tokens
 			// allocated by the runtime
 			if (member is TypeBuilderInstantiation || member is SymbolType)
@@ -764,10 +767,8 @@ namespace System.Reflection.Emit {
 				token = typespec_tokengen --;
 			} else
 				throw new NotImplementedException ();
-			if (create_open_instance)
-				inst_tokens_open [member] = token;
-			else
-				inst_tokens [member] = token;
+
+			dict [member] = token;
 			RegisterToken (member, token);
 			return token;
 		}
@@ -893,11 +894,14 @@ namespace System.Reflection.Emit {
 		//
 		// Fixup the pseudo tokens assigned to the various SRE objects
 		//
-		void FixupTokens () {
+		void FixupTokens ()
+		{
 			var token_map = new Dictionary<int, int> ();
 			var member_map = new Dictionary<int, MemberInfo> ();
-			FixupTokens (token_map, member_map, inst_tokens, false);
-			FixupTokens (token_map, member_map, inst_tokens_open, true);
+			if (inst_tokens != null)
+				FixupTokens (token_map, member_map, inst_tokens, false);
+			if (inst_tokens_open != null)
+				FixupTokens (token_map, member_map, inst_tokens_open, true);
 
 			// Replace the tokens in the IL stream
 			if (types != null) {

+ 34 - 0
mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs

@@ -569,6 +569,40 @@ namespace MonoTests.System.Reflection.Emit
 			}
 		}
 
+		[Test]
+		public void TestEnumWithLateUnderlyingField ()
+		{
+			TypeBuilder enumToCreate = module.DefineType (genTypeName (), TypeAttributes.Public, typeof (Enum));
+			enumToCreate.DefineField ("value__", typeof (Int32),
+				FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
+
+			TypeBuilder enumToCreate2 = module.DefineType (genTypeName (), TypeAttributes.Public, typeof (Enum));
+
+			TypeBuilder ivTypeBld = module.DefineType (genTypeName (), TypeAttributes.Public);
+
+			ConstructorBuilder ivCtor = ivTypeBld.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
+
+			ILGenerator ctorIL = ivCtor.GetILGenerator ();
+
+			ctorIL.Emit (OpCodes.Ldtoken, typeof (Object));
+			ctorIL.Emit (OpCodes.Pop);
+			ctorIL.Emit (OpCodes.Ldtoken, enumToCreate);
+			ctorIL.Emit (OpCodes.Pop);
+			ctorIL.Emit (OpCodes.Ldtoken, enumToCreate2);
+			ctorIL.Emit (OpCodes.Pop);
+			ctorIL.Emit (OpCodes.Ret);
+
+			var ivType = ivTypeBld.CreateType ();
+
+			enumToCreate2.DefineField ("value__", typeof (Int32), FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
+
+			FieldBuilder fb = enumToCreate2.DefineField ("A", enumToCreate, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
+			fb.SetConstant (0);
+
+			enumToCreate.CreateType ();
+			enumToCreate2.CreateType ();
+		}
+
 		[Test]
 		public void TestIsAbstract ()
 		{

+ 2 - 0
mcs/class/corlib/corlib.dll.sources

@@ -1660,6 +1660,8 @@ corert/ThreadPoolBoundHandle.cs
 
 corefx/SR.cs
 
+../../../external/corefx/src/Common/src/System/Collections/Generic/ReferenceEqualityComparer.cs
+
 ../../../external/corefx/src/System.Collections/src/System/Collections/Generic/CollectionExtensions.cs
 
 ../../../external/corefx/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs