[corlib] ModuleBuilder pseudo-token lookup needs to use references insteads of logica...
authorMarek Safar <marek.safar@gmail.com>
Tue, 25 Jul 2017 14:32:13 +0000 (16:32 +0200)
committerMarek Safar <marek.safar@gmail.com>
Wed, 26 Jul 2017 11:04:27 +0000 (13:04 +0200)
Fixes #58291

mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs
mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs
mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs
mcs/class/corlib/corlib.dll.sources

index 47aee14e4c57d9f357f359f3ce70ca1d1b1a5ec1..97f9e047e6d543afa711984aed41eac9e3260ecb 100644 (file)
@@ -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 }");
+               }
        }
 }
\ No newline at end of file
index 60d78ded37c689b1f56a2b59d01e9d9e0bd84021..2e985180ef549a1f9daac1d89129ded9b73a354b 100644 (file)
@@ -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) {
index 5386ae2460c82e2ca2bca8bd4ab7596edc7891e9..bd2f52bfbb7d3954fc09ec986dd4948ca5e98c3f 100644 (file)
@@ -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 ()
                {
index 9b245081069acf75ec49ec7942b32ac00137b1f1..89d190cbaeae41fb5cdd8c672c57ed75046ac038 100644 (file)
@@ -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