From d5ff770959d8d447b59c91df0486bca49b2f6151 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Fri, 11 Sep 2026 23:55:33 +0200 Subject: [PATCH 1/3] Recognize a VB exception filter's type test vbc builds an exception filter as a single non-short-circuiting expression: `isinst`, then the user's `when` conditions, combined with `and`. DetectCatchWhenConditionBlocks only knew the branch chain csc emits, so the type test stayed inside the filter and the handler kept the `object` variable it has in IL: catch (object obj) when ((obj is Exception) & (num2 != 0) & (num == 0)) { ProjectData.SetProjectError((Exception)obj); A catch type has to derive from Exception, so that does not compile. The conjunction form is matched too now, lifting the test to the catch type as the block form already does. The other conjuncts stop running for a non-matching exception once the test moves, so the filter has to be pure for this to be invisible; PropagateExceptionVariable then drops the castclass in the handler: catch (Exception ex) when ((num2 != 0) & (num == 0)) { ProjectData.SetProjectError(ex); Closes #3659 --- .../ICSharpCode.Decompiler.Tests.csproj | 2 + .../TestCases/VBPretty/Issue3659.cs | 91 +++++++++++++++++++ .../TestCases/VBPretty/Issue3659.vb | 17 ++++ .../VBPrettyTestRunner.cs | 6 ++ .../DetectCatchWhenConditionBlocks.cs | 68 ++++++++++++++ 5 files changed, 184 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Issue3659.vb diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index a70de1e14..5accf84e3 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -224,6 +224,8 @@ + + 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/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index a700d4e7c..f608cca35 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) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs index 5aa9064e2..2cc1ba5ef 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs @@ -69,11 +69,79 @@ namespace ICSharpCode.Decompiler.IL.Transforms container.SortBlocks(deleteUnreachableBlocks: true); } + PropagateExceptionVariable(context, catchBlock); + } + else if (catchBlock.Filter is BlockContainer filterContainer + && MatchTypeTestConjunction(catchBlock.Variable, filterContainer, + out var conjunctionType, out var typeTest) + && conjunctionType.GetStackType() == catchBlock.Variable.StackType) + { + context.Step($"Detected catch-when type test for {catchBlock.Variable.Name}", typeTest); + catchBlock.Variable.Type = conjunctionType; + var remainder = typeTest.Right; + typeTest.ReplaceWith(remainder); + context.EndStep(remainder); + PropagateExceptionVariable(context, catchBlock); } } } + /// + /// BlockContainer { + /// Block entryPoint (incoming: 1) { + /// leave container(bit.and(bit.and(comp(isinst T(ldloc exceptionVar) != ldnull), cond1), cond2)) + /// } + /// } + /// The Visual Basic compiler emits the whole filter as one non-short-circuiting + /// expression rather than the block chain csc emits, so the type test sits in a + /// conjunction instead of a branch. On a match, typeTest is the innermost `bit.and`, + /// whose right operand is the filter that remains once the test moves to the catch type. + /// + bool MatchTypeTestConjunction(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; + // Once the test moves to the catch type, the other conjuncts stop running for a + // non-matching exception, which is only invisible if they have no side effects. + if (!SemanticHelper.IsPure(condition.Flags)) + return false; + // The test is the leftmost operand of a left-nested chain of `&`. + while (condition is BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd } and) + { + if (MatchTypeTest(and.Left, exceptionVar, out exceptionType)) + { + typeTest = and; + return true; + } + condition = and.Left; + } + return false; + } + + /// + /// comp(isinst T(ldloc exceptionVar) != ldnull), however the compiler spelled the null test. + /// + static bool MatchTypeTest(ILInstruction condition, ILVariable exceptionVar, out IType exceptionType) + { + exceptionType = null; + if (condition is not Comp comp || !comp.Right.MatchLdNull()) + return false; + // `cgt.un x, null` is how both compilers spell `x != null` for a reference. + if (comp.Kind != ComparisonKind.Inequality + && !(comp.Kind == ComparisonKind.GreaterThan && comp.InputType == StackType.O)) + return false; + if (!comp.Left.MatchIsInst(out var argument, out exceptionType)) + return false; + return argument.MatchLdLoc(exceptionVar); + } + /// /// catch E_189 : 0200007C System.Exception when (BlockContainer { /// Block IL_0079 (incoming: 1) { From 4a6dcd8d68590596ba5111ad444e22e44a299dd2 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 15 Sep 2026 19:16:29 +0200 Subject: [PATCH 2/3] Match the VB On Error catch filter exactly Only vbc's On Error lowering produces this filter; structured Catch...When filters call SetProjectError and never reach it. Roslyn emits it from a single code path with System.Exception as the type, and legacy vbc output has the same shape, so there is no chain of unknown conjuncts to walk. The transform runs before the expression transforms canonicalize comparisons, so the filter still compares with cgt against ldnull and cgt.un against zero: the ldnull comparison is fixed up first, and MatchCompUnsignedZero accepts both the unsigned and canonical form. Assisted-by: Claude:claude-opus-5:Claude Code --- .../IL/Instructions/PatternMatching.cs | 19 +++++ .../DetectCatchWhenConditionBlocks.cs | 79 +++++++------------ 2 files changed, 49 insertions(+), 49 deletions(-) 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 2cc1ba5ef..9b6d7e67b 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs @@ -72,15 +72,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms PropagateExceptionVariable(context, catchBlock); } else if (catchBlock.Filter is BlockContainer filterContainer - && MatchTypeTestConjunction(catchBlock.Variable, filterContainer, - out var conjunctionType, out var typeTest) - && conjunctionType.GetStackType() == catchBlock.Variable.StackType) + && MatchVBOnErrorCatchFilter(context, catchBlock.Variable, filterContainer, out exceptionType, out var typeTest) + && exceptionType.GetStackType() == catchBlock.Variable.StackType) { - context.Step($"Detected catch-when type test for {catchBlock.Variable.Name}", typeTest); - catchBlock.Variable.Type = conjunctionType; - var remainder = typeTest.Right; - typeTest.ReplaceWith(remainder); - context.EndStep(remainder); + 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); } @@ -90,16 +89,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// BlockContainer { /// Block entryPoint (incoming: 1) { - /// leave container(bit.and(bit.and(comp(isinst T(ldloc exceptionVar) != ldnull), cond1), cond2)) + /// leave container(bit.and(bit.and(comp(isinst System.Exception(ldloc exceptionVar) > ldnull), comp.unsigned(ldloc activeHandler > ldc.i4 0)), logic.not(ldloc resumeTarget))) /// } /// } - /// The Visual Basic compiler emits the whole filter as one non-short-circuiting - /// expression rather than the block chain csc emits, so the type test sits in a - /// conjunction instead of a branch. On a match, typeTest is the innermost `bit.and`, - /// whose right operand is the filter that remains once the test moves to the catch type. + /// Only emitted for On Error Resume Next/GoTo. /// - bool MatchTypeTestConjunction(ILVariable exceptionVar, BlockContainer container, - out IType exceptionType, out BinaryNumericInstruction typeTest) + bool MatchVBOnErrorCatchFilter(ILTransformContext context, ILVariable exceptionVar, BlockContainer container, out IType exceptionType, out BinaryNumericInstruction typeTest) { exceptionType = null; typeTest = null; @@ -108,38 +103,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!entryPoint.Instructions[0].MatchLeave(container, out var condition)) return false; - // Once the test moves to the catch type, the other conjuncts stop running for a - // non-matching exception, which is only invisible if they have no side effects. - if (!SemanticHelper.IsPure(condition.Flags)) + if (condition is not BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd, Left: BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd } bitAnd } outer) return false; - // The test is the leftmost operand of a left-nested chain of `&`. - while (condition is BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd } and) - { - if (MatchTypeTest(and.Left, exceptionVar, out exceptionType)) - { - typeTest = and; - return true; - } - condition = and.Left; - } - 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 T(ldloc exceptionVar) != ldnull), however the compiler spelled the null test. + /// comp(isinst exceptionType(ldloc exceptionVar) != ldnull) /// - static bool MatchTypeTest(ILInstruction condition, ILVariable exceptionVar, out IType exceptionType) + static bool MatchIsInstNotNull(ILInstruction condition, ILVariable exceptionVar, out ILInstruction exceptionSlot, out IType exceptionType) { + exceptionSlot = null; exceptionType = null; - if (condition is not Comp comp || !comp.Right.MatchLdNull()) - return false; - // `cgt.un x, null` is how both compilers spell `x != null` for a reference. - if (comp.Kind != ComparisonKind.Inequality - && !(comp.Kind == ComparisonKind.GreaterThan && comp.InputType == StackType.O)) - return false; - if (!comp.Left.MatchIsInst(out var argument, out exceptionType)) - return false; - return argument.MatchLdLoc(exceptionVar); + return condition.MatchCompNotEqualsNull(out var arg) + && arg.MatchIsInst(out exceptionSlot, out exceptionType) + && exceptionSlot.MatchLdLoc(exceptionVar); } /// @@ -263,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; } From 483a8661f65339feb5343155266534a453c8dea7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 15 Sep 2026 19:16:29 +0200 Subject: [PATCH 3/3] Add VB tests for On Error and Try/Catch/Finally VB lowers error handling differently from C# and no fixture covered it: every Catch brackets its body with SetProjectError/ClearProjectError, Catch...When moves that call into the filter, and On Error becomes one try block with a dispatch switch driven by line and handler state. The expected output is the current decompilation, rough spots included (delegate-invoked filter blocks; gotos into the dispatch switch that leave unreachable code, which keeps VBOnError.cs out of the warnings-as-errors project), so improvements show up as diffs. IL offset labels differ per compiler and optimization level, hence the per-method #if variants. Legacy vbc output was verified on Windows. The correctness test covers what a pretty test cannot: catching object made the decompiled On Error code fail to recompile with CS0155, and the round trip shows the rewritten dispatch code still runs the same. Like the mcs configurations, the legacy and Roslyn 2.10/.NET Core 2.2 ones recompile the decompiled VB code with the latest Roslyn: C# 5 cannot express the exception filters VB error handling compiles to, and the .NET Core 2.2 Microsoft.VisualBasic.dll lacks Information.Err and ProjectData.CreateProjectError. Assisted-by: Claude:claude-opus-5:Claude Code --- .../CorrectnessTestRunner.cs | 18 + .../ICSharpCode.Decompiler.Tests.csproj | 5 + .../Correctness/VBOnErrorCorrectness.vb | 91 + .../TestCases/VBPretty/VBOnError.cs | 3120 +++++++++++++++++ .../TestCases/VBPretty/VBOnError.vb | 107 + .../TestCases/VBPretty/VBTryCatchFinally.cs | 619 ++++ .../TestCases/VBPretty/VBTryCatchFinally.vb | 308 ++ .../VBPrettyTestRunner.cs | 14 + 8 files changed, 4282 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb 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 5accf84e3..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 @@ + + @@ -306,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/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 f608cca35..3b3bcd78b 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -151,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) { @@ -170,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) {