Skip to content

Instantly share code, notes, and snippets.

@lambdageek
Created February 12, 2019 20:07
Show Gist options
  • Select an option

  • Save lambdageek/bf268c3e037dacfafb0e1734dee0b397 to your computer and use it in GitHub Desktop.

Select an option

Save lambdageek/bf268c3e037dacfafb0e1734dee0b397 to your computer and use it in GitHub Desktop.
custom modifier IL tests
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 $<
// 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 { }
// 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