Browse Source

Fix #1621: Add AllowUnreachableCases in switch analysis.

pull/1649/head
Siegfried Pammer 6 years ago
parent
commit
def681ccdf
  1. 23
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  2. 12
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs
  3. 2
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

23
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs

@ -1145,5 +1145,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
Console.WriteLine(); Console.WriteLine();
} }
public static string Issue1621(int x)
{
if (x == 5) {
return "5";
}
switch (x) {
case 1:
return "1";
case 2:
case 6:
case 7:
return "2-6-7";
case 3:
return "3";
case 4:
return "4";
case 5:
return "unreachable";
default:
throw new Exception();
}
}
} }
} }

12
ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs

@ -28,10 +28,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary> /// <summary>
/// The variable to be used as the argument of the switch instruction. /// The variable to be used as the argument of the switch instruction.
/// </summary> /// </summary>
public ILVariable SwitchVariable public ILVariable SwitchVariable => switchVar;
{
get { return switchVar; }
}
/// <summary> /// <summary>
/// Whether at least one the analyzed blocks contained an IL switch constructors. /// Whether at least one the analyzed blocks contained an IL switch constructors.
@ -62,6 +59,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
public Block RootBlock { get; private set; } public Block RootBlock { get; private set; }
/// <summary>
/// Gets/sets whether to allow unreachable cases in switch instructions.
/// </summary>
public bool AllowUnreachableCases { get; set; }
/// <summary> /// <summary>
/// Analyze the last two statements in the block and see if they can be turned into a /// Analyze the last two statements in the block and see if they can be turned into a
/// switch instruction. /// switch instruction.
@ -180,6 +182,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} }
foreach (var section in inst.Sections) { foreach (var section in inst.Sections) {
var matchValues = section.Labels.AddOffset(offset).IntersectWith(inputValues); var matchValues = section.Labels.AddOffset(offset).IntersectWith(inputValues);
if (!AllowUnreachableCases && matchValues.IsEmpty)
return false;
if (matchValues.Count() > 1 && section.Body.MatchBranch(out var targetBlock) && AnalyzeBlock(targetBlock, matchValues)) { if (matchValues.Count() > 1 && section.Body.MatchBranch(out var targetBlock) && AnalyzeBlock(targetBlock, matchValues)) {
InnerBlocks.Add(targetBlock); InnerBlocks.Add(targetBlock);
} else { } else {

2
ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

@ -132,6 +132,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{ {
this.context = context; this.context = context;
analysis.AllowUnreachableCases = context.Settings.RemoveDeadCode;
foreach (var container in function.Descendants.OfType<BlockContainer>()) { foreach (var container in function.Descendants.OfType<BlockContainer>()) {
currentContainer = container; currentContainer = container;
controlFlowGraph = null; controlFlowGraph = null;

Loading…
Cancel
Save