Browse Source

Fix bug in AwaitInFinallyTransform

pull/1087/head
Siegfried Pammer 8 years ago
parent
commit
96ddabed57
  1. 28
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs
  2. 37
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

28
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs

@ -43,6 +43,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -43,6 +43,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
await AwaitCatch(Task.FromResult(1));
await AwaitMultipleCatchBlocks(Task.FromResult(1));
await AwaitMultipleCatchBlocks2(Task.FromResult(1));
Console.WriteLine(await AwaitInComplexFinally());
try {
await AwaitFinally(Task.FromResult(2));
} catch (Exception ex) {
@ -219,6 +220,33 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -219,6 +220,33 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("End Method");
}
public static async Task<int> AwaitInComplexFinally()
{
Console.WriteLine("a");
try {
Console.WriteLine("b");
await Task.Delay(1);
Console.WriteLine("c");
} catch (Exception ex) {
await Task.Delay(ex.HResult);
} finally {
Console.WriteLine("d");
int i = 0;
if (Console.CapsLock) {
i++;
await Task.Delay(i);
} else {
while (i < 5) {
Console.WriteLine("i: " + i);
i++;
}
}
Console.WriteLine("e");
}
Console.WriteLine("f");
return 1;
}
public async Task AwaitInCatchAndFinally(Task<int> task1, Task<int> task2, Task<int> task3)
{
try {

37
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

@ -231,24 +231,37 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -231,24 +231,37 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
continue;
if (globalCopyVarSplitted.StoreCount != 1 || globalCopyVarSplitted.LoadCount != 0)
continue;
context.Step("Inline finally block with await", tryCatch.Handlers[0]);
var cfg = new ControlFlowGraph(container, context.CancellationToken);
var exitOfFinallyNode = cfg.GetNode(exitOfFinally);
var entryPointOfFinallyNode = cfg.GetNode(entryPointOfFinally);
var nodes = new Stack<ControlFlowNode>(new[] { entryPointOfFinallyNode });
var blocksInFinally = new HashSet<Block>();
var additionalBlocksInFinally = new HashSet<Block>();
var invalidExits = new List<ControlFlowNode>();
while (nodes.Count > 0) {
var currentNode = nodes.Pop();
if (currentNode != exitOfFinallyNode) {
foreach (var successor in currentNode.Successors)
nodes.Push(successor);
if (entryPointOfFinallyNode.Dominates(currentNode))
blocksInFinally.Add((Block)currentNode.UserData);
TraverseDominatorTree(entryPointOfFinallyNode);
void TraverseDominatorTree(ControlFlowNode node)
{
if (entryPointOfFinallyNode != node) {
if (entryPointOfFinallyNode.Dominates(node))
additionalBlocksInFinally.Add((Block)node.UserData);
else
invalidExits.Add(currentNode);
invalidExits.Add(node);
}
if (node == exitOfFinallyNode)
return;
foreach (var child in node.DominatorTreeChildren) {
TraverseDominatorTree(child);
}
}
if (invalidExits.Any())
continue;
context.Step("Inline finally block with await", tryCatch.Handlers[0]);
foreach (var blockToRemove in blocksToRemove) {
blockToRemove.Remove();
}
@ -264,7 +277,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -264,7 +277,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (branchToFinally.TargetBlock == entryPointOfFinally)
branchToFinally.ReplaceWith(new Branch(afterFinally));
}
foreach (var newBlock in blocksInFinally) {
foreach (var newBlock in additionalBlocksInFinally) {
newBlock.Remove();
finallyContainer.Blocks.Add(newBlock);
}

Loading…
Cancel
Save