Browse Source

Merge pull request #3995 from icsharpcode/fix/instance-operator-call-resolution

Report a call as unresolvable when nothing matched at all
pull/4008/head
Daniel Grunwald 1 month ago committed by GitHub
parent
commit
865cf1e534
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  3. 24
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InstanceOperatorCall.cs
  4. 89
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InstanceOperatorCall.il
  5. 7
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs

5
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@ -196,6 +196,9 @@ @@ -196,6 +196,9 @@
<None Include="TestCases\ILPretty\CS1xSwitch_Release.cs" />
<Compile Remove="TestCases\ILPretty\CallIndirect.cs" />
<None Include="TestCases\ILPretty\CallIndirect.cs" />
<Compile Remove="TestCases\ILPretty\InstanceOperatorCall.cs" />
<None Include="TestCases\ILPretty\InstanceOperatorCall.cs" />
<None Include="TestCases\ILPretty\InstanceOperatorCall.il" />
<Compile Remove="TestCases\ILPretty\EmptyBodies.cs" />
<None Include="TestCases\ILPretty\EmptyBodies.cs" />
<Compile Remove="TestCases\ILPretty\TruncatedAccessorBody.cs" />

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -333,6 +333,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -333,6 +333,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
[Test]
public async Task InstanceOperatorCall()
{
await Run();
}
[Test]
public async Task FSharpLoops_Debug()
{

24
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InstanceOperatorCall.cs

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
public class CallSite
{
public static bool CompareVirtual<T>(Source<T> s, T a, T b)
{
return a < b;
}
public static bool CompareDirect(Source<int> s, int a, int b)
{
return a > b;
}
}
public class Source<T>
{
public virtual bool operator <(T a, T b)
{
return false;
}
public bool operator >(T a, T b)
{
return false;
}
}

89
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InstanceOperatorCall.il

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
// Metadata version: v4.0.30319
.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 11:0:0:0
}
.assembly InstanceOperatorCall
{
.ver 1:0:0:0
}
.module InstanceOperatorCall.dll
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// F# emits comparison operators as instance members, so operator metadata names appear on
// methods C# would never bind as operators: the operands are the arguments, and the operator
// lives on the receiver type rather than on either operand type.
.class public auto ansi beforefieldinit Source`1<T>
extends [System.Runtime]System.Object
{
.method public hidebysig specialname newslot virtual
instance bool op_LessThan(!T a,
!T b) cil managed
{
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ret
}
.method public hidebysig specialname
instance bool op_GreaterThan(!T a,
!T b) cil managed
{
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ret
}
.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 CallSite
extends [System.Runtime]System.Object
{
.method public hidebysig static bool CompareVirtual<T>(class Source`1<!!T> s,
!!T a,
!!T b) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: callvirt instance bool class Source`1<!!T>::op_LessThan(!0,
!0)
IL_0008: ret
}
.method public hidebysig static bool CompareDirect(class Source`1<int32> s,
int32 a,
int32 b) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: call instance bool class Source`1<int32>::op_GreaterThan(!0,
!0)
IL_0008: ret
}
.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
}
}

7
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1643,6 +1643,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1643,6 +1643,13 @@ namespace ICSharpCode.Decompiler.CSharp
if (or.IsAmbiguous)
return OverloadResolutionErrors.AmbiguousMatch;
foundMember = or.GetBestCandidateWithSubstitutedTypeArguments();
if (foundMember == null)
{
// Overload resolution reports no error for an empty candidate set - there is no
// best candidate to carry one - so a call that matched nothing has to be reported
// as unresolvable here.
return OverloadResolutionErrors.AmbiguousMatch;
}
if (!IsAppropriateCallTarget(expectedTargetDetails, method, foundMember))
return OverloadResolutionErrors.AmbiguousMatch;
var map = or.GetArgumentToParameterMap();

Loading…
Cancel
Save