Skip to content

Commit 4ad9c0f

Browse files
authored
Fix that method resolution would consider all function-pointers to be the same (#885)
1 parent cc48622 commit 4ad9c0f

File tree

3 files changed

+91
-2
lines changed

3 files changed

+91
-2
lines changed

Mono.Cecil/MetadataResolver.cs

+29
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,35 @@ static bool AreSame (TypeSpecification a, TypeSpecification b)
334334
if (a.IsArray)
335335
return AreSame ((ArrayType) a, (ArrayType) b);
336336

337+
if (a.IsFunctionPointer)
338+
return AreSame ((FunctionPointerType) a, (FunctionPointerType) b);
339+
340+
return true;
341+
}
342+
343+
static bool AreSame (FunctionPointerType a, FunctionPointerType b)
344+
{
345+
if (a.HasThis != b.HasThis)
346+
return false;
347+
348+
if (a.CallingConvention != b.CallingConvention)
349+
return false;
350+
351+
if (!AreSame (a.ReturnType, b.ReturnType))
352+
return false;
353+
354+
if (a.ContainsGenericParameter != b.ContainsGenericParameter)
355+
return false;
356+
357+
if (a.HasParameters != b.HasParameters)
358+
return false;
359+
360+
if (!a.HasParameters)
361+
return true;
362+
363+
if (!AreSame (a.Parameters, b.Parameters))
364+
return false;
365+
337366
return true;
338367
}
339368

Test/Mono.Cecil.Tests/MethodTests.cs

+46-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
using Mono.Cecil;
55
using Mono.Cecil.Metadata;
6-
6+
using Mono.Collections.Generic;
77
using NUnit.Framework;
88

99
namespace Mono.Cecil.Tests {
@@ -236,5 +236,50 @@ public void InstanceAndStaticMethodComparison ()
236236
Assert.AreNotEqual(instance_method, static_method_reference.Resolve ());
237237
});
238238
}
239+
240+
[Test]
241+
public void FunctionPointerArgumentOverload ()
242+
{
243+
TestIL ("others.il", module => {
244+
var others = module.GetType ("Others");
245+
var overloaded_methods = others.Methods.Where (m => m.Name == "OverloadedWithFpArg").ToArray ();
246+
// Manually create the function-pointer type so `AreSame` won't exit early due to reference equality
247+
var overloaded_method_int_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
248+
{
249+
HasThis = false,
250+
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
251+
HasThis = false,
252+
ReturnType = module.TypeSystem.Int32,
253+
Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
254+
}) }
255+
};
256+
257+
var overloaded_method_long_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
258+
{
259+
HasThis = false,
260+
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
261+
HasThis = false,
262+
ReturnType = module.TypeSystem.Int32,
263+
Parameters = { new ParameterDefinition (module.TypeSystem.Int64) }
264+
}) }
265+
};
266+
267+
var overloaded_method_cdecl_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
268+
{
269+
HasThis = false,
270+
Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
271+
CallingConvention = MethodCallingConvention.C,
272+
HasThis = false,
273+
ReturnType = module.TypeSystem.Int32,
274+
Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
275+
}) }
276+
};
277+
278+
279+
Assert.AreEqual (overloaded_methods[0], overloaded_method_int_reference.Resolve ());
280+
Assert.AreEqual (overloaded_methods[1], overloaded_method_long_reference.Resolve ());
281+
Assert.AreEqual (overloaded_methods[2], overloaded_method_cdecl_reference.Resolve ());
282+
});
283+
}
239284
}
240285
}

Test/Resources/il/others.il

+16-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,22 @@
7878
.other instance void Others::dang_Handler (class [mscorlib]System.EventHandler)
7979
.other instance void Others::fang_Handler (class [mscorlib]System.EventHandler)
8080
}
81-
81+
82+
.method public static void OverloadedWithFpArg(method int32 *(int32) X) cil managed
83+
{
84+
ret
85+
}
86+
87+
.method public static void OverloadedWithFpArg(method int32 *(int64) X) cil managed
88+
{
89+
ret
90+
}
91+
92+
.method public static void OverloadedWithFpArg(method unmanaged cdecl int32 *(int32) X) cil managed
93+
{
94+
ret
95+
}
96+
8297
.method public instance void SameMethodNameInstanceStatic() cil managed
8398
{
8499
ret

0 commit comments

Comments
 (0)