diff --git a/src/tests/Interop/UnmanagedCallersOnly/InvalidCSharp.ilproj b/src/tests/Interop/UnmanagedCallersOnly/InvalidCSharp.ilproj
new file mode 100644
index 00000000000000..b7b8b4d7665382
--- /dev/null
+++ b/src/tests/Interop/UnmanagedCallersOnly/InvalidCSharp.ilproj
@@ -0,0 +1,8 @@
+
+
+ library
+
+
+
+
+
\ No newline at end of file
diff --git a/src/tests/Interop/UnmanagedCallersOnly/InvalidCallbacks.il b/src/tests/Interop/UnmanagedCallersOnly/InvalidCallbacks.il
new file mode 100644
index 00000000000000..bd391367f52332
--- /dev/null
+++ b/src/tests/Interop/UnmanagedCallersOnly/InvalidCallbacks.il
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+.assembly extern System.Runtime { }
+.assembly extern System.Runtime.InteropServices { }
+
+.assembly InvalidCSharp { }
+
+.class public auto ansi beforefieldinit InvalidCSharp.GenericClass`1
+ extends System.Object
+{
+ .method public hidebysig static
+ void CallbackMethod (
+ int32 n
+ ) cil managed preservesig
+ {
+ .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = (
+ 01 00 00 00
+ )
+ .maxstack 8
+ IL_0000: ldstr "Functions with attribute UnmanagedCallersOnlyAttribute within a generic type are invalid"
+ IL_0005: newobj instance void [System.Runtime]System.Exception::.ctor(string)
+ IL_000a: throw
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InvalidCSharp.Callbacks
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig static
+ int32 CallbackMethodGeneric (
+ !!T arg
+ ) cil managed preservesig
+ {
+ .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = (
+ 01 00 00 00
+ )
+ .maxstack 8
+ IL_0000: ldstr "Functions with attribute UnmanagedCallersOnlyAttribute cannot have generic arguments"
+ IL_0005: newobj instance void [System.Runtime]System.Exception::.ctor(string)
+ IL_000a: throw
+ }
+
+ .method public hidebysig
+ instance int32 CallbackNonStatic (
+ int32 val
+ ) cil managed preservesig
+ {
+ .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = (
+ 01 00 00 00
+ )
+ .maxstack 8
+ IL_0000: ldstr "Instance functions with attribute UnmanagedCallersOnlyAttribute are invalid"
+ IL_0005: newobj instance void [System.Runtime]System.Exception::.ctor(string)
+ IL_000a: throw
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
diff --git a/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs b/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs
index 68d700c9ccfa96..0a2b5307da315e 100644
--- a/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs
+++ b/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs
@@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Runtime.CompilerServices;
using System.Reflection;
using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using TestLibrary;
@@ -35,6 +35,20 @@ public static class UnmanagedCallersOnlyDll
public static extern int PInvokeMarkedWithUnmanagedCallersOnly(int n);
}
+ private const string InvalidCSharpAssemblyName = "InvalidCSharp";
+
+ public static Type GetCallbacksType()
+ {
+ var asm = Assembly.Load(InvalidCSharpAssemblyName);
+ return asm.GetType("InvalidCSharp.Callbacks");
+ }
+
+ public static Type GetGenericClassOfIntType()
+ {
+ var asm = Assembly.Load(InvalidCSharpAssemblyName);
+ return asm.GetType("InvalidCSharp.GenericClass`1").MakeGenericType(typeof(int));
+ }
+
private delegate int IntNativeMethodInvoker();
private delegate void NativeMethodInvoker();
@@ -338,12 +352,6 @@ void CallAsDelegate()
}
}
- [UnmanagedCallersOnly]
- public int CallbackNonStatic(int val)
- {
- Assert.Fail($"Instance functions with attribute {nameof(UnmanagedCallersOnlyAttribute)} are invalid");
- return -1;
- }
public static void NegativeTest_NonStaticMethod()
{
@@ -354,7 +362,7 @@ void TestUnmanagedCallersOnlyNonStatic()
{
.locals init ([0] native int ptr)
nop
- ldftn int CallbackNonStatic(int)
+ ldftn int GetCallbacksType().CallbackNonStatic(int)
stloc.0
ldloc.0
@@ -371,7 +379,7 @@ ldftn int CallbackNonStatic(int)
il.Emit(OpCodes.Nop);
// Get native function pointer of the callback
- il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod(nameof(CallbackNonStatic)));
+ il.Emit(OpCodes.Ldftn, GetCallbacksType().GetMethod("CallbackNonStatic"));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
@@ -436,13 +444,6 @@ ldftn int CallbackMethodNonBlittable(bool)
Assert.Throws(() => { testNativeMethod(); });
}
- [UnmanagedCallersOnly]
- public static int CallbackMethodGeneric(T arg)
- {
- Assert.Fail($"Functions with attribute {nameof(UnmanagedCallersOnlyAttribute)} cannot have generic arguments");
- return -1;
- }
-
public static void NegativeTest_NonInstantiatedGenericArguments()
{
Console.WriteLine($"Running {nameof(NegativeTest_NonInstantiatedGenericArguments)}...");
@@ -452,7 +453,7 @@ void TestUnmanagedCallersOnlyNonInstGenericArguments()
{
.locals init ([0] native int ptr)
IL_0000: nop
- IL_0001: ldftn void CallbackMethodGeneric(T)
+ IL_0001: ldftn void InvalidCSharp.Callbacks.CallbackMethodGeneric(T)
IL_0007: stloc.0
IL_0008: ret
}
@@ -463,7 +464,7 @@ .locals init ([0] native int ptr)
il.Emit(OpCodes.Nop);
// Get native function pointer of the callback
- il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod(nameof(CallbackMethodGeneric)));
+ il.Emit(OpCodes.Ldftn, GetCallbacksType().GetMethod("CallbackMethodGeneric"));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ret);
@@ -482,7 +483,7 @@ void TestUnmanagedCallersOnlyInstGenericArguments()
{
.locals init ([0] native int ptr)
nop
- ldftn void CallbackMethodGeneric(int)
+ ldftn void InvalidCSharp.Callbacks.CallbackMethodGeneric(int)
stloc.0
ldloc.0
@@ -499,7 +500,7 @@ ldftn void CallbackMethodGeneric(int)
il.Emit(OpCodes.Nop);
// Get native function pointer of the instantiated generic callback
- il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod(nameof(CallbackMethodGeneric)).MakeGenericMethod(new [] { typeof(int) }));
+ il.Emit(OpCodes.Ldftn, GetCallbacksType().GetMethod("CallbackMethodGeneric").MakeGenericMethod(new [] { typeof(int) }));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
@@ -515,15 +516,6 @@ ldftn void CallbackMethodGeneric(int)
Assert.Throws(() => { testNativeMethod(); });
}
- public class GenericClass
- {
- [UnmanagedCallersOnly]
- public static void CallbackMethod(int n)
- {
- Assert.Fail($"Functions with attribute {nameof(UnmanagedCallersOnlyAttribute)} within a generic type are invalid");
- }
- }
-
public static void NegativeTest_FromInstantiatedGenericClass()
{
Console.WriteLine($"Running {nameof(NegativeTest_FromInstantiatedGenericClass)}...");
@@ -533,7 +525,7 @@ void TestUnmanagedCallersOnlyInstGenericType()
{
.locals init ([0] native int ptr)
nop
- ldftn int GenericClass::CallbackMethod(int)
+ ldftn int InvalidCSharp.GenericClass::CallbackMethod(int)
stloc.0
ldloc.0
@@ -550,7 +542,7 @@ .locals init ([0] native int ptr)
il.Emit(OpCodes.Nop);
// Get native function pointer of the callback from the instantiated generic class.
- il.Emit(OpCodes.Ldftn, typeof(GenericClass).GetMethod(nameof(GenericClass.CallbackMethod)));
+ il.Emit(OpCodes.Ldftn, GetGenericClassOfIntType().GetMethod("CallbackMethod"));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
diff --git a/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.csproj b/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.csproj
index a8c1862cc6f6c7..170fac3899124b 100644
--- a/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.csproj
+++ b/src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.csproj
@@ -1,7 +1,6 @@
Exe
- 1
@@ -10,5 +9,6 @@
+