diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index d9a0b27f2..aaa97af62 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -608,6 +608,65 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(); } + + public static bool SwitchlikeIf(int i, int j) + { + if (i != 0 && j != 0) { + if (i == -1 && j == -1) { + Console.WriteLine("-1, -1"); + } + if (i == -1 && j == 1) { + Console.WriteLine("-1, 1"); + } + if (i == 1 && j == -1) { + Console.WriteLine("1, -1"); + } + if (i == 1 && j == 1) { + Console.WriteLine("1, 1"); + } + return false; + } + + if (i != 0) { + if (i == -1) { + Console.WriteLine("-1, 0"); + } + if (i == 1) { + Console.WriteLine("1, 0"); + } + return false; + } + + if (j != 0) { + if (j == -1) { + Console.WriteLine("0, -1"); + } + if (j == 1) { + Console.WriteLine("0, 1"); + } + return false; + } + + return true; + } + + public static bool SwitchlikeIf2(int i) + { + if (i != 0) { + // note that using else-if in this chain creates a nice-looking switch here (as expected) + if (i == 1) { + Console.WriteLine(1); + } + if (i == 2) { + Console.WriteLine(2); + } + if (i == 3) { + Console.WriteLine(3); + } + return false; + } + return false; + } #endregion // Ensure correctness of SwitchDetection.FindBreakTarget diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il index d99f3a787..7321936f5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il @@ -2196,6 +2196,278 @@ IL_00a8: ret } // end of method Switch::IfChainWithCondition + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 280 (0x118) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brfalse.s IL_000a + + IL_0004: ldarg.1 + IL_0005: ldc.i4.0 + IL_0006: ceq + IL_0008: br.s IL_000b + + IL_000a: ldc.i4.1 + IL_000b: nop + IL_000c: stloc.1 + IL_000d: ldloc.1 + IL_000e: brtrue IL_0098 + + IL_0013: nop + IL_0014: ldarg.0 + IL_0015: ldc.i4.m1 + IL_0016: bne.un.s IL_0021 + + IL_0018: ldarg.1 + IL_0019: ldc.i4.m1 + IL_001a: ceq + IL_001c: ldc.i4.0 + IL_001d: ceq + IL_001f: br.s IL_0022 + + IL_0021: ldc.i4.1 + IL_0022: nop + IL_0023: stloc.1 + IL_0024: ldloc.1 + IL_0025: brtrue.s IL_0034 + + IL_0027: nop + IL_0028: ldstr "-1, -1" + IL_002d: call void [mscorlib]System.Console::WriteLine(string) + IL_0032: nop + IL_0033: nop + IL_0034: ldarg.0 + IL_0035: ldc.i4.m1 + IL_0036: bne.un.s IL_0041 + + IL_0038: ldarg.1 + IL_0039: ldc.i4.1 + IL_003a: ceq + IL_003c: ldc.i4.0 + IL_003d: ceq + IL_003f: br.s IL_0042 + + IL_0041: ldc.i4.1 + IL_0042: nop + IL_0043: stloc.1 + IL_0044: ldloc.1 + IL_0045: brtrue.s IL_0054 + + IL_0047: nop + IL_0048: ldstr "-1, 1" + IL_004d: call void [mscorlib]System.Console::WriteLine(string) + IL_0052: nop + IL_0053: nop + IL_0054: ldarg.0 + IL_0055: ldc.i4.1 + IL_0056: bne.un.s IL_0061 + + IL_0058: ldarg.1 + IL_0059: ldc.i4.m1 + IL_005a: ceq + IL_005c: ldc.i4.0 + IL_005d: ceq + IL_005f: br.s IL_0062 + + IL_0061: ldc.i4.1 + IL_0062: nop + IL_0063: stloc.1 + IL_0064: ldloc.1 + IL_0065: brtrue.s IL_0074 + + IL_0067: nop + IL_0068: ldstr "1, -1" + IL_006d: call void [mscorlib]System.Console::WriteLine(string) + IL_0072: nop + IL_0073: nop + IL_0074: ldarg.0 + IL_0075: ldc.i4.1 + IL_0076: bne.un.s IL_0081 + + IL_0078: ldarg.1 + IL_0079: ldc.i4.1 + IL_007a: ceq + IL_007c: ldc.i4.0 + IL_007d: ceq + IL_007f: br.s IL_0082 + + IL_0081: ldc.i4.1 + IL_0082: nop + IL_0083: stloc.1 + IL_0084: ldloc.1 + IL_0085: brtrue.s IL_0094 + + IL_0087: nop + IL_0088: ldstr "1, 1" + IL_008d: call void [mscorlib]System.Console::WriteLine(string) + IL_0092: nop + IL_0093: nop + IL_0094: ldc.i4.0 + IL_0095: stloc.0 + IL_0096: br.s IL_0116 + + IL_0098: ldarg.0 + IL_0099: ldc.i4.0 + IL_009a: ceq + IL_009c: stloc.1 + IL_009d: ldloc.1 + IL_009e: brtrue.s IL_00d5 + + IL_00a0: nop + IL_00a1: ldarg.0 + IL_00a2: ldc.i4.m1 + IL_00a3: ceq + IL_00a5: ldc.i4.0 + IL_00a6: ceq + IL_00a8: stloc.1 + IL_00a9: ldloc.1 + IL_00aa: brtrue.s IL_00b9 + + IL_00ac: nop + IL_00ad: ldstr "-1, 0" + IL_00b2: call void [mscorlib]System.Console::WriteLine(string) + IL_00b7: nop + IL_00b8: nop + IL_00b9: ldarg.0 + IL_00ba: ldc.i4.1 + IL_00bb: ceq + IL_00bd: ldc.i4.0 + IL_00be: ceq + IL_00c0: stloc.1 + IL_00c1: ldloc.1 + IL_00c2: brtrue.s IL_00d1 + + IL_00c4: nop + IL_00c5: ldstr "1, 0" + IL_00ca: call void [mscorlib]System.Console::WriteLine(string) + IL_00cf: nop + IL_00d0: nop + IL_00d1: ldc.i4.0 + IL_00d2: stloc.0 + IL_00d3: br.s IL_0116 + + IL_00d5: ldarg.1 + IL_00d6: ldc.i4.0 + IL_00d7: ceq + IL_00d9: stloc.1 + IL_00da: ldloc.1 + IL_00db: brtrue.s IL_0112 + + IL_00dd: nop + IL_00de: ldarg.1 + IL_00df: ldc.i4.m1 + IL_00e0: ceq + IL_00e2: ldc.i4.0 + IL_00e3: ceq + IL_00e5: stloc.1 + IL_00e6: ldloc.1 + IL_00e7: brtrue.s IL_00f6 + + IL_00e9: nop + IL_00ea: ldstr "0, -1" + IL_00ef: call void [mscorlib]System.Console::WriteLine(string) + IL_00f4: nop + IL_00f5: nop + IL_00f6: ldarg.1 + IL_00f7: ldc.i4.1 + IL_00f8: ceq + IL_00fa: ldc.i4.0 + IL_00fb: ceq + IL_00fd: stloc.1 + IL_00fe: ldloc.1 + IL_00ff: brtrue.s IL_010e + + IL_0101: nop + IL_0102: ldstr "0, 1" + IL_0107: call void [mscorlib]System.Console::WriteLine(string) + IL_010c: nop + IL_010d: nop + IL_010e: ldc.i4.0 + IL_010f: stloc.0 + IL_0110: br.s IL_0116 + + IL_0112: ldc.i4.1 + IL_0113: stloc.0 + IL_0114: br.s IL_0116 + + IL_0116: ldloc.0 + IL_0117: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 80 (0x50) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: stloc.1 + IL_0006: ldloc.1 + IL_0007: brtrue.s IL_004a + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: ceq + IL_000e: ldc.i4.0 + IL_000f: ceq + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: brtrue.s IL_001e + + IL_0015: nop + IL_0016: ldc.i4.1 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: nop + IL_001d: nop + IL_001e: ldarg.0 + IL_001f: ldc.i4.2 + IL_0020: ceq + IL_0022: ldc.i4.0 + IL_0023: ceq + IL_0025: stloc.1 + IL_0026: ldloc.1 + IL_0027: brtrue.s IL_0032 + + IL_0029: nop + IL_002a: ldc.i4.2 + IL_002b: call void [mscorlib]System.Console::WriteLine(int32) + IL_0030: nop + IL_0031: nop + IL_0032: ldarg.0 + IL_0033: ldc.i4.3 + IL_0034: ceq + IL_0036: ldc.i4.0 + IL_0037: ceq + IL_0039: stloc.1 + IL_003a: ldloc.1 + IL_003b: brtrue.s IL_0046 + + IL_003d: nop + IL_003e: ldc.i4.3 + IL_003f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0044: nop + IL_0045: nop + IL_0046: ldc.i4.0 + IL_0047: stloc.0 + IL_0048: br.s IL_004e + + IL_004a: ldc.i4.0 + IL_004b: stloc.0 + IL_004c: br.s IL_004e + + IL_004e: ldloc.0 + IL_004f: ret + } // end of method Switch::SwitchlikeIf2 + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, bool b) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il index c944af68a..41c744b50 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il @@ -1818,6 +1818,132 @@ IL_0061: ret } // end of method Switch::IfChainWithCondition + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 148 (0x94) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0050 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0050 + + IL_0006: ldarg.0 + IL_0007: ldc.i4.m1 + IL_0008: bne.un.s IL_0018 + + IL_000a: ldarg.1 + IL_000b: ldc.i4.m1 + IL_000c: bne.un.s IL_0018 + + IL_000e: ldstr "-1, -1" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: ldarg.0 + IL_0019: ldc.i4.m1 + IL_001a: bne.un.s IL_002a + + IL_001c: ldarg.1 + IL_001d: ldc.i4.1 + IL_001e: bne.un.s IL_002a + + IL_0020: ldstr "-1, 1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: ldarg.0 + IL_002b: ldc.i4.1 + IL_002c: bne.un.s IL_003c + + IL_002e: ldarg.1 + IL_002f: ldc.i4.m1 + IL_0030: bne.un.s IL_003c + + IL_0032: ldstr "1, -1" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ldarg.0 + IL_003d: ldc.i4.1 + IL_003e: bne.un.s IL_004e + + IL_0040: ldarg.1 + IL_0041: ldc.i4.1 + IL_0042: bne.un.s IL_004e + + IL_0044: ldstr "1, 1" + IL_0049: call void [mscorlib]System.Console::WriteLine(string) + IL_004e: ldc.i4.0 + IL_004f: ret + + IL_0050: ldarg.0 + IL_0051: brfalse.s IL_0071 + + IL_0053: ldarg.0 + IL_0054: ldc.i4.m1 + IL_0055: bne.un.s IL_0061 + + IL_0057: ldstr "-1, 0" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldarg.0 + IL_0062: ldc.i4.1 + IL_0063: bne.un.s IL_006f + + IL_0065: ldstr "1, 0" + IL_006a: call void [mscorlib]System.Console::WriteLine(string) + IL_006f: ldc.i4.0 + IL_0070: ret + + IL_0071: ldarg.1 + IL_0072: brfalse.s IL_0092 + + IL_0074: ldarg.1 + IL_0075: ldc.i4.m1 + IL_0076: bne.un.s IL_0082 + + IL_0078: ldstr "0, -1" + IL_007d: call void [mscorlib]System.Console::WriteLine(string) + IL_0082: ldarg.1 + IL_0083: ldc.i4.1 + IL_0084: bne.un.s IL_0090 + + IL_0086: ldstr "0, 1" + IL_008b: call void [mscorlib]System.Console::WriteLine(string) + IL_0090: ldc.i4.0 + IL_0091: ret + + IL_0092: ldc.i4.1 + IL_0093: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 37 (0x25) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0023 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: bne.un.s IL_000d + + IL_0007: ldc.i4.1 + IL_0008: call void [mscorlib]System.Console::WriteLine(int32) + IL_000d: ldarg.0 + IL_000e: ldc.i4.2 + IL_000f: bne.un.s IL_0017 + + IL_0011: ldc.i4.2 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: ldarg.0 + IL_0018: ldc.i4.3 + IL_0019: bne.un.s IL_0021 + + IL_001b: ldc.i4.3 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: ldc.i4.0 + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + } // end of method Switch::SwitchlikeIf2 + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, bool b) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il index 5fb6e6fef..625a70267 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il @@ -1952,6 +1952,132 @@ IL_0061: ret } // end of method Switch::IfChainWithCondition + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 148 (0x94) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0050 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0050 + + IL_0006: ldarg.0 + IL_0007: ldc.i4.m1 + IL_0008: bne.un.s IL_0018 + + IL_000a: ldarg.1 + IL_000b: ldc.i4.m1 + IL_000c: bne.un.s IL_0018 + + IL_000e: ldstr "-1, -1" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: ldarg.0 + IL_0019: ldc.i4.m1 + IL_001a: bne.un.s IL_002a + + IL_001c: ldarg.1 + IL_001d: ldc.i4.1 + IL_001e: bne.un.s IL_002a + + IL_0020: ldstr "-1, 1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: ldarg.0 + IL_002b: ldc.i4.1 + IL_002c: bne.un.s IL_003c + + IL_002e: ldarg.1 + IL_002f: ldc.i4.m1 + IL_0030: bne.un.s IL_003c + + IL_0032: ldstr "1, -1" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ldarg.0 + IL_003d: ldc.i4.1 + IL_003e: bne.un.s IL_004e + + IL_0040: ldarg.1 + IL_0041: ldc.i4.1 + IL_0042: bne.un.s IL_004e + + IL_0044: ldstr "1, 1" + IL_0049: call void [mscorlib]System.Console::WriteLine(string) + IL_004e: ldc.i4.0 + IL_004f: ret + + IL_0050: ldarg.0 + IL_0051: brfalse.s IL_0071 + + IL_0053: ldarg.0 + IL_0054: ldc.i4.m1 + IL_0055: bne.un.s IL_0061 + + IL_0057: ldstr "-1, 0" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldarg.0 + IL_0062: ldc.i4.1 + IL_0063: bne.un.s IL_006f + + IL_0065: ldstr "1, 0" + IL_006a: call void [mscorlib]System.Console::WriteLine(string) + IL_006f: ldc.i4.0 + IL_0070: ret + + IL_0071: ldarg.1 + IL_0072: brfalse.s IL_0092 + + IL_0074: ldarg.1 + IL_0075: ldc.i4.m1 + IL_0076: bne.un.s IL_0082 + + IL_0078: ldstr "0, -1" + IL_007d: call void [mscorlib]System.Console::WriteLine(string) + IL_0082: ldarg.1 + IL_0083: ldc.i4.1 + IL_0084: bne.un.s IL_0090 + + IL_0086: ldstr "0, 1" + IL_008b: call void [mscorlib]System.Console::WriteLine(string) + IL_0090: ldc.i4.0 + IL_0091: ret + + IL_0092: ldc.i4.1 + IL_0093: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 37 (0x25) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0023 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: bne.un.s IL_000d + + IL_0007: ldc.i4.1 + IL_0008: call void [mscorlib]System.Console::WriteLine(int32) + IL_000d: ldarg.0 + IL_000e: ldc.i4.2 + IL_000f: bne.un.s IL_0017 + + IL_0011: ldc.i4.2 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: ldarg.0 + IL_0018: ldc.i4.3 + IL_0019: bne.un.s IL_0021 + + IL_001b: ldc.i4.3 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: ldc.i4.0 + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + } // end of method Switch::SwitchlikeIf2 + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, bool b) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il index 96cfd1e76..a64fee342 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il @@ -2492,6 +2492,264 @@ IL_0096: ret } // end of method Switch::IfChainWithCondition + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 270 (0x10e) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2, + bool V_3, + bool V_4, + bool V_5, + bool V_6, + bool V_7, + bool V_8, + bool V_9, + bool V_10, + bool V_11) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brfalse.s IL_000a + + IL_0004: ldarg.1 + IL_0005: ldc.i4.0 + IL_0006: cgt.un + IL_0008: br.s IL_000b + + IL_000a: ldc.i4.0 + IL_000b: stloc.0 + IL_000c: ldloc.0 + IL_000d: brfalse.s IL_008a + + IL_000f: nop + IL_0010: ldarg.0 + IL_0011: ldc.i4.m1 + IL_0012: bne.un.s IL_001a + + IL_0014: ldarg.1 + IL_0015: ldc.i4.m1 + IL_0016: ceq + IL_0018: br.s IL_001b + + IL_001a: ldc.i4.0 + IL_001b: stloc.1 + IL_001c: ldloc.1 + IL_001d: brfalse.s IL_002c + + IL_001f: nop + IL_0020: ldstr "-1, -1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: nop + IL_002b: nop + IL_002c: ldarg.0 + IL_002d: ldc.i4.m1 + IL_002e: bne.un.s IL_0036 + + IL_0030: ldarg.1 + IL_0031: ldc.i4.1 + IL_0032: ceq + IL_0034: br.s IL_0037 + + IL_0036: ldc.i4.0 + IL_0037: stloc.2 + IL_0038: ldloc.2 + IL_0039: brfalse.s IL_0048 + + IL_003b: nop + IL_003c: ldstr "-1, 1" + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: nop + IL_0047: nop + IL_0048: ldarg.0 + IL_0049: ldc.i4.1 + IL_004a: bne.un.s IL_0052 + + IL_004c: ldarg.1 + IL_004d: ldc.i4.m1 + IL_004e: ceq + IL_0050: br.s IL_0053 + + IL_0052: ldc.i4.0 + IL_0053: stloc.3 + IL_0054: ldloc.3 + IL_0055: brfalse.s IL_0064 + + IL_0057: nop + IL_0058: ldstr "1, -1" + IL_005d: call void [mscorlib]System.Console::WriteLine(string) + IL_0062: nop + IL_0063: nop + IL_0064: ldarg.0 + IL_0065: ldc.i4.1 + IL_0066: bne.un.s IL_006e + + IL_0068: ldarg.1 + IL_0069: ldc.i4.1 + IL_006a: ceq + IL_006c: br.s IL_006f + + IL_006e: ldc.i4.0 + IL_006f: stloc.s V_4 + IL_0071: ldloc.s V_4 + IL_0073: brfalse.s IL_0082 + + IL_0075: nop + IL_0076: ldstr "1, 1" + IL_007b: call void [mscorlib]System.Console::WriteLine(string) + IL_0080: nop + IL_0081: nop + IL_0082: ldc.i4.0 + IL_0083: stloc.s V_5 + IL_0085: br IL_010b + + IL_008a: ldarg.0 + IL_008b: ldc.i4.0 + IL_008c: cgt.un + IL_008e: stloc.s V_6 + IL_0090: ldloc.s V_6 + IL_0092: brfalse.s IL_00c8 + + IL_0094: nop + IL_0095: ldarg.0 + IL_0096: ldc.i4.m1 + IL_0097: ceq + IL_0099: stloc.s V_7 + IL_009b: ldloc.s V_7 + IL_009d: brfalse.s IL_00ac + + IL_009f: nop + IL_00a0: ldstr "-1, 0" + IL_00a5: call void [mscorlib]System.Console::WriteLine(string) + IL_00aa: nop + IL_00ab: nop + IL_00ac: ldarg.0 + IL_00ad: ldc.i4.1 + IL_00ae: ceq + IL_00b0: stloc.s V_8 + IL_00b2: ldloc.s V_8 + IL_00b4: brfalse.s IL_00c3 + + IL_00b6: nop + IL_00b7: ldstr "1, 0" + IL_00bc: call void [mscorlib]System.Console::WriteLine(string) + IL_00c1: nop + IL_00c2: nop + IL_00c3: ldc.i4.0 + IL_00c4: stloc.s V_5 + IL_00c6: br.s IL_010b + + IL_00c8: ldarg.1 + IL_00c9: ldc.i4.0 + IL_00ca: cgt.un + IL_00cc: stloc.s V_9 + IL_00ce: ldloc.s V_9 + IL_00d0: brfalse.s IL_0106 + + IL_00d2: nop + IL_00d3: ldarg.1 + IL_00d4: ldc.i4.m1 + IL_00d5: ceq + IL_00d7: stloc.s V_10 + IL_00d9: ldloc.s V_10 + IL_00db: brfalse.s IL_00ea + + IL_00dd: nop + IL_00de: ldstr "0, -1" + IL_00e3: call void [mscorlib]System.Console::WriteLine(string) + IL_00e8: nop + IL_00e9: nop + IL_00ea: ldarg.1 + IL_00eb: ldc.i4.1 + IL_00ec: ceq + IL_00ee: stloc.s V_11 + IL_00f0: ldloc.s V_11 + IL_00f2: brfalse.s IL_0101 + + IL_00f4: nop + IL_00f5: ldstr "0, 1" + IL_00fa: call void [mscorlib]System.Console::WriteLine(string) + IL_00ff: nop + IL_0100: nop + IL_0101: ldc.i4.0 + IL_0102: stloc.s V_5 + IL_0104: br.s IL_010b + + IL_0106: ldc.i4.1 + IL_0107: stloc.s V_5 + IL_0109: br.s IL_010b + + IL_010b: ldloc.s V_5 + IL_010d: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 74 (0x4a) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2, + bool V_3, + bool V_4) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: cgt.un + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: brfalse.s IL_0042 + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: ceq + IL_000e: stloc.1 + IL_000f: ldloc.1 + IL_0010: brfalse.s IL_001b + + IL_0012: nop + IL_0013: ldc.i4.1 + IL_0014: call void [mscorlib]System.Console::WriteLine(int32) + IL_0019: nop + IL_001a: nop + IL_001b: ldarg.0 + IL_001c: ldc.i4.2 + IL_001d: ceq + IL_001f: stloc.2 + IL_0020: ldloc.2 + IL_0021: brfalse.s IL_002c + + IL_0023: nop + IL_0024: ldc.i4.2 + IL_0025: call void [mscorlib]System.Console::WriteLine(int32) + IL_002a: nop + IL_002b: nop + IL_002c: ldarg.0 + IL_002d: ldc.i4.3 + IL_002e: ceq + IL_0030: stloc.3 + IL_0031: ldloc.3 + IL_0032: brfalse.s IL_003d + + IL_0034: nop + IL_0035: ldc.i4.3 + IL_0036: call void [mscorlib]System.Console::WriteLine(int32) + IL_003b: nop + IL_003c: nop + IL_003d: ldc.i4.0 + IL_003e: stloc.s V_4 + IL_0040: br.s IL_0047 + + IL_0042: ldc.i4.0 + IL_0043: stloc.s V_4 + IL_0045: br.s IL_0047 + + IL_0047: ldloc.s V_4 + IL_0049: ret + } // end of method Switch::SwitchlikeIf2 + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, bool b) cil managed { diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index 7b184431c..c9517dc22 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -206,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // These goto statements may be "goto case x" or "goto default", but these are a hint that the original code was not a switch, // and that the switch statement may be very poor quality. // Thus the rule of thumb is no goto statements if the original code didn't include them - return !SwitchRequiresGoto(); + return !SwitchUsesGoto(); } /// @@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// /// Determines if the analysed switch can be constructed without any gotos /// - private bool SwitchRequiresGoto() + private bool SwitchUsesGoto() { if (controlFlowGraph == null) controlFlowGraph = new ControlFlowGraph(currentContainer, context.CancellationToken); @@ -252,9 +252,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var caseNode in caseNodes) if (caseNode.Predecessors.Any(n => !flowBlocks.Contains(n.UserData))) return true; + + if (!FindBreakTarget(caseNodes, defaultNode, out var breakTarget)) + return true; // more than one exit point, requires goto statements - // determine if the switch would have a single exit point (break target) - return !FindBreakTarget(caseNodes, defaultNode, out var _); + // if the switch has a single break target there is one more hint + // The break target cannot be inlined, and should have a higher IL offset than anything in the switch body + return breakTarget?.UserIndex < caseNodes.Select(c => c.UserIndex).Max(); } ///