Browse Source

Merge pull request #4075 from icsharpcode/fix/3704-ldlen-infertype

Infer the C# type of ldlen
pull/4085/head
Siegfried Pammer 2 weeks ago committed by GitHub
parent
commit
19e702cc70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 60
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  2. 11
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs
  3. 6
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  4. 6
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

60
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs

@ -23,13 +23,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -23,13 +23,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
private class CtorTarget
{
public CtorTarget(dynamic d, int i)
{
}
}
private struct MyValueType
{
private readonly dynamic _getOnlyProperty;
@ -384,57 +377,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -384,57 +377,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
private static dynamic M5(dynamic d, int i)
{
return null;
}
private static void M6<T>(dynamic d, int i)
{
}
#if CS60
// #3704: the call target of a dynamic member access on a static type is typeof(DynamicTests).
// The array is loaded into a temporary that survives as its own statement, which strands the
// typeof between the two, so it cannot reach the call site by ordinary inlining.
private static void StaticTargetBehindSurvivingTemporary(dynamic d)
{
#if EXPECTED_OUTPUT
byte[] data = GetData();
DynamicTests.M4(d, (data != null) ? data.Length : 0);
#else
DynamicTests.M4(d, GetData()?.Length ?? 0);
#endif
}
private static dynamic StaticTargetResultUsed(dynamic d)
{
#if EXPECTED_OUTPUT
byte[] data = GetData();
return DynamicTests.M5(d, (data != null) ? data.Length : 0);
#else
return DynamicTests.M5(d, GetData()?.Length ?? 0);
#endif
}
private static void StaticTargetWithTypeArguments(dynamic d)
// #3704: the call target of a dynamic member access on a static type is
// typeof(DynamicTests), which has to reach the call site.
private static void StaticTargetOnDynamicCall(dynamic d)
{
#if EXPECTED_OUTPUT
byte[] data = GetData();
DynamicTests.M6<int>(d, (data != null) ? data.Length : 0);
#else
DynamicTests.M6<int>(d, GetData()?.Length ?? 0);
#endif
}
private static void StaticCtorBehindSurvivingTemporary(dynamic d)
{
#if EXPECTED_OUTPUT
byte[] data = GetData();
new CtorTarget(d, (data != null) ? data.Length : 0);
#else
new CtorTarget(d, GetData()?.Length ?? 0);
#endif
DynamicTests.M4(d, GetData()?.Length ?? 0);
}
#endif

11
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs

@ -320,6 +320,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -320,6 +320,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null);
}
private static byte[] GetBytes()
{
return null;
}
private static void ArrayLengthWithFallback()
{
Console.WriteLine(GetBytes()?.Length ?? 0);
Console.WriteLine(GetBytes()?.LongLength ?? 0);
}
private static dynamic DynamicNullProp(dynamic a)
{
return a?.b.c(1)?.d[10];

6
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -4601,10 +4601,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4601,10 +4601,10 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicInvokeMemberInstruction(DynamicInvokeMemberInstruction inst, TranslationContext context)
{
Expression targetExpr;
var target = inst.StaticTargetType is IType staticTargetType
? new TypeReferenceExpression(ConvertType(staticTargetType))
var target = inst.StaticTargetType != null
? new TypeReferenceExpression(ConvertType(inst.StaticTargetType))
.WithoutILInstruction()
.WithRR(new TypeResolveResult(staticTargetType))
.WithRR(new TypeResolveResult(inst.StaticTargetType))
: TranslateDynamicTarget(inst.Arguments[0], inst.ArgumentInfo[0]);
if (inst.BinderFlags.HasFlag(CSharpBinderFlags.InvokeSimpleName) && target.Expression is ThisReferenceExpression)
{

6
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -287,6 +287,12 @@ namespace ICSharpCode.Decompiler.IL @@ -287,6 +287,12 @@ namespace ICSharpCode.Decompiler.IL
default:
return SpecialType.UnknownType;
}
case LdLen ldLen:
if (compilation == null)
return SpecialType.UnknownType;
// Mirrors ExpressionBuilder.VisitLdLen, which picks Array.Length or
// Array.LongLength based on the result type alone.
return compilation.FindType(ldLen.ResultType == StackType.I4 ? KnownTypeCode.Int32 : KnownTypeCode.Int64);
case DefaultValue defaultValue:
return defaultValue.Type;
case ILFunction func when func.DelegateType != null:

Loading…
Cancel
Save