From ebfae1efa8f0ecb0262312674503faccf561b2dc Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 25 Jul 2017 16:32:13 +0200 Subject: [PATCH] [corlib] ModuleBuilder pseudo-token lookup needs to use references insteads of logical equality comparer. Fixes #58291 --- mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs | 6 ++++ .../corlib/System.Reflection.Emit/ModuleBuilder.cs | 38 ++++++++++++---------- .../Test/System.Reflection.Emit/TypeBuilderTest.cs | 34 +++++++++++++++++++ mcs/class/corlib/corlib.dll.sources | 2 ++ 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs b/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs index 47aee14e4c5..97f9e047e6d 100644 --- a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs +++ b/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 }"); + } } } \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs index 60d78ded37c..2e985180ef5 100644 --- a/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs +++ b/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 inst_tokens = new Dictionary (); - Dictionary inst_tokens_open = new Dictionary (); + Dictionary 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 (ReferenceEqualityComparer.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 (); var member_map = new Dictionary (); - 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) { diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs index 5386ae2460c..bd2f52bfbb7 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs @@ -570,6 +570,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 () { TypeBuilder tb = module.DefineType (genTypeName ()); diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 9b245081069..89d190cbaea 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/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 -- 2.11.4.GIT