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
} }
} }
private class CtorTarget
{
public CtorTarget(dynamic d, int i)
{
}
}
private struct MyValueType private struct MyValueType
{ {
private readonly dynamic _getOnlyProperty; private readonly dynamic _getOnlyProperty;
@ -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 #if CS60
// #3704: the call target of a dynamic member access on a static type is typeof(DynamicTests). // #3704: the call target of a dynamic member access on a static type is
// The array is loaded into a temporary that survives as its own statement, which strands the // typeof(DynamicTests), which has to reach the call site.
// typeof between the two, so it cannot reach the call site by ordinary inlining. private static void StaticTargetOnDynamicCall(dynamic d)
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)
{ {
#if EXPECTED_OUTPUT DynamicTests.M4(d, GetData()?.Length ?? 0);
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
} }
#endif #endif

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

@ -320,6 +320,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null); 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) private static dynamic DynamicNullProp(dynamic a)
{ {
return a?.b.c(1)?.d[10]; return a?.b.c(1)?.d[10];

6
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

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

6
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -287,6 +287,12 @@ namespace ICSharpCode.Decompiler.IL
default: default:
return SpecialType.UnknownType; 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: case DefaultValue defaultValue:
return defaultValue.Type; return defaultValue.Type;
case ILFunction func when func.DelegateType != null: case ILFunction func when func.DelegateType != null:

Loading…
Cancel
Save