Created
February 12, 2019 20:07
-
-
Save lambdageek/bf268c3e037dacfafb0e1734dee0b397 to your computer and use it in GitHub Desktop.
custom modifier IL tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| all: Repro11350.exe | |
| .PHONY: all clean | |
| Repro11350.exe: Repro11350.cs modifiersdata.dll | |
| csc /out:$@ /target:exe $< -r:./modifiersdata.dll | |
| modifiersdata.dll: modifiersdata.il | |
| ilasm /output:$@ /dll $< | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Licensed to the .NET Foundation under one or more agreements. | |
| // The .NET Foundation licenses this file to you under the MIT license. | |
| // See the LICENSE file in the project root for more information. | |
| .assembly extern mscorlib { } | |
| .assembly modifiersdata { } | |
| .class public BaseClass | |
| { | |
| .method public hidebysig specialname rtspecialname instance void .ctor() cil managed | |
| { | |
| ldarg.0 | |
| call instance void [mscorlib]System.Object::.ctor() | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32 modopt (FooModifier)) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32 modopt (FooModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.0 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32 modopt (BarModifier)) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32 modopt (BarModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.1 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32 modreq (FooModifier)) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32 modreq (FooModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.2 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32)" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.3 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 modopt (FooModifier) Override(int32) | |
| { | |
| ldstr "In int32 modopt (FooModifier) BaseClass::Override(int32)" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.4 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32 modopt (FooModifier)[]) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32 modopt (FooModifier)[])" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.5 | |
| ret | |
| } | |
| .method public hidebysig virtual newslot instance int32 Override(int32 modopt (BarModifier)[]) | |
| { | |
| ldstr "In int32 BaseClass::Override(int32 modopt (BarModifier)[])" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4.6 | |
| ret | |
| } | |
| } | |
| .class public DerivedClass extends BaseClass | |
| { | |
| .method public hidebysig specialname rtspecialname instance void .ctor() cil managed | |
| { | |
| ldarg.0 | |
| call instance void BaseClass::.ctor() | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32 modopt (FooModifier)) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32 modopt (FooModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 100 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32 modopt (BarModifier)) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32 modopt (BarModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 101 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32 modreq (FooModifier)) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32 modreq (FooModifier))" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 102 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32)" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 103 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 modopt (FooModifier) Override(int32) | |
| { | |
| ldstr "In int32 modopt (FooModifier) DerivedClass::Override(int32)" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 104 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32 modopt (FooModifier)[]) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32 modopt (FooModifier)[])" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 105 | |
| ret | |
| } | |
| .method public hidebysig virtual instance int32 Override(int32 modopt (BarModifier)[]) | |
| { | |
| ldstr "In int32 DerivedClass::Override(int32 modopt (BarModifier)[])" | |
| call void class [mscorlib]System.Console::WriteLine(string) | |
| ldc.i4 106 | |
| ret | |
| } | |
| } | |
| .class public GenericClass`1<T> | |
| { | |
| .method public hidebysig specialname rtspecialname instance void .ctor() cil managed | |
| { | |
| ldarg.0 | |
| call instance void [mscorlib]System.Object::.ctor() | |
| ret | |
| } | |
| } | |
| .class public value sequential GenericStruct`1<T> { .size 1 } | |
| .class public Factory | |
| { | |
| .method public static hidebysig object TryAllocWithModifiedArray() | |
| { | |
| newobj void class GenericClass`1<int32 modopt (FooModifier)[]>::.ctor() | |
| ret | |
| } | |
| .method public static hidebysig object TryBoxWithModifiedPointer() | |
| { | |
| .locals init (valuetype GenericStruct`1<int32 modreq (BarModifier)*[]>) | |
| ldloc 0 | |
| box valuetype GenericStruct`1<int32 modreq (BarModifier)*[]> | |
| ret | |
| } | |
| } | |
| .class public FooModifier { } | |
| .class public BarModifier { } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Licensed to the .NET Foundation under one or more agreements. | |
| // The .NET Foundation licenses this file to you under the MIT license. | |
| // See the LICENSE file in the project root for more information. | |
| using System; | |
| using System.Reflection; | |
| class Program | |
| { | |
| static int Main() | |
| { | |
| var baseClass = new BaseClass(); | |
| var derivedClass = new DerivedClass(); | |
| var superDerivedClass = new SuperDerivedClass(); | |
| // | |
| // C# will generate a call to the unmodified version of the method so this is easy to check statically | |
| // | |
| if (baseClass.Override(0) != 3) | |
| Console.WriteLine ("ERR: expected the no-modifier BaseClass::Override to run"); | |
| //return 1; | |
| if (derivedClass.Override(0) != 103) | |
| Console.WriteLine ("ERR: expected the no-modifier DerivedClass::Override to run"); | |
| //return 2; | |
| if (superDerivedClass.Override(0) != 203) | |
| return 3; | |
| // | |
| // Reflection-locate rest of the `Override` method overloads | |
| // | |
| MethodInfo paramModoptFoo = null; | |
| MethodInfo paramModoptBar = null; | |
| MethodInfo paramModreqFoo = null; | |
| MethodInfo paramUnmodified = null; | |
| MethodInfo returnModoptFoo = null; | |
| MethodInfo arrayModopt1 = null; | |
| MethodInfo arrayModopt2 = null; | |
| foreach (var method in typeof(BaseClass).GetTypeInfo().DeclaredMethods) | |
| { | |
| ParameterInfo param = method.GetParameters()[0]; | |
| Type[] paramRequiredModifiers = param.GetRequiredCustomModifiers(); | |
| Type[] paramOptionalModifiers = param.GetOptionalCustomModifiers(); | |
| ParameterInfo retParam = method.ReturnParameter; | |
| Type[] retParamOptionalModifiers = retParam.GetOptionalCustomModifiers(); | |
| if (param.ParameterType != typeof(int) && param.ParameterType != typeof(int[])) | |
| throw new Exception(); | |
| if (paramRequiredModifiers.Length > 0) | |
| { | |
| if (paramRequiredModifiers.Length > 1 || paramRequiredModifiers[0] != typeof(FooModifier)) | |
| throw new Exception(); | |
| else | |
| paramModreqFoo = method; | |
| } | |
| else if (paramOptionalModifiers.Length > 0) | |
| { | |
| if (paramOptionalModifiers.Length > 1) | |
| throw new Exception(); | |
| else if (paramOptionalModifiers[0] == typeof(FooModifier)) | |
| paramModoptFoo = method; | |
| else if (paramOptionalModifiers[0] == typeof(BarModifier)) | |
| paramModoptBar = method; | |
| else | |
| throw new Exception(); | |
| } | |
| else if (retParamOptionalModifiers.Length > 0) | |
| { | |
| if (retParamOptionalModifiers.Length > 1 || retParamOptionalModifiers[0] != typeof(FooModifier)) | |
| throw new Exception(); | |
| else | |
| returnModoptFoo = method; | |
| } | |
| else | |
| { | |
| if (param.ParameterType == typeof(int)) | |
| paramUnmodified = method; | |
| else if (param.ParameterType == typeof(int[])) | |
| { | |
| // Reflection can't distinguish between the two overloads | |
| if (arrayModopt1 == null) | |
| arrayModopt1 = method; | |
| else if (arrayModopt2 == null) | |
| arrayModopt2 = method; | |
| else | |
| throw new Exception(); | |
| } | |
| else | |
| throw new Exception(); | |
| } | |
| } | |
| if ((int)paramModoptFoo.Invoke(baseClass, new object[] { 0 }) != 0) | |
| return 101; | |
| if ((int)paramModoptBar.Invoke(baseClass, new object[] { 0 }) != 1) | |
| return 102; | |
| if ((int)paramModreqFoo.Invoke(baseClass, new object[] { 0 }) != 2) | |
| return 103; | |
| if ((int)paramUnmodified.Invoke(baseClass, new object[] { 0 }) != 3) | |
| return 104; | |
| if ((int)returnModoptFoo.Invoke(baseClass, new object[] { 0 }) != 4) | |
| return 105; | |
| if ((int)paramModoptFoo.Invoke(derivedClass, new object[] { 0 }) != 100) | |
| return 201; | |
| if ((int)paramModoptBar.Invoke(derivedClass, new object[] { 0 }) != 101) | |
| return 202; | |
| if ((int)paramModreqFoo.Invoke(derivedClass, new object[] { 0 }) != 102) | |
| return 203; | |
| if ((int)paramUnmodified.Invoke(derivedClass, new object[] { 0 }) != 103) | |
| return 204; | |
| if ((int)returnModoptFoo.Invoke(derivedClass, new object[] { 0 }) != 104) | |
| return 205; | |
| if ((int)arrayModopt1.Invoke(baseClass, new object[] { null }) + 100 != (int)arrayModopt1.Invoke(derivedClass, new object[] { null })) | |
| return 301; | |
| if ((int)arrayModopt2.Invoke(baseClass, new object[] { null }) + 100 != (int)arrayModopt2.Invoke(derivedClass, new object[] { null })) | |
| return 302; | |
| // | |
| // Make sure modifiers are ignored for newobj/box | |
| // | |
| object tryAllocWithModifiedArrayResult = Factory.TryAllocWithModifiedArray(); | |
| if (!(tryAllocWithModifiedArrayResult is GenericClass<int[]>)) | |
| return 401; | |
| if (tryAllocWithModifiedArrayResult.GetType() != typeof(GenericClass<int[]>)) | |
| return 402; | |
| object tryBoxWithModifiedPointerResult = Factory.TryBoxWithModifiedPointer(); | |
| if (!(tryBoxWithModifiedPointerResult is GenericStruct<int*[]>)) | |
| return 501; | |
| if (tryBoxWithModifiedPointerResult.GetType() != typeof(GenericStruct<int*[]>)) | |
| return 502; | |
| return 100; | |
| } | |
| class SuperDerivedClass : DerivedClass | |
| { | |
| public override int Override(int A_0) | |
| { | |
| Console.WriteLine("In int32 SuperDerivedClass::Override(int32)"); | |
| return 203; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment