diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 0adc49150..f04ba50a8 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
return new TypeOfExpression(ConvertType(inst.Type))
.WithILInstruction(inst)
- .WithRR(new TypeOfResolveResult(compilation.FindType(KnownTypeCode.Type), inst.Type);
+ .WithRR(new TypeOfResolveResult(compilation.FindType(KnownTypeCode.Type), inst.Type));
}
protected internal override TranslatedExpression VisitLogicNot(LogicNot inst)
diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
index d5a9692ea..dde2acc1d 100644
--- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
@@ -88,6 +88,22 @@ namespace ICSharpCode.Decompiler.CSharp
return new GotoStatement(inst.TargetLabel);
}
+ /// Target container that a 'break;' statement would break out of
+ BlockContainer breakTarget;
+ /// Dictionary from BlockContainer to label name for 'goto of_container';
+ readonly Dictionary endContainerLabels = new Dictionary();
+
+ protected internal override Statement VisitLeave(Leave inst)
+ {
+ if (inst.TargetContainer == breakTarget)
+ return new BreakStatement();
+ string label;
+ if (!endContainerLabels.TryGetValue(inst.TargetContainer, out label)) {
+ endContainerLabels.Add(inst.TargetContainer, "end_" + inst.TargetLabel);
+ }
+ return new GotoStatement(label);
+ }
+
protected internal override Statement VisitThrow(Throw inst)
{
return new ThrowStatement(exprBuilder.Translate(inst.Argument));
@@ -163,8 +179,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (container.EntryPoint.IncomingEdgeCount > 1) {
var oldContinueTarget = continueTarget;
var oldContinueCount = continueCount;
+ var oldBreakTarget = breakTarget;
continueTarget = container.EntryPoint;
continueCount = 0;
+ breakTarget = container;
var blockStatement = ConvertBlockContainer(container);
Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount);
Debug.Assert(blockStatement.Statements.First() is LabelStatement);
@@ -174,6 +192,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
continueTarget = oldContinueTarget;
continueCount = oldContinueCount;
+ breakTarget = oldBreakTarget;
return new WhileStatement(new PrimitiveExpression(true), blockStatement);
} else {
return ConvertBlockContainer(container);
@@ -195,6 +214,10 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Add(Convert(block.FinalInstruction));
}
}
+ string label;
+ if (endContainerLabels.TryGetValue(container, out label)) {
+ blockStatement.Add(new LabelStatement { Label = label });
+ }
return blockStatement;
}
}
diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
index 03edd5863..626c62c58 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
@@ -51,8 +51,9 @@ namespace ICSharpCode.Decompiler.IL
///
///
///
- /// Fun fact: the empty block acts like a phase-2 pop instruction,
- /// which is a slightly different behavior than the normal phase-1 instruction!
+ /// Fun fact: wrapping a pop instruction in a block
+ /// (new Block { FinalInstruction = popInst }) turns it
+ /// from a phase-1 pop instruction to a phase-2 pop instruction.
/// However, this is just of theoretical interest; we currently don't plan to use inline blocks that
/// pop elements that they didn't push themselves.
///