Browse Source

Fix #2741: CallBuilder produces invalid invocation target when disambiguating calls to protected methods.

pull/2747/head
Siegfried Pammer 3 years ago
parent
commit
fbafc0289b
  1. 59
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  2. 20
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

59
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -37,6 +37,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -37,6 +37,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
CallAmbiguousOutParam();
CallWithInParam();
Issue2444.M2();
Issue2741.B.Test(new Issue2741.C());
}
#region ConstructorTest
@ -366,6 +367,64 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -366,6 +367,64 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("#2444: after M1");
}
}
public class Issue2741
{
public class B
{
private void M()
{
Console.WriteLine("B::M");
}
protected void M2()
{
Console.WriteLine("B::M2");
}
protected void M3()
{
Console.WriteLine("B::M3");
}
protected void M4()
{
Console.WriteLine("B::M4");
}
public static void Test(C c)
{
((B)c).M();
((B)c).M2();
c.Test();
}
}
public class C : B
{
public void M()
{
Console.WriteLine("C::M");
}
public new void M2()
{
Console.WriteLine("C::M2");
}
public new void M3()
{
Console.WriteLine("C::M3");
}
public void Test()
{
M3();
base.M3();
M4();
}
}
}
#endregion
}

20
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -917,7 +917,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -917,7 +917,7 @@ namespace ICSharpCode.Decompiler.CSharp
else if (target.Expression is BaseReferenceExpression)
requireTarget = (expectedTargetDetails.CallOpCode != OpCode.CallVirt && method.IsVirtual);
else
requireTarget = !(target.Expression is ThisReferenceExpression);
requireTarget = target.Expression is not ThisReferenceExpression;
}
targetResolveResult = requireTarget ? target.ResolveResult : null;
}
@ -962,6 +962,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -962,6 +962,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool targetCasted = false;
bool argumentsCasted = false;
bool originalRequireTarget = requireTarget;
bool skipTargetCast = method.Accessibility <= Accessibility.Protected && expressionBuilder.IsBaseTypeOfCurrentType(method.DeclaringTypeDefinition);
OverloadResolutionErrors errors;
while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments,
argumentList.GetArgumentResolveResults().ToArray(), argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod,
@ -1015,9 +1017,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1015,9 +1017,19 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !targetCasted)
{
targetCasted = true;
target = target.ConvertTo(method.DeclaringType, expressionBuilder);
targetResolveResult = target.ResolveResult;
if (skipTargetCast && requireTarget != originalRequireTarget)
{
requireTarget = originalRequireTarget;
if (!originalRequireTarget)
targetResolveResult = null;
allowedTransforms &= ~CallTransformation.RequireTarget;
}
else
{
targetCasted = true;
target = target.ConvertTo(method.DeclaringType, expressionBuilder);
targetResolveResult = target.ResolveResult;
}
}
else if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0 && !requireTypeArguments)
{

5
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2272,6 +2272,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2272,6 +2272,11 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
internal bool IsBaseTypeOfCurrentType(ITypeDefinition type)
{
return decompilationContext.CurrentTypeDefinition.GetAllBaseTypeDefinitions().Any(t => t == type);
}
internal ExpressionWithResolveResult TranslateFunction(IType delegateType, ILFunction function)
{
var method = function.Method?.MemberDefinition as IMethod;

Loading…
Cancel
Save