diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs index 37fea77c9..2d6970fc7 100644 --- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs @@ -277,6 +277,12 @@ namespace ICSharpCode.Decompiler.Tests await RunVB(options: options); } + [Test] + public async Task VBOnErrorCorrectness([ValueSource(nameof(noMonoOptions))] CompilerOptions options) + { + await RunVB(options: options); + } + [Test] public async Task MemberLookup([ValueSource(nameof(defaultOptions))] CompilerOptions options) { @@ -497,6 +503,18 @@ namespace ICSharpCode.Decompiler.Tests outputFile = await Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options, outputFileName: testOutputFileName).ConfigureAwait(false); string decompiledCodeFile = await Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)).ConfigureAwait(false); + if ((options & CompilerOptions.UseRoslynMask) == 0) + { + // For second pass, use roslyn instead of the legacy csc. + // VB error handling compiles to exception filters, which C# 5 cannot express. + options |= CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40; + } + else if ((options & CompilerOptions.UseRoslyn2_10_0) != 0 && (options & CompilerOptions.TargetNet40) == 0) + { + // The .NET Core 2.2 Microsoft.VisualBasic.dll lacks most of the VB runtime + // that decompiled VB code calls, such as Information.Err. + options = (options & ~CompilerOptions.UseRoslyn2_10_0) | CompilerOptions.UseRoslynLatest; + } decompiledOutputFile = await Tester.CompileCSharp(decompiledCodeFile, options).ConfigureAwait(false); await Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile, (options & CompilerOptions.UseTestRunner) != 0, (options & CompilerOptions.Force32Bit) != 0); diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index a70de1e14..7bbdf3087 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -109,6 +109,7 @@ + @@ -161,6 +162,8 @@ + + @@ -224,6 +227,8 @@ + + @@ -304,6 +309,8 @@ + + diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb new file mode 100644 index 000000000..23e430f0a --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb @@ -0,0 +1,91 @@ +Imports System +Imports Microsoft.VisualBasic + +Module VBOnErrorCorrectness + Sub Main() + ResumeNext() + GoToHandler() + GoToHandlerResumeNext() + Console.WriteLine(GoToHandlerResume(3)) + GoToHandlerResumeLabel() + Try + GoToZero() + Catch ex As InvalidOperationException + Console.WriteLine("outer: " & ex.Message) + End Try + Console.WriteLine(GoToHandlerWithResult()) + End Sub + + Sub FailWhilePositive(retries As Integer) + If retries > 0 Then Fail("retry " & retries) + End Sub + + Sub Fail(message As String) + Throw New InvalidOperationException(message) + End Sub + + Sub ResumeNext() + On Error Resume Next + Fail("a") + Console.WriteLine("after a: " & Err.Number & " " & Err.Description) + Err.Clear() + Console.WriteLine("cleared: " & Err.Number) + End Sub + + Sub GoToHandler() + On Error GoTo Handler + Fail("b") + Console.WriteLine("unreachable") + Exit Sub +Handler: + Console.WriteLine("handler: " & Err.Description) + End Sub + + Sub GoToHandlerResumeNext() + On Error GoTo Handler + Fail("c1") + Console.WriteLine("between") + Fail("c2") + Console.WriteLine("done") + Exit Sub +Handler: + Console.WriteLine("handler: " & Err.Description) + Resume Next + End Sub + + Function GoToHandlerResume(retries As Integer) As Integer + On Error GoTo Handler + FailWhilePositive(retries) + Return retries +Handler: + retries -= 1 + Resume + End Function + + Sub GoToHandlerResumeLabel() + On Error GoTo Handler + Fail("d") +Done: + Console.WriteLine("done") + Exit Sub +Handler: + Console.WriteLine("handler: " & Err.Description) + Resume Done + End Sub + + Sub GoToZero() + On Error Resume Next + Fail("e1") + Console.WriteLine("swallowed") + On Error GoTo 0 + Fail("e2") + Console.WriteLine("unreachable") + End Sub + + Function GoToHandlerWithResult() As Integer + On Error GoTo Handler + Return Integer.Parse("x") +Handler: + Return -1 + End Function +End Module diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.cs new file mode 100644 index 000000000..9f5c35d72 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.cs @@ -0,0 +1,91 @@ +using System; +using System.Runtime.CompilerServices; +using Microsoft.VisualBasic.CompilerServices; + +public class Issue3659 +{ + public static void Func(ref Issue3659 obj, object value) + { + } + + public static int ShowMessage(string a, int b, string c, object d, int e) + { + return 0; + } + + internal void VBFunction(object value) + { +#if OPT || LEGACY_VBC + int try0000_dispatch = -1; +#else + int try0001_dispatch = -1; +#endif + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; +#if OPT || LEGACY_VBC + switch (try0000_dispatch) +#else + switch (try0001_dispatch) +#endif + { + default: + { + ProjectData.ClearProjectError(); + num2 = 2; + Issue3659 obj = this; + Func(ref obj, RuntimeHelpers.GetObjectValue(value)); +#if OPT || LEGACY_VBC + goto end_IL_0000; +#else + goto end_IL_0001; +#endif + } +#if OPT || LEGACY_VBC + case 45: +#else + case 50: +#endif + num = -1; + switch (num2) + { + case 2: + ShowMessage("VBFunction", 0, "Exception", null, 0); +#if OPT || LEGACY_VBC + goto end_IL_0000; +#else + goto end_IL_0001; +#endif + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); +#if OPT || LEGACY_VBC + try0000_dispatch = 45; +#else + try0001_dispatch = 50; +#endif + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; +#if OPT || LEGACY_VBC + end_IL_0000: +#else + end_IL_0001: +#endif + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.vb b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.vb new file mode 100644 index 000000000..1575fdd6d --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.vb @@ -0,0 +1,17 @@ +Imports System +Public Class Issue3659 + Public Shared Sub Func(ByRef obj As Issue3659, value As Object) + End Sub + + Public Shared Function ShowMessage(a As String, b As Integer, c As String, d As Object, e As Integer) As Integer + Return 0 + End Function + + Friend Sub VBFunction(value As Object) + On Error GoTo Handler + Func(Me, value) + Exit Sub +Handler: + ShowMessage("VBFunction", 0, "Exception", Nothing, 0) + End Sub +End Class diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs new file mode 100644 index 000000000..b97926380 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs @@ -0,0 +1,3120 @@ +using System; +using Microsoft.VisualBasic; +using Microsoft.VisualBasic.CompilerServices; + +public class VBOnError +{ +#if OPT + public static void ResumeNext() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 65: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 4: + goto end_IL_0000_3; + } + goto default; + } + IL_0007: + num2 = 2; + Console.WriteLine("A"); + break; + end_IL_0000_2: + break; + } + num2 = 3; + Console.WriteLine("B"); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 65; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void ResumeNext() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 68: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 4: + goto end_IL_0000_3; + } + goto default; + } + IL_0007: + num2 = 2; + Console.WriteLine("A"); + break; + end_IL_0000_2: + break; + } + num2 = 3; + Console.WriteLine("B"); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 68; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void ResumeNext() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = -2; + goto IL_000b; + case 71: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 1: + break; + default: + goto end_IL_0001; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000b; + case 3: + goto end_IL_0001_2; + default: + goto end_IL_0001; + case 4: + goto end_IL_0001_3; + } + goto default; + } + IL_000b: + num2 = 2; + Console.WriteLine("A"); + break; + end_IL_0001_2: + break; + } + num2 = 3; + Console.WriteLine("B"); + break; + end_IL_0001:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 71; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static int ResumeNextWithResult() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + int num5 = default; + int num6 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 64: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_000c; + case 4: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 5: + goto end_IL_0000_3; + } + goto default; + } + IL_000c: + num2 = 3; + num5 /= 0; + break; + IL_0007: + num2 = 2; + num5 = 1; + goto IL_000c; + end_IL_0000_2: + break; + } + num2 = 4; + num6 = num5; + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 64; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + int result = num6; + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#elif (LEGACY_VBC && !OPT) + public static int ResumeNextWithResult() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + int num5 = default; + int num6 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 67: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_000c; + case 4: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 5: + goto end_IL_0000_3; + } + goto default; + } + IL_000c: + num2 = 3; + num5 /= 0; + break; + IL_0007: + num2 = 2; + num5 = 1; + goto IL_000c; + end_IL_0000_2: + break; + } + num2 = 4; + num6 = num5; + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 67; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + int result = num6; + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#elif (!LEGACY_VBC && OPT) + public static int ResumeNextWithResult() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + int num5 = default; + int result = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 63: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_000c; + case 4: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 5: + goto end_IL_0000_3; + } + goto default; + } + IL_000c: + num2 = 3; + num5 /= 0; + break; + IL_0007: + num2 = 2; + num5 = 1; + goto IL_000c; + end_IL_0000_2: + break; + } + num2 = 4; + result = num5; + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 63; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#else + public static int ResumeNextWithResult() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + int num5 = default; + int result = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = -2; + goto IL_000b; + case 69: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 1: + break; + default: + goto end_IL_0001; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000b; + case 3: + goto IL_0010; + case 4: + goto end_IL_0001_2; + default: + goto end_IL_0001; + case 5: + goto end_IL_0001_3; + } + goto default; + } + IL_000b: + num2 = 2; + num5 = 1; + goto IL_0010; + IL_0010: + num2 = 3; + num5 /= 0; + break; + end_IL_0001_2: + break; + } + num2 = 4; + result = num5; + break; + end_IL_0001:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 69; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#endif + +#if (LEGACY_VBC && OPT) + public static void ResumeNextErrNumber() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 109: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_0022; + case 5: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 6: + case 7: + goto end_IL_0000_3; + } + goto default; + } + IL_0022: + num2 = 4; + Console.WriteLine(Information.Err().Description); + break; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + IL_0013: + num2 = 3; + if (Information.Err().Number == 0) + { + goto end_IL_0000_3; + } + goto IL_0022; + end_IL_0000_2: + break; + } + num2 = 5; + Information.Err().Clear(); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 109; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void ResumeNextErrNumber() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 112: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_0022; + case 5: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 6: + case 7: + goto end_IL_0000_3; + } + goto default; + } + IL_0022: + num2 = 4; + Console.WriteLine(Information.Err().Description); + break; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + IL_0013: + num2 = 3; + if (Information.Err().Number == 0) + { + goto end_IL_0000_3; + } + goto IL_0022; + end_IL_0000_2: + break; + } + num2 = 5; + Information.Err().Clear(); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 112; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (!LEGACY_VBC && OPT) + public static void ResumeNextErrNumber() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 104: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_0021; + case 5: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 6: + goto end_IL_0000_3; + } + goto default; + } + IL_0021: + num2 = 4; + Console.WriteLine(Information.Err().Description); + break; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + IL_0013: + num2 = 3; + if (Information.Err().Number == 0) + { + goto end_IL_0000_3; + } + goto IL_0021; + end_IL_0000_2: + break; + } + num2 = 5; + Information.Err().Clear(); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 104; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void ResumeNextErrNumber() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = -2; + goto IL_000b; + case 122: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 1: + break; + default: + goto end_IL_0001; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000b; + case 3: + goto IL_0018; + case 4: + goto IL_002b; + case 5: + goto end_IL_0001_2; + default: + goto end_IL_0001; + case 6: + case 7: + goto end_IL_0001_3; + } + goto default; + } + IL_000b: + num2 = 2; + Console.WriteLine("A"); + goto IL_0018; + IL_0018: + num2 = 3; + if (Information.Err().Number == 0) + { + goto end_IL_0001_3; + } + goto IL_002b; + IL_002b: + num2 = 4; + Console.WriteLine(Information.Err().Description); + break; + end_IL_0001_2: + break; + } + num2 = 5; + Information.Err().Clear(); + break; + end_IL_0001:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 122; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if LEGACY_VBC || OPT + public static void GoToHandler() + { + int try0000_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0000; + case 36: + num = -1; + switch (num2) + { + case 2: + Console.WriteLine(Information.Err().Description); + goto end_IL_0000; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 36; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToHandler() + { + int try0001_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0001; + case 42: + num = -1; + switch (num2) + { + case 2: + Console.WriteLine(Information.Err().Description); + goto end_IL_0001; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 42; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static void GoToHandlerResumeNext() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 120: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_004c; + default: + goto end_IL_0000; + } + goto IL_0024; + } + IL_0024: + num2 = 5; + Console.WriteLine(Information.Err().Number); + goto IL_0035; + IL_0035: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_004c; + IL_0013: + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_004c: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 5: + goto IL_0024; + case 6: + goto IL_0035; + default: + goto end_IL_0000; + case 4: + case 7: + goto end_IL_0000_2; + } + goto default; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 120; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void GoToHandlerResumeNext() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 125: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_0051; + default: + goto end_IL_0000; + } + goto IL_0024; + } + IL_0024: + num2 = 5; + Console.WriteLine(Information.Err().Number); + goto IL_0035; + IL_0035: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0051; + IL_0013: + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_0051: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 5: + goto IL_0024; + case 6: + goto IL_0035; + default: + goto end_IL_0000; + case 4: + case 7: + goto end_IL_0000_2; + } + goto default; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 125; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (!LEGACY_VBC && OPT) + public static void GoToHandlerResumeNext() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 117: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_0049; + default: + goto end_IL_0000; + } + goto IL_0021; + } + IL_0021: + num2 = 5; + Console.WriteLine(Information.Err().Number); + goto IL_0032; + IL_0032: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0049; + IL_0013: + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_0049: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 5: + goto IL_0021; + case 6: + goto IL_0032; + default: + goto end_IL_0000; + case 4: + case 7: + goto end_IL_0000_2; + } + goto default; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 117; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToHandlerResumeNext() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_000a; + case 127: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 2: + break; + case 1: + goto IL_0053; + default: + goto end_IL_0001; + } + goto IL_0027; + } + IL_000a: + num2 = 2; + Console.WriteLine("A"); + goto IL_0017; + IL_0053: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000a; + case 3: + goto IL_0017; + case 5: + goto IL_0027; + case 6: + goto IL_0039; + default: + goto end_IL_0001; + case 4: + case 7: + goto end_IL_0001_2; + } + goto default; + IL_0027: + num2 = 5; + Console.WriteLine(Information.Err().Number); + goto IL_0039; + IL_0039: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0053; + IL_0017: + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0001_2; + end_IL_0001: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 127; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static void GoToHandlerResume(int retries) + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 115: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_003f; + default: + goto end_IL_0000; + } + goto IL_0018; + } + IL_003f: + num4 = num + 1; + goto IL_0042; + IL_0018: + num2 = 4; + retries = checked(retries - 1); + goto IL_001f; + IL_001f: + num2 = 5; + if (retries <= 0) + { + goto end_IL_0000_2; + } + goto IL_0025; + IL_0025: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num4 = num; + goto IL_0042; + IL_0007: + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0000_2; + IL_0042: + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 4: + goto IL_0018; + case 5: + goto IL_001f; + case 6: + goto IL_0025; + default: + goto end_IL_0000; + case 3: + case 7: + case 8: + case 9: + goto end_IL_0000_2; + } + goto default; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 115; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void GoToHandlerResume(int retries) + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 117: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_0041; + default: + goto end_IL_0000; + } + goto IL_0018; + } + IL_0041: + num4 = num + 1; + goto IL_0044; + IL_0018: + num2 = 4; + retries = checked(retries - 1); + goto IL_001f; + IL_001f: + num2 = 5; + if (retries <= 0) + { + goto end_IL_0000_2; + } + goto IL_0025; + IL_0025: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num4 = num; + goto IL_0044; + IL_0007: + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0000_2; + IL_0044: + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 4: + goto IL_0018; + case 5: + goto IL_001f; + case 6: + goto IL_0025; + default: + goto end_IL_0000; + case 3: + case 7: + case 8: + case 9: + goto end_IL_0000_2; + } + goto default; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 117; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (!LEGACY_VBC && OPT) + public static void GoToHandlerResume(int retries) + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 104: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_003c; + default: + goto end_IL_0000; + } + goto IL_0015; + } + IL_003c: + num4 = num + 1; + goto IL_003f; + IL_0015: + num2 = 4; + retries = checked(retries - 1); + goto IL_001c; + IL_001c: + num2 = 5; + if (retries <= 0) + { + goto end_IL_0000_2; + } + goto IL_0022; + IL_0022: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num4 = num; + goto IL_003f; + IL_0007: + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0000_2; + IL_003f: + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 4: + goto IL_0015; + case 5: + goto IL_001c; + case 6: + goto IL_0022; + default: + goto end_IL_0000; + case 3: + case 7: + goto end_IL_0000_2; + } + goto default; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 104; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToHandlerResume(int retries) + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_000a; + case 122: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 2: + break; + case 1: + goto IL_004a; + default: + goto end_IL_0001; + } + goto IL_001a; + } + IL_000a: + num2 = 2; + Console.WriteLine("Body"); + goto end_IL_0001_2; + IL_004d: + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000a; + case 4: + goto IL_001a; + case 5: + goto IL_0021; + case 6: + goto IL_002b; + default: + goto end_IL_0001; + case 3: + case 7: + case 8: + goto end_IL_0001_2; + } + goto default; + IL_004a: + num4 = num + 1; + goto IL_004d; + IL_001a: + num2 = 4; + retries = checked(retries - 1); + goto IL_0021; + IL_0021: + num2 = 5; + if (retries <= 0) + { + goto end_IL_0001_2; + } + goto IL_002b; + IL_002b: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num4 = num; + goto IL_004d; + end_IL_0001: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 122; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static void GoToHandlerResumeLabel() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 128: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_0050; + default: + goto end_IL_0000; + } + goto IL_0024; + } + IL_0050: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + case 7: + goto IL_0013; + case 5: + goto IL_0024; + case 6: + goto IL_0035; + default: + goto end_IL_0000; + case 4: + case 8: + goto end_IL_0000_2; + } + goto default; + IL_0024: + num2 = 5; + Console.WriteLine(Information.Err().Description); + goto IL_0035; + IL_0035: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num = 0; + goto IL_0013; + IL_0007: + num2 = 2; + Console.WriteLine("Body"); + goto IL_0013; + IL_0013: + num2 = 3; + Console.WriteLine("Done"); + goto end_IL_0000_2; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 128; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void GoToHandlerResumeLabel() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 131: + { + num = num2; + switch (num3) + { + case 2: + break; + case 1: + goto IL_0053; + default: + goto end_IL_0000; + } + goto IL_0024; + } + IL_0053: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + case 7: + goto IL_0013; + case 5: + goto IL_0024; + case 6: + goto IL_0035; + default: + goto end_IL_0000; + case 4: + case 8: + goto end_IL_0000_2; + } + goto default; + IL_0024: + num2 = 5; + Console.WriteLine(Information.Err().Description); + goto IL_0035; + IL_0035: + num2 = 6; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num = 0; + goto IL_0013; + IL_0007: + num2 = 2; + Console.WriteLine("Body"); + goto IL_0013; + IL_0013: + num2 = 3; + Console.WriteLine("Done"); + goto end_IL_0000_2; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 131; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (!LEGACY_VBC && OPT) + public static void GoToHandlerResumeLabel() + { + int try0000_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("Body"); + break; + case 69: + num = -1; + switch (num2) + { + case 2: + Console.WriteLine(Information.Err().Description); + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num = 0; + break; + default: + goto end_IL_0000; + } + break; + } + Console.WriteLine("Done"); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 69; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToHandlerResumeLabel() + { + int try0001_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("Body"); + break; + case 78: + num = -1; + switch (num2) + { + case 2: + Console.WriteLine(Information.Err().Description); + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + num = 0; + break; + default: + goto end_IL_0001; + } + break; + } + Console.WriteLine("Done"); + break; + end_IL_0001:; + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 78; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if OPT + public static void GoToZero() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 76: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 5: + goto end_IL_0000_3; + } + goto default; + } + IL_0013: + ProjectData.ClearProjectError(); + num3 = 0; + break; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000_2: + break; + } + num2 = 4; + Console.WriteLine("B"); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 76; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void GoToZero() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 1; + goto IL_0007; + case 79: + { + num = num2; + switch (num3) + { + case 1: + break; + default: + goto end_IL_0000; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto end_IL_0000_2; + default: + goto end_IL_0000; + case 5: + goto end_IL_0000_3; + } + goto default; + } + IL_0013: + ProjectData.ClearProjectError(); + num3 = 0; + break; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000_2: + break; + } + num2 = 4; + Console.WriteLine("B"); + break; + end_IL_0000:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 79; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToZero() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = -2; + goto IL_000b; + case 83: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 1: + break; + default: + goto end_IL_0001; + } + int num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000b; + case 3: + goto IL_0018; + case 4: + goto end_IL_0001_2; + default: + goto end_IL_0001; + case 5: + goto end_IL_0001_3; + } + goto default; + } + IL_000b: + num2 = 2; + Console.WriteLine("A"); + goto IL_0018; + IL_0018: + ProjectData.ClearProjectError(); + num3 = 0; + break; + end_IL_0001_2: + break; + } + num2 = 4; + Console.WriteLine("B"); + break; + end_IL_0001:; + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 83; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_3: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if LEGACY_VBC || OPT + public static void GoToMinusOne() + { + int try0000_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("A"); + goto end_IL_0000; + case 57: + num = -1; + switch (num2) + { + case 2: + ProjectData.ClearProjectError(); + num = 0; + ProjectData.ClearProjectError(); + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0000; + case 3: + Console.WriteLine("C"); + goto end_IL_0000; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 57; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void GoToMinusOne() + { + int try0001_dispatch = -1; + int num2 = default; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + Console.WriteLine("A"); + goto end_IL_0001; + case 67: + num = -1; + switch (num2) + { + case 2: + ProjectData.ClearProjectError(); + num = 0; + ProjectData.ClearProjectError(); + num2 = 3; + Console.WriteLine("B"); + goto end_IL_0001; + case 3: + Console.WriteLine("C"); + goto end_IL_0001; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 67; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static void SwitchHandlers() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 176: + { + num = num2; + switch (num3) + { + case 2: + break; + case 3: + goto IL_004c; + case 1: + goto IL_0074; + default: + goto end_IL_0000; + } + goto IL_002b; + } + IL_002b: + num2 = 6; + Console.WriteLine("Handler1"); + goto IL_0037; + IL_0037: + num2 = 7; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0074; + IL_001a: + num2 = 4; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_0074: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_001a; + case 6: + goto IL_002b; + case 7: + goto IL_0037; + case 8: + case 9: + goto IL_004c; + case 10: + goto IL_0059; + default: + goto end_IL_0000; + case 5: + case 11: + goto end_IL_0000_2; + } + goto default; + IL_004c: + num2 = 9; + Console.WriteLine("Handler2"); + goto IL_0059; + IL_0059: + num2 = 10; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0074; + IL_0013: + ProjectData.ClearProjectError(); + num3 = 3; + goto IL_001a; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 176; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (LEGACY_VBC && !OPT) + public static void SwitchHandlers() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 183: + { + num = num2; + switch (num3) + { + case 2: + break; + case 3: + goto IL_004e; + case 1: + goto IL_007b; + default: + goto end_IL_0000; + } + goto IL_002b; + } + IL_002b: + num2 = 6; + Console.WriteLine("Handler1"); + goto IL_0037; + IL_0037: + num2 = 7; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_007b; + IL_001a: + num2 = 4; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_007b: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_001a; + case 6: + goto IL_002b; + case 7: + goto IL_0037; + case 8: + case 9: + goto IL_004e; + case 10: + goto IL_005b; + default: + goto end_IL_0000; + case 5: + case 11: + goto end_IL_0000_2; + } + goto default; + IL_004e: + num2 = 9; + Console.WriteLine("Handler2"); + goto IL_005b; + IL_005b: + num2 = 10; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_007b; + IL_0013: + ProjectData.ClearProjectError(); + num3 = 3; + goto IL_001a; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 183; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#elif (!LEGACY_VBC && OPT) + public static void SwitchHandlers() + { + int try0000_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_0007; + case 165: + { + num = num2; + switch (num3) + { + case 2: + break; + case 3: + goto IL_0049; + case 1: + goto IL_006d; + default: + goto end_IL_0000; + } + goto IL_0028; + } + IL_0028: + num2 = 6; + Console.WriteLine("Handler1"); + goto IL_0034; + IL_0034: + num2 = 7; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_006d; + IL_001a: + num2 = 4; + Console.WriteLine("B"); + goto end_IL_0000_2; + IL_006d: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_0007; + case 3: + goto IL_0013; + case 4: + goto IL_001a; + case 6: + goto IL_0028; + case 7: + goto IL_0034; + case 8: + goto IL_0049; + case 9: + goto IL_0055; + default: + goto end_IL_0000; + case 5: + case 10: + goto end_IL_0000_2; + } + goto default; + IL_0049: + num2 = 8; + Console.WriteLine("Handler2"); + goto IL_0055; + IL_0055: + num2 = 9; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_006d; + IL_0013: + ProjectData.ClearProjectError(); + num3 = 3; + goto IL_001a; + IL_0007: + num2 = 2; + Console.WriteLine("A"); + goto IL_0013; + end_IL_0000: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 165; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#else + public static void SwitchHandlers() + { + int try0001_dispatch = -1; + int num3 = default; + int num = default; + int num2 = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + int num4; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num3 = 2; + goto IL_000a; + case 184: + { + num = num2; + switch ((num3 <= -2) ? 1 : num3) + { + case 2: + break; + case 3: + goto IL_0055; + case 1: + goto IL_0080; + default: + goto end_IL_0001; + } + goto IL_002f; + } + IL_000a: + num2 = 2; + Console.WriteLine("A"); + goto IL_0017; + IL_0017: + ProjectData.ClearProjectError(); + num3 = 3; + goto IL_001f; + IL_002f: + num2 = 6; + Console.WriteLine("Handler1"); + goto IL_003c; + IL_003c: + num2 = 7; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0080; + IL_001f: + num2 = 4; + Console.WriteLine("B"); + goto end_IL_0001_2; + IL_0080: + num4 = num + 1; + num = 0; + switch (num4) + { + case 1: + break; + case 2: + goto IL_000a; + case 3: + goto IL_0017; + case 4: + goto IL_001f; + case 6: + goto IL_002f; + case 7: + goto IL_003c; + case 8: + goto IL_0055; + case 9: + goto IL_0062; + default: + goto end_IL_0001; + case 5: + case 10: + goto end_IL_0001_2; + } + goto default; + IL_0055: + num2 = 8; + Console.WriteLine("Handler2"); + goto IL_0062; + IL_0062: + num2 = 9; + ProjectData.ClearProjectError(); + if (num == 0) + { + throw ProjectData.CreateProjectError(-2146828268); + } + goto IL_0080; + end_IL_0001: + break; + } + } + catch (Exception ex) when ((num3 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 184; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001_2: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + } +#endif + +#if (LEGACY_VBC && OPT) + public static int GoToHandlerWithResult() + { + int try0000_dispatch = -1; + int num2 = default; + int num3; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + num3 = int.Parse("x"); + goto end_IL_0000; + case 24: + num = -1; + switch (num2) + { + case 2: + num3 = -1; + goto end_IL_0000; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 24; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000: + break; + } + int result = num3; + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#elif (LEGACY_VBC && !OPT) + public static int GoToHandlerWithResult() + { + int try0000_dispatch = -1; + int num2 = default; + int num3; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + num3 = int.Parse("x"); + goto end_IL_0000; + case 26: + num = -1; + switch (num2) + { + case 2: + num3 = -1; + goto end_IL_0000; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 26; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000: + break; + } + int result = num3; + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#elif (!LEGACY_VBC && OPT) + public static int GoToHandlerWithResult() + { + int try0000_dispatch = -1; + int num2 = default; + int result; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0000_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + result = int.Parse("x"); + goto end_IL_0000; + case 24: + num = -1; + switch (num2) + { + case 2: + result = -1; + goto end_IL_0000; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0000_dispatch = 24; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0000: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#else + public static int GoToHandlerWithResult() + { + int try0001_dispatch = -1; + int num2 = default; + int result; + int num = default; + while (true) + { + try + { + /*Note: ILSpy has introduced the following switch to emulate a goto from catch-block to try-block*/; + switch (try0001_dispatch) + { + default: + ProjectData.ClearProjectError(); + num2 = 2; + result = int.Parse("x"); + goto end_IL_0001; + case 30: + num = -1; + switch (num2) + { + case 2: + result = -1; + goto end_IL_0001; + } + break; + } + } + catch (Exception ex) when ((num2 != 0) & (num == 0)) + { + ProjectData.SetProjectError(ex); + try0001_dispatch = 30; + continue; + } + throw ProjectData.CreateProjectError(-2146828237); + continue; + end_IL_0001: + break; + } + if (num != 0) + { + ProjectData.ClearProjectError(); + } + return result; + } +#endif +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb new file mode 100644 index 000000000..ed82ac645 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb @@ -0,0 +1,107 @@ +Imports System +Imports Microsoft.VisualBasic + +Public Class VBOnError + Public Shared Sub ResumeNext() + On Error Resume Next + Console.WriteLine("A") + Console.WriteLine("B") + End Sub + + Public Shared Function ResumeNextWithResult() As Integer + On Error Resume Next + Dim x As Integer = 1 + x = x \ 0 + Return x + End Function + + Public Shared Sub ResumeNextErrNumber() + On Error Resume Next + Console.WriteLine("A") + If Err.Number <> 0 Then + Console.WriteLine(Err.Description) + Err.Clear() + End If + End Sub + + Public Shared Sub GoToHandler() + On Error GoTo Handler + Console.WriteLine("Body") + Exit Sub +Handler: + Console.WriteLine(Err.Description) + End Sub + + Public Shared Sub GoToHandlerResumeNext() + On Error GoTo Handler + Console.WriteLine("A") + Console.WriteLine("B") + Exit Sub +Handler: + Console.WriteLine(Err.Number) + Resume Next + End Sub + + Public Shared Sub GoToHandlerResume(retries As Integer) + On Error GoTo Handler + Console.WriteLine("Body") + Exit Sub +Handler: + retries -= 1 + If retries > 0 Then + Resume + End If + End Sub + + Public Shared Sub GoToHandlerResumeLabel() + On Error GoTo Handler + Console.WriteLine("Body") +Done: + Console.WriteLine("Done") + Exit Sub +Handler: + Console.WriteLine(Err.Description) + Resume Done + End Sub + + Public Shared Sub GoToZero() + On Error Resume Next + Console.WriteLine("A") + On Error GoTo 0 + Console.WriteLine("B") + End Sub + + Public Shared Sub GoToMinusOne() + On Error GoTo Handler + Console.WriteLine("A") + Exit Sub +Handler: + On Error GoTo -1 + On Error GoTo Handler2 + Console.WriteLine("B") + Exit Sub +Handler2: + Console.WriteLine("C") + End Sub + + Public Shared Sub SwitchHandlers() + On Error GoTo Handler1 + Console.WriteLine("A") + On Error GoTo Handler2 + Console.WriteLine("B") + Exit Sub +Handler1: + Console.WriteLine("Handler1") + Resume Next +Handler2: + Console.WriteLine("Handler2") + Resume Next + End Sub + + Public Shared Function GoToHandlerWithResult() As Integer + On Error GoTo Handler + Return Integer.Parse("x") +Handler: + Return -1 + End Function +End Class diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs new file mode 100644 index 000000000..4a61a242f --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs @@ -0,0 +1,619 @@ +using System; +using System.IO; + +using Microsoft.VisualBasic.CompilerServices; + +public class VBTryCatchFinally +{ + private static bool Condition() + { + return true; + } + + public static void TryFinally() + { + try + { + Console.WriteLine("Try"); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void TryCatchBare() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchVariable() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + Console.WriteLine(ex2.Message); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchSpecificType() + { + try + { + Console.WriteLine("Try"); + } + catch (IOException ex) + { + ProjectData.SetProjectError(ex); + IOException ex2 = ex; + Console.WriteLine(ex2.Message); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchUnusedVariable() + { + try + { + Console.WriteLine("Try"); + } + catch (InvalidOperationException ex) + { + ProjectData.SetProjectError(ex); + InvalidOperationException ex2 = ex; + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchWhen() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception projectError) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(projectError); + return Condition(); + }).Invoke()) + { + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchVariableWhen() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(ex); + return ex.Message != null; + }).Invoke()) + { + Console.WriteLine(ex.Message); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchSpecificTypeWhen() + { + try + { + Console.WriteLine("Try"); + } + catch (IOException ex) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(ex); + return Condition(); + }).Invoke()) + { + Console.WriteLine(ex.Message); + ProjectData.ClearProjectError(); + } + } + + public static void TryCatchExistingLocal() + { + Exception value = null; + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + value = ex; + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + Console.WriteLine(value); + } + + public static void TryCatchExistingLocalWhen() + { + Exception value = null; + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) when (((Func)delegate { + // Could not convert BlockContainer to single expression +#if LEGACY_VBC + value = ex; + ProjectData.SetProjectError(ex); +#else + ProjectData.SetProjectError(ex); + value = ex; +#endif + return ex.Message != null; + }).Invoke()) + { + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + Console.WriteLine(value); + } + + public static void TryCatchFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + Console.WriteLine(ex2.Message); + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void TryCatchBareFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void TryCatchWhenFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(ex); + return Condition(); + }).Invoke()) + { + Console.WriteLine(ex.Message); + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void TryMultipleCatch() + { + try + { + Console.WriteLine("Try"); + } + catch (FileNotFoundException ex) + { + ProjectData.SetProjectError(ex); + FileNotFoundException ex2 = ex; + Console.WriteLine(ex2.FileName); + ProjectData.ClearProjectError(); + } + catch (IOException ex3) + { + ProjectData.SetProjectError(ex3); + IOException ex4 = ex3; + Console.WriteLine(ex4.Message); + ProjectData.ClearProjectError(); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + } + + public static void TryMultipleCatchFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (FileNotFoundException ex) + { + ProjectData.SetProjectError(ex); + FileNotFoundException ex2 = ex; + Console.WriteLine(ex2.FileName); + ProjectData.ClearProjectError(); + } + catch (IOException ex3) + { + ProjectData.SetProjectError(ex3); + IOException ex4 = ex3; + Console.WriteLine(ex4.Message); + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void TryMultipleCatchWhen() + { + try + { + Console.WriteLine("Try"); + } + catch (IOException ex) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(ex); + return Condition(); + }).Invoke()) + { + Console.WriteLine(ex.Message); + ProjectData.ClearProjectError(); + } + catch (Exception projectError) when (((Func)delegate { + // Could not convert BlockContainer to single expression + ProjectData.SetProjectError(projectError); + return Condition(); + }).Invoke()) + { + Console.WriteLine("Catch When"); + ProjectData.ClearProjectError(); + } + catch (Exception ex2) + { + ProjectData.SetProjectError(ex2); + Exception ex3 = ex2; + Console.WriteLine(ex3.Message); + ProjectData.ClearProjectError(); + } + } + + public static void EmptyTryFinally() + { + try + { + } + finally + { + Console.WriteLine("Finally"); + } + } + + public static void EmptyCatch() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + ProjectData.ClearProjectError(); + } + } + + public static void EmptyFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + Console.WriteLine(ex2.Message); + ProjectData.ClearProjectError(); + } +#if !OPT || LEGACY_VBC + finally + { + } +#endif + } + + public static void ExitTryInTry(bool b) + { + try + { + if (!b) + { + Console.WriteLine("Try"); + } + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + Console.WriteLine("End"); + } + + public static void ExitTryInCatch(bool b) + { + try + { + Console.WriteLine("Try"); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + if (b) + { + ProjectData.ClearProjectError(); + } + else + { + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + } + Console.WriteLine("End"); + } + + public static void ExitTryWithFinally(bool b) + { + try + { + if (!b) + { + Console.WriteLine("Try"); + } + } + finally + { + Console.WriteLine("Finally"); + } + Console.WriteLine("End"); + } + + public static void Rethrow() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + Console.WriteLine(ex2.Message); + throw; + } + } + + public static void ThrowNew() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception innerException = ex; + throw new InvalidOperationException("Catch", innerException); + } + } + + public static int ReturnFromTry() + { + int result; + try + { + result = 1; + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + result = 2; + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + return result; + } + + public static int ReturnAfterTry() + { +#if !(LEGACY_VBC && OPT) + int result; +#endif + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + Console.WriteLine(ex2.Message); +#if LEGACY_VBC && OPT + int result = -1; + ProjectData.ClearProjectError(); + return result; + } + return 0; +#else + result = -1; + ProjectData.ClearProjectError(); +#if LEGACY_VBC + goto IL_0032; +#elif OPT + goto IL_0029; +#else + goto IL_0031; +#endif + } + result = 0; +#if LEGACY_VBC + goto IL_0032; + IL_0032: +#elif OPT + goto IL_0029; + IL_0029: +#else + goto IL_0031; + IL_0031: +#endif + return result; +#endif + } + + public static void NestedTryInTry() + { + try + { + try + { + Console.WriteLine("Inner Try"); + } + catch (IOException ex) + { + ProjectData.SetProjectError(ex); + IOException ex2 = ex; + Console.WriteLine(ex2.Message); + ProjectData.ClearProjectError(); + } + } + catch (Exception ex3) + { + ProjectData.SetProjectError(ex3); + Exception ex4 = ex3; + Console.WriteLine(ex4.Message); + ProjectData.ClearProjectError(); + } + } + + public static void NestedTryInCatch() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + ProjectData.SetProjectError(ex); + Exception ex2 = ex; + try + { + Console.WriteLine(ex2.Message); + } + catch (Exception ex3) + { + ProjectData.SetProjectError(ex3); + Exception ex4 = ex3; + Console.WriteLine(ex4.Message); + ProjectData.ClearProjectError(); + } + ProjectData.ClearProjectError(); + } + } + + public static void NestedTryInFinally() + { + try + { + Console.WriteLine("Try"); + } + finally + { + try + { + Console.WriteLine("Inner Try"); + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Inner Catch"); + ProjectData.ClearProjectError(); + } + } + } + + public static void TryInLoop() + { + int num = 0; + do + { + try + { + switch (num) + { + case 5: + break; + case 8: + return; + default: + Console.WriteLine(num); + break; + } + } + catch (Exception projectError) + { + ProjectData.SetProjectError(projectError); + Console.WriteLine("Catch"); + ProjectData.ClearProjectError(); + } + finally + { + Console.WriteLine("Finally"); + } + num = checked(num + 1); + } while (num <= 9); + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb new file mode 100644 index 000000000..27f2e53c1 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb @@ -0,0 +1,308 @@ +Imports System +Imports System.IO + +Public Class VBTryCatchFinally + Private Shared Function Condition() As Boolean + Return True + End Function + + Public Shared Sub TryFinally() + Try + Console.WriteLine("Try") + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub TryCatchBare() + Try + Console.WriteLine("Try") + Catch + Console.WriteLine("Catch") + End Try + End Sub + + Public Shared Sub TryCatchVariable() + Try + Console.WriteLine("Try") + Catch ex As Exception + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub TryCatchSpecificType() + Try + Console.WriteLine("Try") + Catch ex As IOException + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub TryCatchUnusedVariable() + Try + Console.WriteLine("Try") + Catch ex As InvalidOperationException + Console.WriteLine("Catch") + End Try + End Sub + + Public Shared Sub TryCatchWhen() + Try + Console.WriteLine("Try") + Catch When Condition() + Console.WriteLine("Catch") + End Try + End Sub + + Public Shared Sub TryCatchVariableWhen() + Try + Console.WriteLine("Try") + Catch ex As Exception When ex.Message IsNot Nothing + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub TryCatchSpecificTypeWhen() + Try + Console.WriteLine("Try") + Catch ex As IOException When Condition() + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub TryCatchExistingLocal() + Dim ex As Exception = Nothing + Try + Console.WriteLine("Try") + Catch ex + Console.WriteLine("Catch") + End Try + Console.WriteLine(ex) + End Sub + + Public Shared Sub TryCatchExistingLocalWhen() + Dim ex As Exception = Nothing + Try + Console.WriteLine("Try") + Catch ex When ex.Message IsNot Nothing + Console.WriteLine("Catch") + End Try + Console.WriteLine(ex) + End Sub + + Public Shared Sub TryCatchFinally() + Try + Console.WriteLine("Try") + Catch ex As Exception + Console.WriteLine(ex.Message) + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub TryCatchBareFinally() + Try + Console.WriteLine("Try") + Catch + Console.WriteLine("Catch") + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub TryCatchWhenFinally() + Try + Console.WriteLine("Try") + Catch ex As Exception When Condition() + Console.WriteLine(ex.Message) + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub TryMultipleCatch() + Try + Console.WriteLine("Try") + Catch ex As FileNotFoundException + Console.WriteLine(ex.FileName) + Catch ex As IOException + Console.WriteLine(ex.Message) + Catch + Console.WriteLine("Catch") + End Try + End Sub + + Public Shared Sub TryMultipleCatchFinally() + Try + Console.WriteLine("Try") + Catch ex As FileNotFoundException + Console.WriteLine(ex.FileName) + Catch ex As IOException + Console.WriteLine(ex.Message) + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub TryMultipleCatchWhen() + Try + Console.WriteLine("Try") + Catch ex As IOException When Condition() + Console.WriteLine(ex.Message) + Catch When Condition() + Console.WriteLine("Catch When") + Catch ex As Exception + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub EmptyTryFinally() + Try + Finally + Console.WriteLine("Finally") + End Try + End Sub + + Public Shared Sub EmptyCatch() + Try + Console.WriteLine("Try") + Catch + End Try + End Sub + + Public Shared Sub EmptyFinally() + Try + Console.WriteLine("Try") + Catch ex As Exception + Console.WriteLine(ex.Message) + Finally + End Try + End Sub + + Public Shared Sub ExitTryInTry(b As Boolean) + Try + If b Then + Exit Try + End If + Console.WriteLine("Try") + Catch + Console.WriteLine("Catch") + End Try + Console.WriteLine("End") + End Sub + + Public Shared Sub ExitTryInCatch(b As Boolean) + Try + Console.WriteLine("Try") + Catch + If b Then + Exit Try + End If + Console.WriteLine("Catch") + End Try + Console.WriteLine("End") + End Sub + + Public Shared Sub ExitTryWithFinally(b As Boolean) + Try + If b Then + Exit Try + End If + Console.WriteLine("Try") + Finally + Console.WriteLine("Finally") + End Try + Console.WriteLine("End") + End Sub + + Public Shared Sub Rethrow() + Try + Console.WriteLine("Try") + Catch ex As Exception + Console.WriteLine(ex.Message) + Throw + End Try + End Sub + + Public Shared Sub ThrowNew() + Try + Console.WriteLine("Try") + Catch ex As Exception + Throw New InvalidOperationException("Catch", ex) + End Try + End Sub + + Public Shared Function ReturnFromTry() As Integer + Try + Return 1 + Catch + Return 2 + Finally + Console.WriteLine("Finally") + End Try + End Function + + Public Shared Function ReturnAfterTry() As Integer + Try + Console.WriteLine("Try") + Catch ex As Exception + Console.WriteLine(ex.Message) + Return -1 + End Try + Return 0 + End Function + + Public Shared Sub NestedTryInTry() + Try + Try + Console.WriteLine("Inner Try") + Catch ex As IOException + Console.WriteLine(ex.Message) + End Try + Catch ex As Exception + Console.WriteLine(ex.Message) + End Try + End Sub + + Public Shared Sub NestedTryInCatch() + Try + Console.WriteLine("Try") + Catch ex As Exception + Try + Console.WriteLine(ex.Message) + Catch ex2 As Exception + Console.WriteLine(ex2.Message) + End Try + End Try + End Sub + + Public Shared Sub NestedTryInFinally() + Try + Console.WriteLine("Try") + Finally + Try + Console.WriteLine("Inner Try") + Catch + Console.WriteLine("Inner Catch") + End Try + End Try + End Sub + + Public Shared Sub TryInLoop() + For i = 0 To 9 + Try + If i = 5 Then + Continue For + End If + If i = 8 Then + Exit For + End If + Console.WriteLine(i) + Catch + Console.WriteLine("Catch") + Finally + Console.WriteLine("Finally") + End Try + Next + End Sub +End Class diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index a700d4e7c..3b3bcd78b 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -132,6 +132,12 @@ namespace ICSharpCode.Decompiler.Tests await Run(options: options | CompilerOptions.Library); } + [Test] + public async Task Issue3659([ValueSource(nameof(defaultOptions))] CompilerOptions options) + { + await Run(options: options | CompilerOptions.Library); + } + [Test] public async Task Issue1906([ValueSource(nameof(defaultOptions))] CompilerOptions options) { @@ -145,6 +151,13 @@ namespace ICSharpCode.Decompiler.Tests await Run(options: options | CompilerOptions.Library); } + [Test] + public async Task VBOnError([ValueSource(nameof(defaultOptions))] CompilerOptions options) + { + IgnoreIfVbRuntimeSubstituted(options); + await Run(options: options | CompilerOptions.Library); + } + [Test] public async Task VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options) { @@ -164,6 +177,13 @@ namespace ICSharpCode.Decompiler.Tests await Run(options: options | CompilerOptions.Library); } + [Test] + public async Task VBTryCatchFinally([ValueSource(nameof(defaultOptions))] CompilerOptions options) + { + IgnoreIfVbRuntimeSubstituted(options); + await Run(options: options | CompilerOptions.Library); + } + [Test] public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs index 6a0390bad..e3b4418c6 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs @@ -17,6 +17,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ICSharpCode.Decompiler.TypeSystem; @@ -467,6 +468,24 @@ namespace ICSharpCode.Decompiler.IL } } + /// + /// For == Equality, matches 'comp(arg == ldc.i4 0)' or 'comp.unsigned(arg <= ldc.i4 0)'. + /// For == Inequality, matches 'comp(arg != ldc.i4 0)' or 'comp.unsigned(arg > ldc.i4 0)'. + /// + public bool MatchCompUnsignedZero(ComparisonKind kind, [NotNullWhen(true)] out ILInstruction? arg) + { + Debug.Assert(kind.IsEqualityOrInequality()); + var unsignedKind = kind == ComparisonKind.Equality ? ComparisonKind.LessThanOrEqual : ComparisonKind.GreaterThan; + if (this is Comp { IsLifted: false } comp && comp.Right.MatchLdcI4(0) + && (comp.Kind == kind || (comp.Kind == unsignedKind && comp.Sign == Sign.Unsigned))) + { + arg = comp.Left; + return true; + } + arg = null; + return false; + } + public bool MatchLdFld([NotNullWhen(true)] out ILInstruction? target, [NotNullWhen(true)] out IField? field) { if (this is LdObj ldobj && ldobj.Target is LdFlda ldflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile) diff --git a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs index 5aa9064e2..9b6d7e67b 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs @@ -69,11 +69,67 @@ namespace ICSharpCode.Decompiler.IL.Transforms container.SortBlocks(deleteUnreachableBlocks: true); } + PropagateExceptionVariable(context, catchBlock); + } + else if (catchBlock.Filter is BlockContainer filterContainer + && MatchVBOnErrorCatchFilter(context, catchBlock.Variable, filterContainer, out exceptionType, out var typeTest) + && exceptionType.GetStackType() == catchBlock.Variable.StackType) + { + context.Step($"Detected catch-when for {catchBlock.Variable.Name} (bit.and)", typeTest); + catchBlock.Variable.Type = exceptionType; + var condition = typeTest.Right; + typeTest.ReplaceWith(condition); + context.EndStep(condition); + PropagateExceptionVariable(context, catchBlock); } } } + /// + /// BlockContainer { + /// Block entryPoint (incoming: 1) { + /// leave container(bit.and(bit.and(comp(isinst System.Exception(ldloc exceptionVar) > ldnull), comp.unsigned(ldloc activeHandler > ldc.i4 0)), logic.not(ldloc resumeTarget))) + /// } + /// } + /// Only emitted for On Error Resume Next/GoTo. + /// + bool MatchVBOnErrorCatchFilter(ILTransformContext context, ILVariable exceptionVar, BlockContainer container, out IType exceptionType, out BinaryNumericInstruction typeTest) + { + exceptionType = null; + typeTest = null; + var entryPoint = container.EntryPoint; + if (entryPoint == null || entryPoint.IncomingEdgeCount != 1 || entryPoint.Instructions.Count != 1) + return false; + if (!entryPoint.Instructions[0].MatchLeave(container, out var condition)) + return false; + if (condition is not BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd, Left: BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd } bitAnd } outer) + return false; + if (!outer.Right.MatchCompUnsignedZero(ComparisonKind.Equality, out var resumeTarget) || !resumeTarget.MatchLdLoc(out _)) + return false; + if (!bitAnd.Right.MatchCompUnsignedZero(ComparisonKind.Inequality, out var activeHandler) || !activeHandler.MatchLdLoc(out _)) + return false; + if (bitAnd.Left is not Comp comp) + return false; + EarlyExpressionTransforms.FixComparisonKindLdNull(comp, context); + if (!MatchIsInstNotNull(comp, exceptionVar, out _, out exceptionType) || !exceptionType.IsKnownType(KnownTypeCode.Exception)) + return false; + typeTest = bitAnd; + return true; + } + + /// + /// comp(isinst exceptionType(ldloc exceptionVar) != ldnull) + /// + static bool MatchIsInstNotNull(ILInstruction condition, ILVariable exceptionVar, out ILInstruction exceptionSlot, out IType exceptionType) + { + exceptionSlot = null; + exceptionType = null; + return condition.MatchCompNotEqualsNull(out var arg) + && arg.MatchIsInst(out exceptionSlot, out exceptionType) + && exceptionSlot.MatchLdLoc(exceptionVar); + } + /// /// catch E_189 : 0200007C System.Exception when (BlockContainer { /// Block IL_0079 (incoming: 1) { @@ -195,18 +251,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms // br falseBlock if (!entryPoint.Instructions[0].MatchIfInstruction(out var condition, out var branch)) return false; - if (!condition.MatchCompNotEquals(out var left, out var right)) + if (!MatchIsInstNotNull(condition, exceptionVar, out exceptionSlot, out exceptionType)) return false; if (!entryPoint.Instructions[1].MatchBranch(out var falseBlock) || !MatchFalseBlock(container, falseBlock, out var returnVar, out var exitBlock)) return false; - if (!left.MatchIsInst(out exceptionSlot, out exceptionType)) - return false; - if (!exceptionSlot.MatchLdLoc(exceptionVar)) - return false; - if (right.MatchLdNull()) - { - return branch.MatchBranch(out whenConditionBlock); - } + return branch.MatchBranch(out whenConditionBlock); } return false; }