Browse Source

[async] Fix bug when async method uses this pointer.

pull/850/head
Daniel Grunwald 8 years ago
parent
commit
e024641a5f
  1. 4
      ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  3. 31
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

4
ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs

@ -42,9 +42,9 @@ namespace ICSharpCode.Decompiler.Tests @@ -42,9 +42,9 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void NewtonsoftJson_net40()
public void NewtonsoftJson_net45()
{
RunWithTest("Newtonsoft.Json-net40", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll");
RunWithTest("Newtonsoft.Json-net45", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll");
}
[Test]

2
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -361,7 +361,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -361,7 +361,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (v.Type.Kind == TypeKind.ByReference) {
expectedExpr = new DirectionExpression(FieldDirection.Ref, expectedExpr);
}
if (assignment != null && assignment.Left.IsMatch(expectedExpr)) {
if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign && assignment.Left.IsMatch(expectedExpr)) {
AstType type;
if (v.Type.ContainsAnonymousType()) {
type = new SimpleType("var");

31
ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
IField stateField;
int initialState;
Dictionary<IField, ILVariable> fieldToParameterMap = new Dictionary<IField, ILVariable>();
Dictionary<ILVariable, ILVariable> cachedFieldToParameterMap = new Dictionary<ILVariable, ILVariable>();
// These fields are set by AnalyzeMoveNext():
ILFunction moveNextFunction;
@ -70,6 +71,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -70,6 +71,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return; // abort if async/await decompilation is disabled
this.context = context;
fieldToParameterMap.Clear();
cachedFieldToParameterMap.Clear();
awaitBlocks.Clear();
if (!MatchTaskCreationPattern(function))
return;
@ -90,6 +92,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -90,6 +92,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
context.Step("Translate fields to local accesses", function);
MarkGeneratedVariables(function);
YieldReturnDecompiler.TranslateFieldsToLocalAccess(function, function, fieldToParameterMap);
TranslateCachedFieldsToLocals();
FinalizeInlineMoveNext(function);
@ -309,7 +312,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -309,7 +312,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
throw new SymbolicAnalysisFailedException();
++pos;
}
while (blockContainer.EntryPoint.Instructions[pos] is StLoc stloc) {
// stloc V_1(ldfld <>4__this(ldloc this))
if (!stloc.Variable.IsSingleDefinition)
throw new SymbolicAnalysisFailedException();
if (!stloc.Value.MatchLdFld(out var target, out var field))
throw new SymbolicAnalysisFailedException();
if (!target.MatchLdThis())
throw new SymbolicAnalysisFailedException();
if (!fieldToParameterMap.TryGetValue((IField)field.MemberDefinition, out var param))
throw new SymbolicAnalysisFailedException();
cachedFieldToParameterMap[stloc.Variable] = param;
pos++;
}
mainTryCatch = blockContainer.EntryPoint.Instructions[pos] as TryCatch;
if (mainTryCatch == null)
throw new SymbolicAnalysisFailedException();
// CatchHandler will be validated in ValidateCatchBlock()
if (((BlockContainer)mainTryCatch.TryBlock).EntryPoint.Instructions[0] is StLoc initDoFinallyBodies
@ -861,5 +879,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -861,5 +879,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
return entryPoint;
}
void TranslateCachedFieldsToLocals()
{
foreach (var (cachedVar, param) in cachedFieldToParameterMap) {
Debug.Assert(cachedVar.StoreCount <= 1);
foreach (var inst in cachedVar.LoadInstructions.ToArray()) {
inst.Variable = param;
}
foreach (var inst in cachedVar.AddressInstructions.ToArray()) {
inst.Variable = param;
}
}
}
}
}

Loading…
Cancel
Save