Fix #1946: Don't move return into try block when doing so changes the semantics of a finally block.

This commit is contained in:
Daniel Grunwald committed 2020-04-20 20:12:45 +02:00
1 parent 2665d800d0
commit c1265ad830
2 files changed
+29 -2

No files matched your search

@@ -41,6 +41,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
BreakUnlessContinue(true);
BreakUnlessContinue(false);
TestConditionals();
Console.WriteLine("Issue1946:\n" + Issue1946());
return 0;
}
@@ -149,5 +150,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
byte answer = (byte)(value == 128 ? 255 : 0);
return answer;
}
static string Issue1946()
{
string obj = "1";
try {
obj = "2";
} catch {
obj = "3";
} finally {
obj = "4";
}
return obj;
}
}
}
@@ -197,9 +197,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
bool IsBranchToReturnBlock(Branch branch)
{
var targetBlock = branch.TargetBlock;
if (targetBlock.Instructions.Count != 1 || targetBlock.FinalInstruction.OpCode != OpCode.Nop)
if (targetBlock.Instructions.Count != 1)
return false;
return targetBlock.Instructions[0].MatchReturn(out var value) && value is LdLoc;
if (!targetBlock.Instructions[0].MatchReturn(out var value))
return false;
if (!targetBlock.MatchLdLoc(out var returnVar))
return false;
var container = branch.TargetContainer;
for (ILInstruction inst = branch; inst != container; inst = inst.Parent) {
if (inst.Parent is TryFinally tryFinally && inst.SlotInfo == TryFinally.TryBlockSlot) {
// The branch will trigger the finally block.
// Moving the return block into the try is only possible if the finally block doesn't touch the return variable.
if (returnVar.IsUsedWithin(tryFinally.FinallyBlock))
return false;
}
}
return true;
}
static bool CombineBlockWithNextBlock(BlockContainer container, Block block, ILTransformContext context)