Skip to content

Commit

Permalink
Fix that method resolution would consider all function-pointers to be…
Browse files Browse the repository at this point in the history
… the same (jbevain#885)
  • Loading branch information
nulldatamap committed Nov 30, 2022
1 parent 55142e2 commit 0d2cf2e
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Mono.Cecil/MetadataResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,35 @@ static bool AreSame (TypeSpecification a, TypeSpecification b)
if (a.IsArray)
return AreSame ((ArrayType) a, (ArrayType) b);

if (a.IsFunctionPointer)
return AreSame ((FunctionPointerType) a, (FunctionPointerType) b);

return true;
}

static bool AreSame (FunctionPointerType a, FunctionPointerType b)
{
if (a.HasThis != b.HasThis)
return false;

if (a.CallingConvention != b.CallingConvention)
return false;

if (!AreSame (a.ReturnType, b.ReturnType))
return false;

if (a.ContainsGenericParameter != b.ContainsGenericParameter)
return false;

if (a.HasParameters != b.HasParameters)
return false;

if (!a.HasParameters)
return true;

if (!AreSame (a.Parameters, b.Parameters))
return false;

return true;
}

Expand Down
62 changes: 61 additions & 1 deletion Test/Mono.Cecil.Tests/MethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using Mono.Cecil;
using Mono.Cecil.Metadata;

using Mono.Collections.Generic;
using NUnit.Framework;

namespace Mono.Cecil.Tests {
Expand Down Expand Up @@ -219,5 +219,65 @@ public void ReturnParameterMethod ()
Assert.IsNotNull (method);
Assert.AreEqual (method, method.MethodReturnType.Parameter.Method);
}

[Test]
public void InstanceAndStaticMethodComparison ()
{
TestIL ("others.il", module => {
var others = module.GetType ("Others");
var instance_method = others.Methods.Single (m => m.Name == "SameMethodNameInstanceStatic" && m.HasThis);
var static_method_reference = new MethodReference ("SameMethodNameInstanceStatic", instance_method.ReturnType, others)
{
HasThis = false
};
Assert.AreNotEqual(instance_method, static_method_reference.Resolve ());
});
}

[Test]
public void FunctionPointerArgumentOverload ()
{
TestIL ("others.il", module => {
var others = module.GetType ("Others");
var overloaded_methods = others.Methods.Where (m => m.Name == "OverloadedWithFpArg").ToArray ();
// Manually create the function-pointer type so `AreSame` won't exit early due to reference equality
var overloaded_method_int_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
{
HasThis = false,
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
HasThis = false,
ReturnType = module.TypeSystem.Int32,
Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
}) }
};
var overloaded_method_long_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
{
HasThis = false,
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
HasThis = false,
ReturnType = module.TypeSystem.Int32,
Parameters = { new ParameterDefinition (module.TypeSystem.Int64) }
}) }
};
var overloaded_method_cdecl_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
{
HasThis = false,
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
CallingConvention = MethodCallingConvention.C,
HasThis = false,
ReturnType = module.TypeSystem.Int32,
Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
}) }
};
Assert.AreEqual (overloaded_methods[0], overloaded_method_int_reference.Resolve ());
Assert.AreEqual (overloaded_methods[1], overloaded_method_long_reference.Resolve ());
Assert.AreEqual (overloaded_methods[2], overloaded_method_cdecl_reference.Resolve ());
});
}
}
}
25 changes: 25 additions & 0 deletions Test/Resources/il/others.il
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,29 @@
.other instance void Others::dang_Handler (class [mscorlib]System.EventHandler)
.other instance void Others::fang_Handler (class [mscorlib]System.EventHandler)
}

.method public static void OverloadedWithFpArg(method int32 *(int32) X) cil managed
{
ret
}

.method public static void OverloadedWithFpArg(method int32 *(int64) X) cil managed
{
ret
}

.method public static void OverloadedWithFpArg(method unmanaged cdecl int32 *(int32) X) cil managed
{
ret
}

.method public instance void SameMethodNameInstanceStatic() cil managed
{
ret
}

.method public static void SameMethodNameInstanceStatic() cil managed
{
ret
} // end of static method MethodNameTests::MethodName
}

0 comments on commit 0d2cf2e

Please sign in to comment.