diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs index 10ae53f5b..e5d95a565 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs @@ -306,6 +306,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty await Task.Yield(); } } + + public async Task Issue2366a() + { + while (true) + { + try + { + await Task.CompletedTask; + } + catch + { + } + } + } + + public async Task Issue2366b() + { + try + { + await Task.CompletedTask; + } + catch (NullReferenceException) + { + await Task.CompletedTask; + } + catch (InvalidOperationException) + { + await Task.CompletedTask; + } + catch (ArgumentException) + { + await Task.CompletedTask; + } + } #endif public static async Task GetIntegerSumAsync(IEnumerable items) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs index c46fbe74f..5ac50c1c1 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs @@ -66,6 +66,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var cfg = new ControlFlowGraph(container, context.CancellationToken); if (transformableCatchBlocks.Count > 0) changedContainers.Add(container); + SwitchInstruction switchInstructionOpt = null; foreach (var result in transformableCatchBlocks) { removedBlocks.Clear(); @@ -74,28 +75,34 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.StepStartGroup($"Inline catch block with await (at {result.Handler.Variable.Name})", result.Handler); // Remove the IfInstruction from the jump table and eliminate all branches to the block. - if (result.JumpTableEntry is IfInstruction jumpTableEntry) + switch (result.JumpTableEntry) { - var jumpTableBlock = (Block)jumpTableEntry.Parent; - context.Step("Remove jump-table entry", result.JumpTableEntry); - jumpTableBlock.Instructions.RemoveAt(result.JumpTableEntry.ChildIndex); + case IfInstruction jumpTableEntry: + var jumpTableBlock = (Block)jumpTableEntry.Parent; + context.Step("Remove jump-table entry", result.JumpTableEntry); + jumpTableBlock.Instructions.RemoveAt(result.JumpTableEntry.ChildIndex); - foreach (var branch in tryCatch.Descendants.OfType()) - { - if (branch.TargetBlock == jumpTableBlock) + foreach (var branch in tryCatch.Descendants.OfType()) { - if (result.NextBlockOrExitContainer is BlockContainer exitContainer) - { - context.Step("branch jumpTableBlock => leave exitContainer", branch); - branch.ReplaceWith(new Leave(exitContainer)); - } - else + if (branch.TargetBlock == jumpTableBlock) { - context.Step("branch jumpTableBlock => branch nextBlock", branch); - branch.ReplaceWith(new Branch((Block)result.NextBlockOrExitContainer)); + if (result.NextBlockOrExitContainer is BlockContainer exitContainer) + { + context.Step("branch jumpTableBlock => leave exitContainer", branch); + branch.ReplaceWith(new Leave(exitContainer)); + } + else + { + context.Step("branch jumpTableBlock => branch nextBlock", branch); + branch.ReplaceWith(new Branch((Block)result.NextBlockOrExitContainer)); + } } } - } + break; + case SwitchSection jumpTableEntry: + Debug.Assert(switchInstructionOpt == null || jumpTableEntry.Parent == switchInstructionOpt); + switchInstructionOpt = (SwitchInstruction)jumpTableEntry.Parent; + break; } // Add the real catch block entry-point to the block container @@ -170,6 +177,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.StepEndGroup(keepIfEmpty: true); } + + if (switchInstructionOpt != null && switchInstructionOpt.Parent is Block b && b.IncomingEdgeCount > 0) + { + var defaultSection = switchInstructionOpt.GetDefaultSection(); + + foreach (var branch in container.Descendants.OfType()) + { + if (branch.TargetBlock != b) + continue; + branch.ReplaceWith(defaultSection.Body.Clone()); + } + } } // clean up all modified containers @@ -275,6 +294,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!catchBlock.Instructions.Last().MatchBranch(out var jumpTableStartBlock)) return false; var identifierVariableAssignment = catchBlock.Instructions.SecondToLastOrDefault(); + if (identifierVariableAssignment == null) + return false; if (!identifierVariableAssignment.MatchStLoc(out identifierVariable, out value) || !value.MatchLdcI4(out id)) return false; // analyze jump table: