Upstream icsharpcode/ILSpy state of the touched files before d5ff770959
This commit is contained in:
1 parent
167098573c
commit
aa0b6871d2
3 files changed
+756
No files matched your search
@@ -0,0 +1,309 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net11.0</TargetFramework>
|
||||||
|
<LangVersion>preview</LangVersion>
|
||||||
|
<!-- A single (host) RID makes the build copy the native DiaSymReader.Native assets the
|
||||||
|
Windows PDB tests need; the explicit RID list makes packages.lock.json carry every RID
|
||||||
|
(host-independent), so the lock does not drift between Linux and Windows restores. -->
|
||||||
|
<RuntimeIdentifier>$(NETCoreSdkRuntimeIdentifier)</RuntimeIdentifier>
|
||||||
|
<RuntimeIdentifiers>win-x64;win-arm64;linux-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
<GenerateTestingPlatformEntryPoint>true</GenerateTestingPlatformEntryPoint>
|
||||||
|
<StartupObject>ICSharpCode.Decompiler.Tests.MicrosoftTestingPlatformEntryPoint</StartupObject>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
|
||||||
|
<!-- The suite runs dozens of allocation-heavy decompiles concurrently (one NUnit worker per
|
||||||
|
logical CPU, each roundtrip adding WholeProjectDecompiler's own Parallel.ForEach). Workstation
|
||||||
|
GC stops the whole process for every gen0/gen1 collection any worker triggers; measured on a
|
||||||
|
24-thread machine that was ~300 s of pause in a ~550 s run. Server GC gives each core its own
|
||||||
|
heap and collects in parallel. -->
|
||||||
|
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||||
|
<!-- NU1902/1903 are "Package 'X' has a known security vulnerability". In our tests, we don't care. -->
|
||||||
|
<!-- CA1416 fires because the TFM dropped its -windows suffix: Windows-only helpers (SdkUtility,
|
||||||
|
Tester.SignAssembly/FindMSBuild/RunWithTestRunner) and Windows-only test inputs (Console.CapsLock
|
||||||
|
in Async/Switch fixtures) are reachable from non-Windows in principle, but gated by
|
||||||
|
OperatingSystem.IsWindows() + Assert.Ignore at runtime. The analyzer can't see that. -->
|
||||||
|
<NoWarn>$(NoWarn);1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632;626;8618;8714;8602;8981;NU1902;NU1903;CA1416</NoWarn>
|
||||||
|
<DefineConstants>ROSLYN;ROSLYN2;ROSLYN3;ROSLYN4;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100;CS110;CS120;CS130</DefineConstants>
|
||||||
|
|
||||||
|
<GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute>
|
||||||
|
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
|
||||||
|
<GenerateAssemblyInformationalVersionAttribute>False</GenerateAssemblyInformationalVersionAttribute>
|
||||||
|
<!-- Compile items come from the SDK default **/*.cs glob; the ItemGroup near the end excludes
|
||||||
|
only the test-case sources that still do not compile under the current toolchain. Default
|
||||||
|
None globbing stays off so the non-C# inputs (.il/.vb/.fs) and Content stay explicit. -->
|
||||||
|
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
|
||||||
|
|
||||||
|
<AutoGenerateBindingRedirects>True</AutoGenerateBindingRedirects>
|
||||||
|
|
||||||
|
<SignAssembly>True</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DefineConstants>TRACE;DEBUG;$(DefineConstants)</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DefineConstants>TRACE;$(DefineConstants)</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DiffLib" />
|
||||||
|
<PackageReference Include="CliWrap" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
|
||||||
|
<PackageReference Include="NuGet.Protocol" />
|
||||||
|
<PackageReference Include="System.Collections.Immutable" />
|
||||||
|
<PackageReference Include="System.Reflection.Metadata" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" />
|
||||||
|
<PackageReference Include="Microsoft.DiaSymReader.Converter.Xml" />
|
||||||
|
<PackageReference Include="Microsoft.DiaSymReader" />
|
||||||
|
<!-- Referenced unconditionally so restore yields the same packages.lock.json on every OS.
|
||||||
|
The native asset only resolves for win-* RIDs; non-Windows builds ignore it, and the
|
||||||
|
tests that use it are gated by OperatingSystem.IsWindows() + Assert.Ignore at runtime. -->
|
||||||
|
<PackageReference Include="Microsoft.DiaSymReader.Native" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" />
|
||||||
|
<PackageReference Include="coverlet.MTP" />
|
||||||
|
<PackageReference Include="NUnit" />
|
||||||
|
<PackageReference Include="AwesomeAssertions" />
|
||||||
|
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" />
|
||||||
|
<PackageReference Include="Microsoft.Testing.Extensions.VSTestBridge" />
|
||||||
|
<PackageReference Include="System.Memory" />
|
||||||
|
<PackageReference Include="Mono.Cecil" />
|
||||||
|
<PackageReference Include="Microsoft.NETCore.ILAsm" />
|
||||||
|
<PackageReference Include="Microsoft.NETCore.ILDAsm" />
|
||||||
|
<PackageReference Include="System.Resources.Extensions" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- A .resources container holding two stream entries, so this assembly itself is the module
|
||||||
|
WholeProjectDecompiler's per-entry resource path can be exercised against. -->
|
||||||
|
<EmbeddedResource Include="Helpers\TwoStreamEntries.resources" LogicalName="TwoStreamEntries.g.resources" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ICSharpCode.ILSpyX\ICSharpCode.ILSpyX.csproj" />
|
||||||
|
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TestCases\Correctness\Jmp.il" />
|
||||||
|
<None Include="TestCases\Correctness\StackTests.il" />
|
||||||
|
<None Include="TestCases\Correctness\StackTypes.il" />
|
||||||
|
<None Include="TestCases\Correctness\Uninit.vb" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\GenericConstraints.il" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\NegativeConstants.il" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\SortMembers.expected.il" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\SortMembers.il" />
|
||||||
|
<None Include="TestCases\IsolatedDecompilation\IsolatedStaticCtor.il" />
|
||||||
|
<None Include="TestCases\ILPretty\ExtensionEncodingV2.il" />
|
||||||
|
<None Include="testcases\ilpretty\ExtensionEncodingV1.il" />
|
||||||
|
<None Include="TestCases\ILPretty\GuessAccessors.il" />
|
||||||
|
<None Include="TestCases\ILPretty\InaccessibleParameterTypes.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue2260SwitchString.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3442.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3344CkFinite.il" />
|
||||||
|
<None Include="testcases\ilpretty\Issue3465.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3466.il" />
|
||||||
|
<None Include="testcases\ilpretty\Issue3504.il" />
|
||||||
|
<None Include="testcases\ilpretty\Issue3524.il" />
|
||||||
|
<None Include="testcases\ilpretty\Issue3552.il" />
|
||||||
|
<None Include="TestCases\ILPretty\MonoFixed.il" />
|
||||||
|
<None Include="TestCases\Correctness\NonGenericConstrainedCallVirt.il" />
|
||||||
|
<None Include="TestCases\ILPretty\UnknownTypes.il" />
|
||||||
|
<None Include="TestCases\ILPretty\EvalOrder.il" />
|
||||||
|
<None Include="TestCases\ILPretty\CallIndirect.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1454.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1681.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1922.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1918.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue2104.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3421.il" />
|
||||||
|
<None Include="TestCases\ILPretty\WeirdEnums.il" />
|
||||||
|
<None Include="TestCases\ILPretty\EnumArithmeticOutOfRange.il" />
|
||||||
|
<None Include="TestCases\ILPretty\ConstantBlobs.il" />
|
||||||
|
<None Include="TestCases\ILPretty\CS1xSwitch_Debug.il" />
|
||||||
|
<None Include="TestCases\ILPretty\CS1xSwitch_Release.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1157.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue684.il" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpLoops.fs" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpLoops_Debug.il" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpLoops_Release.il" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpUsing.fs" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpUsing_Debug.il" />
|
||||||
|
<None Include="TestCases\ILPretty\DirectCallToExplicitInterfaceImpl.il" />
|
||||||
|
<None Include="TestCases\ILPretty\TruncatedAccessorBody.il" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpUsing_Release.il" />
|
||||||
|
<None Include="TestCases\Correctness\BitNot.il" />
|
||||||
|
<None Include="TestCases\Correctness\Readme.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\VBNonGenericForEach.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\YieldReturn.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\Issue1906.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\Issue2192.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\Select.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\VBAnonymousTypes.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\ParameterizedProperties.vb" />
|
||||||
|
<None Include="TestCases\ILPretty\Unsafe.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1389.il" />
|
||||||
|
<None Include="TestCases\ILPretty\SequenceOfNestedIfs.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1256.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1323.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1325.il" />
|
||||||
|
<None Include="TestCases\Disassembler\Pretty\SecurityDeclarations.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1038.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1145.il" />
|
||||||
|
<None Include="TestCases\ILPretty\NoAccessorProperties.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1047.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue959.il" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TestCases\PdbGen\*.cs" />
|
||||||
|
<None Include="TestCases\PdbGen\PinnedRegionWarning.il" />
|
||||||
|
<None Include="TestCases\PdbGen\PinnedLocalSlot.il" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TestCases\ILPretty\Issue646.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue379.il" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue982.il" />
|
||||||
|
<None Include="TestCases\Pretty\Readme.txt" />
|
||||||
|
<None Include="TestCases\VBPretty\VBCompoundAssign.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\Async.vb" />
|
||||||
|
<None Include="TestCases\VBPretty\VBPropertiesTest.vb" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Label="ExcludedTestInputs">
|
||||||
|
<!-- Test-case sources that cannot be compiled into the test assembly: decompiler inputs that
|
||||||
|
are not valid standalone C#, expected-output fixtures that reuse type names, and
|
||||||
|
MetadataAttributes.cs (applies assembly/module attributes that break NUnit discovery).
|
||||||
|
The harness compiles these from disk at test time; kept as None for IDE visibility. -->
|
||||||
|
<Compile Remove="TestCases\PdbGen\*.cs" />
|
||||||
|
<Compile Remove="TestCases\Correctness\ComInterop.cs" />
|
||||||
|
<None Include="TestCases\Correctness\ComInterop.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\CS1xSwitch_Debug.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\CS1xSwitch_Debug.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\CS1xSwitch_Release.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\CS1xSwitch_Release.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\CallIndirect.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\CallIndirect.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\InstanceOperatorCall.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\InstanceOperatorCall.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\InstanceOperatorCall.il" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\EnumArithmeticOutOfRange.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\EnumArithmeticOutOfRange.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\EmptyBodies.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\EmptyBodies.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\TruncatedAccessorBody.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\TruncatedAccessorBody.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\SealedRecordProtectedCopyCtor.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\SealedRecordProtectedCopyCtor.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue3729.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3729.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3729.il" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\FSharpLoops_Debug.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpLoops_Debug.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\FSharpLoops_Release.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpLoops_Release.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\FSharpUsing_Release.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\FSharpUsing_Release.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\GuessAccessors.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\GuessAccessors.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\InaccessibleParameterTypes.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\InaccessibleParameterTypes.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\NoAccessorProperties.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\NoAccessorProperties.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue1145.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1145.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue1325.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1325.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue1918.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue1918.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue2260SwitchString.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue2260SwitchString.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue2443.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue2443.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue3504.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue3504.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Issue646.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Issue646.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\UnknownTypes.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\UnknownTypes.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\Unsafe.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\Unsafe.cs" />
|
||||||
|
<Compile Remove="TestCases\ILPretty\WeirdEnums.cs" />
|
||||||
|
<None Include="TestCases\ILPretty\WeirdEnums.cs" />
|
||||||
|
<Compile Remove="TestCases\Pretty\FieldKeyword.cs" />
|
||||||
|
<None Include="TestCases\Pretty\FieldKeyword.cs" />
|
||||||
|
<Compile Remove="TestCases\Pretty\IndexRangeTest.cs" />
|
||||||
|
<None Include="TestCases\Pretty\IndexRangeTest.cs" />
|
||||||
|
<Compile Remove="TestCases\Pretty\MetadataAttributes.cs" />
|
||||||
|
<None Include="TestCases\Pretty\MetadataAttributes.cs" />
|
||||||
|
<Compile Remove="TestCases\Pretty\NullableRefTypes.cs" />
|
||||||
|
<None Include="TestCases\Pretty\NullableRefTypes.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\AggressiveScalarReplacementOfAggregates.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\AggressiveScalarReplacementOfAggregates.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoArrayInitializers.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoArrayInitializers.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoAutomaticProperties.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoAutomaticProperties.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoDecimalConstants.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoDecimalConstants.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoExtensionMethods.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoExtensionMethods.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoFieldKeyword.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoFieldKeyword.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoForEachStatement.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoForEachStatement.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoGetterOnlyAutomaticProperties.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoGetterOnlyAutomaticProperties.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoInitAccessors.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoInitAccessors.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoLocalFunctions.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoLocalFunctions.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoNewOfT.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoNewOfT.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoPropertiesAndEvents.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoPropertiesAndEvents.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\NoUnsignedRightShift.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\NoUnsignedRightShift.Expected.cs" />
|
||||||
|
<!-- top-level statements: neither the input nor the expected output can be compiled
|
||||||
|
into the test assembly, which is a library and has its own entry point rules -->
|
||||||
|
<Compile Remove="TestCases\Ugly\TopLevelProgram.cs" />
|
||||||
|
<None Include="TestCases\Ugly\TopLevelProgram.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\TopLevelProgram.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\TopLevelProgram.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\TopLevelProgramAsync.cs" />
|
||||||
|
<None Include="TestCases\Ugly\TopLevelProgramAsync.cs" />
|
||||||
|
<Compile Remove="TestCases\Ugly\TopLevelProgramAsync.Expected.cs" />
|
||||||
|
<None Include="TestCases\Ugly\TopLevelProgramAsync.Expected.cs" />
|
||||||
|
<Compile Remove="TestCases\VBPretty\VBCompoundAssign.cs" />
|
||||||
|
<None Include="TestCases\VBPretty\VBCompoundAssign.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using ICSharpCode.Decompiler.Tests.Helpers;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.Tests
|
||||||
|
{
|
||||||
|
[TestFixture, Parallelizable(ParallelScope.All)]
|
||||||
|
public class VBPrettyTestRunner
|
||||||
|
{
|
||||||
|
static readonly string TestCasePath = Tester.TestCasePath + "/VBPretty";
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AllFilesHaveTests()
|
||||||
|
{
|
||||||
|
var testNames = typeof(VBPrettyTestRunner).GetMethods()
|
||||||
|
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
|
||||||
|
.Select(m => m.Name)
|
||||||
|
.ToArray();
|
||||||
|
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles())
|
||||||
|
{
|
||||||
|
if (file.Extension.Equals(".vb", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var testName = file.Name.Split('.')[0];
|
||||||
|
Assert.That(testNames, Has.Member(testName));
|
||||||
|
Assert.That(File.Exists(Path.Combine(TestCasePath, testName + ".cs")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly CompilerOptions[] defaultOptions = Tester.SupportedOnCurrentPlatform(new[]
|
||||||
|
{
|
||||||
|
CompilerOptions.None,
|
||||||
|
CompilerOptions.Optimize,
|
||||||
|
CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn4_14_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn4_14_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn1_3_2,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
|
||||||
|
CompilerOptions.UseRoslyn2_10_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
|
||||||
|
CompilerOptions.UseRoslyn3_11_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn3_11_0,
|
||||||
|
CompilerOptions.UseRoslyn4_14_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn4_14_0,
|
||||||
|
CompilerOptions.UseRoslynLatest,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
|
||||||
|
});
|
||||||
|
|
||||||
|
static readonly CompilerOptions[] roslynOnlyOptions = Tester.SupportedOnCurrentPlatform(new[]
|
||||||
|
{
|
||||||
|
CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn4_14_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn4_14_0 | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
|
||||||
|
CompilerOptions.UseRoslyn1_3_2,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
|
||||||
|
CompilerOptions.UseRoslyn2_10_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
|
||||||
|
CompilerOptions.UseRoslyn3_11_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn3_11_0,
|
||||||
|
CompilerOptions.UseRoslyn4_14_0,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslyn4_14_0,
|
||||||
|
CompilerOptions.UseRoslynLatest,
|
||||||
|
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Async([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test] // TODO: legacy VB compound assign
|
||||||
|
public async Task VBCompoundAssign([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ParameterizedProperties([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Select([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task VBAnonymousTypes([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
IgnoreIfVbRuntimeSubstituted(options);
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Issue1906([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Issue2192([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
IgnoreIfVbRuntimeSubstituted(options);
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task VBAutomaticEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task VBNonGenericForEach([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
IgnoreIfVbRuntimeSubstituted(options);
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
|
||||||
|
{
|
||||||
|
await Run(options: options | CompilerOptions.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IgnoreIfVbRuntimeSubstituted(CompilerOptions options)
|
||||||
|
{
|
||||||
|
if (!OperatingSystem.IsWindows()
|
||||||
|
&& (options & CompilerOptions.UseRoslynMask) == CompilerOptions.UseRoslyn2_10_0
|
||||||
|
&& (options & CompilerOptions.TargetNet40) == 0)
|
||||||
|
{
|
||||||
|
Assert.Ignore("The non-Windows netcore-2.2 configuration substitutes the legacy " +
|
||||||
|
"Microsoft.VisualBasic as -vbruntime (see Tester.CompileVB); the resulting " +
|
||||||
|
"reference graph changes this test's decompiled output.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
|
||||||
|
{
|
||||||
|
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
|
||||||
|
var csFile = Path.Combine(TestCasePath, testName + ".cs");
|
||||||
|
var exeFile = TestsAssemblyOutput.GetFilePath(TestCasePath, testName, Tester.GetSuffix(options) + ".exe");
|
||||||
|
if (options.HasFlag(CompilerOptions.Library))
|
||||||
|
{
|
||||||
|
exeFile = Path.ChangeExtension(exeFile, ".dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
var executable = await Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile).ConfigureAwait(false);
|
||||||
|
settings ??= new DecompilerSettings { FileScopedNamespaces = false, SortCustomAttributes = true };
|
||||||
|
var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
|
||||||
|
Tester.RepeatOnIOError(() => File.Delete(decompiled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
// Copyright (c) 2017 Siegfried Pammer
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using ICSharpCode.Decompiler.TypeSystem;
|
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.IL.Transforms
|
||||||
|
{
|
||||||
|
public class DetectCatchWhenConditionBlocks : IILTransform
|
||||||
|
{
|
||||||
|
public void Run(ILFunction function, ILTransformContext context)
|
||||||
|
{
|
||||||
|
foreach (var catchBlock in function.Descendants.OfType<TryCatchHandler>())
|
||||||
|
{
|
||||||
|
if (catchBlock.Filter is BlockContainer container
|
||||||
|
&& MatchCatchWhenEntryPoint(catchBlock.Variable, container, container.EntryPoint,
|
||||||
|
out var exceptionType, out var exceptionSlot, out var whenConditionBlock)
|
||||||
|
&& exceptionType.GetStackType() == catchBlock.Variable.StackType)
|
||||||
|
{
|
||||||
|
// set exceptionType
|
||||||
|
catchBlock.Variable.Type = exceptionType;
|
||||||
|
// Block entryPoint (incoming: 1) {
|
||||||
|
// stloc temp(isinst exceptionType(ldloc exceptionVar))
|
||||||
|
// if (comp(ldloc temp != ldnull)) br whenConditionBlock
|
||||||
|
// br falseBlock
|
||||||
|
// }
|
||||||
|
// =>
|
||||||
|
// Block entryPoint (incoming: 1) {
|
||||||
|
// stloc temp(ldloc exceptionSlot)
|
||||||
|
// br whenConditionBlock
|
||||||
|
// }
|
||||||
|
var instructions = container.EntryPoint.Instructions;
|
||||||
|
if (instructions.Count == 3)
|
||||||
|
{
|
||||||
|
// stloc temp(isinst exceptionType(ldloc exceptionVar))
|
||||||
|
// if (comp(ldloc temp != ldnull)) br whenConditionBlock
|
||||||
|
// br falseBlock
|
||||||
|
context.Step($"Detected catch-when for {catchBlock.Variable.Name} (extra store)", instructions[0]);
|
||||||
|
((StLoc)instructions[0]).Value = exceptionSlot;
|
||||||
|
instructions[1].ReplaceWith(new Branch(whenConditionBlock));
|
||||||
|
instructions.RemoveAt(2);
|
||||||
|
container.SortBlocks(deleteUnreachableBlocks: true);
|
||||||
|
}
|
||||||
|
else if (instructions.Count == 2)
|
||||||
|
{
|
||||||
|
// if (comp(isinst exceptionType(ldloc exceptionVar) != ldnull)) br whenConditionBlock
|
||||||
|
// br falseBlock
|
||||||
|
context.Step($"Detected catch-when for {catchBlock.Variable.Name}", instructions[0]);
|
||||||
|
var branch = new Branch(whenConditionBlock);
|
||||||
|
instructions[0].ReplaceWith(branch);
|
||||||
|
instructions.RemoveAt(1);
|
||||||
|
context.EndStep(branch);
|
||||||
|
container.SortBlocks(deleteUnreachableBlocks: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PropagateExceptionVariable(context, catchBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// catch E_189 : 0200007C System.Exception when (BlockContainer {
|
||||||
|
/// Block IL_0079 (incoming: 1) {
|
||||||
|
/// stloc S_30(ldloc E_189)
|
||||||
|
/// br IL_0085
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// Block IL_0085 (incoming: 1) {
|
||||||
|
/// stloc I_1(ldloc S_30)
|
||||||
|
/// where S_30 and I_1 are single definition
|
||||||
|
/// =>
|
||||||
|
/// copy-propagate E_189 to replace all uses of S_30 and I_1
|
||||||
|
/// </summary>
|
||||||
|
static void PropagateExceptionVariable(ILTransformContext context, TryCatchHandler handler)
|
||||||
|
{
|
||||||
|
var exceptionVariable = handler.Variable;
|
||||||
|
if (!exceptionVariable.IsSingleDefinition)
|
||||||
|
return;
|
||||||
|
context.StepStartGroup(nameof(PropagateExceptionVariable));
|
||||||
|
int i = 0;
|
||||||
|
while (i < exceptionVariable.LoadInstructions.Count)
|
||||||
|
{
|
||||||
|
var load = exceptionVariable.LoadInstructions[i];
|
||||||
|
|
||||||
|
if (!load.IsDescendantOf(handler))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are only interested in store "statements" copying the exception variable
|
||||||
|
// without modifying it.
|
||||||
|
var statement = Block.GetContainingStatement(load);
|
||||||
|
if (!(statement is StLoc stloc))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// simple copy case:
|
||||||
|
// stloc b(ldloc a)
|
||||||
|
if (stloc.Value == load)
|
||||||
|
{
|
||||||
|
PropagateExceptionInstance(stloc);
|
||||||
|
}
|
||||||
|
// if the type of the cast-class instruction matches the exceptionType,
|
||||||
|
// this cast can be removed without losing any side-effects.
|
||||||
|
// Note: this would also hold true iff exceptionType were an exception derived
|
||||||
|
// from cc.Type, however, we are more restrictive to match the pattern exactly.
|
||||||
|
// stloc b(castclass exceptionType(ldloc a))
|
||||||
|
else if (stloc.Value is CastClass cc && cc.Type.Equals(exceptionVariable.Type) && cc.Argument == load)
|
||||||
|
{
|
||||||
|
stloc.Value = load;
|
||||||
|
PropagateExceptionInstance(stloc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropagateExceptionInstance(StLoc store)
|
||||||
|
{
|
||||||
|
foreach (var load in store.Variable.LoadInstructions.ToArray())
|
||||||
|
{
|
||||||
|
if (!load.IsDescendantOf(handler))
|
||||||
|
continue;
|
||||||
|
load.ReplaceWith(new LdLoc(exceptionVariable).WithILRange(load));
|
||||||
|
}
|
||||||
|
if (store.Variable.LoadCount == 0 && store.Parent is Block block)
|
||||||
|
{
|
||||||
|
block.Instructions.RemoveAt(store.ChildIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.StepEndGroup(keepIfEmpty: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block entryPoint (incoming: 1) {
|
||||||
|
/// stloc temp(isinst exceptionType(ldloc exceptionVar))
|
||||||
|
/// if (comp(ldloc temp != ldnull)) br whenConditionBlock
|
||||||
|
/// br falseBlock
|
||||||
|
/// }
|
||||||
|
/// </summary>
|
||||||
|
bool MatchCatchWhenEntryPoint(ILVariable exceptionVar, BlockContainer container, Block entryPoint, out IType exceptionType, out ILInstruction exceptionSlot, out Block whenConditionBlock)
|
||||||
|
{
|
||||||
|
exceptionType = null;
|
||||||
|
exceptionSlot = null;
|
||||||
|
whenConditionBlock = null;
|
||||||
|
if (entryPoint == null || entryPoint.IncomingEdgeCount != 1)
|
||||||
|
return false;
|
||||||
|
if (entryPoint.Instructions.Count == 3)
|
||||||
|
{
|
||||||
|
// stloc temp(isinst exceptionType(ldloc exceptionVar))
|
||||||
|
// if (comp(ldloc temp != ldnull)) br whenConditionBlock
|
||||||
|
// br falseBlock
|
||||||
|
if (!entryPoint.Instructions[0].MatchStLoc(out var temp, out var isinst) ||
|
||||||
|
temp.Kind != VariableKind.StackSlot || !isinst.MatchIsInst(out exceptionSlot, out exceptionType))
|
||||||
|
return false;
|
||||||
|
if (!exceptionSlot.MatchLdLoc(exceptionVar))
|
||||||
|
return false;
|
||||||
|
if (!entryPoint.Instructions[1].MatchIfInstruction(out var condition, out var branch))
|
||||||
|
return false;
|
||||||
|
if (!condition.MatchCompNotEquals(out var left, out var right))
|
||||||
|
return false;
|
||||||
|
if (!entryPoint.Instructions[2].MatchBranch(out var falseBlock) || !MatchFalseBlock(container, falseBlock, out var returnVar, out var exitBlock))
|
||||||
|
return false;
|
||||||
|
if ((left.MatchLdNull() && right.MatchLdLoc(temp)) || (right.MatchLdNull() && left.MatchLdLoc(temp)))
|
||||||
|
{
|
||||||
|
return branch.MatchBranch(out whenConditionBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (entryPoint.Instructions.Count == 2)
|
||||||
|
{
|
||||||
|
// if (comp(isinst exceptionType(ldloc exceptionVar) != ldnull)) br whenConditionBlock
|
||||||
|
// br falseBlock
|
||||||
|
if (!entryPoint.Instructions[0].MatchIfInstruction(out var condition, out var branch))
|
||||||
|
return false;
|
||||||
|
if (!condition.MatchCompNotEquals(out var left, out var right))
|
||||||
|
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block falseBlock (incoming: 1) {
|
||||||
|
/// stloc returnVar(ldc.i4 0)
|
||||||
|
/// br exitBlock
|
||||||
|
/// }
|
||||||
|
/// </summary>
|
||||||
|
bool MatchFalseBlock(BlockContainer container, Block falseBlock, out ILVariable returnVar, out Block exitBlock)
|
||||||
|
{
|
||||||
|
returnVar = null;
|
||||||
|
exitBlock = null;
|
||||||
|
if (falseBlock.IncomingEdgeCount != 1 || falseBlock.Instructions.Count != 2)
|
||||||
|
return false;
|
||||||
|
return falseBlock.Instructions[0].MatchStLoc(out returnVar, out var zero) &&
|
||||||
|
zero.MatchLdcI4(0) && falseBlock.Instructions[1].MatchBranch(out exitBlock) &&
|
||||||
|
MatchExitBlock(container, exitBlock, returnVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block exitBlock(incoming: 2) {
|
||||||
|
/// leave container(ldloc returnVar)
|
||||||
|
/// }
|
||||||
|
/// </summary>
|
||||||
|
bool MatchExitBlock(BlockContainer container, Block exitBlock, ILVariable returnVar)
|
||||||
|
{
|
||||||
|
if (exitBlock.IncomingEdgeCount != 2 || exitBlock.Instructions.Count != 1)
|
||||||
|
return false;
|
||||||
|
return exitBlock.Instructions[0].MatchLeave(container, out var value) &&
|
||||||
|
value.MatchLdLoc(returnVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user