mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Merge pull request #4134 from dualfroz/fix-vb-exception-filter-type-test
Recognize a VB exception filter's type test
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<None Include="TestCases\Correctness\StackTests.il" />
|
||||
<None Include="TestCases\Correctness\StackTypes.il" />
|
||||
<None Include="TestCases\Correctness\Uninit.vb" />
|
||||
<None Include="TestCases\Correctness\VBOnErrorCorrectness.vb" />
|
||||
<None Include="TestCases\Disassembler\Pretty\GenericConstraints.il" />
|
||||
<None Include="TestCases\Disassembler\Pretty\NegativeConstants.il" />
|
||||
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
|
||||
@@ -161,6 +162,8 @@
|
||||
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
|
||||
<None Include="TestCases\VBPretty\VBNonGenericForEach.vb" />
|
||||
<None Include="TestCases\VBPretty\YieldReturn.vb" />
|
||||
<None Include="TestCases\VBPretty\VBTryCatchFinally.vb" />
|
||||
<None Include="TestCases\VBPretty\VBOnError.vb" />
|
||||
<None Include="TestCases\VBPretty\Issue1906.vb" />
|
||||
<None Include="TestCases\VBPretty\Issue2192.vb" />
|
||||
<None Include="TestCases\VBPretty\Select.vb" />
|
||||
@@ -224,6 +227,8 @@
|
||||
<Compile Remove="TestCases\ILPretty\Issue3729.cs" />
|
||||
<None Include="TestCases\ILPretty\Issue3729.cs" />
|
||||
<None Include="TestCases\ILPretty\Issue3729.il" />
|
||||
<Compile Remove="TestCases\VBPretty\Issue3659.cs" />
|
||||
<None Include="TestCases\VBPretty\Issue3659.cs" />
|
||||
<Compile Remove="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
|
||||
<None Include="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
|
||||
<Compile Remove="TestCases\ILPretty\FSharpLoops_Debug.cs" />
|
||||
@@ -304,6 +309,8 @@
|
||||
<None Include="TestCases\Ugly\TopLevelProgramAsync.Expected.cs" />
|
||||
<Compile Remove="TestCases\VBPretty\VBCompoundAssign.cs" />
|
||||
<None Include="TestCases\VBPretty\VBCompoundAssign.cs" />
|
||||
<Compile Remove="TestCases\VBPretty\VBOnError.cs" />
|
||||
<None Include="TestCases\VBPretty\VBOnError.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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<bool>)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<bool>)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<bool>)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<bool>)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<bool>)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<bool>)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<bool>)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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -132,6 +132,12 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Issue3659([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Issue1906([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
@@ -145,6 +151,13 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VBOnError([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
IgnoreIfVbRuntimeSubstituted(options);
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
@@ -164,6 +177,13 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VBTryCatchFinally([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
IgnoreIfVbRuntimeSubstituted(options);
|
||||
await Run(options: options | CompilerOptions.Library);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For <paramref name="kind"/> == Equality, matches 'comp(arg == ldc.i4 0)' or 'comp.unsigned(arg <= ldc.i4 0)'.
|
||||
/// For <paramref name="kind"/> == Inequality, matches 'comp(arg != ldc.i4 0)' or 'comp.unsigned(arg > ldc.i4 0)'.
|
||||
/// </summary>
|
||||
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)
|
||||
|
||||
@@ -69,11 +69,67 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
||||
container.SortBlocks(deleteUnreachableBlocks: true);
|
||||
}
|
||||
|
||||
PropagateExceptionVariable(context, catchBlock);
|
||||
}
|
||||
else if (catchBlock.Filter is BlockContainer filterContainer
|
||||
&& MatchVBOnErrorCatchFilter(context, catchBlock.Variable, filterContainer, out exceptionType, out var typeTest)
|
||||
&& exceptionType.GetStackType() == catchBlock.Variable.StackType)
|
||||
{
|
||||
context.Step($"Detected catch-when for {catchBlock.Variable.Name} (bit.and)", typeTest);
|
||||
catchBlock.Variable.Type = exceptionType;
|
||||
var condition = typeTest.Right;
|
||||
typeTest.ReplaceWith(condition);
|
||||
context.EndStep(condition);
|
||||
|
||||
PropagateExceptionVariable(context, catchBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BlockContainer {
|
||||
/// Block entryPoint (incoming: 1) {
|
||||
/// leave container(bit.and(bit.and(comp(isinst System.Exception(ldloc exceptionVar) > ldnull), comp.unsigned(ldloc activeHandler > ldc.i4 0)), logic.not(ldloc resumeTarget)))
|
||||
/// }
|
||||
/// }
|
||||
/// Only emitted for On Error Resume Next/GoTo.
|
||||
/// </summary>
|
||||
bool MatchVBOnErrorCatchFilter(ILTransformContext context, ILVariable exceptionVar, BlockContainer container, out IType exceptionType, out BinaryNumericInstruction typeTest)
|
||||
{
|
||||
exceptionType = null;
|
||||
typeTest = null;
|
||||
var entryPoint = container.EntryPoint;
|
||||
if (entryPoint == null || entryPoint.IncomingEdgeCount != 1 || entryPoint.Instructions.Count != 1)
|
||||
return false;
|
||||
if (!entryPoint.Instructions[0].MatchLeave(container, out var condition))
|
||||
return false;
|
||||
if (condition is not BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd, Left: BinaryNumericInstruction { Operator: BinaryNumericOperator.BitAnd } bitAnd } outer)
|
||||
return false;
|
||||
if (!outer.Right.MatchCompUnsignedZero(ComparisonKind.Equality, out var resumeTarget) || !resumeTarget.MatchLdLoc(out _))
|
||||
return false;
|
||||
if (!bitAnd.Right.MatchCompUnsignedZero(ComparisonKind.Inequality, out var activeHandler) || !activeHandler.MatchLdLoc(out _))
|
||||
return false;
|
||||
if (bitAnd.Left is not Comp comp)
|
||||
return false;
|
||||
EarlyExpressionTransforms.FixComparisonKindLdNull(comp, context);
|
||||
if (!MatchIsInstNotNull(comp, exceptionVar, out _, out exceptionType) || !exceptionType.IsKnownType(KnownTypeCode.Exception))
|
||||
return false;
|
||||
typeTest = bitAnd;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// comp(isinst exceptionType(ldloc exceptionVar) != ldnull)
|
||||
/// </summary>
|
||||
static bool MatchIsInstNotNull(ILInstruction condition, ILVariable exceptionVar, out ILInstruction exceptionSlot, out IType exceptionType)
|
||||
{
|
||||
exceptionSlot = null;
|
||||
exceptionType = null;
|
||||
return condition.MatchCompNotEqualsNull(out var arg)
|
||||
&& arg.MatchIsInst(out exceptionSlot, out exceptionType)
|
||||
&& exceptionSlot.MatchLdLoc(exceptionVar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// catch E_189 : 0200007C System.Exception when (BlockContainer {
|
||||
/// Block IL_0079 (incoming: 1) {
|
||||
@@ -195,18 +251,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
||||
// br falseBlock
|
||||
if (!entryPoint.Instructions[0].MatchIfInstruction(out var condition, out var branch))
|
||||
return false;
|
||||
if (!condition.MatchCompNotEquals(out var left, out var right))
|
||||
if (!MatchIsInstNotNull(condition, exceptionVar, out exceptionSlot, out exceptionType))
|
||||
return false;
|
||||
if (!entryPoint.Instructions[1].MatchBranch(out var falseBlock) || !MatchFalseBlock(container, falseBlock, out var returnVar, out var exitBlock))
|
||||
return false;
|
||||
if (!left.MatchIsInst(out exceptionSlot, out exceptionType))
|
||||
return false;
|
||||
if (!exceptionSlot.MatchLdLoc(exceptionVar))
|
||||
return false;
|
||||
if (right.MatchLdNull())
|
||||
{
|
||||
return branch.MatchBranch(out whenConditionBlock);
|
||||
}
|
||||
return branch.MatchBranch(out whenConditionBlock);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user