diff options
author | Aleksey Kliger <alklig@microsoft.com> | 2017-12-19 00:55:18 +0300 |
---|---|---|
committer | Aleksey Kliger (λgeek) <akliger@gmail.com> | 2018-01-02 20:05:48 +0300 |
commit | 6102b9538555180cea57b92c3969d324cedf2f7f (patch) | |
tree | 663ec036319e821039fec8c298130faa6fd2d07d /mcs/class/corlib | |
parent | af165436b5a1feaee945046b99fbdcdd93a84534 (diff) |
[tests] SRE check that a memberref token is emitted for a gtd
Regression test for https://github.com/mono/mono/issues/6192
Diffstat (limited to 'mcs/class/corlib')
-rw-r--r-- | mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs | 6 | ||||
-rw-r--r-- | mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs | 123 |
2 files changed, 126 insertions, 3 deletions
diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs index b31ed2e117e..07b8032c6c3 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs @@ -19,6 +19,7 @@ namespace MonoTests.System.Reflection.Emit [TestFixture] public class ILGeneratorTest { + ModuleBuilder modulebuilder; TypeBuilder tb; ILGenerator il_gen; @@ -38,8 +39,8 @@ namespace MonoTests.System.Reflection.Emit AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly ( assemblyName, AssemblyBuilderAccess.Run); - ModuleBuilder module = assembly.DefineDynamicModule ("module1"); - tb = module.DefineType ("T", TypeAttributes.Public); + modulebuilder = assembly.DefineDynamicModule ("module1"); + tb = modulebuilder.DefineType ("T", TypeAttributes.Public); } [Test] @@ -610,6 +611,5 @@ namespace MonoTests.System.Reflection.Emit Assert.AreEqual ("1", s); } - } } diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs index c1ae91971f9..807a1dd3e95 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs @@ -1062,5 +1062,128 @@ namespace MonoTests.System.Reflection.Emit Assert.AreEqual (0, module.MetadataToken); } + [Test] + public void SaveMemberRefGtd () { + // Ensure that the a memberref token is emitted for a + // field or for a method of a gtd in the same dynamic assembly. + // Regression test for GitHub #6192 + + // class T { + // public string F () { + // int i = new C<int>().Foo (42).field1; + // return i.ToString(); + // } + // public string F2 () { + // int i = new C<int>().Bar (42); + // return i.ToString (); + // } + // } + // class C<X> { + // public X field1; + // public C<X> Foo (X x) { + // this.field1 = x; + // return this; + // } + // public X Bar (X x) { + // return this.Foo (x).field1; + // } + //} + + AssemblyName an = genAssemblyName (); + AssemblyBuilder ab = Thread.GetDomain ().DefineDynamicAssembly (an, AssemblyBuilderAccess.RunAndSave, tempDir); + ModuleBuilder modulebuilder = ab.DefineDynamicModule (an.Name, an.Name + ".dll"); + + var tb = modulebuilder.DefineType ("T", TypeAttributes.Public); + var il_gen = tb.DefineMethod ("F", MethodAttributes.Public, typeof(string), null).GetILGenerator (); + var il_gen2 = tb.DefineMethod ("F2", MethodAttributes.Public, typeof(string), null).GetILGenerator (); + + var cbuilder = modulebuilder.DefineType ("C", TypeAttributes.Public); + var genericParams = cbuilder.DefineGenericParameters ("X"); + + var field1builder = cbuilder.DefineField ("field1", genericParams[0], FieldAttributes.Public); + + var cOfX = cbuilder.MakeGenericType(genericParams); + + var fooBuilder = cbuilder.DefineMethod ("Foo", + MethodAttributes.Public, + cOfX, + new Type [] { genericParams[0] }); + var cdefaultCtor = cbuilder.DefineDefaultConstructor (MethodAttributes.Public); + + var fooIL = fooBuilder.GetILGenerator (); + + fooIL.Emit (OpCodes.Ldarg_0); + fooIL.Emit (OpCodes.Ldarg_1); + // Emit (Stfld, field1builder) must generate a memberref token, not fielddef. + fooIL.Emit (OpCodes.Stfld, field1builder); + fooIL.Emit (OpCodes.Ldarg_0); + fooIL.Emit (OpCodes.Ret); + + var barBuilder = cbuilder.DefineMethod ("Bar", + MethodAttributes.Public, + genericParams [0], + new Type [] { genericParams [0] }); + var barIL = barBuilder.GetILGenerator (); + + barIL.Emit (OpCodes.Ldarg_0); + barIL.Emit (OpCodes.Ldarg_1); + // Emit (Call, fooBuilder) must generate a memberref token, not a methoddef. + barIL.Emit (OpCodes.Call, fooBuilder); + barIL.Emit (OpCodes.Ldfld, field1builder); + barIL.Emit (OpCodes.Ret); + + var cOfInt32 = cbuilder.MakeGenericType (new Type [] { typeof (int) }); + var fooOfInt32 = TypeBuilder.GetMethod (cOfInt32, fooBuilder); + var cfield1OfInt32 = TypeBuilder.GetField (cOfInt32, field1builder); + var intToString = typeof(int).GetMethod ("ToString", Type.EmptyTypes); + + var ilocal = il_gen.DeclareLocal (typeof(int)); + il_gen.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (cOfInt32, cdefaultCtor)); + il_gen.Emit (OpCodes.Ldc_I4, 42); + il_gen.Emit (OpCodes.Call, fooOfInt32); + il_gen.Emit (OpCodes.Ldfld, cfield1OfInt32); + il_gen.Emit (OpCodes.Stloc, ilocal); + il_gen.Emit (OpCodes.Ldloca, ilocal); + il_gen.Emit (OpCodes.Call, intToString); + il_gen.Emit (OpCodes.Ret); + + + var i2local = il_gen2.DeclareLocal (typeof (int)); + var barOfInt32 = TypeBuilder.GetMethod (cOfInt32, barBuilder); + il_gen2.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (cOfInt32, cdefaultCtor)); + il_gen2.Emit (OpCodes.Ldc_I4, 17); + il_gen2.Emit (OpCodes.Call, barOfInt32); + il_gen2.Emit (OpCodes.Stloc, i2local); + il_gen2.Emit (OpCodes.Ldloca, i2local); + il_gen2.Emit (OpCodes.Call, intToString); + il_gen2.Emit (OpCodes.Ret); + + cbuilder.CreateType (); + tb.CreateType (); + + ab.Save (an.Name + ".dll"); + + /* Yes the test really needs to roundtrip through SRE.Save(). + * The regression is in the token fixup code on the saving codepath. + */ + + var assm = Assembly.LoadFrom (Path.Combine (tempDir, an.Name + ".dll")); + + var baked = assm.GetType ("T"); + + var x = Activator.CreateInstance (baked); + var m = baked.GetMethod ("F"); + + var s = m.Invoke (x, null); + + Assert.AreEqual ("42", s); + + var m2 = baked.GetMethod ("F2"); + + var s2 = m2.Invoke (x, null); + + Assert.AreEqual ("17", s2); + } + } } |