diff options
-rw-r--r-- | mono/mini/interp/interp.c | 3 | ||||
-rw-r--r-- | mono/mini/mini-trampolines.c | 2 | ||||
-rw-r--r-- | mono/tests/delegate17.cs | 59 |
3 files changed, 40 insertions, 24 deletions
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c index e7b1f90483d..f9cdc168898 100644 --- a/mono/mini/interp/interp.c +++ b/mono/mini/interp/interp.c @@ -1635,6 +1635,9 @@ interp_init_delegate (MonoDelegate *del, MonoError *error) if (del->interp_method) { /* Delegate created by a call to ves_icall_mono_delegate_ctor_interp () */ del->method = ((InterpMethod *)del->interp_method)->method; + } if (del->method_ptr && !del->method) { + /* Delegate created from methodInfo.MethodHandle.GetFunctionPointer() */ + del->interp_method = (InterpMethod *)del->method_ptr; } else if (del->method) { /* Delegate created dynamically */ del->interp_method = mono_interp_get_imethod (del->object.vtable->domain, del->method, error); diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 55834cd393d..e5bb1cea2a2 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -1142,7 +1142,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint } } - if (tramp_info->method == NULL && delegate->target != NULL && method->flags & METHOD_ATTRIBUTE_VIRTUAL) { + if (delegate->method_ptr == NULL && tramp_info->method == NULL && delegate->target != NULL && method->flags & METHOD_ATTRIBUTE_VIRTUAL) { /* tramp_info->method == NULL happens when someone asks us to JIT some delegate's * Invoke method (see compile_special). In that case if method is virtual, the target * could be some derived class, so we need to find the correct override. diff --git a/mono/tests/delegate17.cs b/mono/tests/delegate17.cs index 09818514ecd..235e168ebc2 100644 --- a/mono/tests/delegate17.cs +++ b/mono/tests/delegate17.cs @@ -1,6 +1,33 @@ using System; using System.Reflection; +public enum WasCalled { + BaseWasCalled, + DerivedWasCalled +} + +public delegate WasCalled Del1 (string s); +public delegate WasCalled Del2 (string s); + +public class Base +{ + public virtual WasCalled Foo (string s) + { + Console.WriteLine ("Base.Foo called. Expected {0}", s); + return WasCalled.BaseWasCalled; + } +} + +public class Derived : Base +{ + public override WasCalled Foo (string s) + { + Console.WriteLine ("Derived.Foo called. Expected {0}", s); + return WasCalled.DerivedWasCalled; + } +} + + internal class Program { public static int Main (string[] args) @@ -14,29 +41,15 @@ internal class Program // newobj Del2::.ctor Del2 f = new Del2 (b.Invoke); // should call Derived.Foo not Base.Foo - var r = f ("abcd"); - return r; - } -} - - -public delegate int Del1 (string s); -public delegate int Del2 (string s); - -public class Base -{ - public virtual int Foo (string s) - { - Console.WriteLine ("Base.Foo called. Bad"); - return 1; - } -} - -public class Derived : Base -{ - public override int Foo (string s) - { - Console.WriteLine ("Derived.Foo called. Good"); + var r = f ("Derived.Foo"); + if (r != WasCalled.DerivedWasCalled) + return 1; + // should call Base.Foo not Derived.Foo + var boundDelegate = (Del2)Activator.CreateInstance (typeof (Del2), b, typeof (Base).GetMethod (nameof (Base.Foo)).MethodHandle.GetFunctionPointer()); + r = boundDelegate ("Base.Foo"); + if (r != WasCalled.BaseWasCalled) + return 2; return 0; } } + |