Skip to content

Commit

Permalink
Fix #2763: Improve decompilation of switch-on-enum by preserving enum…
Browse files Browse the repository at this point in the history
… type information when inlining local variables into SwitchInstruction.Value.
  • Loading branch information
siegfriedpammer committed Sep 16, 2022
1 parent 73144e4 commit a3191f1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 1 deletion.
35 changes: 35 additions & 0 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ public enum State
Null
}

public enum KnownColor
{
DarkBlue,
DarkCyan,
DarkGoldenrod,
DarkGray,
DarkGreen,
DarkKhaki
}

private static char ch1767;

#if !ROSLYN
Expand Down Expand Up @@ -1474,5 +1484,30 @@ public static void Issue1767(string s)
break;
}
}

public static void Issue2763(int value)
{
switch ((KnownColor)value)
{
case KnownColor.DarkBlue:
Console.WriteLine("DarkBlue");
break;
case KnownColor.DarkCyan:
Console.WriteLine("DarkCyan");
break;
case KnownColor.DarkGoldenrod:
Console.WriteLine("DarkGoldenrod");
break;
case KnownColor.DarkGray:
Console.WriteLine("DarkGray");
break;
case KnownColor.DarkGreen:
Console.WriteLine("DarkGreen");
break;
case KnownColor.DarkKhaki:
Console.WriteLine("DarkKhaki");
break;
}
}
}
}
4 changes: 4 additions & 0 deletions ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3819,6 +3819,10 @@ protected internal override TranslatedExpression VisitSwitchInstruction(SwitchIn
{
strToInt = null;
value = Translate(inst.Value);
if (inst.Type != null)
{
value = value.ConvertTo(inst.Type, this, allowImplicitConversion: true);
}
type = value.Type;
}

Expand Down
4 changes: 4 additions & 0 deletions ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ SwitchStatement TranslateSwitch(BlockContainer switchContainer, SwitchInstructio
{
strToInt = null;
value = exprBuilder.Translate(inst.Value);
if (inst.Type != null)
{
value = value.ConvertTo(inst.Type, exprBuilder, allowImplicitConversion: true);
}
type = value.Type;
}

Expand Down
11 changes: 10 additions & 1 deletion ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using System.Diagnostics;
using System.Linq;

using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;

namespace ICSharpCode.Decompiler.IL
Expand All @@ -42,6 +43,12 @@ partial class SwitchInstruction
/// </summary>
public bool IsLifted;

/// <summary>
/// Additional type information used to interpret the value instruction.
/// Set by ILInlining to preserve stack information that would otherwise be lost.
/// </summary>
public IType? Type;

public SwitchInstruction(ILInstruction value)
: base(OpCode.SwitchInstruction)
{
Expand Down Expand Up @@ -82,7 +89,9 @@ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
output.Write("switch");
if (IsLifted)
output.Write(".lifted");
output.Write(" (");
output.Write(' ');
Type?.WriteTo(output);
output.Write('(');
value.WriteTo(output, options);
output.Write(") ");
output.MarkFoldStart("{...}");
Expand Down
6 changes: 6 additions & 0 deletions ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,12 @@ static bool NonAggressiveInlineInto(ILInstruction next, FindResult findResult, I
case OpCode.YieldReturn:
return true;
case OpCode.SwitchInstruction:
// Preserve type info on switch instruction, if we're inlining a local variable into the switch-value slot.
if (v.Kind != VariableKind.StackSlot && loadInst.SlotInfo == SwitchInstruction.ValueSlot)
{
((SwitchInstruction)parent).Type ??= v.Type;
}
return true;
//case OpCode.BinaryNumericInstruction when parent.SlotInfo == SwitchInstruction.ValueSlot:
case OpCode.StringToInt when parent.SlotInfo == SwitchInstruction.ValueSlot:
return true;
Expand Down

0 comments on commit a3191f1

Please sign in to comment.