Browse Source

#1456: add test case; add additional checks to ensure we only transform normal locals into using/foreach-locals

pull/1612/head
Daniel Grunwald 6 years ago
parent
commit
856cedc95e
  1. 11
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 3
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  4. 1
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  5. 10
      ICSharpCode.Decompiler/IL/ILVariable.cs
  6. 2
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

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

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
#pragma warning disable 1998
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@ -126,6 +127,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -126,6 +127,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
#endif
public static async Task<int> GetIntegerSumAsync(IEnumerable<int> items)
{
await Task.Delay(100);
int num = 0;
foreach (int item in items) {
num += item;
}
return num;
}
}
public struct HopToThreadPoolAwaitable : INotifyCompletion

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// * Otherwise, the C# type of the resulting expression shall match the IL stack type,
/// and the evaluated values shall be the same.
/// </remarks>
class ExpressionBuilder : ILVisitor<TranslationContext, TranslatedExpression>
sealed class ExpressionBuilder : ILVisitor<TranslationContext, TranslatedExpression>
{
readonly IDecompilerTypeSystem typeSystem;
internal readonly ITypeResolveContext decompilationContext;

3
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -32,7 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Resolver; @@ -32,7 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Resolver;
namespace ICSharpCode.Decompiler.CSharp
{
class StatementBuilder : ILVisitor<Statement>
sealed class StatementBuilder : ILVisitor<Statement>
{
internal readonly ExpressionBuilder exprBuilder;
readonly ILFunction currentFunction;
@ -412,6 +412,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -412,6 +412,7 @@ namespace ICSharpCode.Decompiler.CSharp
AstNode usingInit = resource;
var var = inst.Variable;
if (!inst.ResourceExpression.MatchLdNull() && !NullableType.GetUnderlyingType(var.Type).GetAllBaseTypes().Any(b => b.IsKnownType(KnownTypeCode.IDisposable))) {
Debug.Assert(var.Kind == VariableKind.UsingLocal);
var.Kind = VariableKind.Local;
var disposeType = exprBuilder.compilation.FindType(KnownTypeCode.IDisposable);
var disposeVariable = currentFunction.RegisterVariable(

1
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -467,6 +467,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -467,6 +467,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
statementsToDelete.Add(stmt.GetNextStatement());
var itemVariable = foreachVariable.GetILVariable();
if (itemVariable == null || !itemVariable.IsSingleDefinition
|| (itemVariable.Kind != IL.VariableKind.Local && itemVariable.Kind != IL.VariableKind.StackSlot)
|| !upperBounds.All(ub => ub.IsSingleDefinition && ub.LoadCount == 1)
|| !lowerBounds.All(lb => lb.StoreCount == 2 && lb.LoadCount == 3 && lb.AddressCount == 0))
return null;

10
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -107,8 +107,12 @@ namespace ICSharpCode.Decompiler.IL @@ -107,8 +107,12 @@ namespace ICSharpCode.Decompiler.IL
internal set {
if (kind == VariableKind.Parameter)
throw new InvalidOperationException("Kind=Parameter cannot be changed!");
if (Index != null && value.IsLocal())
Debug.Assert(kind.IsLocal());
if (Index != null && value.IsLocal() && !kind.IsLocal()) {
// For variables, Index has different meaning than for stack slots,
// so we need to reset it to null.
// StackSlot -> ForeachLocal can happen sometimes (e.g. PST.TransformForeachOnArray)
Index = null;
}
kind = value;
}
}
@ -138,7 +142,7 @@ namespace ICSharpCode.Decompiler.IL @@ -138,7 +142,7 @@ namespace ICSharpCode.Decompiler.IL
/// For ExceptionStackSlot, the index is the IL offset of the exception handler.
/// For other kinds, the index has no meaning, and is usually null.
/// </summary>
public readonly int? Index;
public int? Index { get; private set; }
[Conditional("DEBUG")]
internal void CheckInvariant()

2
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -127,6 +127,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -127,6 +127,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!(storeInst.Value.MatchLdNull() || CheckResourceType(storeInst.Variable.Type)))
return false;
if (storeInst.Variable.Kind != VariableKind.Local)
return false;
if (storeInst.Variable.LoadInstructions.Any(ld => !ld.IsDescendantOf(tryFinally)))
return false;
if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(tryFinally) || (la.IsDescendantOf(tryFinally.TryBlock) && !ILInlining.IsUsedAsThisPointerInCall(la))))

Loading…
Cancel
Save