Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into cs73-stackalloc-initializers

pull/1246/head
Siegfried Pammer 7 years ago
parent
commit
7e89e3dc3e
  1. 2
      ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj
  2. 14
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  4. 90
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  5. 13
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs
  6. 19
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  7. 39
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs
  8. 11
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1323.cs
  9. 40
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1323.il
  10. 2
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs
  11. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs
  12. 26
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.opt.roslyn.il
  13. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.roslyn.il
  14. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs
  15. 17
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il
  16. 20
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il
  17. 24
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs
  18. 76
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.il
  19. 65
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.opt.il
  20. 61
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.opt.roslyn.il
  21. 83
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.roslyn.il
  22. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  23. 90
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.il
  24. 74
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.opt.il
  25. 68
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.opt.roslyn.il
  26. 84
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.roslyn.il
  27. 96
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
  28. 233
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.il
  29. 247
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.opt.il
  30. 677
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.opt.roslyn.il
  31. 678
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.roslyn.il
  32. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs
  33. 6390
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.opt.roslyn.il
  34. 7088
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.roslyn.il
  35. 203
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.il
  36. 201
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.roslyn.il
  37. 270
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs
  38. 949
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.il
  39. 650
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.opt.il
  40. 668
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.opt.roslyn.il
  41. 954
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.roslyn.il
  42. 339
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs
  43. 7400
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.il
  44. 5897
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.opt.il
  45. 6068
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.opt.roslyn.il
  46. 6641
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.roslyn.il
  47. 22
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  48. 8
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
  49. 26
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  50. 49
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  51. 39
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  52. 17
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  53. 8
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  54. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  55. 13
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  56. 44
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  57. 2
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  58. 1
      ICSharpCode.Decompiler/Documentation/IdStringProvider.cs
  59. 5
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  60. 10
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  61. 4
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs
  62. 12
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  63. 9
      ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs
  64. 7
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
  65. 4
      ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs
  66. 2
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs
  67. 1
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs
  68. 116
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  69. 32
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  70. 1
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  71. 2
      ICSharpCode.Decompiler/IL/Instructions/Comp.cs
  72. 2
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  73. 21
      ICSharpCode.Decompiler/IL/SemanticHelper.cs
  74. 5
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  75. 11
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  76. 21
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  77. 1
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  78. 5
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs
  79. 30
      ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs
  80. 418
      ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs
  81. 2
      ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs
  82. 2
      ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs
  83. 11
      ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
  84. 34
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs
  85. 8
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs
  86. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  87. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  88. 5
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  89. 22
      ILSpy.AddIn/Commands/OpenILSpyCommand.cs
  90. 3
      ILSpy.AddIn/ILSpy.AddIn.csproj
  91. 112
      ILSpy.AddIn/ILSpyInstance.cs
  92. 2
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
  93. 10
      ILSpy.Tests/ILSpy.Tests.csproj
  94. 121
      ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs
  95. 3
      ILSpy/Controls/GridViewColumnAutoSize.cs
  96. 16
      ILSpy/Controls/ResourceObjectTable.xaml
  97. 16
      ILSpy/Controls/ResourceStringTable.xaml
  98. 2
      ILSpy/ILSpy.csproj
  99. 1
      ILSpy/Languages/CSharpLanguage.cs
  100. 22
      ILSpy/MainWindow.xaml.cs
  101. Some files were not shown because too many files have changed in this diff Show More

2
ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
</ItemGroup>
<ItemGroup>

14
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -37,11 +37,11 @@ @@ -37,11 +37,11 @@
<ItemGroup>
<PackageReference Include="DiffLib" Version="2017.7.26.1241" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="2.8.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.9.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="NUnit" Version="3.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="2.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.11.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="NUnit" Version="3.11.0" />
</ItemGroup>
<ItemGroup>
@ -71,11 +71,15 @@ @@ -71,11 +71,15 @@
<Compile Include="TestCases\Correctness\LocalFunctions.cs" />
<Compile Include="TestCases\Correctness\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\ILPretty\Issue1256.cs" />
<Compile Include="TestCases\ILPretty\Issue1323.cs" />
<Compile Include="TestCases\Pretty\CS73_StackAllocInitializers.cs" />
<Compile Include="TestCases\Pretty\OptionalArguments.cs" />
<Compile Include="TestCases\Pretty\CustomShortCircuitOperators.cs" />
<Compile Include="TestCases\Pretty\ReduceNesting.cs" />
<Compile Include="TestCases\Pretty\TypeTests.cs" />
<Compile Include="TestCases\Pretty\YieldReturn.cs" />
<None Include="TestCases\ILPretty\Issue1256.il" />
<None Include="TestCases\ILPretty\Issue1323.il" />
<None Include="TestCases\Ugly\NoDecimalConstants.Expected.cs" />
<Compile Include="TestCases\Ugly\NoDecimalConstants.cs" />
<None Include="TestCases\Disassembler\Pretty\SecurityDeclarations.il" />

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -124,6 +124,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -124,6 +124,12 @@ namespace ICSharpCode.Decompiler.Tests
Run();
}
[Test]
public void Issue1323()
{
Run();
}
[Test]
public void FSharpLoops_Debug()
{

90
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -85,31 +85,31 @@ namespace ICSharpCode.Decompiler.Tests @@ -85,31 +85,31 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void InlineAssignmentTest([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void InlineAssignmentTest([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CompoundAssignmentTest([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void CompoundAssignmentTest([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ShortCircuit([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void ShortCircuit([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomShortCircuitOperators([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void CustomShortCircuitOperators([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ExceptionHandling([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void ExceptionHandling([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
NullPropagation = false,
@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void Switch([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void Switch([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
@ -128,49 +128,55 @@ namespace ICSharpCode.Decompiler.Tests @@ -128,49 +128,55 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void DelegateConstruction([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void ReduceNesting([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AnonymousTypes([ValueSource("defaultOptionsWithMcs")] CSharpCompilerOptions cscOptions)
public void DelegateConstruction([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Async([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void AnonymousTypes([ValueSource(nameof(defaultOptionsWithMcs))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Lock([ValueSource("defaultOptionsWithMcs")] CSharpCompilerOptions cscOptions)
public void Async([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Using([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void Lock([ValueSource(nameof(defaultOptionsWithMcs))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void LiftedOperators([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void Using([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Generics([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void LiftedOperators([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Loops([ValueSource("defaultOptionsWithMcs")] CSharpCompilerOptions cscOptions)
public void Generics([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Loops([ValueSource(nameof(defaultOptionsWithMcs))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
@ -179,62 +185,62 @@ namespace ICSharpCode.Decompiler.Tests @@ -179,62 +185,62 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void PropertiesAndEvents([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AutoProperties([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void AutoProperties([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void QueryExpressions([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void QueryExpressions([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TypeAnalysisTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void TypeAnalysisTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CheckedUnchecked([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void CheckedUnchecked([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void UnsafeCode([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void UnsafeCode([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void PInvoke([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void PInvoke([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
// This tests needs our own disassembler; ildasm has a bug with marshalinfo.
RunForLibrary(cscOptions: cscOptions, asmOptions: AssemblerOptions.UseOwnDisassembler);
}
[Test]
public void InitializerTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void InitializerTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void DynamicTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void DynamicTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ExpressionTrees([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void ExpressionTrees([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
@ -246,79 +252,79 @@ namespace ICSharpCode.Decompiler.Tests @@ -246,79 +252,79 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void VariableNaming([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void VariableNaming([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void VariableNamingWithoutSymbols([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void VariableNamingWithoutSymbols([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings { UseDebugSymbols = false });
}
[Test]
public void CS72_PrivateProtected([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void CS72_PrivateProtected([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AsyncMain([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void AsyncMain([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}
[Test]
public void NullPropagation([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CS6_StringInterpolation([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void CS6_StringInterpolation([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}
[Test]
public void CS73_StackAllocInitializers([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void CS73_StackAllocInitializers([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void RefLocalsAndReturns([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void RefLocalsAndReturns([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void WellKnownConstants([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void WellKnownConstants([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void QualifierTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void QualifierTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TupleTests([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
public void TupleTests([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void NamedArguments([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void NamedArguments([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void OptionalArguments([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void OptionalArguments([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
@ -354,13 +360,19 @@ namespace ICSharpCode.Decompiler.Tests @@ -354,13 +360,19 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void MemberTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void MemberTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TypeTests([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TypeTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
public void YieldReturn([ValueSource(nameof(defaultOptions))] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}

13
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs

@ -79,6 +79,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -79,6 +79,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(NoForeachDueToMultipleCurrentAccess(new List<int> { 1, 2, 3, 4, 5 }));
Console.WriteLine(NoForeachCallWithSideEffect(new CustomClassEnumeratorWithIDisposable<int>()));
LoopWithGotoRepeat();
Console.WriteLine("LoopFollowedByIf: {0}", LoopFollowedByIf());
}
public static void ForWithMultipleVariables()
@ -246,5 +247,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -246,5 +247,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
}
Console.WriteLine("after finally");
}
private static int LoopFollowedByIf()
{
int num = 0;
while (num == 0) {
num++;
}
if (num == 0) {
return -1;
}
return num;
}
}
}

19
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Generics();
ConstructorTest();
TestIndexer();
Issue1281();
}
#region ConstructorTest
@ -86,6 +87,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -86,6 +87,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{
Console.WriteLine("TestCall with params: " + (p2 == null ? "null" : p2.Length.ToString()));
}
static void Issue1281()
{
var arg = new object[0];
TestCallIssue1281(arg);
TestCallIssue1281((object)arg);
TestCallIssue1281(new[] { arg });
}
static void TestCallIssue1281(params object[] args)
{
Console.Write("TestCallIssue1281: count = " + args.Length + ": ");
foreach (var arg in args) {
Console.Write(arg);
Console.Write(", ");
}
Console.WriteLine();
}
#endregion
#region Simple Overloaded Method

39
ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs

@ -76,6 +76,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -76,6 +76,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
int fieldOnThis;
public static IEnumerable<char> YieldChars {
get {
yield return 'a';
yield return 'b';
yield return 'c';
}
}
public static IEnumerable<string> SimpleYieldReturn()
{
yield return "A";
@ -188,8 +196,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -188,8 +196,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
yield return "E";
yield return "F";
// outer try-finally block
foreach (string line in input)
foreach (string line in input) {
yield return line.ToUpper();
}
}
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input)
@ -210,17 +219,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -210,17 +219,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> GetEvenNumbers(int n)
{
for (int i = 0; i < n; i++) {
if (i % 2 == 0)
if (i % 2 == 0) {
yield return i;
}
}
public static IEnumerable<char> YieldChars
{
get {
yield return 'a';
yield return 'b';
yield return 'c';
}
}
}
@ -283,7 +284,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -283,7 +284,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
yield return 0;
try {
Console.WriteLine("In Try");
yield break; // same compiler bug as in YieldBreakInCatchInTryFinally
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
} catch {
Console.WriteLine("Catch");
}
@ -299,8 +301,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -299,8 +301,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
yield return 0;
try {
Console.WriteLine("In Try");
if (b)
yield break; // same compiler bug as in YieldBreakInCatchInTryFinally
if (b) {
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
}
} finally {
Console.WriteLine("Inner Finally");
}
@ -406,7 +410,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -406,7 +410,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> TryFinallyWithTwoExitPointsInNestedCatch(bool b)
{
// The first user IL instruction is already in 2 nested try blocks.
try {
yield return 1;
try {
@ -434,9 +437,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -434,9 +437,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
try {
yield return 2;
} finally {
T b = a;
b.Dispose();
b.Dispose();
T val = a;
val.Dispose();
val.Dispose();
}
yield return 3;
}

11
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1323.cs

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
public enum Enum0
{
// error: enumerator has no value
const_0,
// error: enumerator has no value
const_1,
// error: enumerator has no value
const_2,
// error: enumerator has no value
const_3
}

40
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1323.il

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern System
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern System.Core
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly Issue1323
{
.ver 1:0:0:0
}
.module Issue1323.dll
// MVID: {B973FCD6-A9C4-48A9-8291-26DDC248E208}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00020003 // ILONLY 32BITPREFERRED
// Image base: 0x000001C4B6C90000
.class public auto ansi sealed Enum0
extends [mscorlib]System.Enum
{
// Fields
.field public specialname rtspecialname int32 value__
.field public static literal valuetype Enum0 const_0
.field public static literal valuetype Enum0 const_1
.field public static literal valuetype Enum0 const_2
.field public static literal valuetype Enum0 const_3
} // end of class Enum0

2
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
{
public void Test(bool arg)
{
switch (arg) {
if (!arg && arg) {
}
}

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs

@ -29,5 +29,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -29,5 +29,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
get;
set;
}
public int issue1319 {
get;
}
public AutoProperties(int issue1319)
{
this.issue1319 = issue1319;
}
}
}

26
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.opt.roslyn.il

@ -47,6 +47,8 @@ @@ -47,6 +47,8 @@
.field private int32 '<PropertyWithAttributeOnBackingField>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 05 46 69 65 6C 64 00 00 ) // ...Field..
.field private initonly int32 '<issue1319>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance int32
get_A() cil managed
{
@ -135,10 +137,21 @@ @@ -135,10 +137,21 @@
IL_0007: ret
} // end of method AutoProperties::set_PropertyWithAttributeOnBackingField
.method public hidebysig specialname instance int32
get_issue1319() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::'<issue1319>k__BackingField'
IL_0006: ret
} // end of method AutoProperties::get_issue1319
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
instance void .ctor(int32 issue1319) cil managed
{
// Code size 21 (0x15)
// Code size 28 (0x1c)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
@ -148,7 +161,10 @@ @@ -148,7 +161,10 @@
IL_0009: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::'<B>k__BackingField'
IL_000e: ldarg.0
IL_000f: call instance void [mscorlib]System.Object::.ctor()
IL_0014: ret
IL_0014: ldarg.0
IL_0015: ldarg.1
IL_0016: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::'<issue1319>k__BackingField'
IL_001b: ret
} // end of method AutoProperties::.ctor
.method private hidebysig specialname rtspecialname static
@ -187,6 +203,10 @@ @@ -187,6 +203,10 @@
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::get_PropertyWithAttributeOnBackingField()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::set_PropertyWithAttributeOnBackingField(int32)
} // end of property AutoProperties::PropertyWithAttributeOnBackingField
.property instance int32 issue1319()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::get_issue1319()
} // end of property AutoProperties::issue1319
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.roslyn.il

@ -52,6 +52,9 @@ @@ -52,6 +52,9 @@
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 05 46 69 65 6C 64 00 00 ) // ...Field..
.field private initonly int32 '<issue1319>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.method public hidebysig specialname instance int32
get_A() cil managed
{
@ -140,10 +143,21 @@ @@ -140,10 +143,21 @@
IL_0007: ret
} // end of method AutoProperties::set_PropertyWithAttributeOnBackingField
.method public hidebysig specialname instance int32
get_issue1319() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::'<issue1319>k__BackingField'
IL_0006: ret
} // end of method AutoProperties::get_issue1319
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
instance void .ctor(int32 issue1319) cil managed
{
// Code size 22 (0x16)
// Code size 30 (0x1e)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
@ -154,7 +168,11 @@ @@ -154,7 +168,11 @@
IL_000e: ldarg.0
IL_000f: call instance void [mscorlib]System.Object::.ctor()
IL_0014: nop
IL_0015: ret
IL_0015: nop
IL_0016: ldarg.0
IL_0017: ldarg.1
IL_0018: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::'<issue1319>k__BackingField'
IL_001d: ret
} // end of method AutoProperties::.ctor
.method private hidebysig specialname rtspecialname static
@ -193,6 +211,10 @@ @@ -193,6 +211,10 @@
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::get_PropertyWithAttributeOnBackingField()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::set_PropertyWithAttributeOnBackingField(int32)
} // end of property AutoProperties::PropertyWithAttributeOnBackingField
.property instance int32 issue1319()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties::get_issue1319()
} // end of property AutoProperties::issue1319
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.AutoProperties

8
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs

@ -21,8 +21,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -21,8 +21,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine($"\ta{$"a{args.Length}" == args[0]}");
}
public static void ArrayExpansionSpecialCases(object[] args)
{
Console.WriteLine($"args: {args}");
Console.WriteLine(string.Format("args: {0}", args));
}
public static void InvalidFormatString(string[] args)
{
#pragma warning disable IDE0043
Console.WriteLine(string.Format("", args.Length));
Console.WriteLine(string.Format("a", args.Length));
Console.WriteLine(string.Format("}", args.Length));
@ -47,6 +54,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -47,6 +54,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(string.Format("{0:}", args.Length));
Console.WriteLine(string.Format("{0{a}0}", args.Length));
Console.WriteLine(string.Format("test: {0}", string.Join(",", args)));
#pragma warning restore
}
public void FormattableStrings(FormattableString s, string[] args)

17
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il

@ -169,6 +169,23 @@ @@ -169,6 +169,23 @@
IL_0115: ret
} // end of method CS6_StringInterpolation::General
.method public hidebysig static void ArrayExpansionSpecialCases(object[] args) cil managed
{
// Code size 33 (0x21)
.maxstack 8
IL_0000: ldstr "args: {0}"
IL_0005: ldarg.0
IL_0006: call string [mscorlib]System.String::Format(string,
object)
IL_000b: call void [mscorlib]System.Console::WriteLine(string)
IL_0010: ldstr "args: {0}"
IL_0015: ldarg.0
IL_0016: call string [mscorlib]System.String::Format(string,
object[])
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: ret
} // end of method CS6_StringInterpolation::ArrayExpansionSpecialCases
.method public hidebysig static void InvalidFormatString(string[] args) cil managed
{
// Code size 556 (0x22c)

20
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il

@ -180,6 +180,26 @@ @@ -180,6 +180,26 @@
IL_011f: ret
} // end of method CS6_StringInterpolation::General
.method public hidebysig static void ArrayExpansionSpecialCases(object[] args) cil managed
{
// Code size 36 (0x24)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "args: {0}"
IL_0006: ldarg.0
IL_0007: call string [mscorlib]System.String::Format(string,
object)
IL_000c: call void [mscorlib]System.Console::WriteLine(string)
IL_0011: nop
IL_0012: ldstr "args: {0}"
IL_0017: ldarg.0
IL_0018: call string [mscorlib]System.String::Format(string,
object[])
IL_001d: call void [mscorlib]System.Console::WriteLine(string)
IL_0022: nop
IL_0023: ret
} // end of method CS6_StringInterpolation::ArrayExpansionSpecialCases
.method public hidebysig static void InvalidFormatString(string[] args) cil managed
{
// Code size 581 (0x245)

24
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs

@ -103,5 +103,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -103,5 +103,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
Console.WriteLine(new int[checked(a + b)]);
}
public short Unbox(TypeCode c, object b)
{
checked {
switch (c) {
case TypeCode.Int32:
return (short)((Box<int>)b).Value;
case TypeCode.UInt32:
return (short)((Box<uint>)b).Value;
case TypeCode.Double: {
float num = (float)((Box<double>)b).Value;
Console.WriteLine(num);
return (short)num;
}
default:
throw new Exception();
}
}
}
}
internal class Box<T>
{
public readonly T Value;
}
}

76
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.il

@ -345,6 +345,66 @@ @@ -345,6 +345,66 @@
IL_000f: ret
} // end of method CheckedUnchecked::CheckedInArrayCreationArgument
.method public hidebysig instance int16
Unbox(valuetype [mscorlib]System.TypeCode c,
object b) cil managed
{
// Code size 92 (0x5c)
.maxstack 2
.locals init (float32 V_0,
int16 V_1,
valuetype [mscorlib]System.TypeCode V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.2
IL_0004: ldloc.2
IL_0005: ldc.i4.s 9
IL_0007: sub
IL_0008: switch (
IL_001c,
IL_002b)
IL_0015: ldloc.2
IL_0016: ldc.i4.s 14
IL_0018: beq.s IL_003a
IL_001a: br.s IL_0054
IL_001c: ldarg.2
IL_001d: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>
IL_0022: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>::Value
IL_0027: conv.ovf.i2
IL_0028: stloc.1
IL_0029: br.s IL_005a
IL_002b: ldarg.2
IL_002c: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>
IL_0031: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>::Value
IL_0036: conv.ovf.i2.un
IL_0037: stloc.1
IL_0038: br.s IL_005a
IL_003a: nop
IL_003b: ldarg.2
IL_003c: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>
IL_0041: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>::Value
IL_0046: conv.r4
IL_0047: stloc.0
IL_0048: ldloc.0
IL_0049: call void [mscorlib]System.Console::WriteLine(float32)
IL_004e: nop
IL_004f: ldloc.0
IL_0050: conv.ovf.i2
IL_0051: stloc.1
IL_0052: br.s IL_005a
IL_0054: newobj instance void [mscorlib]System.Exception::.ctor()
IL_0059: throw
IL_005a: ldloc.1
IL_005b: ret
} // end of method CheckedUnchecked::Unbox
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
@ -440,6 +500,22 @@ @@ -440,6 +500,22 @@
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CheckedUnchecked
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<T>
extends [mscorlib]System.Object
{
.field public initonly !T Value
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Box`1::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType0`2'<'<x>j__TPar','<l>j__TPar'>
extends [mscorlib]System.Object
{

65
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.opt.il

@ -300,6 +300,55 @@ @@ -300,6 +300,55 @@
IL_000d: ret
} // end of method CheckedUnchecked::CheckedInArrayCreationArgument
.method public hidebysig instance int16
Unbox(valuetype [mscorlib]System.TypeCode c,
object b) cil managed
{
// Code size 80 (0x50)
.maxstack 2
.locals init (float32 V_0,
valuetype [mscorlib]System.TypeCode V_1)
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.s 9
IL_0005: sub
IL_0006: switch (
IL_001a,
IL_0027)
IL_0013: ldloc.1
IL_0014: ldc.i4.s 14
IL_0016: beq.s IL_0034
IL_0018: br.s IL_004a
IL_001a: ldarg.2
IL_001b: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>
IL_0020: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>::Value
IL_0025: conv.ovf.i2
IL_0026: ret
IL_0027: ldarg.2
IL_0028: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>
IL_002d: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>::Value
IL_0032: conv.ovf.i2.un
IL_0033: ret
IL_0034: ldarg.2
IL_0035: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>
IL_003a: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>::Value
IL_003f: conv.r4
IL_0040: stloc.0
IL_0041: ldloc.0
IL_0042: call void [mscorlib]System.Console::WriteLine(float32)
IL_0047: ldloc.0
IL_0048: conv.ovf.i2
IL_0049: ret
IL_004a: newobj instance void [mscorlib]System.Exception::.ctor()
IL_004f: throw
} // end of method CheckedUnchecked::Unbox
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
@ -380,6 +429,22 @@ @@ -380,6 +429,22 @@
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CheckedUnchecked
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<T>
extends [mscorlib]System.Object
{
.field public initonly !T Value
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Box`1::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType0`2'<'<x>j__TPar','<l>j__TPar'>
extends [mscorlib]System.Object
{

61
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.opt.roslyn.il

@ -574,6 +574,51 @@ @@ -574,6 +574,51 @@
IL_000d: ret
} // end of method CheckedUnchecked::CheckedInArrayCreationArgument
.method public hidebysig instance int16
Unbox(valuetype [mscorlib]System.TypeCode c,
object b) cil managed
{
// Code size 69 (0x45)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldc.i4.s 9
IL_0003: beq.s IL_0011
IL_0005: ldarg.1
IL_0006: ldc.i4.s 10
IL_0008: beq.s IL_001e
IL_000a: ldarg.1
IL_000b: ldc.i4.s 14
IL_000d: beq.s IL_002b
IL_000f: br.s IL_003f
IL_0011: ldarg.2
IL_0012: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>
IL_0017: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>::Value
IL_001c: conv.ovf.i2
IL_001d: ret
IL_001e: ldarg.2
IL_001f: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>
IL_0024: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>::Value
IL_0029: conv.ovf.i2.un
IL_002a: ret
IL_002b: ldarg.2
IL_002c: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>
IL_0031: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>::Value
IL_0036: conv.r4
IL_0037: dup
IL_0038: call void [mscorlib]System.Console::WriteLine(float32)
IL_003d: conv.ovf.i2
IL_003e: ret
IL_003f: newobj instance void [mscorlib]System.Exception::.ctor()
IL_0044: throw
} // end of method CheckedUnchecked::Unbox
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
@ -586,6 +631,22 @@ @@ -586,6 +631,22 @@
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CheckedUnchecked
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<T>
extends [mscorlib]System.Object
{
.field public initonly !T Value
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Box`1::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1
// =============================================================

83
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.roslyn.il

@ -624,6 +624,72 @@ @@ -624,6 +624,72 @@
IL_000f: ret
} // end of method CheckedUnchecked::CheckedInArrayCreationArgument
.method public hidebysig instance int16
Unbox(valuetype [mscorlib]System.TypeCode c,
object b) cil managed
{
// Code size 89 (0x59)
.maxstack 2
.locals init (valuetype [mscorlib]System.TypeCode V_0,
int16 V_1,
float32 V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.s 9
IL_0007: beq.s IL_0019
IL_0009: br.s IL_000b
IL_000b: ldloc.0
IL_000c: ldc.i4.s 10
IL_000e: beq.s IL_0028
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ldc.i4.s 14
IL_0015: beq.s IL_0037
IL_0017: br.s IL_0051
IL_0019: ldarg.2
IL_001a: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>
IL_001f: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<int32>::Value
IL_0024: conv.ovf.i2
IL_0025: stloc.1
IL_0026: br.s IL_0057
IL_0028: ldarg.2
IL_0029: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>
IL_002e: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<uint32>::Value
IL_0033: conv.ovf.i2.un
IL_0034: stloc.1
IL_0035: br.s IL_0057
IL_0037: nop
IL_0038: ldarg.2
IL_0039: castclass class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>
IL_003e: ldfld !0 class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<float64>::Value
IL_0043: conv.r4
IL_0044: stloc.2
IL_0045: ldloc.2
IL_0046: call void [mscorlib]System.Console::WriteLine(float32)
IL_004b: nop
IL_004c: ldloc.2
IL_004d: conv.ovf.i2
IL_004e: stloc.1
IL_004f: br.s IL_0057
IL_0051: newobj instance void [mscorlib]System.Exception::.ctor()
IL_0056: throw
IL_0057: ldloc.1
IL_0058: ret
} // end of method CheckedUnchecked::Unbox
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
@ -637,6 +703,23 @@ @@ -637,6 +703,23 @@
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CheckedUnchecked
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1<T>
extends [mscorlib]System.Object
{
.field public initonly !T Value
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Box`1::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Box`1
// =============================================================

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs

@ -435,5 +435,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -435,5 +435,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(GetBool(1) || GetDynamic(2));
Console.WriteLine(i == 1 || d == null);
}
private static int ImplicitCast(object o)
{
return (dynamic)o;
}
private static int ExplicitCast(object o)
{
return (int)(dynamic)o;
}
}
}

90
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.il

@ -20,10 +20,10 @@ @@ -20,10 +20,10 @@
}
.assembly DynamicTests
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
@ -112,8 +112,8 @@ @@ -112,8 +112,8 @@
.field public object Field
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private object '<Property>k__BackingField'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname
instance object get_GetOnlyProperty() cil managed
{
@ -802,12 +802,26 @@ @@ -802,12 +802,26 @@
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,object,object>> '<>p__Site17b'
} // end of class '<LogicOrExtended>o__SiteContainer170'
.class abstract auto ansi sealed nested private beforefieldinit '<ImplicitCast>o__SiteContainer17c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__Site17d'
} // end of class '<ImplicitCast>o__SiteContainer17c'
.class abstract auto ansi sealed nested private beforefieldinit '<ExplicitCast>o__SiteContainer17e'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__Site17f'
} // end of class '<ExplicitCast>o__SiteContainer17e'
.field private static object 'field'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private static object objectField
.field private object '<Property>k__BackingField'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance object
get_Property() cil managed
{
@ -15600,6 +15614,76 @@ @@ -15600,6 +15614,76 @@
IL_043f: ret
} // end of method DynamicTests::LogicOrExtended
.method private hidebysig static int32
ImplicitCast(object o) cil managed
{
// Code size 72 (0x48)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_0006: brtrue.s IL_002e
IL_0008: ldc.i4.0
IL_0009: ldtoken [mscorlib]System.Int32
IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0013: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001d: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0022: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0027: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_002c: br.s IL_002e
IL_002e: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_0033: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0038: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_003d: ldarg.0
IL_003e: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0043: stloc.0
IL_0044: br.s IL_0046
IL_0046: ldloc.0
IL_0047: ret
} // end of method DynamicTests::ImplicitCast
.method private hidebysig static int32
ExplicitCast(object o) cil managed
{
// Code size 73 (0x49)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_0006: brtrue.s IL_002f
IL_0008: ldc.i4.s 16
IL_000a: ldtoken [mscorlib]System.Int32
IL_000f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0014: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0019: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001e: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0023: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0028: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_002d: br.s IL_002f
IL_002f: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_0034: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0039: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_003e: ldarg.0
IL_003f: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0044: stloc.0
IL_0045: br.s IL_0047
IL_0047: ldloc.0
IL_0048: ret
} // end of method DynamicTests::ExplicitCast
.property instance object Property()
{
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )

74
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.opt.il

@ -20,10 +20,10 @@ @@ -20,10 +20,10 @@
}
.assembly DynamicTests.opt
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
@ -105,8 +105,8 @@ @@ -105,8 +105,8 @@
.field public object Field
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private object '<Property>k__BackingField'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname
instance object get_GetOnlyProperty() cil managed
{
@ -783,12 +783,26 @@ @@ -783,12 +783,26 @@
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,object,object>> '<>p__Site17b'
} // end of class '<LogicOrExtended>o__SiteContainer170'
.class abstract auto ansi sealed nested private beforefieldinit '<ImplicitCast>o__SiteContainer17c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__Site17d'
} // end of class '<ImplicitCast>o__SiteContainer17c'
.class abstract auto ansi sealed nested private beforefieldinit '<ExplicitCast>o__SiteContainer17e'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__Site17f'
} // end of class '<ExplicitCast>o__SiteContainer17e'
.field private static object 'field'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private static object objectField
.field private object '<Property>k__BackingField'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance object
get_Property() cil managed
{
@ -14889,6 +14903,60 @@ @@ -14889,6 +14903,60 @@
IL_044b: ret
} // end of method DynamicTests::LogicOrExtended
.method private hidebysig static int32
ImplicitCast(object o) cil managed
{
// Code size 65 (0x41)
.maxstack 3
IL_0000: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_0005: brtrue.s IL_002b
IL_0007: ldc.i4.0
IL_0008: ldtoken [mscorlib]System.Int32
IL_000d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0012: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0017: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001c: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0021: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0026: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_002b: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_0030: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0035: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ImplicitCast>o__SiteContainer17c'::'<>p__Site17d'
IL_003a: ldarg.0
IL_003b: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0040: ret
} // end of method DynamicTests::ImplicitCast
.method private hidebysig static int32
ExplicitCast(object o) cil managed
{
// Code size 66 (0x42)
.maxstack 3
IL_0000: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_0005: brtrue.s IL_002c
IL_0007: ldc.i4.s 16
IL_0009: ldtoken [mscorlib]System.Int32
IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0013: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001d: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0022: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0027: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_002c: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_0031: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0036: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<ExplicitCast>o__SiteContainer17e'::'<>p__Site17f'
IL_003b: ldarg.0
IL_003c: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0041: ret
} // end of method DynamicTests::ExplicitCast
.property instance object Property()
{
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )

68
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.opt.roslyn.il

@ -785,6 +785,20 @@ @@ -785,6 +785,20 @@
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,object>> '<>p__10'
} // end of class '<>o__55'
.class abstract auto ansi sealed nested private beforefieldinit '<>o__56'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__0'
} // end of class '<>o__56'
.class abstract auto ansi sealed nested private beforefieldinit '<>o__57'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__0'
} // end of class '<>o__57'
.field private static object 'field'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private static object objectField
@ -13951,6 +13965,60 @@ @@ -13951,6 +13965,60 @@
IL_040a: ret
} // end of method DynamicTests::LogicOrExtended
.method private hidebysig static int32
ImplicitCast(object o) cil managed
{
// Code size 65 (0x41)
.maxstack 3
IL_0000: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_0005: brtrue.s IL_002b
IL_0007: ldc.i4.0
IL_0008: ldtoken [mscorlib]System.Int32
IL_000d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0012: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0017: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001c: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0021: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0026: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_002b: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_0030: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0035: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_003a: ldarg.0
IL_003b: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0040: ret
} // end of method DynamicTests::ImplicitCast
.method private hidebysig static int32
ExplicitCast(object o) cil managed
{
// Code size 66 (0x42)
.maxstack 3
IL_0000: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_0005: brtrue.s IL_002c
IL_0007: ldc.i4.s 16
IL_0009: ldtoken [mscorlib]System.Int32
IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0013: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001d: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0022: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0027: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_002c: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_0031: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0036: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_003b: ldarg.0
IL_003c: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0041: ret
} // end of method DynamicTests::ExplicitCast
.property instance object Property()
{
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )

84
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.roslyn.il

@ -792,6 +792,20 @@ @@ -792,6 +792,20 @@
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,object>> '<>p__10'
} // end of class '<>o__55'
.class abstract auto ansi sealed nested private beforefieldinit '<>o__56'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__0'
} // end of class '<>o__56'
.class abstract auto ansi sealed nested private beforefieldinit '<>o__57'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> '<>p__0'
} // end of class '<>o__57'
.field private static object 'field'
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )
.field private static object objectField
@ -14904,6 +14918,76 @@ @@ -14904,6 +14918,76 @@
IL_0425: ret
} // end of method DynamicTests::LogicOrExtended
.method private hidebysig static int32
ImplicitCast(object o) cil managed
{
// Code size 72 (0x48)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_0006: brfalse.s IL_000a
IL_0008: br.s IL_002e
IL_000a: ldc.i4.0
IL_000b: ldtoken [mscorlib]System.Int32
IL_0010: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0015: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_001a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001f: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0024: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0029: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_002e: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_0033: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0038: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__56'::'<>p__0'
IL_003d: ldarg.0
IL_003e: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0043: stloc.0
IL_0044: br.s IL_0046
IL_0046: ldloc.0
IL_0047: ret
} // end of method DynamicTests::ImplicitCast
.method private hidebysig static int32
ExplicitCast(object o) cil managed
{
// Code size 73 (0x49)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_0006: brfalse.s IL_000a
IL_0008: br.s IL_002f
IL_000a: ldc.i4.s 16
IL_000c: ldtoken [mscorlib]System.Int32
IL_0011: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0016: ldtoken ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests
IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0020: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0025: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_002a: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_002f: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_0034: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>>::Target
IL_0039: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>> ICSharpCode.Decompiler.Tests.TestCases.Pretty.DynamicTests/'<>o__57'::'<>p__0'
IL_003e: ldarg.0
IL_003f: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32>::Invoke(!0,
!1)
IL_0044: stloc.0
IL_0045: br.s IL_0047
IL_0047: ldloc.0
IL_0048: ret
} // end of method DynamicTests::ExplicitCast
.property instance object Property()
{
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )

96
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs

@ -322,47 +322,47 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -322,47 +322,47 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
if (ID == 0) {
ViewBag.data = "''";
} else {
var model = (from a in db.Contracts
where a.ID == ID
select new {
ID = a.ID,
ContractNo = a.ContractNo,
HouseAddress = a.HouseAddress,
AdminID = (from b in db.Administrator
where b.ID == a.AdminID
select b.TrueName).FirstOrDefault(),
StoreID = (from b in db.Store
where b.ID == a.StoreID
select b.Name).FirstOrDefault(),
SigningTime = a.SigningTime,
YeWuPhone = (from b in db.Administrator
where b.ID == a.AdminID
select b.Phone).FirstOrDefault(),
BuyerName = a.BuyerName,
BuyerTelephone = a.BuyerTelephone,
Customer = a.Customer,
CustTelephone = a.CustTelephone,
Credit = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.Credit).FirstOrDefault(),
LoanBank = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.LoanBank).FirstOrDefault(),
Remarks = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.Remarks).FirstOrDefault()
}).FirstOrDefault();
ViewBag.data = model.ToJson();
DateTime? dateTime = (from b in db.Loan
where b.ContractNo == model.ContractNo
select b.ShenDate).FirstOrDefault();
DateTime? dateTime2 = (from b in db.Loan
where b.ContractNo == model.ContractNo
select b.LoanDate).FirstOrDefault();
ViewBag.ShenDate = ((!dateTime.HasValue) ? "" : dateTime.ParseDateTime().ToString("yyyy-MM-dd"));
ViewBag.LoanDate = ((!dateTime2.HasValue) ? "" : dateTime2.ParseDateTime().ToString("yyyy-MM-dd"));
}
return;
}
var model = (from a in db.Contracts
where a.ID == ID
select new {
ID = a.ID,
ContractNo = a.ContractNo,
HouseAddress = a.HouseAddress,
AdminID = (from b in db.Administrator
where b.ID == a.AdminID
select b.TrueName).FirstOrDefault(),
StoreID = (from b in db.Store
where b.ID == a.StoreID
select b.Name).FirstOrDefault(),
SigningTime = a.SigningTime,
YeWuPhone = (from b in db.Administrator
where b.ID == a.AdminID
select b.Phone).FirstOrDefault(),
BuyerName = a.BuyerName,
BuyerTelephone = a.BuyerTelephone,
Customer = a.Customer,
CustTelephone = a.CustTelephone,
Credit = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.Credit).FirstOrDefault(),
LoanBank = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.LoanBank).FirstOrDefault(),
Remarks = (from b in db.Loan
where b.ContractNo == a.ContractNo
select b.Remarks).FirstOrDefault()
}).FirstOrDefault();
ViewBag.data = model.ToJson();
DateTime? dateTime = (from b in db.Loan
where b.ContractNo == model.ContractNo
select b.ShenDate).FirstOrDefault();
DateTime? dateTime2 = (from b in db.Loan
where b.ContractNo == model.ContractNo
select b.LoanDate).FirstOrDefault();
ViewBag.ShenDate = ((!dateTime.HasValue) ? "" : dateTime.ParseDateTime().ToString("yyyy-MM-dd"));
ViewBag.LoanDate = ((!dateTime2.HasValue) ? "" : dateTime2.ParseDateTime().ToString("yyyy-MM-dd"));
}
private static object ToCode<R>(object x, Expression<Action<R>> expr)
@ -533,7 +533,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -533,7 +533,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void MembersBuiltin()
{
ToCode(X(), () => 1.23m.ToString());
ToCode(X(), () => AttributeTargets.All.HasFlag((Enum)AttributeTargets.Assembly));
ToCode(X(), () => AttributeTargets.All.HasFlag(AttributeTargets.Assembly));
ToCode(X(), () => "abc".Length == 3);
ToCode(X(), () => 'a'.CompareTo('b') < 0);
}
@ -844,7 +844,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -844,7 +844,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ToCode(null, (object a) => a ?? new MyClass());
}
public static void BinaryLogicalOperators()
public static void ComparisonOperators()
{
ToCode(null, (int a, int b) => a == b);
ToCode(null, (int a, int b) => a != b);
@ -865,6 +865,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -865,6 +865,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ToCode(null, (int a, int b) => a == 1 || b == 2);
}
public static void LiftedComparisonOperators()
{
ToCode(X(), (int? a, int? b) => a == b);
ToCode(X(), (int? a, int? b) => a != b);
ToCode(X(), (int? a, int? b) => a < b);
ToCode(X(), (int? a, int? b) => a <= b);
ToCode(X(), (int? a, int? b) => a > b);
ToCode(X(), (int? a, int? b) => a >= b);
}
public static void UnaryArithmeticOperators()
{
Test<Func<int, int>>((int a) => a, (int a) => a);

233
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.il

@ -8876,7 +8876,7 @@ @@ -8876,7 +8876,7 @@
IL_00ac: ret
} // end of method ExpressionTrees::ConditionalOperator
.method public hidebysig static void BinaryLogicalOperators() cil managed
.method public hidebysig static void ComparisonOperators() cil managed
{
// Code size 1639 (0x667)
.maxstack 5
@ -9559,7 +9559,222 @@ @@ -9559,7 +9559,222 @@
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0665: pop
IL_0666: ret
} // end of method ExpressionTrees::BinaryLogicalOperators
} // end of method ExpressionTrees::ComparisonOperators
.method public hidebysig static void LiftedComparisonOperators() cil managed
{
// Code size 488 (0x1e8)
.maxstack 5
.locals init (class [System.Core]System.Linq.Expressions.ParameterExpression V_0,
class [System.Core]System.Linq.Expressions.ParameterExpression V_1,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_2)
IL_0000: nop
IL_0001: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0006: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0010: ldstr "a"
IL_0015: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_001a: stloc.0
IL_001b: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0020: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0025: ldstr "b"
IL_002a: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_002f: stloc.1
IL_0030: ldloc.0
IL_0031: ldloc.1
IL_0032: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_0037: ldc.i4.2
IL_0038: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_003d: stloc.2
IL_003e: ldloc.2
IL_003f: ldc.i4.0
IL_0040: ldloc.0
IL_0041: stelem.ref
IL_0042: ldloc.2
IL_0043: ldc.i4.1
IL_0044: ldloc.1
IL_0045: stelem.ref
IL_0046: ldloc.2
IL_0047: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_004c: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0051: pop
IL_0052: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0057: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_005c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0061: ldstr "a"
IL_0066: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_006b: stloc.0
IL_006c: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0071: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0076: ldstr "b"
IL_007b: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0080: stloc.1
IL_0081: ldloc.0
IL_0082: ldloc.1
IL_0083: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::NotEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_0088: ldc.i4.2
IL_0089: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_008e: stloc.2
IL_008f: ldloc.2
IL_0090: ldc.i4.0
IL_0091: ldloc.0
IL_0092: stelem.ref
IL_0093: ldloc.2
IL_0094: ldc.i4.1
IL_0095: ldloc.1
IL_0096: stelem.ref
IL_0097: ldloc.2
IL_0098: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_009d: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_00a2: pop
IL_00a3: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_00a8: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_00ad: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_00b2: ldstr "a"
IL_00b7: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_00bc: stloc.0
IL_00bd: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_00c2: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_00c7: ldstr "b"
IL_00cc: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_00d1: stloc.1
IL_00d2: ldloc.0
IL_00d3: ldloc.1
IL_00d4: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::LessThan(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_00d9: ldc.i4.2
IL_00da: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_00df: stloc.2
IL_00e0: ldloc.2
IL_00e1: ldc.i4.0
IL_00e2: ldloc.0
IL_00e3: stelem.ref
IL_00e4: ldloc.2
IL_00e5: ldc.i4.1
IL_00e6: ldloc.1
IL_00e7: stelem.ref
IL_00e8: ldloc.2
IL_00e9: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_00ee: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_00f3: pop
IL_00f4: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_00f9: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_00fe: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0103: ldstr "a"
IL_0108: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_010d: stloc.0
IL_010e: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0113: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0118: ldstr "b"
IL_011d: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0122: stloc.1
IL_0123: ldloc.0
IL_0124: ldloc.1
IL_0125: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::LessThanOrEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_012a: ldc.i4.2
IL_012b: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_0130: stloc.2
IL_0131: ldloc.2
IL_0132: ldc.i4.0
IL_0133: ldloc.0
IL_0134: stelem.ref
IL_0135: ldloc.2
IL_0136: ldc.i4.1
IL_0137: ldloc.1
IL_0138: stelem.ref
IL_0139: ldloc.2
IL_013a: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_013f: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0144: pop
IL_0145: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_014a: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_014f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0154: ldstr "a"
IL_0159: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_015e: stloc.0
IL_015f: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0164: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0169: ldstr "b"
IL_016e: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0173: stloc.1
IL_0174: ldloc.0
IL_0175: ldloc.1
IL_0176: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::GreaterThan(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_017b: ldc.i4.2
IL_017c: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_0181: stloc.2
IL_0182: ldloc.2
IL_0183: ldc.i4.0
IL_0184: ldloc.0
IL_0185: stelem.ref
IL_0186: ldloc.2
IL_0187: ldc.i4.1
IL_0188: ldloc.1
IL_0189: stelem.ref
IL_018a: ldloc.2
IL_018b: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_0190: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0195: pop
IL_0196: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_019b: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_01a0: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_01a5: ldstr "a"
IL_01aa: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_01af: stloc.0
IL_01b0: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_01b5: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_01ba: ldstr "b"
IL_01bf: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_01c4: stloc.1
IL_01c5: ldloc.0
IL_01c6: ldloc.1
IL_01c7: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::GreaterThanOrEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_01cc: ldc.i4.2
IL_01cd: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_01d2: stloc.2
IL_01d3: ldloc.2
IL_01d4: ldc.i4.0
IL_01d5: ldloc.0
IL_01d6: stelem.ref
IL_01d7: ldloc.2
IL_01d8: ldc.i4.1
IL_01d9: ldloc.1
IL_01da: stelem.ref
IL_01db: ldloc.2
IL_01dc: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_01e1: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_01e6: pop
IL_01e7: ret
} // end of method ExpressionTrees::LiftedComparisonOperators
.method public hidebysig static void UnaryArithmeticOperators() cil managed
{
@ -12718,7 +12933,7 @@ @@ -12718,7 +12933,7 @@
IL_0000: ldc.i4.3
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x600010d-1'
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x600010e-1'
IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0011: stloc.0
@ -12794,7 +13009,7 @@ @@ -12794,7 +13009,7 @@
IL_0009: ldc.i4.3
IL_000a: newarr [mscorlib]System.Int32
IL_000f: dup
IL_0010: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x6000111-1'
IL_0010: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x6000112-1'
IL_0015: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_001a: stelem.ref
@ -14617,8 +14832,8 @@ @@ -14617,8 +14832,8 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x600010d-1' at I_00009008
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x6000111-1' at I_00009080
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x600010e-1' at I_00009200
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x6000112-1' at I_00009278
} // end of class '<PrivateImplementationDetails>'
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType3`2'<'<A>j__TPar','<B>j__TPar'>
@ -14810,9 +15025,9 @@ @@ -14810,9 +15025,9 @@
// =============================================================
.data cil I_00009008 = bytearray (
.data cil I_00009200 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
.data cil I_00009014 = int8[108]
.data cil I_00009080 = bytearray (
.data cil I_0000920C = int8[4]
.data cil I_00009278 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************

247
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.opt.il

@ -8565,7 +8565,7 @@ @@ -8565,7 +8565,7 @@
IL_00ab: ret
} // end of method ExpressionTrees::ConditionalOperator
.method public hidebysig static void BinaryLogicalOperators() cil managed
.method public hidebysig static void ComparisonOperators() cil managed
{
// Code size 1795 (0x703)
.maxstack 5
@ -9295,7 +9295,236 @@ @@ -9295,7 +9295,236 @@
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0701: pop
IL_0702: ret
} // end of method ExpressionTrees::BinaryLogicalOperators
} // end of method ExpressionTrees::ComparisonOperators
.method public hidebysig static void LiftedComparisonOperators() cil managed
{
// Code size 534 (0x216)
.maxstack 5
.locals init (class [System.Core]System.Linq.Expressions.ParameterExpression V_0,
class [System.Core]System.Linq.Expressions.ParameterExpression V_1,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_2,
class [System.Core]System.Linq.Expressions.ParameterExpression V_3,
class [System.Core]System.Linq.Expressions.ParameterExpression V_4,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_5,
class [System.Core]System.Linq.Expressions.ParameterExpression V_6,
class [System.Core]System.Linq.Expressions.ParameterExpression V_7,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_8,
class [System.Core]System.Linq.Expressions.ParameterExpression V_9,
class [System.Core]System.Linq.Expressions.ParameterExpression V_10,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_11,
class [System.Core]System.Linq.Expressions.ParameterExpression V_12,
class [System.Core]System.Linq.Expressions.ParameterExpression V_13,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_14,
class [System.Core]System.Linq.Expressions.ParameterExpression V_15,
class [System.Core]System.Linq.Expressions.ParameterExpression V_16,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_17)
IL_0000: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0005: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_000a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000f: ldstr "a"
IL_0014: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0019: stloc.0
IL_001a: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_001f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0024: ldstr "b"
IL_0029: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_002e: stloc.1
IL_002f: ldloc.0
IL_0030: ldloc.1
IL_0031: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_0036: ldc.i4.2
IL_0037: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_003c: stloc.2
IL_003d: ldloc.2
IL_003e: ldc.i4.0
IL_003f: ldloc.0
IL_0040: stelem.ref
IL_0041: ldloc.2
IL_0042: ldc.i4.1
IL_0043: ldloc.1
IL_0044: stelem.ref
IL_0045: ldloc.2
IL_0046: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_004b: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0050: pop
IL_0051: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0056: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_005b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0060: ldstr "a"
IL_0065: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_006a: stloc.3
IL_006b: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0070: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0075: ldstr "b"
IL_007a: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_007f: stloc.s V_4
IL_0081: ldloc.3
IL_0082: ldloc.s V_4
IL_0084: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::NotEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_0089: ldc.i4.2
IL_008a: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_008f: stloc.s V_5
IL_0091: ldloc.s V_5
IL_0093: ldc.i4.0
IL_0094: ldloc.3
IL_0095: stelem.ref
IL_0096: ldloc.s V_5
IL_0098: ldc.i4.1
IL_0099: ldloc.s V_4
IL_009b: stelem.ref
IL_009c: ldloc.s V_5
IL_009e: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_00a3: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_00a8: pop
IL_00a9: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_00ae: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_00b3: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_00b8: ldstr "a"
IL_00bd: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_00c2: stloc.s V_6
IL_00c4: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_00c9: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_00ce: ldstr "b"
IL_00d3: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_00d8: stloc.s V_7
IL_00da: ldloc.s V_6
IL_00dc: ldloc.s V_7
IL_00de: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::LessThan(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_00e3: ldc.i4.2
IL_00e4: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_00e9: stloc.s V_8
IL_00eb: ldloc.s V_8
IL_00ed: ldc.i4.0
IL_00ee: ldloc.s V_6
IL_00f0: stelem.ref
IL_00f1: ldloc.s V_8
IL_00f3: ldc.i4.1
IL_00f4: ldloc.s V_7
IL_00f6: stelem.ref
IL_00f7: ldloc.s V_8
IL_00f9: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_00fe: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0103: pop
IL_0104: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0109: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_010e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0113: ldstr "a"
IL_0118: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_011d: stloc.s V_9
IL_011f: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0124: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0129: ldstr "b"
IL_012e: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0133: stloc.s V_10
IL_0135: ldloc.s V_9
IL_0137: ldloc.s V_10
IL_0139: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::LessThanOrEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_013e: ldc.i4.2
IL_013f: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_0144: stloc.s V_11
IL_0146: ldloc.s V_11
IL_0148: ldc.i4.0
IL_0149: ldloc.s V_9
IL_014b: stelem.ref
IL_014c: ldloc.s V_11
IL_014e: ldc.i4.1
IL_014f: ldloc.s V_10
IL_0151: stelem.ref
IL_0152: ldloc.s V_11
IL_0154: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_0159: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_015e: pop
IL_015f: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_0164: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0169: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_016e: ldstr "a"
IL_0173: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_0178: stloc.s V_12
IL_017a: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_017f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0184: ldstr "b"
IL_0189: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_018e: stloc.s V_13
IL_0190: ldloc.s V_12
IL_0192: ldloc.s V_13
IL_0194: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::GreaterThan(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_0199: ldc.i4.2
IL_019a: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_019f: stloc.s V_14
IL_01a1: ldloc.s V_14
IL_01a3: ldc.i4.0
IL_01a4: ldloc.s V_12
IL_01a6: stelem.ref
IL_01a7: ldloc.s V_14
IL_01a9: ldc.i4.1
IL_01aa: ldloc.s V_13
IL_01ac: stelem.ref
IL_01ad: ldloc.s V_14
IL_01af: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_01b4: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_01b9: pop
IL_01ba: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::X()
IL_01bf: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_01c4: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_01c9: ldstr "a"
IL_01ce: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_01d3: stloc.s V_15
IL_01d5: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_01da: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_01df: ldstr "b"
IL_01e4: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
string)
IL_01e9: stloc.s V_16
IL_01eb: ldloc.s V_15
IL_01ed: ldloc.s V_16
IL_01ef: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::GreaterThanOrEqual(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.Expression)
IL_01f4: ldc.i4.2
IL_01f5: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_01fa: stloc.s V_17
IL_01fc: ldloc.s V_17
IL_01fe: ldc.i4.0
IL_01ff: ldloc.s V_15
IL_0201: stelem.ref
IL_0202: ldloc.s V_17
IL_0204: ldc.i4.1
IL_0205: ldloc.s V_16
IL_0207: stelem.ref
IL_0208: ldloc.s V_17
IL_020a: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`3<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>>(class [System.Core]System.Linq.Expressions.Expression,
class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_020f: call object ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExpressionTrees::ToCode<valuetype [mscorlib]System.Nullable`1<int32>,valuetype [mscorlib]System.Nullable`1<int32>,bool>(object,
class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`3<!!0,!!1,!!2>>)
IL_0214: pop
IL_0215: ret
} // end of method ExpressionTrees::LiftedComparisonOperators
.method public hidebysig static void UnaryArithmeticOperators() cil managed
{
@ -12111,7 +12340,7 @@ @@ -12111,7 +12340,7 @@
IL_0000: ldc.i4.3
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x600010d-1'
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x600010e-1'
IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0011: ret
@ -12167,7 +12396,7 @@ @@ -12167,7 +12396,7 @@
IL_0009: ldc.i4.3
IL_000a: newarr [mscorlib]System.Int32
IL_000f: dup
IL_0010: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x6000111-1'
IL_0010: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'$$method0x6000112-1'
IL_0015: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_001a: stelem.ref
@ -13856,8 +14085,8 @@ @@ -13856,8 +14085,8 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x600010d-1' at I_00008B38
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x6000111-1' at I_00008B70
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x600010e-1' at I_00008D60
.field static assembly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '$$method0x6000112-1' at I_00008D98
} // end of class '<PrivateImplementationDetails>'
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType3`2'<'<A>j__TPar','<B>j__TPar'>
@ -14023,9 +14252,9 @@ @@ -14023,9 +14252,9 @@
// =============================================================
.data cil I_00008B38 = bytearray (
.data cil I_00008D60 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
.data cil I_00008B44 = int8[12]
.data cil I_00008B70 = bytearray (
.data cil I_00008D6C = int8[4]
.data cil I_00008D98 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************

677
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.opt.roslyn.il

File diff suppressed because it is too large Load Diff

678
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.roslyn.il

File diff suppressed because it is too large Load Diff

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs

@ -322,9 +322,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -322,9 +322,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
if (a == b) {
Console.WriteLine();
}
#if ROSLYN
// Roslyn 2.9 started invoking op_Equality even if the source code says 'a != b'
if (!(a == b)) {
Console.WriteLine();
}
#else
if (a != b) {
Console.WriteLine();
}
#endif
if (a > b) {
Console.WriteLine();
}
@ -399,7 +406,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -399,7 +406,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void NumberValueBasic(decimal? a, decimal? b)
{
Console.WriteLine(a == b);
#if ROSLYN
// Roslyn 2.9 started invoking op_Equality even if the source code says 'a != b'
Console.WriteLine(!(a == b));
#else
Console.WriteLine(a != b);
#endif
Console.WriteLine(a > b);
Console.WriteLine(!(a > b));

6390
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.opt.roslyn.il

File diff suppressed because it is too large Load Diff

7088
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.roslyn.il

File diff suppressed because it is too large Load Diff

203
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.il

@ -2938,7 +2938,7 @@ @@ -2938,7 +2938,7 @@
NestedForeach(class [mscorlib]System.Collections.Generic.List`1<object> items1,
class [mscorlib]System.Collections.Generic.List`1<object> items2) cil managed
{
// Code size 150 (0x96)
// Code size 152 (0x98)
.maxstack 2
.locals init (object V_0,
bool V_1,
@ -2953,7 +2953,7 @@ @@ -2953,7 +2953,7 @@
IL_0008: stloc.3
.try
{
IL_0009: br.s IL_006b
IL_0009: br.s IL_006d
IL_000b: ldloca.s V_3
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
@ -3009,47 +3009,49 @@ @@ -3009,47 +3009,49 @@
IL_005c: ldloc.1
IL_005d: stloc.s V_5
IL_005f: ldloc.s V_5
IL_0061: brtrue.s IL_006a
IL_0061: brtrue.s IL_006c
IL_0063: ldloc.0
IL_0064: call void [mscorlib]System.Console::WriteLine(object)
IL_0069: nop
IL_0063: nop
IL_0064: ldloc.0
IL_0065: call void [mscorlib]System.Console::WriteLine(object)
IL_006a: nop
IL_006b: ldloca.s V_3
IL_006d: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0072: stloc.s V_5
IL_0074: ldloc.s V_5
IL_0076: brtrue.s IL_000b
IL_006b: nop
IL_006c: nop
IL_006d: ldloca.s V_3
IL_006f: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0074: stloc.s V_5
IL_0076: ldloc.s V_5
IL_0078: brtrue.s IL_000b
IL_0078: leave.s IL_0089
IL_007a: leave.s IL_008b
} // end .try
finally
{
IL_007a: ldloca.s V_3
IL_007c: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_0082: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0087: nop
IL_0088: endfinally
IL_007c: ldloca.s V_3
IL_007e: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_0084: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0089: nop
IL_008a: endfinally
} // end handler
IL_0089: nop
IL_008a: ldstr "end"
IL_008f: call void [mscorlib]System.Console::WriteLine(string)
IL_0094: nop
IL_0095: ret
IL_008b: nop
IL_008c: ldstr "end"
IL_0091: call void [mscorlib]System.Console::WriteLine(string)
IL_0096: nop
IL_0097: ret
} // end of method Loops::NestedForeach
.method public hidebysig instance void
MergeAroundContinue() cil managed
{
// Code size 137 (0x89)
// Code size 140 (0x8c)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0074
IL_0003: br.s IL_0077
IL_0005: nop
IL_0006: ldloc.0
@ -3061,7 +3063,7 @@ @@ -3061,7 +3063,7 @@
IL_000d: ceq
IL_000f: stloc.1
IL_0010: ldloc.1
IL_0011: brtrue.s IL_0021
IL_0011: brtrue.s IL_0022
IL_0013: nop
IL_0014: ldloc.0
@ -3069,94 +3071,97 @@ @@ -3069,94 +3071,97 @@
IL_0016: ceq
IL_0018: stloc.1
IL_0019: ldloc.1
IL_001a: brtrue.s IL_001e
IL_001a: brtrue.s IL_001f
IL_001c: br.s IL_0070
IL_001c: nop
IL_001d: br.s IL_0073
IL_001e: nop
IL_001f: br.s IL_0068
IL_0021: ldloc.0
IL_0022: ldc.i4.5
IL_0023: rem
IL_0024: ldc.i4.0
IL_0025: ceq
IL_0027: ldc.i4.0
IL_0028: ceq
IL_002a: stloc.1
IL_002b: ldloc.1
IL_002c: brtrue.s IL_003c
IL_002e: nop
IL_002f: ldloc.0
IL_0030: ldc.i4.5
IL_0031: ceq
IL_0033: stloc.1
IL_0034: ldloc.1
IL_0035: brtrue.s IL_0039
IL_001f: nop
IL_0020: br.s IL_006b
IL_0022: ldloc.0
IL_0023: ldc.i4.5
IL_0024: rem
IL_0025: ldc.i4.0
IL_0026: ceq
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b: stloc.1
IL_002c: ldloc.1
IL_002d: brtrue.s IL_003e
IL_0037: br.s IL_0070
IL_002f: nop
IL_0030: ldloc.0
IL_0031: ldc.i4.5
IL_0032: ceq
IL_0034: stloc.1
IL_0035: ldloc.1
IL_0036: brtrue.s IL_003b
IL_0039: nop
IL_003a: br.s IL_0068
IL_0038: nop
IL_0039: br.s IL_0073
IL_003c: ldloc.0
IL_003d: ldc.i4.7
IL_003e: rem
IL_003f: ldc.i4.0
IL_0040: ceq
IL_0042: ldc.i4.0
IL_0043: ceq
IL_0045: stloc.1
IL_0046: ldloc.1
IL_0047: brtrue.s IL_0057
IL_003b: nop
IL_003c: br.s IL_006b
IL_0049: nop
IL_004a: ldloc.0
IL_004b: ldc.i4.7
IL_004c: ceq
IL_004e: stloc.1
IL_004f: ldloc.1
IL_0050: brtrue.s IL_0054
IL_003e: ldloc.0
IL_003f: ldc.i4.7
IL_0040: rem
IL_0041: ldc.i4.0
IL_0042: ceq
IL_0044: ldc.i4.0
IL_0045: ceq
IL_0047: stloc.1
IL_0048: ldloc.1
IL_0049: brtrue.s IL_005a
IL_0052: br.s IL_0070
IL_004b: nop
IL_004c: ldloc.0
IL_004d: ldc.i4.7
IL_004e: ceq
IL_0050: stloc.1
IL_0051: ldloc.1
IL_0052: brtrue.s IL_0057
IL_0054: nop
IL_0055: br.s IL_0068
IL_0055: br.s IL_0073
IL_0057: nop
IL_0058: br.s IL_006b
IL_0057: ldloc.0
IL_0058: ldc.i4.s 11
IL_005a: rem
IL_005b: ldc.i4.0
IL_005c: ceq
IL_005a: ldloc.0
IL_005b: ldc.i4.s 11
IL_005d: rem
IL_005e: ldc.i4.0
IL_005f: ceq
IL_0061: stloc.1
IL_0062: ldloc.1
IL_0063: brtrue.s IL_0068
IL_0061: ldc.i4.0
IL_0062: ceq
IL_0064: stloc.1
IL_0065: ldloc.1
IL_0066: brtrue.s IL_006b
IL_0065: nop
IL_0066: br.s IL_0070
IL_0068: nop
IL_0069: br.s IL_0073
IL_0068: ldloc.0
IL_0069: call void [mscorlib]System.Console::WriteLine(int32)
IL_006e: nop
IL_006f: nop
IL_0070: ldloc.0
IL_0071: ldc.i4.1
IL_0072: add
IL_0073: stloc.0
IL_0074: ldloc.0
IL_0075: ldc.i4.s 20
IL_0077: clt
IL_0079: stloc.1
IL_007a: ldloc.1
IL_007b: brtrue.s IL_0005
IL_007d: ldstr "end"
IL_0082: call void [mscorlib]System.Console::WriteLine(string)
IL_0087: nop
IL_0088: ret
IL_006b: ldloc.0
IL_006c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0071: nop
IL_0072: nop
IL_0073: ldloc.0
IL_0074: ldc.i4.1
IL_0075: add
IL_0076: stloc.0
IL_0077: ldloc.0
IL_0078: ldc.i4.s 20
IL_007a: clt
IL_007c: stloc.1
IL_007d: ldloc.1
IL_007e: brtrue.s IL_0005
IL_0080: ldstr "end"
IL_0085: call void [mscorlib]System.Console::WriteLine(string)
IL_008a: nop
IL_008b: ret
} // end of method Loops::MergeAroundContinue
.method public hidebysig specialname rtspecialname

201
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.roslyn.il

@ -2756,7 +2756,7 @@ @@ -2756,7 +2756,7 @@
NestedForeach(class [mscorlib]System.Collections.Generic.List`1<object> items1,
class [mscorlib]System.Collections.Generic.List`1<object> items2) cil managed
{
// Code size 141 (0x8d)
// Code size 143 (0x8f)
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_0,
object V_1,
@ -2772,7 +2772,7 @@ @@ -2772,7 +2772,7 @@
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_0067
IL_0009: br.s IL_0069
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
@ -2825,37 +2825,39 @@ @@ -2825,37 +2825,39 @@
IL_0057: ceq
IL_0059: stloc.s V_6
IL_005b: ldloc.s V_6
IL_005d: brfalse.s IL_0066
IL_005d: brfalse.s IL_0068
IL_005f: ldloc.1
IL_0060: call void [mscorlib]System.Console::WriteLine(object)
IL_0065: nop
IL_005f: nop
IL_0060: ldloc.1
IL_0061: call void [mscorlib]System.Console::WriteLine(object)
IL_0066: nop
IL_0067: ldloca.s V_0
IL_0069: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_006e: brtrue.s IL_000b
IL_0067: nop
IL_0068: nop
IL_0069: ldloca.s V_0
IL_006b: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0070: brtrue.s IL_000b
IL_0070: leave.s IL_0081
IL_0072: leave.s IL_0083
} // end .try
finally
{
IL_0072: ldloca.s V_0
IL_0074: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_007a: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_007f: nop
IL_0080: endfinally
IL_0074: ldloca.s V_0
IL_0076: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_007c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0081: nop
IL_0082: endfinally
} // end handler
IL_0081: ldstr "end"
IL_0086: call void [mscorlib]System.Console::WriteLine(string)
IL_008b: nop
IL_008c: ret
IL_0083: ldstr "end"
IL_0088: call void [mscorlib]System.Console::WriteLine(string)
IL_008d: nop
IL_008e: ret
} // end of method Loops::NestedForeach
.method public hidebysig instance void
MergeAroundContinue() cil managed
{
// Code size 144 (0x90)
// Code size 150 (0x96)
.maxstack 2
.locals init (int32 V_0,
bool V_1,
@ -2869,7 +2871,7 @@ @@ -2869,7 +2871,7 @@
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0079
IL_0003: br.s IL_007c
IL_0005: nop
IL_0006: ldloc.0
@ -2879,7 +2881,7 @@ @@ -2879,7 +2881,7 @@
IL_000a: ceq
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: brfalse.s IL_0021
IL_000e: brfalse.s IL_0022
IL_0010: nop
IL_0011: ldloc.0
@ -2889,92 +2891,95 @@ @@ -2889,92 +2891,95 @@
IL_0016: ceq
IL_0018: stloc.2
IL_0019: ldloc.2
IL_001a: brfalse.s IL_001e
IL_001a: brfalse.s IL_001f
IL_001c: br.s IL_0075
IL_001c: nop
IL_001d: br.s IL_0078
IL_001e: nop
IL_001f: br.s IL_006d
IL_001f: nop
IL_0020: br.s IL_0070
IL_0021: ldloc.0
IL_0022: ldc.i4.5
IL_0023: rem
IL_0024: ldc.i4.0
IL_0025: ceq
IL_0027: stloc.3
IL_0028: ldloc.3
IL_0029: brfalse.s IL_003e
IL_0022: ldloc.0
IL_0023: ldc.i4.5
IL_0024: rem
IL_0025: ldc.i4.0
IL_0026: ceq
IL_0028: stloc.3
IL_0029: ldloc.3
IL_002a: brfalse.s IL_0040
IL_002b: nop
IL_002c: ldloc.0
IL_002d: ldc.i4.5
IL_002e: ceq
IL_0030: ldc.i4.0
IL_0031: ceq
IL_0033: stloc.s V_4
IL_0035: ldloc.s V_4
IL_0037: brfalse.s IL_003b
IL_002c: nop
IL_002d: ldloc.0
IL_002e: ldc.i4.5
IL_002f: ceq
IL_0031: ldc.i4.0
IL_0032: ceq
IL_0034: stloc.s V_4
IL_0036: ldloc.s V_4
IL_0038: brfalse.s IL_003d
IL_0039: br.s IL_0075
IL_003a: nop
IL_003b: br.s IL_0078
IL_003b: nop
IL_003c: br.s IL_006d
IL_003e: ldloc.0
IL_003f: ldc.i4.7
IL_0040: rem
IL_0041: ldc.i4.0
IL_0042: ceq
IL_0044: stloc.s V_5
IL_0046: ldloc.s V_5
IL_0048: brfalse.s IL_005d
IL_004a: nop
IL_004b: ldloc.0
IL_004c: ldc.i4.7
IL_004d: ceq
IL_004f: ldc.i4.0
IL_0050: ceq
IL_0052: stloc.s V_6
IL_0054: ldloc.s V_6
IL_0056: brfalse.s IL_005a
IL_0058: br.s IL_0075
IL_003d: nop
IL_003e: br.s IL_0070
IL_0040: ldloc.0
IL_0041: ldc.i4.7
IL_0042: rem
IL_0043: ldc.i4.0
IL_0044: ceq
IL_0046: stloc.s V_5
IL_0048: ldloc.s V_5
IL_004a: brfalse.s IL_0060
IL_004c: nop
IL_004d: ldloc.0
IL_004e: ldc.i4.7
IL_004f: ceq
IL_0051: ldc.i4.0
IL_0052: ceq
IL_0054: stloc.s V_6
IL_0056: ldloc.s V_6
IL_0058: brfalse.s IL_005d
IL_005a: nop
IL_005b: br.s IL_006d
IL_005b: br.s IL_0078
IL_005d: ldloc.0
IL_005e: ldc.i4.s 11
IL_0060: rem
IL_0061: ldc.i4.0
IL_0062: ceq
IL_0064: stloc.s V_7
IL_0066: ldloc.s V_7
IL_0068: brfalse.s IL_006d
IL_005d: nop
IL_005e: br.s IL_0070
IL_006a: nop
IL_006b: br.s IL_0075
IL_006d: ldloc.0
IL_006e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0073: nop
IL_0074: nop
IL_0075: ldloc.0
IL_0076: ldc.i4.1
IL_0077: add
IL_0078: stloc.0
IL_0079: ldloc.0
IL_007a: ldc.i4.s 20
IL_007c: clt
IL_007e: stloc.s V_8
IL_0080: ldloc.s V_8
IL_0082: brtrue.s IL_0005
IL_0084: ldstr "end"
IL_0089: call void [mscorlib]System.Console::WriteLine(string)
IL_008e: nop
IL_008f: ret
IL_0060: ldloc.0
IL_0061: ldc.i4.s 11
IL_0063: rem
IL_0064: ldc.i4.0
IL_0065: ceq
IL_0067: stloc.s V_7
IL_0069: ldloc.s V_7
IL_006b: brfalse.s IL_0070
IL_006d: nop
IL_006e: br.s IL_0078
IL_0070: ldloc.0
IL_0071: call void [mscorlib]System.Console::WriteLine(int32)
IL_0076: nop
IL_0077: nop
IL_0078: ldloc.0
IL_0079: ldc.i4.1
IL_007a: add
IL_007b: stloc.0
IL_007c: ldloc.0
IL_007d: ldc.i4.s 20
IL_007f: clt
IL_0081: stloc.s V_8
IL_0083: ldloc.s V_8
IL_0085: brtrue IL_0005
IL_008a: ldstr "end"
IL_008f: call void [mscorlib]System.Console::WriteLine(string)
IL_0094: nop
IL_0095: ret
} // end of method Loops::MergeAroundContinue
.method public hidebysig specialname rtspecialname

270
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs

@ -0,0 +1,270 @@ @@ -0,0 +1,270 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public abstract class ReduceNesting
{
public abstract bool B(int i);
public abstract int I(int i);
public void IfIf()
{
if (B(0)) {
Console.WriteLine(0);
return;
}
if (B(1)) {
Console.WriteLine(1);
}
Console.WriteLine("end");
}
public void IfSwitch()
{
if (B(0)) {
Console.WriteLine(0);
return;
}
Console.WriteLine("switch");
switch (I(0)) {
case 0:
Console.WriteLine("case 0");
break;
case 1:
Console.WriteLine("case 1");
break;
default:
Console.WriteLine("end");
break;
}
}
public void IfSwitchSwitch()
{
if (B(0)) {
Console.WriteLine(0);
return;
}
Console.WriteLine("switch 0");
switch (I(1)) {
case 0:
Console.WriteLine("case 0");
return;
case 1:
Console.WriteLine("case 1");
return;
}
Console.WriteLine("switch 1");
switch (I(1)) {
case 0:
Console.WriteLine("case 0");
break;
case 1:
Console.WriteLine("case 1");
break;
default:
Console.WriteLine("end");
break;
}
}
public void IfLoop()
{
if (B(0)) {
Console.WriteLine(0);
return;
}
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
}
Console.WriteLine("end");
}
public void LoopContinue()
{
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
if (B(0)) {
Console.WriteLine(0);
continue;
}
if (B(1)) {
Console.WriteLine(1);
}
Console.WriteLine("loop-tail");
}
}
public void LoopBreak()
{
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
if (B(0)) {
Console.WriteLine(0);
continue;
}
if (B(1)) {
Console.WriteLine(1);
break;
}
if (B(2)) {
Console.WriteLine(2);
}
Console.WriteLine("break");
break;
}
Console.WriteLine("end");
}
public void LoopBreakElseIf()
{
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
if (B(0)) {
Console.WriteLine(0);
continue;
}
if (B(1)) {
Console.WriteLine(1);
} else if (B(2)) {
Console.WriteLine(2);
}
break;
}
Console.WriteLine("end");
}
public void SwitchIf()
{
switch (I(0)) {
case 0:
Console.WriteLine("case 0");
return;
case 1:
Console.WriteLine("case 1");
return;
}
if (B(0)) {
Console.WriteLine(0);
}
Console.WriteLine("end");
}
public void NestedSwitchIf()
{
if (B(0)) {
switch (I(0)) {
case 0:
Console.WriteLine("case 0");
return;
case 1:
Console.WriteLine("case 1");
return;
}
if (B(1)) {
Console.WriteLine(1);
}
} else {
Console.WriteLine("else");
}
}
// nesting should not be reduced as maximum nesting level is 1
public void EarlyExit1()
{
if (!B(0)) {
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
}
Console.WriteLine("end");
}
}
// nesting should not be reduced as maximum nesting level is 2
public void EarlyExit2()
{
if (B(0)) {
return;
}
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
if (i % 2 == 0) {
Console.WriteLine("even");
}
}
Console.WriteLine("end");
}
// nesting should not be reduced as maximum nesting level is 1 and the else block has no more instructions than any other block
public void BalancedIf()
{
if (B(0)) {
Console.WriteLine("true");
if (B(1)) {
Console.WriteLine(1);
}
} else {
if (B(2)) {
Console.WriteLine(2);
}
Console.WriteLine("false");
}
}
public string ComplexCase1(string s)
{
if (B(0)) {
return s;
}
for (int i = 0; i < s.Length; i++) {
if (B(1)) {
Console.WriteLine(1);
} else if (B(2)) {
switch (i) {
case 1:
if (B(3)) {
Console.WriteLine(3);
break;
}
Console.WriteLine("case1");
if (B(4)) {
Console.WriteLine(4);
}
break;
case 2:
case 3:
Console.WriteLine("case23");
break;
}
Console.WriteLine(2);
} else if (B(5)) {
Console.WriteLine(5);
} else {
if (B(6)) {
Console.WriteLine(6);
}
Console.WriteLine("else");
}
}
return s;
}
}
}

949
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.il

@ -0,0 +1,949 @@ @@ -0,0 +1,949 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ReduceNesting
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ReduceNesting.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ReduceNesting::B
.method public hidebysig newslot abstract virtual
instance int32 I(int32 i) cil managed
{
} // end of method ReduceNesting::I
.method public hidebysig instance void
IfIf() cil managed
{
// Code size 60 (0x3c)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_0019
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: br.s IL_003b
IL_0019: ldarg.0
IL_001a: ldc.i4.1
IL_001b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0020: ldc.i4.0
IL_0021: ceq
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: brtrue.s IL_0030
IL_0027: nop
IL_0028: ldc.i4.1
IL_0029: call void [mscorlib]System.Console::WriteLine(int32)
IL_002e: nop
IL_002f: nop
IL_0030: ldstr "end"
IL_0035: call void [mscorlib]System.Console::WriteLine(string)
IL_003a: nop
IL_003b: ret
} // end of method ReduceNesting::IfIf
.method public hidebysig instance void
IfSwitch() cil managed
{
// Code size 100 (0x64)
.maxstack 2
.locals init (bool V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_0019
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: br.s IL_0063
IL_0019: ldstr "switch"
IL_001e: call void [mscorlib]System.Console::WriteLine(string)
IL_0023: nop
IL_0024: ldarg.0
IL_0025: ldc.i4.0
IL_0026: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_002b: stloc.1
IL_002c: ldloc.1
IL_002d: switch (
IL_003c,
IL_0049)
IL_003a: br.s IL_0056
IL_003c: ldstr "case 0"
IL_0041: call void [mscorlib]System.Console::WriteLine(string)
IL_0046: nop
IL_0047: br.s IL_0063
IL_0049: ldstr "case 1"
IL_004e: call void [mscorlib]System.Console::WriteLine(string)
IL_0053: nop
IL_0054: br.s IL_0063
IL_0056: ldstr "end"
IL_005b: call void [mscorlib]System.Console::WriteLine(string)
IL_0060: nop
IL_0061: br.s IL_0063
IL_0063: ret
} // end of method ReduceNesting::IfSwitch
.method public hidebysig instance void
IfSwitchSwitch() cil managed
{
// Code size 164 (0xa4)
.maxstack 2
.locals init (bool V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_001c
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: br IL_00a3
IL_001c: ldstr "switch 0"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: nop
IL_0027: ldarg.0
IL_0028: ldc.i4.1
IL_0029: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_002e: stloc.1
IL_002f: ldloc.1
IL_0030: switch (
IL_003f,
IL_004c)
IL_003d: br.s IL_0059
IL_003f: ldstr "case 0"
IL_0044: call void [mscorlib]System.Console::WriteLine(string)
IL_0049: nop
IL_004a: br.s IL_00a3
IL_004c: ldstr "case 1"
IL_0051: call void [mscorlib]System.Console::WriteLine(string)
IL_0056: nop
IL_0057: br.s IL_00a3
IL_0059: ldstr "switch 1"
IL_005e: call void [mscorlib]System.Console::WriteLine(string)
IL_0063: nop
IL_0064: ldarg.0
IL_0065: ldc.i4.1
IL_0066: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_006b: stloc.1
IL_006c: ldloc.1
IL_006d: switch (
IL_007c,
IL_0089)
IL_007a: br.s IL_0096
IL_007c: ldstr "case 0"
IL_0081: call void [mscorlib]System.Console::WriteLine(string)
IL_0086: nop
IL_0087: br.s IL_00a3
IL_0089: ldstr "case 1"
IL_008e: call void [mscorlib]System.Console::WriteLine(string)
IL_0093: nop
IL_0094: br.s IL_00a3
IL_0096: ldstr "end"
IL_009b: call void [mscorlib]System.Console::WriteLine(string)
IL_00a0: nop
IL_00a1: br.s IL_00a3
IL_00a3: ret
} // end of method ReduceNesting::IfSwitchSwitch
.method public hidebysig instance void
IfLoop() cil managed
{
// Code size 63 (0x3f)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: brtrue.s IL_0019
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: br.s IL_003e
IL_0019: ldc.i4.0
IL_001a: stloc.0
IL_001b: br.s IL_002a
IL_001d: nop
IL_001e: ldloc.0
IL_001f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0024: nop
IL_0025: nop
IL_0026: ldloc.0
IL_0027: ldc.i4.1
IL_0028: add
IL_0029: stloc.0
IL_002a: ldloc.0
IL_002b: ldc.i4.s 10
IL_002d: clt
IL_002f: stloc.1
IL_0030: ldloc.1
IL_0031: brtrue.s IL_001d
IL_0033: ldstr "end"
IL_0038: call void [mscorlib]System.Console::WriteLine(string)
IL_003d: nop
IL_003e: ret
} // end of method ReduceNesting::IfLoop
.method public hidebysig instance void
LoopContinue() cil managed
{
// Code size 86 (0x56)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_004c
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: ldc.i4.0
IL_0015: ceq
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brtrue.s IL_0025
IL_001b: nop
IL_001c: ldc.i4.0
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: nop
IL_0023: br.s IL_0048
IL_0025: ldarg.0
IL_0026: ldc.i4.1
IL_0027: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002c: ldc.i4.0
IL_002d: ceq
IL_002f: stloc.1
IL_0030: ldloc.1
IL_0031: brtrue.s IL_003c
IL_0033: nop
IL_0034: ldc.i4.1
IL_0035: call void [mscorlib]System.Console::WriteLine(int32)
IL_003a: nop
IL_003b: nop
IL_003c: ldstr "loop-tail"
IL_0041: call void [mscorlib]System.Console::WriteLine(string)
IL_0046: nop
IL_0047: nop
IL_0048: ldloc.0
IL_0049: ldc.i4.1
IL_004a: add
IL_004b: stloc.0
IL_004c: ldloc.0
IL_004d: ldc.i4.s 10
IL_004f: clt
IL_0051: stloc.1
IL_0052: ldloc.1
IL_0053: brtrue.s IL_0005
IL_0055: ret
} // end of method ReduceNesting::LoopContinue
.method public hidebysig instance void
LoopBreak() cil managed
{
// Code size 122 (0x7a)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0065
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: ldc.i4.0
IL_0015: ceq
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brtrue.s IL_0025
IL_001b: nop
IL_001c: ldc.i4.0
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: nop
IL_0023: br.s IL_0061
IL_0025: ldarg.0
IL_0026: ldc.i4.1
IL_0027: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002c: ldc.i4.0
IL_002d: ceq
IL_002f: stloc.1
IL_0030: ldloc.1
IL_0031: brtrue.s IL_003d
IL_0033: nop
IL_0034: ldc.i4.1
IL_0035: call void [mscorlib]System.Console::WriteLine(int32)
IL_003a: nop
IL_003b: br.s IL_006e
IL_003d: ldarg.0
IL_003e: ldc.i4.2
IL_003f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0044: ldc.i4.0
IL_0045: ceq
IL_0047: stloc.1
IL_0048: ldloc.1
IL_0049: brtrue.s IL_0054
IL_004b: nop
IL_004c: ldc.i4.2
IL_004d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0052: nop
IL_0053: nop
IL_0054: ldstr "break"
IL_0059: call void [mscorlib]System.Console::WriteLine(string)
IL_005e: nop
IL_005f: br.s IL_006e
IL_0061: ldloc.0
IL_0062: ldc.i4.1
IL_0063: add
IL_0064: stloc.0
IL_0065: ldloc.0
IL_0066: ldc.i4.s 10
IL_0068: clt
IL_006a: stloc.1
IL_006b: ldloc.1
IL_006c: brtrue.s IL_0005
IL_006e: ldstr "end"
IL_0073: call void [mscorlib]System.Console::WriteLine(string)
IL_0078: nop
IL_0079: ret
} // end of method ReduceNesting::LoopBreak
.method public hidebysig instance void
LoopBreakElseIf() cil managed
{
// Code size 112 (0x70)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_005b
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: ldc.i4.0
IL_0015: ceq
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brtrue.s IL_0025
IL_001b: nop
IL_001c: ldc.i4.0
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: nop
IL_0023: br.s IL_0057
IL_0025: ldarg.0
IL_0026: ldc.i4.1
IL_0027: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002c: ldc.i4.0
IL_002d: ceq
IL_002f: stloc.1
IL_0030: ldloc.1
IL_0031: brtrue.s IL_003e
IL_0033: nop
IL_0034: ldc.i4.1
IL_0035: call void [mscorlib]System.Console::WriteLine(int32)
IL_003a: nop
IL_003b: nop
IL_003c: br.s IL_0055
IL_003e: ldarg.0
IL_003f: ldc.i4.2
IL_0040: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0045: ldc.i4.0
IL_0046: ceq
IL_0048: stloc.1
IL_0049: ldloc.1
IL_004a: brtrue.s IL_0055
IL_004c: nop
IL_004d: ldc.i4.2
IL_004e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0053: nop
IL_0054: nop
IL_0055: br.s IL_0064
IL_0057: ldloc.0
IL_0058: ldc.i4.1
IL_0059: add
IL_005a: stloc.0
IL_005b: ldloc.0
IL_005c: ldc.i4.s 10
IL_005e: clt
IL_0060: stloc.1
IL_0061: ldloc.1
IL_0062: brtrue.s IL_0005
IL_0064: ldstr "end"
IL_0069: call void [mscorlib]System.Console::WriteLine(string)
IL_006e: nop
IL_006f: ret
} // end of method ReduceNesting::LoopBreakElseIf
.method public hidebysig instance void
SwitchIf() cil managed
{
// Code size 86 (0x56)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: switch (
IL_0019,
IL_0026)
IL_0017: br.s IL_0033
IL_0019: ldstr "case 0"
IL_001e: call void [mscorlib]System.Console::WriteLine(string)
IL_0023: nop
IL_0024: br.s IL_0055
IL_0026: ldstr "case 1"
IL_002b: call void [mscorlib]System.Console::WriteLine(string)
IL_0030: nop
IL_0031: br.s IL_0055
IL_0033: ldarg.0
IL_0034: ldc.i4.0
IL_0035: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003a: ldc.i4.0
IL_003b: ceq
IL_003d: stloc.1
IL_003e: ldloc.1
IL_003f: brtrue.s IL_004a
IL_0041: nop
IL_0042: ldc.i4.0
IL_0043: call void [mscorlib]System.Console::WriteLine(int32)
IL_0048: nop
IL_0049: nop
IL_004a: ldstr "end"
IL_004f: call void [mscorlib]System.Console::WriteLine(string)
IL_0054: nop
IL_0055: ret
} // end of method ReduceNesting::SwitchIf
.method public hidebysig instance void
NestedSwitchIf() cil managed
{
// Code size 106 (0x6a)
.maxstack 2
.locals init (bool V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_005c
IL_000f: nop
IL_0010: ldarg.0
IL_0011: ldc.i4.0
IL_0012: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: switch (
IL_0028,
IL_0035)
IL_0026: br.s IL_0042
IL_0028: ldstr "case 0"
IL_002d: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: nop
IL_0033: br.s IL_0069
IL_0035: ldstr "case 1"
IL_003a: call void [mscorlib]System.Console::WriteLine(string)
IL_003f: nop
IL_0040: br.s IL_0069
IL_0042: ldarg.0
IL_0043: ldc.i4.1
IL_0044: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0049: ldc.i4.0
IL_004a: ceq
IL_004c: stloc.0
IL_004d: ldloc.0
IL_004e: brtrue.s IL_0059
IL_0050: nop
IL_0051: ldc.i4.1
IL_0052: call void [mscorlib]System.Console::WriteLine(int32)
IL_0057: nop
IL_0058: nop
IL_0059: nop
IL_005a: br.s IL_0069
IL_005c: nop
IL_005d: ldstr "else"
IL_0062: call void [mscorlib]System.Console::WriteLine(string)
IL_0067: nop
IL_0068: nop
IL_0069: ret
} // end of method ReduceNesting::NestedSwitchIf
.method public hidebysig instance void
EarlyExit1() cil managed
{
// Code size 52 (0x34)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: brtrue.s IL_0033
IL_000c: nop
IL_000d: ldc.i4.0
IL_000e: stloc.0
IL_000f: br.s IL_001e
IL_0011: nop
IL_0012: ldloc.0
IL_0013: call void [mscorlib]System.Console::WriteLine(int32)
IL_0018: nop
IL_0019: nop
IL_001a: ldloc.0
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stloc.0
IL_001e: ldloc.0
IL_001f: ldc.i4.s 10
IL_0021: clt
IL_0023: stloc.1
IL_0024: ldloc.1
IL_0025: brtrue.s IL_0011
IL_0027: ldstr "end"
IL_002c: call void [mscorlib]System.Console::WriteLine(string)
IL_0031: nop
IL_0032: nop
IL_0033: ret
} // end of method ReduceNesting::EarlyExit1
.method public hidebysig instance void
EarlyExit2() cil managed
{
// Code size 82 (0x52)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: brtrue.s IL_0012
IL_000f: nop
IL_0010: br.s IL_0051
IL_0012: ldc.i4.0
IL_0013: stloc.0
IL_0014: br.s IL_003d
IL_0016: nop
IL_0017: ldloc.0
IL_0018: call void [mscorlib]System.Console::WriteLine(int32)
IL_001d: nop
IL_001e: ldloc.0
IL_001f: ldc.i4.2
IL_0020: rem
IL_0021: ldc.i4.0
IL_0022: ceq
IL_0024: ldc.i4.0
IL_0025: ceq
IL_0027: stloc.1
IL_0028: ldloc.1
IL_0029: brtrue.s IL_0038
IL_002b: nop
IL_002c: ldstr "even"
IL_0031: call void [mscorlib]System.Console::WriteLine(string)
IL_0036: nop
IL_0037: nop
IL_0038: nop
IL_0039: ldloc.0
IL_003a: ldc.i4.1
IL_003b: add
IL_003c: stloc.0
IL_003d: ldloc.0
IL_003e: ldc.i4.s 10
IL_0040: clt
IL_0042: stloc.1
IL_0043: ldloc.1
IL_0044: brtrue.s IL_0016
IL_0046: ldstr "end"
IL_004b: call void [mscorlib]System.Console::WriteLine(string)
IL_0050: nop
IL_0051: ret
} // end of method ReduceNesting::EarlyExit2
.method public hidebysig instance void
BalancedIf() cil managed
{
// Code size 90 (0x5a)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_0035
IL_000f: nop
IL_0010: ldstr "true"
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: nop
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: ldc.i4.0
IL_0023: ceq
IL_0025: stloc.0
IL_0026: ldloc.0
IL_0027: brtrue.s IL_0032
IL_0029: nop
IL_002a: ldc.i4.1
IL_002b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0030: nop
IL_0031: nop
IL_0032: nop
IL_0033: br.s IL_0059
IL_0035: nop
IL_0036: ldarg.0
IL_0037: ldc.i4.2
IL_0038: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003d: ldc.i4.0
IL_003e: ceq
IL_0040: stloc.0
IL_0041: ldloc.0
IL_0042: brtrue.s IL_004d
IL_0044: nop
IL_0045: ldc.i4.2
IL_0046: call void [mscorlib]System.Console::WriteLine(int32)
IL_004b: nop
IL_004c: nop
IL_004d: ldstr "false"
IL_0052: call void [mscorlib]System.Console::WriteLine(string)
IL_0057: nop
IL_0058: nop
IL_0059: ret
} // end of method ReduceNesting::BalancedIf
.method public hidebysig instance string
ComplexCase1(string s) cil managed
{
// Code size 269 (0x10d)
.maxstack 2
.locals init (int32 V_0,
string V_1,
bool V_2,
int32 V_3)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.2
IL_000c: ldloc.2
IL_000d: brtrue.s IL_0017
IL_000f: nop
IL_0010: ldarg.1
IL_0011: stloc.1
IL_0012: br IL_010b
IL_0017: ldc.i4.0
IL_0018: stloc.0
IL_0019: br IL_00f7
IL_001e: nop
IL_001f: ldarg.0
IL_0020: ldc.i4.1
IL_0021: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0026: ldc.i4.0
IL_0027: ceq
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: brtrue.s IL_003b
IL_002d: nop
IL_002e: ldc.i4.1
IL_002f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0034: nop
IL_0035: nop
IL_0036: br IL_00f2
IL_003b: ldarg.0
IL_003c: ldc.i4.2
IL_003d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0042: ldc.i4.0
IL_0043: ceq
IL_0045: stloc.2
IL_0046: ldloc.2
IL_0047: brtrue.s IL_00b5
IL_0049: nop
IL_004a: ldloc.0
IL_004b: stloc.3
IL_004c: ldloc.3
IL_004d: ldc.i4.1
IL_004e: sub
IL_004f: switch (
IL_0062,
IL_009e,
IL_009e)
IL_0060: br.s IL_00ab
IL_0062: ldarg.0
IL_0063: ldc.i4.3
IL_0064: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0069: ldc.i4.0
IL_006a: ceq
IL_006c: stloc.2
IL_006d: ldloc.2
IL_006e: brtrue.s IL_007a
IL_0070: nop
IL_0071: ldc.i4.3
IL_0072: call void [mscorlib]System.Console::WriteLine(int32)
IL_0077: nop
IL_0078: br.s IL_00ab
IL_007a: ldstr "case1"
IL_007f: call void [mscorlib]System.Console::WriteLine(string)
IL_0084: nop
IL_0085: ldarg.0
IL_0086: ldc.i4.4
IL_0087: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_008c: ldc.i4.0
IL_008d: ceq
IL_008f: stloc.2
IL_0090: ldloc.2
IL_0091: brtrue.s IL_009c
IL_0093: nop
IL_0094: ldc.i4.4
IL_0095: call void [mscorlib]System.Console::WriteLine(int32)
IL_009a: nop
IL_009b: nop
IL_009c: br.s IL_00ab
IL_009e: ldstr "case23"
IL_00a3: call void [mscorlib]System.Console::WriteLine(string)
IL_00a8: nop
IL_00a9: br.s IL_00ab
IL_00ab: ldc.i4.2
IL_00ac: call void [mscorlib]System.Console::WriteLine(int32)
IL_00b1: nop
IL_00b2: nop
IL_00b3: br.s IL_00f2
IL_00b5: ldarg.0
IL_00b6: ldc.i4.5
IL_00b7: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_00bc: ldc.i4.0
IL_00bd: ceq
IL_00bf: stloc.2
IL_00c0: ldloc.2
IL_00c1: brtrue.s IL_00ce
IL_00c3: nop
IL_00c4: ldc.i4.5
IL_00c5: call void [mscorlib]System.Console::WriteLine(int32)
IL_00ca: nop
IL_00cb: nop
IL_00cc: br.s IL_00f2
IL_00ce: nop
IL_00cf: ldarg.0
IL_00d0: ldc.i4.6
IL_00d1: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_00d6: ldc.i4.0
IL_00d7: ceq
IL_00d9: stloc.2
IL_00da: ldloc.2
IL_00db: brtrue.s IL_00e6
IL_00dd: nop
IL_00de: ldc.i4.6
IL_00df: call void [mscorlib]System.Console::WriteLine(int32)
IL_00e4: nop
IL_00e5: nop
IL_00e6: ldstr "else"
IL_00eb: call void [mscorlib]System.Console::WriteLine(string)
IL_00f0: nop
IL_00f1: nop
IL_00f2: nop
IL_00f3: ldloc.0
IL_00f4: ldc.i4.1
IL_00f5: add
IL_00f6: stloc.0
IL_00f7: ldloc.0
IL_00f8: ldarg.1
IL_00f9: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_00fe: clt
IL_0100: stloc.2
IL_0101: ldloc.2
IL_0102: brtrue IL_001e
IL_0107: ldarg.1
IL_0108: stloc.1
IL_0109: br.s IL_010b
IL_010b: ldloc.1
IL_010c: ret
} // end of method ReduceNesting::ComplexCase1
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ReduceNesting::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

650
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.opt.il

@ -0,0 +1,650 @@ @@ -0,0 +1,650 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ReduceNesting.opt
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ReduceNesting.opt.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ReduceNesting::B
.method public hidebysig newslot abstract virtual
instance int32 I(int32 i) cil managed
{
} // end of method ReduceNesting::I
.method public hidebysig instance void
IfIf() cil managed
{
// Code size 42 (0x2a)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldarg.0
IL_0011: ldc.i4.1
IL_0012: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0017: brfalse.s IL_001f
IL_0019: ldc.i4.1
IL_001a: call void [mscorlib]System.Console::WriteLine(int32)
IL_001f: ldstr "end"
IL_0024: call void [mscorlib]System.Console::WriteLine(string)
IL_0029: ret
} // end of method ReduceNesting::IfIf
.method public hidebysig instance void
IfSwitch() cil managed
{
// Code size 83 (0x53)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldstr "switch"
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: ldarg.0
IL_001b: ldc.i4.0
IL_001c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: switch (
IL_0032,
IL_003d)
IL_0030: br.s IL_0048
IL_0032: ldstr "case 0"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ret
IL_003d: ldstr "case 1"
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
IL_0047: ret
IL_0048: ldstr "end"
IL_004d: call void [mscorlib]System.Console::WriteLine(string)
IL_0052: ret
} // end of method ReduceNesting::IfSwitch
.method public hidebysig instance void
IfSwitchSwitch() cil managed
{
// Code size 139 (0x8b)
.maxstack 2
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldstr "switch 0"
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: ldarg.0
IL_001b: ldc.i4.1
IL_001c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: switch (
IL_0032,
IL_003d)
IL_0030: br.s IL_0048
IL_0032: ldstr "case 0"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ret
IL_003d: ldstr "case 1"
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
IL_0047: ret
IL_0048: ldstr "switch 1"
IL_004d: call void [mscorlib]System.Console::WriteLine(string)
IL_0052: ldarg.0
IL_0053: ldc.i4.1
IL_0054: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0059: stloc.1
IL_005a: ldloc.1
IL_005b: switch (
IL_006a,
IL_0075)
IL_0068: br.s IL_0080
IL_006a: ldstr "case 0"
IL_006f: call void [mscorlib]System.Console::WriteLine(string)
IL_0074: ret
IL_0075: ldstr "case 1"
IL_007a: call void [mscorlib]System.Console::WriteLine(string)
IL_007f: ret
IL_0080: ldstr "end"
IL_0085: call void [mscorlib]System.Console::WriteLine(string)
IL_008a: ret
} // end of method ReduceNesting::IfSwitchSwitch
.method public hidebysig instance void
IfLoop() cil managed
{
// Code size 46 (0x2e)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldc.i4.0
IL_0011: stloc.0
IL_0012: br.s IL_001e
IL_0014: ldloc.0
IL_0015: call void [mscorlib]System.Console::WriteLine(int32)
IL_001a: ldloc.0
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stloc.0
IL_001e: ldloc.0
IL_001f: ldc.i4.s 10
IL_0021: blt.s IL_0014
IL_0023: ldstr "end"
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: ret
} // end of method ReduceNesting::IfLoop
.method public hidebysig instance void
LoopContinue() cil managed
{
// Code size 62 (0x3e)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0038
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_0034
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002a
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: ldstr "loop-tail"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: ldloc.0
IL_0035: ldc.i4.1
IL_0036: add
IL_0037: stloc.0
IL_0038: ldloc.0
IL_0039: ldc.i4.s 10
IL_003b: blt.s IL_0004
IL_003d: ret
} // end of method ReduceNesting::LoopContinue
.method public hidebysig instance void
LoopBreak() cil managed
{
// Code size 91 (0x5b)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_004b
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_0047
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002c
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: br.s IL_0050
IL_002c: ldarg.0
IL_002d: ldc.i4.2
IL_002e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0033: brfalse.s IL_003b
IL_0035: ldc.i4.2
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: ldstr "break"
IL_0040: call void [mscorlib]System.Console::WriteLine(string)
IL_0045: br.s IL_0050
IL_0047: ldloc.0
IL_0048: ldc.i4.1
IL_0049: add
IL_004a: stloc.0
IL_004b: ldloc.0
IL_004c: ldc.i4.s 10
IL_004e: blt.s IL_0004
IL_0050: ldstr "end"
IL_0055: call void [mscorlib]System.Console::WriteLine(string)
IL_005a: ret
} // end of method ReduceNesting::LoopBreak
.method public hidebysig instance void
LoopBreakElseIf() cil managed
{
// Code size 81 (0x51)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0041
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_003d
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002c
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: br.s IL_0046
IL_002c: ldarg.0
IL_002d: ldc.i4.2
IL_002e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0033: brfalse.s IL_0046
IL_0035: ldc.i4.2
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: br.s IL_0046
IL_003d: ldloc.0
IL_003e: ldc.i4.1
IL_003f: add
IL_0040: stloc.0
IL_0041: ldloc.0
IL_0042: ldc.i4.s 10
IL_0044: blt.s IL_0004
IL_0046: ldstr "end"
IL_004b: call void [mscorlib]System.Console::WriteLine(string)
IL_0050: ret
} // end of method ReduceNesting::LoopBreakElseIf
.method public hidebysig instance void
SwitchIf() cil managed
{
// Code size 72 (0x48)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: switch (
IL_0018,
IL_0023)
IL_0016: br.s IL_002e
IL_0018: ldstr "case 0"
IL_001d: call void [mscorlib]System.Console::WriteLine(string)
IL_0022: ret
IL_0023: ldstr "case 1"
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: ret
IL_002e: ldarg.0
IL_002f: ldc.i4.0
IL_0030: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0035: brfalse.s IL_003d
IL_0037: ldc.i4.0
IL_0038: call void [mscorlib]System.Console::WriteLine(int32)
IL_003d: ldstr "end"
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
IL_0047: ret
} // end of method ReduceNesting::SwitchIf
.method public hidebysig instance void
NestedSwitchIf() cil managed
{
// Code size 82 (0x52)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0047
IL_0009: ldarg.0
IL_000a: ldc.i4.0
IL_000b: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: switch (
IL_0021,
IL_002c)
IL_001f: br.s IL_0037
IL_0021: ldstr "case 0"
IL_0026: call void [mscorlib]System.Console::WriteLine(string)
IL_002b: ret
IL_002c: ldstr "case 1"
IL_0031: call void [mscorlib]System.Console::WriteLine(string)
IL_0036: ret
IL_0037: ldarg.0
IL_0038: ldc.i4.1
IL_0039: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003e: brfalse.s IL_0051
IL_0040: ldc.i4.1
IL_0041: call void [mscorlib]System.Console::WriteLine(int32)
IL_0046: ret
IL_0047: ldstr "else"
IL_004c: call void [mscorlib]System.Console::WriteLine(string)
IL_0051: ret
} // end of method ReduceNesting::NestedSwitchIf
.method public hidebysig instance void
EarlyExit1() cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brtrue.s IL_0026
IL_0009: ldc.i4.0
IL_000a: stloc.0
IL_000b: br.s IL_0017
IL_000d: ldloc.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: ldloc.0
IL_0014: ldc.i4.1
IL_0015: add
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.s 10
IL_001a: blt.s IL_000d
IL_001c: ldstr "end"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: ret
} // end of method ReduceNesting::EarlyExit1
.method public hidebysig instance void
EarlyExit2() cil managed
{
// Code size 55 (0x37)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_000a
IL_0009: ret
IL_000a: ldc.i4.0
IL_000b: stloc.0
IL_000c: br.s IL_0027
IL_000e: ldloc.0
IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0014: ldloc.0
IL_0015: ldc.i4.2
IL_0016: rem
IL_0017: brtrue.s IL_0023
IL_0019: ldstr "even"
IL_001e: call void [mscorlib]System.Console::WriteLine(string)
IL_0023: ldloc.0
IL_0024: ldc.i4.1
IL_0025: add
IL_0026: stloc.0
IL_0027: ldloc.0
IL_0028: ldc.i4.s 10
IL_002a: blt.s IL_000e
IL_002c: ldstr "end"
IL_0031: call void [mscorlib]System.Console::WriteLine(string)
IL_0036: ret
} // end of method ReduceNesting::EarlyExit2
.method public hidebysig instance void
BalancedIf() cil managed
{
// Code size 61 (0x3d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0023
IL_0009: ldstr "true"
IL_000e: call void [mscorlib]System.Console::WriteLine(string)
IL_0013: ldarg.0
IL_0014: ldc.i4.1
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_001a: brfalse.s IL_003c
IL_001c: ldc.i4.1
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: ret
IL_0023: ldarg.0
IL_0024: ldc.i4.2
IL_0025: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002a: brfalse.s IL_0032
IL_002c: ldc.i4.2
IL_002d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0032: ldstr "false"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ret
} // end of method ReduceNesting::BalancedIf
.method public hidebysig instance string
ComplexCase1(string s) cil managed
{
// Code size 193 (0xc1)
.maxstack 2
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_000b
IL_0009: ldarg.1
IL_000a: ret
IL_000b: ldc.i4.0
IL_000c: stloc.0
IL_000d: br IL_00b3
IL_0012: ldarg.0
IL_0013: ldc.i4.1
IL_0014: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0019: brfalse.s IL_0026
IL_001b: ldc.i4.1
IL_001c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0021: br IL_00af
IL_0026: ldarg.0
IL_0027: ldc.i4.2
IL_0028: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002d: brfalse.s IL_0085
IL_002f: ldloc.0
IL_0030: stloc.1
IL_0031: ldloc.1
IL_0032: ldc.i4.1
IL_0033: sub
IL_0034: switch (
IL_0047,
IL_0073,
IL_0073)
IL_0045: br.s IL_007d
IL_0047: ldarg.0
IL_0048: ldc.i4.3
IL_0049: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_004e: brfalse.s IL_0058
IL_0050: ldc.i4.3
IL_0051: call void [mscorlib]System.Console::WriteLine(int32)
IL_0056: br.s IL_007d
IL_0058: ldstr "case1"
IL_005d: call void [mscorlib]System.Console::WriteLine(string)
IL_0062: ldarg.0
IL_0063: ldc.i4.4
IL_0064: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0069: brfalse.s IL_007d
IL_006b: ldc.i4.4
IL_006c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0071: br.s IL_007d
IL_0073: ldstr "case23"
IL_0078: call void [mscorlib]System.Console::WriteLine(string)
IL_007d: ldc.i4.2
IL_007e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0083: br.s IL_00af
IL_0085: ldarg.0
IL_0086: ldc.i4.5
IL_0087: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_008c: brfalse.s IL_0096
IL_008e: ldc.i4.5
IL_008f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0094: br.s IL_00af
IL_0096: ldarg.0
IL_0097: ldc.i4.6
IL_0098: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_009d: brfalse.s IL_00a5
IL_009f: ldc.i4.6
IL_00a0: call void [mscorlib]System.Console::WriteLine(int32)
IL_00a5: ldstr "else"
IL_00aa: call void [mscorlib]System.Console::WriteLine(string)
IL_00af: ldloc.0
IL_00b0: ldc.i4.1
IL_00b1: add
IL_00b2: stloc.0
IL_00b3: ldloc.0
IL_00b4: ldarg.1
IL_00b5: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_00ba: blt IL_0012
IL_00bf: ldarg.1
IL_00c0: ret
} // end of method ReduceNesting::ComplexCase1
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ReduceNesting::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

668
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.opt.roslyn.il

@ -0,0 +1,668 @@ @@ -0,0 +1,668 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ReduceNesting
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ReduceNesting.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ReduceNesting::B
.method public hidebysig newslot abstract virtual
instance int32 I(int32 i) cil managed
{
} // end of method ReduceNesting::I
.method public hidebysig instance void
IfIf() cil managed
{
// Code size 42 (0x2a)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldarg.0
IL_0011: ldc.i4.1
IL_0012: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0017: brfalse.s IL_001f
IL_0019: ldc.i4.1
IL_001a: call void [mscorlib]System.Console::WriteLine(int32)
IL_001f: ldstr "end"
IL_0024: call void [mscorlib]System.Console::WriteLine(string)
IL_0029: ret
} // end of method ReduceNesting::IfIf
.method public hidebysig instance void
IfSwitch() cil managed
{
// Code size 76 (0x4c)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldstr "switch"
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: ldarg.0
IL_001b: ldc.i4.0
IL_001c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: brfalse.s IL_002b
IL_0025: ldloc.0
IL_0026: ldc.i4.1
IL_0027: beq.s IL_0036
IL_0029: br.s IL_0041
IL_002b: ldstr "case 0"
IL_0030: call void [mscorlib]System.Console::WriteLine(string)
IL_0035: ret
IL_0036: ldstr "case 1"
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: ret
IL_0041: ldstr "end"
IL_0046: call void [mscorlib]System.Console::WriteLine(string)
IL_004b: ret
} // end of method ReduceNesting::IfSwitch
.method public hidebysig instance void
IfSwitchSwitch() cil managed
{
// Code size 125 (0x7d)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldstr "switch 0"
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: ldarg.0
IL_001b: ldc.i4.1
IL_001c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: brfalse.s IL_002b
IL_0025: ldloc.0
IL_0026: ldc.i4.1
IL_0027: beq.s IL_0036
IL_0029: br.s IL_0041
IL_002b: ldstr "case 0"
IL_0030: call void [mscorlib]System.Console::WriteLine(string)
IL_0035: ret
IL_0036: ldstr "case 1"
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: ret
IL_0041: ldstr "switch 1"
IL_0046: call void [mscorlib]System.Console::WriteLine(string)
IL_004b: ldarg.0
IL_004c: ldc.i4.1
IL_004d: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0052: stloc.0
IL_0053: ldloc.0
IL_0054: brfalse.s IL_005c
IL_0056: ldloc.0
IL_0057: ldc.i4.1
IL_0058: beq.s IL_0067
IL_005a: br.s IL_0072
IL_005c: ldstr "case 0"
IL_0061: call void [mscorlib]System.Console::WriteLine(string)
IL_0066: ret
IL_0067: ldstr "case 1"
IL_006c: call void [mscorlib]System.Console::WriteLine(string)
IL_0071: ret
IL_0072: ldstr "end"
IL_0077: call void [mscorlib]System.Console::WriteLine(string)
IL_007c: ret
} // end of method ReduceNesting::IfSwitchSwitch
.method public hidebysig instance void
IfLoop() cil managed
{
// Code size 46 (0x2e)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0010
IL_0009: ldc.i4.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ret
IL_0010: ldc.i4.0
IL_0011: stloc.0
IL_0012: br.s IL_001e
IL_0014: ldloc.0
IL_0015: call void [mscorlib]System.Console::WriteLine(int32)
IL_001a: ldloc.0
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stloc.0
IL_001e: ldloc.0
IL_001f: ldc.i4.s 10
IL_0021: blt.s IL_0014
IL_0023: ldstr "end"
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: ret
} // end of method ReduceNesting::IfLoop
.method public hidebysig instance void
LoopContinue() cil managed
{
// Code size 62 (0x3e)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0038
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_0034
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002a
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: ldstr "loop-tail"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: ldloc.0
IL_0035: ldc.i4.1
IL_0036: add
IL_0037: stloc.0
IL_0038: ldloc.0
IL_0039: ldc.i4.s 10
IL_003b: blt.s IL_0004
IL_003d: ret
} // end of method ReduceNesting::LoopContinue
.method public hidebysig instance void
LoopBreak() cil managed
{
// Code size 91 (0x5b)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_004b
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_0047
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002c
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: br.s IL_0050
IL_002c: ldarg.0
IL_002d: ldc.i4.2
IL_002e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0033: brfalse.s IL_003b
IL_0035: ldc.i4.2
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: ldstr "break"
IL_0040: call void [mscorlib]System.Console::WriteLine(string)
IL_0045: br.s IL_0050
IL_0047: ldloc.0
IL_0048: ldc.i4.1
IL_0049: add
IL_004a: stloc.0
IL_004b: ldloc.0
IL_004c: ldc.i4.s 10
IL_004e: blt.s IL_0004
IL_0050: ldstr "end"
IL_0055: call void [mscorlib]System.Console::WriteLine(string)
IL_005a: ret
} // end of method ReduceNesting::LoopBreak
.method public hidebysig instance void
LoopBreakElseIf() cil managed
{
// Code size 81 (0x51)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0041
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.0
IL_000b: ldc.i4.0
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0011: brfalse.s IL_001b
IL_0013: ldc.i4.0
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: br.s IL_003d
IL_001b: ldarg.0
IL_001c: ldc.i4.1
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0022: brfalse.s IL_002c
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: br.s IL_0046
IL_002c: ldarg.0
IL_002d: ldc.i4.2
IL_002e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0033: brfalse.s IL_0046
IL_0035: ldc.i4.2
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: br.s IL_0046
IL_003d: ldloc.0
IL_003e: ldc.i4.1
IL_003f: add
IL_0040: stloc.0
IL_0041: ldloc.0
IL_0042: ldc.i4.s 10
IL_0044: blt.s IL_0004
IL_0046: ldstr "end"
IL_004b: call void [mscorlib]System.Console::WriteLine(string)
IL_0050: ret
} // end of method ReduceNesting::LoopBreakElseIf
.method public hidebysig instance void
SwitchIf() cil managed
{
// Code size 65 (0x41)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: brfalse.s IL_0011
IL_000b: ldloc.0
IL_000c: ldc.i4.1
IL_000d: beq.s IL_001c
IL_000f: br.s IL_0027
IL_0011: ldstr "case 0"
IL_0016: call void [mscorlib]System.Console::WriteLine(string)
IL_001b: ret
IL_001c: ldstr "case 1"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: ret
IL_0027: ldarg.0
IL_0028: ldc.i4.0
IL_0029: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002e: brfalse.s IL_0036
IL_0030: ldc.i4.0
IL_0031: call void [mscorlib]System.Console::WriteLine(int32)
IL_0036: ldstr "end"
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: ret
} // end of method ReduceNesting::SwitchIf
.method public hidebysig instance void
NestedSwitchIf() cil managed
{
// Code size 75 (0x4b)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0040
IL_0009: ldarg.0
IL_000a: ldc.i4.0
IL_000b: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: brfalse.s IL_001a
IL_0014: ldloc.0
IL_0015: ldc.i4.1
IL_0016: beq.s IL_0025
IL_0018: br.s IL_0030
IL_001a: ldstr "case 0"
IL_001f: call void [mscorlib]System.Console::WriteLine(string)
IL_0024: ret
IL_0025: ldstr "case 1"
IL_002a: call void [mscorlib]System.Console::WriteLine(string)
IL_002f: ret
IL_0030: ldarg.0
IL_0031: ldc.i4.1
IL_0032: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0037: brfalse.s IL_004a
IL_0039: ldc.i4.1
IL_003a: call void [mscorlib]System.Console::WriteLine(int32)
IL_003f: ret
IL_0040: ldstr "else"
IL_0045: call void [mscorlib]System.Console::WriteLine(string)
IL_004a: ret
} // end of method ReduceNesting::NestedSwitchIf
.method public hidebysig instance void
EarlyExit1() cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brtrue.s IL_0026
IL_0009: ldc.i4.0
IL_000a: stloc.0
IL_000b: br.s IL_0017
IL_000d: ldloc.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: ldloc.0
IL_0014: ldc.i4.1
IL_0015: add
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.s 10
IL_001a: blt.s IL_000d
IL_001c: ldstr "end"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: ret
} // end of method ReduceNesting::EarlyExit1
.method public hidebysig instance void
EarlyExit2() cil managed
{
// Code size 55 (0x37)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_000a
IL_0009: ret
IL_000a: ldc.i4.0
IL_000b: stloc.0
IL_000c: br.s IL_0027
IL_000e: ldloc.0
IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0014: ldloc.0
IL_0015: ldc.i4.2
IL_0016: rem
IL_0017: brtrue.s IL_0023
IL_0019: ldstr "even"
IL_001e: call void [mscorlib]System.Console::WriteLine(string)
IL_0023: ldloc.0
IL_0024: ldc.i4.1
IL_0025: add
IL_0026: stloc.0
IL_0027: ldloc.0
IL_0028: ldc.i4.s 10
IL_002a: blt.s IL_000e
IL_002c: ldstr "end"
IL_0031: call void [mscorlib]System.Console::WriteLine(string)
IL_0036: ret
} // end of method ReduceNesting::EarlyExit2
.method public hidebysig instance void
BalancedIf() cil managed
{
// Code size 61 (0x3d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_0023
IL_0009: ldstr "true"
IL_000e: call void [mscorlib]System.Console::WriteLine(string)
IL_0013: ldarg.0
IL_0014: ldc.i4.1
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_001a: brfalse.s IL_003c
IL_001c: ldc.i4.1
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: ret
IL_0023: ldarg.0
IL_0024: ldc.i4.2
IL_0025: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002a: brfalse.s IL_0032
IL_002c: ldc.i4.2
IL_002d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0032: ldstr "false"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ret
} // end of method ReduceNesting::BalancedIf
.method public hidebysig instance string
ComplexCase1(string s) cil managed
{
// Code size 178 (0xb2)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0007: brfalse.s IL_000b
IL_0009: ldarg.1
IL_000a: ret
IL_000b: ldc.i4.0
IL_000c: stloc.0
IL_000d: br IL_00a4
IL_0012: ldarg.0
IL_0013: ldc.i4.1
IL_0014: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0019: brfalse.s IL_0023
IL_001b: ldc.i4.1
IL_001c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0021: br.s IL_00a0
IL_0023: ldarg.0
IL_0024: ldc.i4.2
IL_0025: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_002a: brfalse.s IL_0076
IL_002c: ldloc.0
IL_002d: ldc.i4.1
IL_002e: beq.s IL_0038
IL_0030: ldloc.0
IL_0031: ldc.i4.2
IL_0032: sub
IL_0033: ldc.i4.1
IL_0034: ble.un.s IL_0064
IL_0036: br.s IL_006e
IL_0038: ldarg.0
IL_0039: ldc.i4.3
IL_003a: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003f: brfalse.s IL_0049
IL_0041: ldc.i4.3
IL_0042: call void [mscorlib]System.Console::WriteLine(int32)
IL_0047: br.s IL_006e
IL_0049: ldstr "case1"
IL_004e: call void [mscorlib]System.Console::WriteLine(string)
IL_0053: ldarg.0
IL_0054: ldc.i4.4
IL_0055: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_005a: brfalse.s IL_006e
IL_005c: ldc.i4.4
IL_005d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0062: br.s IL_006e
IL_0064: ldstr "case23"
IL_0069: call void [mscorlib]System.Console::WriteLine(string)
IL_006e: ldc.i4.2
IL_006f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0074: br.s IL_00a0
IL_0076: ldarg.0
IL_0077: ldc.i4.5
IL_0078: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_007d: brfalse.s IL_0087
IL_007f: ldc.i4.5
IL_0080: call void [mscorlib]System.Console::WriteLine(int32)
IL_0085: br.s IL_00a0
IL_0087: ldarg.0
IL_0088: ldc.i4.6
IL_0089: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_008e: brfalse.s IL_0096
IL_0090: ldc.i4.6
IL_0091: call void [mscorlib]System.Console::WriteLine(int32)
IL_0096: ldstr "else"
IL_009b: call void [mscorlib]System.Console::WriteLine(string)
IL_00a0: ldloc.0
IL_00a1: ldc.i4.1
IL_00a2: add
IL_00a3: stloc.0
IL_00a4: ldloc.0
IL_00a5: ldarg.1
IL_00a6: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_00ab: blt IL_0012
IL_00b0: ldarg.1
IL_00b1: ret
} // end of method ReduceNesting::ComplexCase1
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ReduceNesting::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

954
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.roslyn.il

@ -0,0 +1,954 @@ @@ -0,0 +1,954 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ReduceNesting
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ReduceNesting.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ReduceNesting::B
.method public hidebysig newslot abstract virtual
instance int32 I(int32 i) cil managed
{
} // end of method ReduceNesting::I
.method public hidebysig instance void
IfIf() cil managed
{
// Code size 54 (0x36)
.maxstack 2
.locals init (bool V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0016
IL_000c: nop
IL_000d: ldc.i4.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: nop
IL_0014: br.s IL_0035
IL_0016: ldarg.0
IL_0017: ldc.i4.1
IL_0018: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_001d: stloc.1
IL_001e: ldloc.1
IL_001f: brfalse.s IL_002a
IL_0021: nop
IL_0022: ldc.i4.1
IL_0023: call void [mscorlib]System.Console::WriteLine(int32)
IL_0028: nop
IL_0029: nop
IL_002a: ldstr "end"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: nop
IL_0035: ret
} // end of method ReduceNesting::IfIf
.method public hidebysig instance void
IfSwitch() cil managed
{
// Code size 92 (0x5c)
.maxstack 2
.locals init (bool V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0016
IL_000c: nop
IL_000d: ldc.i4.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: nop
IL_0014: br.s IL_005b
IL_0016: ldstr "switch"
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: nop
IL_0021: ldarg.0
IL_0022: ldc.i4.0
IL_0023: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0028: stloc.1
IL_0029: ldloc.1
IL_002a: brfalse.s IL_0034
IL_002c: br.s IL_002e
IL_002e: ldloc.1
IL_002f: ldc.i4.1
IL_0030: beq.s IL_0041
IL_0032: br.s IL_004e
IL_0034: ldstr "case 0"
IL_0039: call void [mscorlib]System.Console::WriteLine(string)
IL_003e: nop
IL_003f: br.s IL_005b
IL_0041: ldstr "case 1"
IL_0046: call void [mscorlib]System.Console::WriteLine(string)
IL_004b: nop
IL_004c: br.s IL_005b
IL_004e: ldstr "end"
IL_0053: call void [mscorlib]System.Console::WriteLine(string)
IL_0058: nop
IL_0059: br.s IL_005b
IL_005b: ret
} // end of method ReduceNesting::IfSwitch
.method public hidebysig instance void
IfSwitchSwitch() cil managed
{
// Code size 148 (0x94)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
int32 V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0016
IL_000c: nop
IL_000d: ldc.i4.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: nop
IL_0014: br.s IL_0093
IL_0016: ldstr "switch 0"
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: nop
IL_0021: ldarg.0
IL_0022: ldc.i4.1
IL_0023: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0028: stloc.1
IL_0029: ldloc.1
IL_002a: brfalse.s IL_0034
IL_002c: br.s IL_002e
IL_002e: ldloc.1
IL_002f: ldc.i4.1
IL_0030: beq.s IL_0041
IL_0032: br.s IL_004e
IL_0034: ldstr "case 0"
IL_0039: call void [mscorlib]System.Console::WriteLine(string)
IL_003e: nop
IL_003f: br.s IL_0093
IL_0041: ldstr "case 1"
IL_0046: call void [mscorlib]System.Console::WriteLine(string)
IL_004b: nop
IL_004c: br.s IL_0093
IL_004e: ldstr "switch 1"
IL_0053: call void [mscorlib]System.Console::WriteLine(string)
IL_0058: nop
IL_0059: ldarg.0
IL_005a: ldc.i4.1
IL_005b: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0060: stloc.2
IL_0061: ldloc.2
IL_0062: brfalse.s IL_006c
IL_0064: br.s IL_0066
IL_0066: ldloc.2
IL_0067: ldc.i4.1
IL_0068: beq.s IL_0079
IL_006a: br.s IL_0086
IL_006c: ldstr "case 0"
IL_0071: call void [mscorlib]System.Console::WriteLine(string)
IL_0076: nop
IL_0077: br.s IL_0093
IL_0079: ldstr "case 1"
IL_007e: call void [mscorlib]System.Console::WriteLine(string)
IL_0083: nop
IL_0084: br.s IL_0093
IL_0086: ldstr "end"
IL_008b: call void [mscorlib]System.Console::WriteLine(string)
IL_0090: nop
IL_0091: br.s IL_0093
IL_0093: ret
} // end of method ReduceNesting::IfSwitchSwitch
.method public hidebysig instance void
IfLoop() cil managed
{
// Code size 60 (0x3c)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
bool V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0016
IL_000c: nop
IL_000d: ldc.i4.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0013: nop
IL_0014: br.s IL_003b
IL_0016: ldc.i4.0
IL_0017: stloc.1
IL_0018: br.s IL_0027
IL_001a: nop
IL_001b: ldloc.1
IL_001c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0021: nop
IL_0022: nop
IL_0023: ldloc.1
IL_0024: ldc.i4.1
IL_0025: add
IL_0026: stloc.1
IL_0027: ldloc.1
IL_0028: ldc.i4.s 10
IL_002a: clt
IL_002c: stloc.2
IL_002d: ldloc.2
IL_002e: brtrue.s IL_001a
IL_0030: ldstr "end"
IL_0035: call void [mscorlib]System.Console::WriteLine(string)
IL_003a: nop
IL_003b: ret
} // end of method ReduceNesting::IfLoop
.method public hidebysig instance void
LoopContinue() cil managed
{
// Code size 80 (0x50)
.maxstack 2
.locals init (int32 V_0,
bool V_1,
bool V_2,
bool V_3)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0046
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: stloc.1
IL_0015: ldloc.1
IL_0016: brfalse.s IL_0022
IL_0018: nop
IL_0019: ldc.i4.0
IL_001a: call void [mscorlib]System.Console::WriteLine(int32)
IL_001f: nop
IL_0020: br.s IL_0042
IL_0022: ldarg.0
IL_0023: ldc.i4.1
IL_0024: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: brfalse.s IL_0036
IL_002d: nop
IL_002e: ldc.i4.1
IL_002f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0034: nop
IL_0035: nop
IL_0036: ldstr "loop-tail"
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: nop
IL_0041: nop
IL_0042: ldloc.0
IL_0043: ldc.i4.1
IL_0044: add
IL_0045: stloc.0
IL_0046: ldloc.0
IL_0047: ldc.i4.s 10
IL_0049: clt
IL_004b: stloc.3
IL_004c: ldloc.3
IL_004d: brtrue.s IL_0005
IL_004f: ret
} // end of method ReduceNesting::LoopContinue
.method public hidebysig instance void
LoopBreak() cil managed
{
// Code size 115 (0x73)
.maxstack 2
.locals init (int32 V_0,
bool V_1,
bool V_2,
bool V_3,
bool V_4)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_005c
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: stloc.1
IL_0015: ldloc.1
IL_0016: brfalse.s IL_0022
IL_0018: nop
IL_0019: ldc.i4.0
IL_001a: call void [mscorlib]System.Console::WriteLine(int32)
IL_001f: nop
IL_0020: br.s IL_0058
IL_0022: ldarg.0
IL_0023: ldc.i4.1
IL_0024: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: brfalse.s IL_0037
IL_002d: nop
IL_002e: ldc.i4.1
IL_002f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0034: nop
IL_0035: br.s IL_0067
IL_0037: ldarg.0
IL_0038: ldc.i4.2
IL_0039: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003e: stloc.3
IL_003f: ldloc.3
IL_0040: brfalse.s IL_004b
IL_0042: nop
IL_0043: ldc.i4.2
IL_0044: call void [mscorlib]System.Console::WriteLine(int32)
IL_0049: nop
IL_004a: nop
IL_004b: ldstr "break"
IL_0050: call void [mscorlib]System.Console::WriteLine(string)
IL_0055: nop
IL_0056: br.s IL_0067
IL_0058: ldloc.0
IL_0059: ldc.i4.1
IL_005a: add
IL_005b: stloc.0
IL_005c: ldloc.0
IL_005d: ldc.i4.s 10
IL_005f: clt
IL_0061: stloc.s V_4
IL_0063: ldloc.s V_4
IL_0065: brtrue.s IL_0005
IL_0067: ldstr "end"
IL_006c: call void [mscorlib]System.Console::WriteLine(string)
IL_0071: nop
IL_0072: ret
} // end of method ReduceNesting::LoopBreak
.method public hidebysig instance void
LoopBreakElseIf() cil managed
{
// Code size 105 (0x69)
.maxstack 2
.locals init (int32 V_0,
bool V_1,
bool V_2,
bool V_3,
bool V_4)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0052
IL_0005: nop
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0014: stloc.1
IL_0015: ldloc.1
IL_0016: brfalse.s IL_0022
IL_0018: nop
IL_0019: ldc.i4.0
IL_001a: call void [mscorlib]System.Console::WriteLine(int32)
IL_001f: nop
IL_0020: br.s IL_004e
IL_0022: ldarg.0
IL_0023: ldc.i4.1
IL_0024: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: brfalse.s IL_0038
IL_002d: nop
IL_002e: ldc.i4.1
IL_002f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0034: nop
IL_0035: nop
IL_0036: br.s IL_004c
IL_0038: ldarg.0
IL_0039: ldc.i4.2
IL_003a: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003f: stloc.3
IL_0040: ldloc.3
IL_0041: brfalse.s IL_004c
IL_0043: nop
IL_0044: ldc.i4.2
IL_0045: call void [mscorlib]System.Console::WriteLine(int32)
IL_004a: nop
IL_004b: nop
IL_004c: br.s IL_005d
IL_004e: ldloc.0
IL_004f: ldc.i4.1
IL_0050: add
IL_0051: stloc.0
IL_0052: ldloc.0
IL_0053: ldc.i4.s 10
IL_0055: clt
IL_0057: stloc.s V_4
IL_0059: ldloc.s V_4
IL_005b: brtrue.s IL_0005
IL_005d: ldstr "end"
IL_0062: call void [mscorlib]System.Console::WriteLine(string)
IL_0067: nop
IL_0068: ret
} // end of method ReduceNesting::LoopBreakElseIf
.method public hidebysig instance void
SwitchIf() cil managed
{
// Code size 78 (0x4e)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0014
IL_000c: br.s IL_000e
IL_000e: ldloc.0
IL_000f: ldc.i4.1
IL_0010: beq.s IL_0021
IL_0012: br.s IL_002e
IL_0014: ldstr "case 0"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: nop
IL_001f: br.s IL_004d
IL_0021: ldstr "case 1"
IL_0026: call void [mscorlib]System.Console::WriteLine(string)
IL_002b: nop
IL_002c: br.s IL_004d
IL_002e: ldarg.0
IL_002f: ldc.i4.0
IL_0030: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0035: stloc.1
IL_0036: ldloc.1
IL_0037: brfalse.s IL_0042
IL_0039: nop
IL_003a: ldc.i4.0
IL_003b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0040: nop
IL_0041: nop
IL_0042: ldstr "end"
IL_0047: call void [mscorlib]System.Console::WriteLine(string)
IL_004c: nop
IL_004d: ret
} // end of method ReduceNesting::SwitchIf
.method public hidebysig instance void
NestedSwitchIf() cil managed
{
// Code size 95 (0x5f)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
bool V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0051
IL_000c: nop
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::I(int32)
IL_0014: stloc.1
IL_0015: ldloc.1
IL_0016: brfalse.s IL_0020
IL_0018: br.s IL_001a
IL_001a: ldloc.1
IL_001b: ldc.i4.1
IL_001c: beq.s IL_002d
IL_001e: br.s IL_003a
IL_0020: ldstr "case 0"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: br.s IL_005e
IL_002d: ldstr "case 1"
IL_0032: call void [mscorlib]System.Console::WriteLine(string)
IL_0037: nop
IL_0038: br.s IL_005e
IL_003a: ldarg.0
IL_003b: ldc.i4.1
IL_003c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0041: stloc.2
IL_0042: ldloc.2
IL_0043: brfalse.s IL_004e
IL_0045: nop
IL_0046: ldc.i4.1
IL_0047: call void [mscorlib]System.Console::WriteLine(int32)
IL_004c: nop
IL_004d: nop
IL_004e: nop
IL_004f: br.s IL_005e
IL_0051: nop
IL_0052: ldstr "else"
IL_0057: call void [mscorlib]System.Console::WriteLine(string)
IL_005c: nop
IL_005d: nop
IL_005e: ret
} // end of method ReduceNesting::NestedSwitchIf
.method public hidebysig instance void
EarlyExit1() cil managed
{
// Code size 55 (0x37)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
bool V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0036
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: stloc.1
IL_0012: br.s IL_0021
IL_0014: nop
IL_0015: ldloc.1
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: nop
IL_001d: ldloc.1
IL_001e: ldc.i4.1
IL_001f: add
IL_0020: stloc.1
IL_0021: ldloc.1
IL_0022: ldc.i4.s 10
IL_0024: clt
IL_0026: stloc.2
IL_0027: ldloc.2
IL_0028: brtrue.s IL_0014
IL_002a: ldstr "end"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: nop
IL_0035: nop
IL_0036: ret
} // end of method ReduceNesting::EarlyExit1
.method public hidebysig instance void
EarlyExit2() cil managed
{
// Code size 76 (0x4c)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
bool V_2,
bool V_3)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_000f
IL_000c: nop
IL_000d: br.s IL_004b
IL_000f: ldc.i4.0
IL_0010: stloc.1
IL_0011: br.s IL_0037
IL_0013: nop
IL_0014: ldloc.1
IL_0015: call void [mscorlib]System.Console::WriteLine(int32)
IL_001a: nop
IL_001b: ldloc.1
IL_001c: ldc.i4.2
IL_001d: rem
IL_001e: ldc.i4.0
IL_001f: ceq
IL_0021: stloc.2
IL_0022: ldloc.2
IL_0023: brfalse.s IL_0032
IL_0025: nop
IL_0026: ldstr "even"
IL_002b: call void [mscorlib]System.Console::WriteLine(string)
IL_0030: nop
IL_0031: nop
IL_0032: nop
IL_0033: ldloc.1
IL_0034: ldc.i4.1
IL_0035: add
IL_0036: stloc.1
IL_0037: ldloc.1
IL_0038: ldc.i4.s 10
IL_003a: clt
IL_003c: stloc.3
IL_003d: ldloc.3
IL_003e: brtrue.s IL_0013
IL_0040: ldstr "end"
IL_0045: call void [mscorlib]System.Console::WriteLine(string)
IL_004a: nop
IL_004b: ret
} // end of method ReduceNesting::EarlyExit2
.method public hidebysig instance void
BalancedIf() cil managed
{
// Code size 81 (0x51)
.maxstack 2
.locals init (bool V_0,
bool V_1,
bool V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_002f
IL_000c: nop
IL_000d: ldstr "true"
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
IL_0017: nop
IL_0018: ldarg.0
IL_0019: ldc.i4.1
IL_001a: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_001f: stloc.1
IL_0020: ldloc.1
IL_0021: brfalse.s IL_002c
IL_0023: nop
IL_0024: ldc.i4.1
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: nop
IL_002b: nop
IL_002c: nop
IL_002d: br.s IL_0050
IL_002f: nop
IL_0030: ldarg.0
IL_0031: ldc.i4.2
IL_0032: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0037: stloc.2
IL_0038: ldloc.2
IL_0039: brfalse.s IL_0044
IL_003b: nop
IL_003c: ldc.i4.2
IL_003d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0042: nop
IL_0043: nop
IL_0044: ldstr "false"
IL_0049: call void [mscorlib]System.Console::WriteLine(string)
IL_004e: nop
IL_004f: nop
IL_0050: ret
} // end of method ReduceNesting::BalancedIf
.method public hidebysig instance string
ComplexCase1(string s) cil managed
{
// Code size 255 (0xff)
.maxstack 2
.locals init (bool V_0,
string V_1,
int32 V_2,
bool V_3,
bool V_4,
int32 V_5,
bool V_6,
bool V_7,
bool V_8,
bool V_9,
bool V_10)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0014
IL_000c: nop
IL_000d: ldarg.1
IL_000e: stloc.1
IL_000f: br IL_00fd
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: br IL_00e7
IL_001b: nop
IL_001c: ldarg.0
IL_001d: ldc.i4.1
IL_001e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_0023: stloc.3
IL_0024: ldloc.3
IL_0025: brfalse.s IL_0035
IL_0027: nop
IL_0028: ldc.i4.1
IL_0029: call void [mscorlib]System.Console::WriteLine(int32)
IL_002e: nop
IL_002f: nop
IL_0030: br IL_00e2
IL_0035: ldarg.0
IL_0036: ldc.i4.2
IL_0037: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_003c: stloc.s V_4
IL_003e: ldloc.s V_4
IL_0040: brfalse.s IL_00a7
IL_0042: nop
IL_0043: ldloc.2
IL_0044: stloc.s V_5
IL_0046: ldloc.s V_5
IL_0048: ldc.i4.1
IL_0049: beq.s IL_0056
IL_004b: br.s IL_004d
IL_004d: ldloc.s V_5
IL_004f: ldc.i4.2
IL_0050: sub
IL_0051: ldc.i4.1
IL_0052: ble.un.s IL_0090
IL_0054: br.s IL_009d
IL_0056: ldarg.0
IL_0057: ldc.i4.3
IL_0058: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_005d: stloc.s V_6
IL_005f: ldloc.s V_6
IL_0061: brfalse.s IL_006d
IL_0063: nop
IL_0064: ldc.i4.3
IL_0065: call void [mscorlib]System.Console::WriteLine(int32)
IL_006a: nop
IL_006b: br.s IL_009d
IL_006d: ldstr "case1"
IL_0072: call void [mscorlib]System.Console::WriteLine(string)
IL_0077: nop
IL_0078: ldarg.0
IL_0079: ldc.i4.4
IL_007a: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_007f: stloc.s V_7
IL_0081: ldloc.s V_7
IL_0083: brfalse.s IL_008e
IL_0085: nop
IL_0086: ldc.i4.4
IL_0087: call void [mscorlib]System.Console::WriteLine(int32)
IL_008c: nop
IL_008d: nop
IL_008e: br.s IL_009d
IL_0090: ldstr "case23"
IL_0095: call void [mscorlib]System.Console::WriteLine(string)
IL_009a: nop
IL_009b: br.s IL_009d
IL_009d: ldc.i4.2
IL_009e: call void [mscorlib]System.Console::WriteLine(int32)
IL_00a3: nop
IL_00a4: nop
IL_00a5: br.s IL_00e2
IL_00a7: ldarg.0
IL_00a8: ldc.i4.5
IL_00a9: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_00ae: stloc.s V_8
IL_00b0: ldloc.s V_8
IL_00b2: brfalse.s IL_00bf
IL_00b4: nop
IL_00b5: ldc.i4.5
IL_00b6: call void [mscorlib]System.Console::WriteLine(int32)
IL_00bb: nop
IL_00bc: nop
IL_00bd: br.s IL_00e2
IL_00bf: nop
IL_00c0: ldarg.0
IL_00c1: ldc.i4.6
IL_00c2: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting::B(int32)
IL_00c7: stloc.s V_9
IL_00c9: ldloc.s V_9
IL_00cb: brfalse.s IL_00d6
IL_00cd: nop
IL_00ce: ldc.i4.6
IL_00cf: call void [mscorlib]System.Console::WriteLine(int32)
IL_00d4: nop
IL_00d5: nop
IL_00d6: ldstr "else"
IL_00db: call void [mscorlib]System.Console::WriteLine(string)
IL_00e0: nop
IL_00e1: nop
IL_00e2: nop
IL_00e3: ldloc.2
IL_00e4: ldc.i4.1
IL_00e5: add
IL_00e6: stloc.2
IL_00e7: ldloc.2
IL_00e8: ldarg.1
IL_00e9: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_00ee: clt
IL_00f0: stloc.s V_10
IL_00f2: ldloc.s V_10
IL_00f4: brtrue IL_001b
IL_00f9: ldarg.1
IL_00fa: stloc.1
IL_00fb: br.s IL_00fd
IL_00fd: ldloc.1
IL_00fe: ret
} // end of method ReduceNesting::ComplexCase1
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method ReduceNesting::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ReduceNesting
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

339
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs

@ -0,0 +1,339 @@ @@ -0,0 +1,339 @@
// 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.Collections.Generic;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class YieldReturnPrettyTest
{
private int fieldOnThis;
public static IEnumerable<char> YieldChars {
get {
yield return 'a';
yield return 'b';
yield return 'c';
}
}
internal static void Print<T>(string name, IEnumerator<T> enumerator)
{
Console.WriteLine(name + ": Test start");
while (enumerator.MoveNext()) {
Console.WriteLine(name + ": " + enumerator.Current);
}
}
public static IEnumerable<string> SimpleYieldReturn()
{
yield return "A";
yield return "B";
yield return "C";
}
public static IEnumerator<string> SimpleYieldReturnEnumerator()
{
yield return "A";
yield return "B";
yield return "C";
}
public IEnumerable<int> YieldReturnParameters(int p)
{
yield return p;
yield return fieldOnThis;
}
public IEnumerator<int> YieldReturnParametersEnumerator(int p)
{
yield return p;
yield return fieldOnThis;
}
public static IEnumerable<int> YieldReturnInLoop()
{
for (int i = 0; i < 100; i++) {
yield return i;
}
}
public static IEnumerable<int> YieldReturnWithTryFinally()
{
yield return 0;
try {
yield return 1;
} finally {
Console.WriteLine("Finally!");
}
yield return 2;
}
#if TODO
// TODO: adjust lock-pattern for this case
public static IEnumerable<int> YieldReturnInLock1(object o)
{
lock (o) {
yield return 1;
}
}
public static IEnumerable<int> YieldReturnInLock2(object o)
{
lock (o) {
yield return 1;
o = null;
yield return 2;
}
}
#endif
public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle)
{
Console.WriteLine("Start of method - 1");
yield return "Start of method";
Console.WriteLine("Start of method - 2");
try {
Console.WriteLine("Within outer try - 1");
yield return "Within outer try";
Console.WriteLine("Within outer try - 2");
try {
Console.WriteLine("Within inner try - 1");
yield return "Within inner try";
Console.WriteLine("Within inner try - 2");
if (breakInMiddle) {
Console.WriteLine("Breaking...");
yield break;
}
Console.WriteLine("End of inner try - 1");
yield return "End of inner try";
Console.WriteLine("End of inner try - 2");
} finally {
Console.WriteLine("Inner Finally");
}
Console.WriteLine("End of outer try - 1");
yield return "End of outer try";
Console.WriteLine("End of outer try - 2");
} finally {
Console.WriteLine("Outer Finally");
}
Console.WriteLine("End of method - 1");
yield return "End of method";
Console.WriteLine("End of method - 2");
}
public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input)
{
// outer try-finally block
foreach (string line in input) {
// nested try-finally block
try {
yield return line;
} finally {
Console.WriteLine("Processed " + line);
}
}
yield return "A";
yield return "B";
yield return "C";
yield return "D";
yield return "E";
yield return "F";
// outer try-finally block
foreach (string item in input) {
yield return item.ToUpper();
}
}
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input)
{
foreach (string line in input) {
yield return () => line;
}
}
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input)
{
foreach (string item in input) {
string copy = item;
yield return () => copy;
}
}
public static IEnumerable<int> GetEvenNumbers(int n)
{
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
yield return i;
}
}
}
public static IEnumerable<char> ExceptionHandling()
{
yield return 'a';
try {
Console.WriteLine("1 - try");
} catch (Exception) {
Console.WriteLine("1 - catch");
}
yield return 'b';
try {
try {
Console.WriteLine("2 - try");
} finally {
Console.WriteLine("2 - finally");
}
yield return 'c';
} finally {
Console.WriteLine("outer finally");
}
}
public static IEnumerable<int> YieldBreakInCatch()
{
yield return 0;
try {
Console.WriteLine("In Try");
} catch {
// yield return is not allowed in catch, but yield break is
yield break;
}
yield return 1;
}
public static IEnumerable<int> YieldBreakInCatchInTryFinally()
{
try {
yield return 0;
try {
Console.WriteLine("In Try");
} catch {
// yield return is not allowed in catch, but yield break is
// Note that pre-roslyn, this code triggers a compiler bug:
// If the finally block throws an exception, it ends up getting
// called a second time.
yield break;
}
yield return 1;
} finally {
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakInTryCatchInTryFinally()
{
try {
yield return 0;
try {
Console.WriteLine("In Try");
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
} catch {
Console.WriteLine("Catch");
}
yield return 1;
} finally {
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakInTryFinallyInTryFinally(bool b)
{
try {
yield return 0;
try {
Console.WriteLine("In Try");
if (b) {
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
}
} finally {
Console.WriteLine("Inner Finally");
}
yield return 1;
} finally {
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakOnly()
{
yield break;
}
public static IEnumerable<int> UnconditionalThrowInTryFinally()
{
// Here, MoveNext() doesn't call the finally methods at all
// (only indirectly via Dispose())
try {
yield return 0;
throw new NotImplementedException();
} finally {
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> NestedTryFinallyStartingOnSamePosition()
{
// The first user IL instruction is already in 2 nested try blocks.
try {
try {
yield return 0;
} finally {
Console.WriteLine("Inner Finally");
}
} finally {
Console.WriteLine("Outer Finally");
}
}
public static IEnumerable<int> LocalInFinally<T>(T a) where T : IDisposable
{
yield return 1;
try {
yield return 2;
} finally {
T val = a;
val.Dispose();
val.Dispose();
}
yield return 3;
}
public static IEnumerable<T> GenericYield<T>() where T : new()
{
T val = new T();
for (int i = 0; i < 3; i++) {
yield return val;
}
}
}
internal struct StructWithYieldReturn
{
private int val;
public IEnumerable<int> Count()
{
yield return val++;
yield return val++;
}
}
}

7400
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.il

File diff suppressed because it is too large Load Diff

5897
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.opt.il

File diff suppressed because it is too large Load Diff

6068
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.opt.roslyn.il

File diff suppressed because it is too large Load Diff

6641
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.roslyn.il

File diff suppressed because it is too large Load Diff

22
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -22,12 +22,10 @@ using System.Collections.Immutable; @@ -22,12 +22,10 @@ using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework;
@ -677,6 +675,26 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -677,6 +675,26 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value);
}
[Test]
public void DllImportAttributeWithPreserveSigFalse()
{
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DoNotPreserveSig");
IAttribute dllImport = method.GetAttributes().Single();
Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName);
Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value);
Assert.AreEqual(false, dllImport.NamedArguments.Single().Value);
}
[Test]
public void PreserveSigAttribute()
{
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "PreserveSigAsAttribute");
IAttribute preserveSig = method.GetAttributes().Single();
Assert.AreEqual("System.Runtime.InteropServices.PreserveSigAttribute", preserveSig.AttributeType.FullName);
Assert.IsTrue(preserveSig.FixedArguments.Length == 0);
Assert.IsTrue(preserveSig.NamedArguments.Length == 0);
}
[Test]
public void InOutParametersOnRefMethod()
{

8
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs

@ -153,6 +153,14 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -153,6 +153,14 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
[DllImport("unmanaged.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DllMethod([In, Out] ref int p);
[DllImport("unmanaged.dll", PreserveSig = false)]
public static extern bool DoNotPreserveSig();
[PreserveSig]
public static void PreserveSigAsAttribute()
{
}
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8)]

26
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -153,6 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -153,6 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp
new ProxyCallReplacer(),
new DelegateConstruction(),
new HighLevelLoopTransform(),
new ReduceNestingTransform(),
new IntroduceDynamicTypeOnLocals(),
new AssignVariableNames(),
};
@ -678,12 +679,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -678,12 +679,15 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definition.
/// Note that decompiling types from modules other than the main module is not supported.
/// </remarks>
public SyntaxTree DecompileType(FullTypeName fullTypeName)
{
var type = typeSystem.FindType(fullTypeName.TopLevelTypeName).GetDefinition();
if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
if (type.ParentModule != typeSystem.MainModule)
throw new NotSupportedException("Decompiling types that are not part of the main module is not supported.");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
@ -980,6 +984,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -980,6 +984,9 @@ namespace ICSharpCode.Decompiler.CSharp
case EnumValueDisplayMode.None:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) {
enumMember.Initializer = null;
if (enumMember.GetSymbol() is IField f && f.ConstantValue == null) {
typeDecl.InsertChildBefore(enumMember, new Comment(" error: enumerator has no value"), Roles.Comment);
}
}
break;
case EnumValueDisplayMode.All:
@ -1006,7 +1013,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1006,7 +1013,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool first = true;
long firstValue = 0, previousValue = 0;
foreach (var field in typeDef.Fields) {
if (MemberIsHidden(module, field.MetadataToken, settings)) continue;
if (MemberIsHidden(module, field.MetadataToken, settings) || field.ConstantValue == null) continue;
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
if (first) {
firstValue = currentValue;
@ -1233,15 +1240,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1233,15 +1240,16 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentMember == field);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.ConstantValue != null) {
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum) {
var enumDec = new EnumMemberDeclaration { Name = field.Name };
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive
&& initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags)
|| (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0))))
{
primitive.SetValue(initValue, $"0x{initValue:X}");
if (field.ConstantValue != null) {
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive
&& initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags)
|| (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) {
primitive.SetValue(initValue, $"0x{initValue:X}");
}
}
enumDec.Attributes.AddRange(field.GetAttributes().Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a))));
enumDec.AddAnnotation(new MemberResolveResult(null, field));

49
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -235,22 +235,41 @@ namespace ICSharpCode.Decompiler.CSharp @@ -235,22 +235,41 @@ namespace ICSharpCode.Decompiler.CSharp
argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm));
}
if (settings.StringInterpolation && IsInterpolatedStringCreation(method) &&
if (settings.StringInterpolation && IsInterpolatedStringCreation(method, argumentList) &&
TryGetStringInterpolationTokens(argumentList, out string format, out var tokens))
{
var arguments = argumentList.Arguments;
var content = new List<InterpolatedStringContent>();
bool unpackSingleElementArray = !argumentList.IsExpandedForm && argumentList.Length == 2
&& argumentList.Arguments[1].Expression is ArrayCreateExpression ace
&& ace.Initializer?.Elements.Count == 1;
void UnpackSingleElementArray(ref TranslatedExpression argument)
{
if (!unpackSingleElementArray) return;
var arrayCreation = (ArrayCreateExpression)argumentList.Arguments[1].Expression;
var arrayCreationRR = (ArrayCreateResolveResult)argumentList.Arguments[1].ResolveResult;
var element = arrayCreation.Initializer.Elements.First().Detach();
argument = new TranslatedExpression(element, arrayCreationRR.InitializerElements.First());
}
if (tokens.Count > 0) {
foreach (var (kind, index, text) in tokens) {
TranslatedExpression argument;
switch (kind) {
case TokenKind.String:
content.Add(new InterpolatedStringText(text));
break;
case TokenKind.Argument:
content.Add(new Interpolation(arguments[index + 1]));
argument = arguments[index + 1];
UnpackSingleElementArray(ref argument);
content.Add(new Interpolation(argument));
break;
case TokenKind.ArgumentWithFormat:
content.Add(new Interpolation(arguments[index + 1], text));
argument = arguments[index + 1];
UnpackSingleElementArray(ref argument);
content.Add(new Interpolation(argument, text));
break;
}
}
@ -405,12 +424,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -405,12 +424,18 @@ namespace ICSharpCode.Decompiler.CSharp
return new ExpressionWithResolveResult(((AssignmentExpression)assignment).Left.Detach());
}
private bool IsInterpolatedStringCreation(IMethod method)
private static bool IsInterpolatedStringCreation(IMethod method, ArgumentList argumentList)
{
return method.IsStatic && (
(method.DeclaringType.IsKnownType(KnownTypeCode.String) && method.Name == "Format") ||
(method.Name == "Create" && method.DeclaringType.Name == "FormattableStringFactory" &&
method.DeclaringType.Namespace == "System.Runtime.CompilerServices")
)
&& argumentList.ArgumentNames == null // Argument names are not allowed
&& (
argumentList.IsExpandedForm // Must be expanded form
|| !method.Parameters.Last().IsParams // -or- not a params overload
|| (argumentList.Length == 2 && argumentList.Arguments[1].Expression is ArrayCreateExpression) // -or- an array literal
);
}
@ -643,7 +668,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -643,7 +668,10 @@ namespace ICSharpCode.Decompiler.CSharp
expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
}
}
if (IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, Empty<IType>.Array, expandedArguments, null, -1, out _) == OverloadResolutionErrors.None) {
if (IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, Empty<IType>.Array,
expandedArguments, argumentNames: null, firstOptionalArgumentIndex: -1, out _,
out var bestCandidateIsExpandedForm) == OverloadResolutionErrors.None && bestCandidateIsExpandedForm)
{
expectedParameters = expandedParameters;
arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach()));
return true;
@ -758,7 +786,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -758,7 +786,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool argumentsCasted = false;
OverloadResolutionErrors errors;
while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments,
argumentList.Arguments, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod)) != OverloadResolutionErrors.None)
argumentList.Arguments, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod,
out var bestCandidateIsExpandedForm)) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm)
{
switch (errors) {
case OverloadResolutionErrors.TypeInferenceFailed:
@ -923,9 +952,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -923,9 +952,10 @@ namespace ICSharpCode.Decompiler.CSharp
OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
ResolveResult target, IType[] typeArguments, IList<TranslatedExpression> arguments,
string[] argumentNames, int firstOptionalArgumentIndex,
out IParameterizedMember foundMember)
out IParameterizedMember foundMember, out bool bestCandidateIsExpandedForm)
{
foundMember = null;
bestCandidateIsExpandedForm = false;
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
var or = new OverloadResolution(resolver.Compilation,
firstOptionalArgumentIndex < 0 ? arguments.SelectArray(a => a.ResolveResult) : arguments.Take(firstOptionalArgumentIndex).Select(a => a.ResolveResult).ToArray(),
@ -964,6 +994,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -964,6 +994,7 @@ namespace ICSharpCode.Decompiler.CSharp
return OverloadResolutionErrors.AmbiguousMatch;
or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
}
bestCandidateIsExpandedForm = or.BestCandidateIsExpandedForm;
if (or.BestCandidateErrors != OverloadResolutionErrors.None)
return or.BestCandidateErrors;
if (or.IsAmbiguous)
@ -1132,7 +1163,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1132,7 +1163,9 @@ namespace ICSharpCode.Decompiler.CSharp
));
} else {
while (IsUnambiguousCall(expectedTargetDetails, method, null, Empty<IType>.Array, argumentList.Arguments,
argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out _) != OverloadResolutionErrors.None) {
argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out _,
out var bestCandidateIsExpandedForm) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm)
{
if (argumentList.FirstOptionalArgumentIndex >= 0) {
argumentList.FirstOptionalArgumentIndex = -1;
continue;

39
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -192,14 +192,31 @@ namespace ICSharpCode.Decompiler.CSharp @@ -192,14 +192,31 @@ namespace ICSharpCode.Decompiler.CSharp
return currentFunction.Ancestors.OfType<ILFunction>().SelectMany(f => f.Variables).Any(v => v.Name == name);
}
bool RequiresQualifier(IMember member, TranslatedExpression target)
{
if (HidesVariableWithName(member.Name))
return true;
if (member.IsStatic)
return !IsCurrentOrContainingType(member.DeclaringTypeDefinition);
return !(target.Expression is ThisReferenceExpression || target.Expression is BaseReferenceExpression);
}
ExpressionWithResolveResult ConvertField(IField field, ILInstruction targetInstruction = null)
{
var target = TranslateTarget(targetInstruction,
nonVirtualInvocation: true,
memberStatic: field.IsStatic,
memberDeclaringType: field.DeclaringType);
bool requireTarget = HidesVariableWithName(field.Name)
|| (field.IsStatic ? !IsCurrentOrContainingType(field.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression || target.Expression is BaseReferenceExpression));
bool requireTarget;
// If this is a reference to the backing field of an automatic property and we're going to transform automatic properties
// in PatternStatementTransform, then we have to do the "requires qualifier"-check based on the property instead of the field.
// It is easier to solve this special case here than in PatternStatementTransform, because here we perform all resolver checks.
// It feels a bit hacky, though.
if (settings.AutomaticProperties && PatternStatementTransform.IsBackingFieldOfAutomaticProperty(field, out var property)) {
requireTarget = RequiresQualifier(property, target);
} else {
requireTarget = RequiresQualifier(field, target);
}
bool targetCasted = false;
var targetResolveResult = requireTarget ? target.ResolveResult : null;
@ -646,9 +663,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -646,9 +663,9 @@ namespace ICSharpCode.Decompiler.CSharp
} else {
targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign()));
}
if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType);
}
}
if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType);
}
if (targetType.Equals(left.Type)) {
right = right.ConvertTo(targetType, this);
@ -2475,9 +2492,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2475,9 +2492,15 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicConvertInstruction(DynamicConvertInstruction inst, TranslationContext context)
{
// TODO : make conversions implicit, if !inst.IsExplicit
// currently this leads to stack type mismatch assertions, if the expected type is not O
return Translate(inst.Argument).ConvertTo(inst.Type, this, inst.IsChecked, allowImplicitConversion: false);
var operand = Translate(inst.Argument).ConvertTo(SpecialType.Dynamic, this);
var result = new CastExpression(ConvertType(inst.Type), operand)
.WithILInstruction(inst)
.WithRR(new ConversionResolveResult(
inst.Type, operand.ResolveResult,
inst.IsExplicit ? Conversion.ExplicitDynamicConversion : Conversion.ImplicitDynamicConversion
));
result.Expression.AddAnnotation(inst.IsChecked ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
return result;
}
protected internal override TranslatedExpression VisitDynamicGetIndexInstruction(DynamicGetIndexInstruction inst, TranslationContext context)

17
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -650,9 +650,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -650,9 +650,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
|| kind == TypeKind.Delegate || kind == TypeKind.Anonymous;
}
#endregion
#region Boxing Conversions
public bool IsBoxingConversion(IType fromType, IType toType)
bool IsBoxingConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.1.7
fromType = NullableType.GetUnderlyingType(fromType);
@ -661,7 +661,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -661,7 +661,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
else
return false;
}
/// <summary>
/// Gets whether the conversion from fromType to toType is a boxing conversion,
/// or an implicit conversion involving a type parameter that might be
/// a boxing conversion when instantiated with a value type.
/// </summary>
public bool IsBoxingConversionOrInvolvingTypeParameter(IType fromType, IType toType)
{
return IsBoxingConversion(fromType, toType)
|| ImplicitTypeParameterConversion(fromType, toType);
}
bool UnboxingConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.2.5

8
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -286,7 +286,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -286,7 +286,9 @@ namespace ICSharpCode.Decompiler.CSharp
return new YieldBreakStatement();
else if (!inst.Value.MatchNop()) {
IType targetType = currentFunction.IsAsync ? currentFunction.AsyncReturnType : currentFunction.ReturnType;
return new ReturnStatement(exprBuilder.Translate(inst.Value, typeHint: targetType).ConvertTo(targetType, exprBuilder, allowImplicitConversion: true));
var expr = exprBuilder.Translate(inst.Value, typeHint: targetType)
.ConvertTo(targetType, exprBuilder, allowImplicitConversion: true);
return new ReturnStatement(expr);
} else
return new ReturnStatement();
}
@ -311,8 +313,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -311,8 +313,10 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override Statement VisitYieldReturn(YieldReturn inst)
{
var elementType = currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem, true, out var isGeneric);
var expr = exprBuilder.Translate(inst.Value, typeHint: elementType)
.ConvertTo(elementType, exprBuilder, allowImplicitConversion: true);
return new YieldReturnStatement {
Expression = exprBuilder.Translate(inst.Value, typeHint: elementType).ConvertTo(elementType, exprBuilder)
Expression = expr
};
}

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -1396,7 +1396,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1396,7 +1396,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
m |= Modifiers.Abstract;
if (member.IsOverride)
m |= Modifiers.Override;
if (member.IsVirtual && !member.IsAbstract && !member.IsOverride)
if (member.IsVirtual && !member.IsAbstract && !member.IsOverride && declaringType.Kind != TypeKind.Interface)
m |= Modifiers.Virtual;
if (member.IsSealed)
m |= Modifiers.Sealed;

13
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -565,6 +565,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -565,6 +565,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return base.VisitIdentifier(identifier);
}
internal static bool IsBackingFieldOfAutomaticProperty(IField field, out IProperty property)
{
property = null;
if (!(field.Name.StartsWith("<") && field.Name.EndsWith(">k__BackingField")))
return false;
if (!field.IsCompilerGenerated())
return false;
var propertyName = field.Name.Substring(1, field.Name.Length - 1 - ">k__BackingField".Length);
property = field.DeclaringTypeDefinition
.GetProperties(p => p.Name == propertyName, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
return property != null;
}
Identifier ReplaceBackingFieldUsage(Identifier identifier)
{
if (identifier.Name.StartsWith("<") && identifier.Name.EndsWith(">k__BackingField")) {

44
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -185,11 +185,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -185,11 +185,12 @@ namespace ICSharpCode.Decompiler.CSharp
if (allowImplicitConversion) {
switch (ResolveResult) {
case ConversionResolveResult conversion: {
if (Expression is CastExpression cast
&& ((type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion
|| conversion.Conversion.IsAnonymousFunctionConversion
|| (conversion.Conversion.IsImplicit && (conversion.Conversion.IsUserDefined || targetType.IsKnownType(KnownTypeCode.Decimal)))
) || (conversion.Conversion.IsInterpolatedStringConversion))) {
if (Expression is CastExpression cast && CastCanBeMadeImplicit(
Resolver.CSharpConversions.Get(expressionBuilder.compilation),
conversion.Conversion,
conversion.Input.Type,
type, targetType
)) {
return this.UnwrapChild(cast.Expression);
} else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion
&& oce.Arguments.Count == 1 && expressionBuilder.settings.UseImplicitMethodGroupConversion) {
@ -228,7 +229,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -228,7 +229,7 @@ namespace ICSharpCode.Decompiler.CSharp
var compilation = expressionBuilder.compilation;
var conversions = Resolver.CSharpConversions.Get(compilation);
if (ResolveResult is ConversionResolveResult conv && Expression is CastExpression cast2 &&
IsBoxingOrInterpolatedStringConversion(conversions, conv.Conversion, conv.Input.Type, targetType))
CastCanBeMadeImplicit(conversions, conv.Conversion, conv.Input.Type, type, targetType))
{
var unwrapped = this.UnwrapChild(cast2.Expression);
if (allowImplicitConversion)
@ -387,21 +388,32 @@ namespace ICSharpCode.Decompiler.CSharp @@ -387,21 +388,32 @@ namespace ICSharpCode.Decompiler.CSharp
return this;
}
var castExpr = new CastExpression(expressionBuilder.ConvertType(targetType), Expression);
bool avoidCheckAnnotation = utype.IsKnownType(KnownTypeCode.Single) && targetUType.IsKnownType(KnownTypeCode.Double);
if (!avoidCheckAnnotation) {
bool needsCheckAnnotation = targetUType.GetStackType().IsIntegerType();
if (needsCheckAnnotation) {
castExpr.AddAnnotation(checkForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
}
return castExpr.WithoutILInstruction().WithRR(rr);
}
bool IsBoxingOrInterpolatedStringConversion(Resolver.CSharpConversions conversions, Conversion conversion, IType inputType, IType targetType)
/// <summary>
/// Gets whether an implicit conversion from 'inputType' to 'newTargetType'
/// would have the same semantics as the existing cast from 'inputType' to 'oldTargetType'.
/// The existing cast is classified in 'conversion'.
/// </summary>
bool CastCanBeMadeImplicit(Resolver.CSharpConversions conversions, Conversion conversion, IType inputType, IType oldTargetType, IType newTargetType)
{
if (conversion.IsBoxingConversion && conversions.IsBoxingConversion(inputType, targetType))
return true;
if (conversion.IsInterpolatedStringConversion && (targetType.IsKnownType(KnownTypeCode.FormattableString)
|| targetType.IsKnownType(KnownTypeCode.IFormattable)))
return true;
return false;
if (!conversion.IsImplicit) {
// If the cast was required for the old conversion, avoid making it implicit.
return false;
}
if (conversion.IsBoxingConversion) {
return conversions.IsBoxingConversionOrInvolvingTypeParameter(inputType, newTargetType);
}
if (conversion.IsInterpolatedStringConversion) {
return newTargetType.IsKnownType(KnownTypeCode.FormattableString)
|| newTargetType.IsKnownType(KnownTypeCode.IFormattable);
}
return oldTargetType.Equals(newTargetType);
}
TranslatedExpression LdcI4(ICompilation compilation, int val)

2
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -666,7 +666,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -666,7 +666,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
break;
default:
output.Write(value.ToString());
DisassemblerHelpers.WriteOperand(output, value);
break;
}
}

1
ICSharpCode.Decompiler/Documentation/IdStringProvider.cs

@ -352,7 +352,6 @@ namespace ICSharpCode.Decompiler.Documentation @@ -352,7 +352,6 @@ namespace ICSharpCode.Decompiler.Documentation
typeParameterCount = ReflectionHelper.ReadTypeParameterCount(typeName, ref pos);
} else if (pos < typeName.Length && typeName[pos] == '{') {
// bound generic type
typeArguments = new List<ITypeReference>();
do {
pos++;
typeArguments.Add(ParseTypeName(typeName, ref pos));

5
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -51,8 +51,8 @@ @@ -51,8 +51,8 @@
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.Reflection.Metadata" Version="1.4.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="System.Reflection.Metadata" Version="1.6.0" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
@ -265,6 +265,7 @@ @@ -265,6 +265,7 @@
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="DecompileRun.cs" />
<Compile Include="Disassembler\ILParser.cs" />
<Compile Include="IL\Transforms\ReduceNestingTransform.cs" />
<Compile Include="IL\Transforms\LocalFunctionDecompiler.cs" />
<Compile Include="IL\Transforms\UserDefinedLogicTransform.cs" />
<Compile Include="Metadata\AssemblyReferences.cs" />

10
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.IL @@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.IL
var tryBlock = new BlockContainer();
tryBlock.ILRange = tryRange;
tryCatch = new TryCatch(tryBlock);
tryCatch.ILRange = tryRange;
tryCatchList.Add(tryCatch);
tryInstructionList.Add(tryCatch);
}
@ -90,7 +91,11 @@ namespace ICSharpCode.Decompiler.IL @@ -90,7 +91,11 @@ namespace ICSharpCode.Decompiler.IL
filter = new LdcI4(1);
}
tryCatch.Handlers.Add(new TryCatchHandler(filter, handlerBlock, variableByExceptionHandler[eh]));
var handler = new TryCatchHandler(filter, handlerBlock, variableByExceptionHandler[eh]);
handler.AddILRange(filter.ILRange);
handler.AddILRange(handlerBlock.ILRange);
tryCatch.Handlers.Add(handler);
tryCatch.AddILRange(handler.ILRange);
}
if (tryInstructionList.Count > 0) {
tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.ILRange.Start).ThenByDescending(tc => tc.TryBlock.ILRange.End).ToList();
@ -128,6 +133,7 @@ namespace ICSharpCode.Decompiler.IL @@ -128,6 +133,7 @@ namespace ICSharpCode.Decompiler.IL
// Leave nested containers if necessary
while (start >= currentContainer.ILRange.End) {
currentContainer = containerStack.Pop();
currentBlock = currentContainer.Blocks.Last();
}
// Enter a handler if necessary
BlockContainer handlerContainer;
@ -136,6 +142,7 @@ namespace ICSharpCode.Decompiler.IL @@ -136,6 +142,7 @@ namespace ICSharpCode.Decompiler.IL
currentContainer = handlerContainer;
currentBlock = handlerContainer.EntryPoint;
} else {
FinalizeCurrentBlock(start, fallthrough: false);
// Create the new block
currentBlock = new Block();
currentContainer.Blocks.Add(currentBlock);
@ -172,6 +179,7 @@ namespace ICSharpCode.Decompiler.IL @@ -172,6 +179,7 @@ namespace ICSharpCode.Decompiler.IL
{
if (currentBlock == null)
return;
Debug.Assert(currentBlock.ILRange.IsEmpty);
currentBlock.ILRange = new Interval(currentBlock.ILRange.Start, currentILOffset);
if (fallthrough) {
if (currentBlock.Instructions.LastOrDefault() is SwitchInstruction switchInst && switchInst.Sections.Last().Body.MatchNop()) {

4
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

@ -265,6 +265,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -265,6 +265,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
var outer = BlockContainer.FindClosestContainer(container.Parent);
if (outer != null) changedContainers.Add(outer);
finallyContainer.Blocks.Add(entryPointOfFinally);
finallyContainer.ILRange = entryPointOfFinally.ILRange;
exitOfFinally.Instructions.RemoveRange(tempStore.ChildIndex, 3);
exitOfFinally.Instructions.Add(new Leave(finallyContainer));
foreach (var branchToFinally in container.Descendants.OfType<Branch>()) {
@ -274,8 +275,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -274,8 +275,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var newBlock in additionalBlocksInFinally) {
newBlock.Remove();
finallyContainer.Blocks.Add(newBlock);
finallyContainer.AddILRange(newBlock.ILRange);
}
tryCatch.ReplaceWith(new TryFinally(tryCatch.TryBlock, finallyContainer));
tryCatch.ReplaceWith(new TryFinally(tryCatch.TryBlock, finallyContainer) {ILRange = tryCatch.TryBlock.ILRange});
}
// clean up all modified containers

12
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </summary>
private void OrderIfBlocks(IfInstruction ifInst)
{
if (IsEmpty(ifInst.FalseInst) || ifInst.TrueInst.ILRange.Start <= ifInst.FalseInst.ILRange.Start)
if (IsEmpty(ifInst.FalseInst) || GetILRange(ifInst.TrueInst).Start <= GetILRange(ifInst.FalseInst).Start)
return;
context.Step("Swap then-branch with else-branch to match IL order", ifInst);
@ -437,6 +437,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -437,6 +437,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
ifInst.Condition = Comp.LogicNot(ifInst.Condition);
}
public static Interval GetILRange(ILInstruction inst)
{
// some compilers merge the leave instructions for different arguments using stack variables
// these get split and inlined, but the ILRange of the value remains a better indicator of the actual location
if (inst is Leave leave && !leave.Value.MatchNop())
return leave.Value.ILRange;
return inst.ILRange;
}
/// <summary>
/// Compares the current block exit, and the exit of ifInst.ThenInst
/// and inverts if necessary to pick the better exit

9
ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs

@ -132,7 +132,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -132,7 +132,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} else if (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0] is Leave leave && leave.Value.MatchNop()) {
context.Step("Replace branch to leave with leave", branch);
// Replace branches to 'leave' instruction with the leave instruction
branch.ReplaceWith(leave.Clone());
var leave2 = leave.Clone();
if (!branch.ILRange.IsEmpty) // use the ILRange of the branch if possible
leave2.ILRange = branch.ILRange;
branch.ReplaceWith(leave2);
}
if (targetBlock.IncomingEdgeCount == 0)
targetBlock.Instructions.Clear(); // mark the block for deletion
@ -187,6 +190,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -187,6 +190,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// The C# compiler generates a dead store for the condition of while (true) loops.
block.Instructions.RemoveRange(block.Instructions.Count - 3, 2);
}
if (block.ILRange.IsEmpty)
block.ILRange = targetBlock.ILRange;
block.Instructions.Remove(br);
block.Instructions.AddRange(targetBlock.Instructions);
targetBlock.Instructions.Clear(); // mark targetBlock for deletion

7
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -147,7 +147,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -147,7 +147,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (p.StackType != StackType.Ref) {
arrayToPointer = new Conv(arrayToPointer, p.StackType.ToPrimitiveType(), false, Sign.None);
}
block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer);
block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer) {
ILRange = block.Instructions[block.Instructions.Count - 2].ILRange
};
((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
modified = true;
}
@ -343,7 +345,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -343,7 +345,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
}
stLoc.ReplaceWith(new PinnedRegion(stLoc.Variable, stLoc.Value, body));
stLoc.ReplaceWith(new PinnedRegion(stLoc.Variable, stLoc.Value, body) { ILRange = stLoc.ILRange });
block.Instructions.RemoveAt(block.Instructions.Count - 1); // remove branch into body
ProcessPinnedRegion((PinnedRegion)block.Instructions.Last());
return true;
@ -400,6 +402,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -400,6 +402,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var block in body.Blocks)
CreatePinnedRegion(block);
body.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks
body.ILRange = body.EntryPoint.ILRange;
}
private void MoveArrayToPointerToPinnedRegionInit(PinnedRegion pinnedRegion)

4
ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs

@ -646,6 +646,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -646,6 +646,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (exitTargetBlock != null)
oldEntryPoint.Instructions.Add(new Branch(exitTargetBlock));
loopContainer.ILRange = newEntryPoint.ILRange;
MoveBlocksIntoContainer(loop, loopContainer);
// Rewrite branches within the loop from oldEntryPoint to newEntryPoint:
@ -731,7 +732,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -731,7 +732,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (exitTargetBlock != null) {
block.Instructions.Add(new Branch(exitTargetBlock));
}
switchContainer.ILRange = newEntryPoint.ILRange;
MoveBlocksIntoContainer(nodesInSwitch, switchContainer);
// Rewrite branches within the loop from oldEntryPoint to newEntryPoint:

2
ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs

@ -116,6 +116,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -116,6 +116,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!(tailOnly || block.Instructions.Count == 2))
return false;
trueValues = trueValues.IntersectWith(inputValues);
if (trueValues.SetEquals(inputValues) || trueValues.IsEmpty)
return false;
Block trueBlock;
if (trueInst.MatchBranch(out trueBlock) && AnalyzeBlock(trueBlock, trueValues)) {
// OK, true block was further analyzed.

1
ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

@ -180,6 +180,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -180,6 +180,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// Remove branch/leave after if; it's getting moved into a section.
block.Instructions.RemoveAt(block.Instructions.Count - 1);
}
sw.ILRange = block.Instructions[block.Instructions.Count - 1].ILRange;
block.Instructions[block.Instructions.Count - 1] = sw;
// mark all inner blocks that were converted to the switch statement for deletion

116
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -70,6 +70,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -70,6 +70,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <remarks>Set in AnalyzeCurrentProperty()</remarks>
IField currentField;
/// <summary>The disposing field of the compiler-generated enumerator class./summary>
/// <remarks>Set in ConstructExceptionTable() for assembly compiled with Mono</remarks>
IField disposingField;
/// <summary>Maps the fields of the compiler-generated class to the original parameters.</summary>
/// <remarks>Set in MatchEnumeratorCreationPattern() and ResolveIEnumerableIEnumeratorFieldMapping()</remarks>
readonly Dictionary<IField, ILVariable> fieldToParameterMap = new Dictionary<IField, ILVariable>();
@ -112,6 +116,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -112,6 +116,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
this.enumeratorCtor = default;
this.stateField = null;
this.currentField = null;
this.disposingField = null;
this.fieldToParameterMap.Clear();
this.finallyMethodToStateRange = null;
this.decompiledFinallyMethods.Clear();
@ -147,22 +152,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -147,22 +152,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
context.Step("Delete unreachable blocks", function);
// Note: because this only deletes blocks outright, the 'stateChanges' entries remain valid
// (though some may point to now-deleted blocks)
newBody.SortBlocks(deleteUnreachableBlocks: true);
if (isCompiledWithMono) {
// mono has try-finally inline (like async on MS); we also need to sort nested blocks:
foreach (var nestedContainer in newBody.Blocks.SelectMany(c => c.Descendants).OfType<BlockContainer>()) {
nestedContainer.SortBlocks(deleteUnreachableBlocks: true);
}
} else {
// We need to clean up nested blocks before the main block, so that edges from unreachable code
// in nested containers into the main container are removed before we clean up the main container.
}
// Note: because this only deletes blocks outright, the 'stateChanges' entries remain valid
// (though some may point to now-deleted blocks)
newBody.SortBlocks(deleteUnreachableBlocks: true);
if (!isCompiledWithMono) {
DecompileFinallyBlocks();
ReconstructTryFinallyBlocks(function);
}
context.Step("Translate fields to local accesses", function);
TranslateFieldsToLocalAccess(function, function, fieldToParameterMap);
TranslateFieldsToLocalAccess(function, function, fieldToParameterMap, isCompiledWithMono);
CleanSkipFinallyBodies(function);
@ -459,18 +468,31 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -459,18 +468,31 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
void ConstructExceptionTable()
{
if (isCompiledWithMono) {
disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "Dispose");
var function = CreateILAst(disposeMethod, context);
BlockContainer body = (BlockContainer)function.Body;
for (var i = 0; (i < body.EntryPoint.Instructions.Count) && !(body.EntryPoint.Instructions[i] is Branch); i++) {
if (body.EntryPoint.Instructions[i] is StObj stobj
&& stobj.MatchStFld(out var target, out var field, out var value)
&& target.MatchLdThis()
&& field.Type.IsKnownType(KnownTypeCode.Boolean)
&& value.MatchLdcI4(1)) {
disposingField = (IField)field.MemberDefinition;
break;
}
}
// On mono, we don't need to analyse Dispose() to reconstruct the try-finally structure.
disposeMethod = default;
finallyMethodToStateRange = default;
return;
} else {
// Non-Mono: analyze try-finally structure in Dispose()
disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "System.IDisposable.Dispose");
var function = CreateILAst(disposeMethod, context);
var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(function.Body, LongSet.Universe);
finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
}
disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "System.IDisposable.Dispose");
var function = CreateILAst(disposeMethod, context);
var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(function.Body, LongSet.Universe);
finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
}
[Conditional("DEBUG")]
@ -633,7 +655,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -633,7 +655,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
newBody.Blocks.Add(new Block { ILRange = oldBody.Blocks[blockIndex].ILRange });
}
// convert contents of blocks
for (int i = 0; i < oldBody.Blocks.Count; i++) {
var oldBlock = oldBody.Blocks[i];
var newBlock = newBody.Blocks[i];
@ -656,7 +678,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -656,7 +678,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} else if (field.MemberDefinition.Equals(currentField)) {
// create yield return
newBlock.Instructions.Add(new YieldReturn(value) { ILRange = oldInst.ILRange });
ConvertBranchAfterYieldReturn(newBlock, oldBlock, oldInst.ChildIndex);
ConvertBranchAfterYieldReturn(newBlock, oldBlock, oldInst.ChildIndex + 1);
break; // we're done with this basic block
}
} else if (oldInst is Call call && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis()
@ -674,6 +696,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -674,6 +696,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
// copy over the instruction to the new block
newBlock.Instructions.Add(oldInst);
newBlock.AddILRange(oldInst.ILRange);
UpdateBranchTargets(oldInst);
}
}
@ -687,16 +710,51 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -687,16 +710,51 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
});
return newBody;
void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int i)
void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos)
{
if (!(oldBlock.Instructions[i + 1].MatchStFld(out var target, out var field, out var value)
Block targetBlock;
if (isCompiledWithMono && disposingField != null) {
// Mono skips over the state assignment if 'this.disposing' is set:
// ...
// stfld $current(ldloc this, yield-expr)
// if (ldfld $disposing(ldloc this)) br IL_007c
// br targetBlock
// }
//
// Block targetBlock (incoming: 1) {
// stfld $PC(ldloc this, ldc.i4 1)
// br setSkipFinallyBodies
// }
//
// Block setSkipFinallyBodies (incoming: 2) {
// stloc skipFinallyBodies(ldc.i4 1)
// br returnBlock
// }
if (oldBlock.Instructions[pos].MatchIfInstruction(out var condition, out _)
&& condition.MatchLdFld(out var condTarget, out var condField)
&& condTarget.MatchLdThis() && condField.MemberDefinition.Equals(disposingField)
&& oldBlock.Instructions[pos + 1].MatchBranch(out targetBlock)
&& targetBlock.Parent == oldBlock.Parent) {
// Keep looking at the target block:
oldBlock = targetBlock;
pos = 0;
}
}
if (oldBlock.Instructions[pos].MatchStFld(out var target, out var field, out var value)
&& target.MatchLdThis()
&& field.MemberDefinition == stateField
&& value.MatchLdcI4(out int newState))) {
&& value.MatchLdcI4(out int newState)) {
pos++;
} else {
newBlock.Instructions.Add(new InvalidBranch("Unable to find new state assignment for yield return"));
return;
}
int pos = i + 2;
// Mono may have 'br setSkipFinallyBodies' here, so follow the branch
if (oldBlock.Instructions[pos].MatchBranch(out targetBlock) && targetBlock.Parent == oldBlock.Parent) {
oldBlock = targetBlock;
pos = 0;
}
if (oldBlock.Instructions[pos].MatchStLoc(skipFinallyBodies, out value)) {
if (!value.MatchLdcI4(1)) {
newBlock.Instructions.Add(new InvalidExpression {
@ -706,9 +764,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -706,9 +764,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
pos++;
}
if (oldBlock.Instructions[pos].MatchReturn(out var retVal) && retVal.MatchLdcI4(1)) {
// OK, found return directly after state assignment
} else if (oldBlock.Instructions[pos].MatchBranch(out var targetBlock)
} else if (oldBlock.Instructions[pos].MatchBranch(out targetBlock)
&& targetBlock.Instructions[0].MatchReturn(out retVal) && retVal.MatchLdcI4(1)) {
// OK, jump to common return block (e.g. on Mono)
} else {
@ -753,8 +812,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -753,8 +812,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
break;
case Leave leave:
if (leave.MatchReturn(out var value)) {
if (value.MatchLdLoc(out var v) && v.IsSingleDefinition
&& v.StoreInstructions.SingleOrDefault() is StLoc stloc) {
if (value.MatchLdLoc(out var v)
&& (v.Kind == VariableKind.Local || v.Kind == VariableKind.StackSlot)
&& v.StoreInstructions.Count == 1
&& v.StoreInstructions[0] is StLoc stloc) {
returnStores.Add(stloc);
value = stloc.Value;
}
@ -782,7 +843,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -782,7 +843,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary>
/// Translates all field accesses in `function` to local variable accesses.
/// </summary>
internal static void TranslateFieldsToLocalAccess(ILFunction function, ILInstruction inst, Dictionary<IField, ILVariable> fieldToVariableMap)
internal static void TranslateFieldsToLocalAccess(ILFunction function, ILInstruction inst, Dictionary<IField, ILVariable> fieldToVariableMap, bool isCompiledWithMono = false)
{
if (inst is LdFlda ldflda && ldflda.Target.MatchLdThis()) {
var fieldDef = (IField)ldflda.Field.MemberDefinition;
@ -804,11 +865,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -804,11 +865,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} else {
inst.ReplaceWith(new LdLoca(v) { ILRange = inst.ILRange });
}
} else if (inst.MatchLdThis()) {
} else if (!isCompiledWithMono && inst.MatchLdThis()) {
inst.ReplaceWith(new InvalidExpression("stateMachine") { ExpectedResultType = inst.ResultType, ILRange = inst.ILRange });
} else {
foreach (var child in inst.Children) {
TranslateFieldsToLocalAccess(function, child, fieldToVariableMap);
TranslateFieldsToLocalAccess(function, child, fieldToVariableMap, isCompiledWithMono);
}
if (inst is LdObj ldobj && ldobj.Target is LdLoca ldloca && ldloca.Variable.StateMachineField != null) {
LdLoc ldloc = new LdLoc(ldloca.Variable);
@ -931,6 +992,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -931,6 +992,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
tryBlock.Instructions.AddRange(block.Instructions);
var tryBlockContainer = new BlockContainer();
tryBlockContainer.Blocks.Add(tryBlock);
tryBlockContainer.ILRange = tryBlock.ILRange;
stateToContainer.Add(state, tryBlockContainer);
ILInstruction finallyBlock;
@ -944,7 +1006,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -944,7 +1006,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
block.Instructions.Clear();
block.Instructions.Add(new TryFinally(tryBlockContainer, finallyBlock));
block.Instructions.Add(new TryFinally(tryBlockContainer, finallyBlock) { ILRange = tryBlockContainer.ILRange});
}
IMethod FindFinallyMethod(int state)

32
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -131,7 +131,7 @@ namespace ICSharpCode.Decompiler.IL @@ -131,7 +131,7 @@ namespace ICSharpCode.Decompiler.IL
///
/// Returns SpecialType.UnknownType for unsupported instructions.
/// </summary>
public static IType InferType(this ILInstruction inst)
public static IType InferType(this ILInstruction inst, ICompilation compilation)
{
switch (inst) {
case NewObj newObj:
@ -159,12 +159,40 @@ namespace ICSharpCode.Decompiler.IL @@ -159,12 +159,40 @@ namespace ICSharpCode.Decompiler.IL
case LdsFlda ldsflda:
return new ByReferenceType(ldsflda.Field.Type);
case LdElema ldelema:
if (ldelema.Array.InferType() is ArrayType arrayType) {
if (ldelema.Array.InferType(compilation) is ArrayType arrayType) {
if (TypeUtils.IsCompatibleTypeForMemoryAccess(arrayType.ElementType, ldelema.Type)) {
return new ByReferenceType(arrayType.ElementType);
}
}
return new ByReferenceType(ldelema.Type);
case Comp comp:
if (compilation == null)
return SpecialType.UnknownType;
switch (comp.LiftingKind) {
case ComparisonLiftingKind.None:
case ComparisonLiftingKind.CSharp:
return compilation.FindType(KnownTypeCode.Boolean);
case ComparisonLiftingKind.ThreeValuedLogic:
return NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Boolean));
default:
return SpecialType.UnknownType;
}
case BinaryNumericInstruction bni:
if (bni.IsLifted)
return SpecialType.UnknownType;
switch (bni.Operator) {
case BinaryNumericOperator.BitAnd:
case BinaryNumericOperator.BitOr:
case BinaryNumericOperator.BitXor:
var left = bni.Left.InferType(compilation);
var right = bni.Right.InferType(compilation);
if (left.Equals(right) && (left.IsCSharpPrimitiveIntegerType() || left.IsKnownType(KnownTypeCode.Boolean)))
return left;
else
return SpecialType.UnknownType;
default:
return SpecialType.UnknownType;
}
default:
return SpecialType.UnknownType;
}

1
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -181,6 +181,7 @@ namespace ICSharpCode.Decompiler.IL @@ -181,6 +181,7 @@ namespace ICSharpCode.Decompiler.IL
base.CheckInvariant(phase);
Debug.Assert(Blocks.Count > 0 && EntryPoint == Blocks[0]);
Debug.Assert(!IsConnected || EntryPoint?.IncomingEdgeCount >= 1);
Debug.Assert(EntryPoint == null || Parent is ILFunction || !ILRange.IsEmpty);
Debug.Assert(Blocks.All(b => b.HasFlag(InstructionFlags.EndPointUnreachable)));
Debug.Assert(Blocks.All(b => b.Kind == BlockKind.ControlFlow)); // this also implies that the blocks don't use FinalInstruction
Block bodyStartBlock;

2
ICSharpCode.Decompiler/IL/Instructions/Comp.cs

@ -183,6 +183,8 @@ namespace ICSharpCode.Decompiler.IL @@ -183,6 +183,8 @@ namespace ICSharpCode.Decompiler.IL
return;
}
output.Write(OpCode);
output.Write('.');
output.Write(InputType.ToString().ToLower());
switch (Sign) {
case Sign.Signed:
output.Write(".signed");

2
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler.IL @@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
// Can't transform if the RHS value would be need to be truncated for the LHS type.
if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, binary.IsLifted))
if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, null, binary.IsLifted))
return false;
return true;
}

21
ICSharpCode.Decompiler/IL/SemanticHelper.cs

@ -44,27 +44,6 @@ namespace ICSharpCode.Decompiler.IL @@ -44,27 +44,6 @@ namespace ICSharpCode.Decompiler.IL
return (inst & ~pureFlags) == 0;
}
/// <summary>
/// Gets whether the instruction sequence 'inst1; inst2;' may be ordered to 'inst2; inst1;'
/// </summary>
internal static bool MayReorder(InstructionFlags inst1, InstructionFlags inst2)
{
// If both instructions perform an impure action, we cannot reorder them
if (!IsPure(inst1) && !IsPure(inst2))
return false;
// We cannot reorder if inst2 might write what inst1 looks at
if (ConflictingPair(inst1, inst2, InstructionFlags.MayReadLocals, InstructionFlags.MayWriteLocals | InstructionFlags.SideEffect))
return false;
return true;
}
private static bool ConflictingPair(InstructionFlags inst1, InstructionFlags inst2, InstructionFlags readFlag, InstructionFlags writeFlag)
{
// if one instruction has the read flag and the other the write flag, that's a conflict
return (inst1 & readFlag) != 0 && (inst2 & writeFlag) != 0
|| (inst2 & readFlag) != 0 && (inst1 & writeFlag) != 0;
}
/// <summary>
/// Gets whether the instruction sequence 'inst1; inst2;' may be ordered to 'inst2; inst1;'
/// </summary>

5
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!variableType.IsKnownType(KnownTypeCode.Object))
return variableType;
IType inferredType = inst.InferType();
IType inferredType = inst.InferType(context.TypeSystem);
if (inferredType.Kind != TypeKind.Unknown)
return inferredType;
else
@ -477,6 +477,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -477,6 +477,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
if (function == null)
throw new ArgumentNullException(nameof(function));
if (existingVariable != null && !existingVariable.HasGeneratedName) {
return existingVariable.Name;
}
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable);
string baseName = GetNameFromInstruction(valueContext);

11
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILFunction f = TransformDelegateConstruction(call, out ILInstruction target);
if (f != null) {
call.ReplaceWith(f);
if (target is IInstructionWithVariableOperand && !target.MatchLdThis())
if (target is IInstructionWithVariableOperand)
targetsToReplace.Add((IInstructionWithVariableOperand)target);
}
}
@ -269,6 +269,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -269,6 +269,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitStLoc(StLoc inst)
{
base.VisitStLoc(inst);
if (targetLoad is ILInstruction instruction && instruction.MatchLdThis())
return;
if (inst.Variable == targetLoad.Variable)
orphanedVariableInits.Add(inst);
if (MatchesTargetOrCopyLoad(inst.Value)) {
@ -285,7 +287,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -285,7 +287,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitStObj(StObj inst)
{
base.VisitStObj(inst);
if (!inst.Target.MatchLdFlda(out ILInstruction target, out IField field) || !MatchesTargetOrCopyLoad(target))
if (!inst.Target.MatchLdFlda(out ILInstruction target, out IField field) || !MatchesTargetOrCopyLoad(target) || target.MatchLdThis())
return;
field = (IField)field.MemberDefinition;
ILInstruction value;
@ -321,6 +323,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -321,6 +323,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitLdFlda(LdFlda inst)
{
base.VisitLdFlda(inst);
if (inst.Target.MatchLdThis() && inst.Field.Name == "$this"
&& inst.Field.MemberDefinition.ReflectionName.Contains("c__Iterator")) {
var variable = currentFunction.Variables.First((f) => f.Index == -1);
inst.ReplaceWith(new LdLoca(variable) { ILRange = inst.ILRange });
}
if (inst.Parent is LdObj || inst.Parent is StObj)
return;
if (!MatchesTargetOrCopyLoad(inst.Target))

21
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -498,21 +498,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -498,21 +498,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
break;
case BinaryNumericOperator.BitAnd:
if (IsBoolean(inst.Left) && IsBoolean(inst.Right) && SemanticHelper.IsPure(inst.Right.Flags))
if (inst.Left.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean)
&& inst.Right.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean))
{
context.Step("Replace bit.and with logic.and", inst);
var expr = IfInstruction.LogicAnd(inst.Left, inst.Right);
inst.ReplaceWith(expr);
expr.AcceptVisitor(this);
if (new NullableLiftingTransform(context).Run(inst)) {
// e.g. "(a.GetValueOrDefault() == b.GetValueOrDefault()) & (a.HasValue & b.HasValue)"
} else if (SemanticHelper.IsPure(inst.Right.Flags)) {
context.Step("Replace bit.and with logic.and", inst);
var expr = IfInstruction.LogicAnd(inst.Left, inst.Right);
inst.ReplaceWith(expr);
expr.AcceptVisitor(this);
}
}
break;
}
}
private static bool IsBoolean(ILInstruction inst) =>
inst is Comp c && c.ResultType == StackType.I4 ||
inst.InferType().IsKnownType(KnownTypeCode.Boolean);
protected internal override void VisitTryCatchHandler(TryCatchHandler inst)
{
base.VisitTryCatchHandler(inst);

1
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -363,6 +363,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -363,6 +363,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// decide based on the target into which we are inlining
switch (next.OpCode) {
case OpCode.Leave:
case OpCode.YieldReturn:
return parent == next;
case OpCode.IfInstruction:
while (parent.MatchLogicNot(out _)) {

5
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -39,7 +39,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -39,7 +39,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// We exclude logic.and to avoid turning
// "logic.and(comp(interfaces != ldnull), call get_Count(interfaces))"
// into "if ((interfaces?.Count ?? 0) != 0)".
return (ifInst.MatchLogicAnd(out _, out _) || ifInst.MatchLogicOr(out _, out _))
return ifInst != null
&& (ifInst.MatchLogicAnd(out _, out _) || ifInst.MatchLogicOr(out _, out _))
&& IfInstruction.IsInConditionSlot(ifInst);
}
@ -111,7 +112,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -111,7 +112,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!IsValidAccessChain(testedVar, mode, nonNullInst, out var varLoad))
return null;
// note: InferType will be accurate in this case because the access chain consists of calls and field accesses
IType returnType = nonNullInst.InferType();
IType returnType = nonNullInst.InferType(context.TypeSystem);
if (nullInst.MatchLdNull()) {
context.Step($"Null propagation (mode={mode}, output=reference type)", nonNullInst);
// testedVar != null ? testedVar.AccessChain : null

30
ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public bool Run(IfInstruction ifInst)
{
var lifted = Lift(ifInst, ifInst.TrueInst, ifInst.FalseInst);
var lifted = Lift(ifInst, ifInst.Condition, ifInst.TrueInst, ifInst.FalseInst);
if (lifted != null) {
ifInst.ReplaceWith(lifted);
return true;
@ -64,6 +64,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -64,6 +64,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
/// <summary>
/// VS2017.8 / Roslyn 2.9 started optimizing some cases of
/// "a.GetValueOrDefault() == b.GetValueOrDefault() && (a.HasValue & b.HasValue)"
/// to
/// "(a.GetValueOrDefault() == b.GetValueOrDefault()) & (a.HasValue & b.HasValue)"
/// so this secondary entry point analyses logic.and as-if it was a short-circuting &&.
/// </summary>
public bool Run(BinaryNumericInstruction bni)
{
Debug.Assert(!bni.IsLifted && bni.Operator == BinaryNumericOperator.BitAnd);
// caller ensures that bni.Left/bni.Right are booleans
var lifted = Lift(bni, bni.Left, bni.Right, new LdcI4(0));
if (lifted != null) {
bni.ReplaceWith(lifted);
return true;
}
return false;
}
public bool RunStatements(Block block, int pos)
{
/// e.g.:
@ -85,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -85,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (elseLeave.TargetContainer != thenLeave.TargetContainer)
return false;
var lifted = Lift(ifInst, thenLeave.Value, elseLeave.Value);
var lifted = Lift(ifInst, ifInst.Condition, thenLeave.Value, elseLeave.Value);
if (lifted != null) {
thenLeave.Value = lifted;
ifInst.ReplaceWith(thenLeave);
@ -118,14 +137,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -118,14 +137,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Main entry point for lifting; called by both the expression-transform
/// and the block transform.
/// </summary>
ILInstruction Lift(IfInstruction ifInst, ILInstruction trueInst, ILInstruction falseInst)
ILInstruction Lift(ILInstruction ifInst, ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst)
{
ILInstruction condition = ifInst.Condition;
// ifInst is usually the IfInstruction to which condition belongs;
// but can also be a BinaryNumericInstruction.
while (condition.MatchLogicNot(out var arg)) {
condition = arg;
ExtensionMethods.Swap(ref trueInst, ref falseInst);
}
if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst)) {
if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst as IfInstruction)) {
var nullPropagated = new NullPropagationTransform(context)
.Run(condition, trueInst, falseInst, ifInst.ILRange);
if (nullPropagated != null)

418
ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs

@ -0,0 +1,418 @@ @@ -0,0 +1,418 @@
// Copyright (c) 2018 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;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// Improves code quality by duplicating keyword exits to reduce nesting and restoring IL order.
/// </summary>
/// <remarks>
/// ConditionDetection and DetectSwitchBody both have agressive inlining policies for else blocks and default cases respectively.
/// This can lead to excessive indentation when the entire rest of the method/loop is included in the else block/default case.
/// When an If/SwitchInstruction is followed immediately by a keyword exit, the exit can be moved into the child blocks
/// allowing the else block or default case to be moved after the if/switch as all prior cases exit.
/// Most importantly, this transformatino does not change the IL order of any code.
///
/// ConditionDetection also has a block exit priority system to assist exit point reduction which in some cases ignores IL order.
/// After HighLevelLoopTransform has run, all structures have been detected and preference can be returned to maintaining IL ordering.
/// </remarks>
public class ReduceNestingTransform : IILTransform
{
private ILTransformContext context;
public void Run(ILFunction function, ILTransformContext context)
{
this.context = context;
Visit((BlockContainer)function.Body, null);
}
private void Visit(BlockContainer container, Block continueTarget)
{
switch (container.Kind) {
case ContainerKind.Loop:
case ContainerKind.While:
continueTarget = container.EntryPoint;
break;
case ContainerKind.DoWhile:
case ContainerKind.For:
continueTarget = container.Blocks.Last();
break;
}
foreach (var block in container.Blocks)
Visit(block, continueTarget);
}
/// <summary>
/// Visits a block in context
/// </summary>
/// <param name="block"></param>
/// <param name="continueTarget">Marks the target block of continue statements.</param>
/// <param name="nextInstruction">The instruction following the end point of the block. Can only be null if the end point is unreachable.</param>
private void Visit(Block block, Block continueTarget, ILInstruction nextInstruction = null)
{
Debug.Assert(block.HasFlag(InstructionFlags.EndPointUnreachable) || nextInstruction != null);
// process each instruction in the block.
for (int i = 0; i < block.Instructions.Count; i++) {
// Transformations may be applied to the current and following instructions but already processed instructions will not be changed
var inst = block.Instructions[i];
// the next instruction to be executed. Transformations will change the next instruction, so this is a method instead of a variable
ILInstruction NextInsn() => i + 1 < block.Instructions.Count ? block.Instructions[i + 1] : nextInstruction;
switch (inst) {
case BlockContainer container:
// visit the contents of the container
Visit(container, continueTarget);
// reduce nesting in switch blocks
if (container.Kind == ContainerKind.Switch &&
CanDuplicateExit(NextInsn(), continueTarget) &&
ReduceNesting(block, container, NextInsn()))
RemoveRedundantExit(block, nextInstruction);
break;
case IfInstruction ifInst:
ImproveILOrdering(block, ifInst);
// reduce nesting in if/else blocks
if (CanDuplicateExit(NextInsn(), continueTarget) && ReduceNesting(block, ifInst, NextInsn()))
RemoveRedundantExit(block, nextInstruction);
// visit content blocks
if (ifInst.TrueInst is Block trueBlock)
Visit(trueBlock, continueTarget, NextInsn());
if (ifInst.FalseInst is Block falseBlock) {
if (ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)) {
ExtractElseBlock(ifInst);
break;
}
Visit(falseBlock, continueTarget, NextInsn());
}
break;
}
}
}
/// <summary>
/// For an if statement with an unreachable end point and no else block,
/// inverts to match IL order of the first statement of each branch
/// </summary>
private void ImproveILOrdering(Block block, IfInstruction ifInst)
{
if (!block.HasFlag(InstructionFlags.EndPointUnreachable)
|| !ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)
|| !ifInst.FalseInst.MatchNop())
return;
Debug.Assert(ifInst != block.Instructions.Last());
var trueRange = ConditionDetection.GetILRange(ifInst.TrueInst);
var falseRange = ConditionDetection.GetILRange(block.Instructions[block.Instructions.IndexOf(ifInst)+1]);
if (!trueRange.IsEmpty && !falseRange.IsEmpty && falseRange.Start < trueRange.Start)
ConditionDetection.InvertIf(block, ifInst, context);
}
/// <summary>
/// Reduce Nesting in if/else statements by duplicating an exit instruction.
/// Does not affect IL order
/// </summary>
private bool ReduceNesting(Block block, IfInstruction ifInst, ILInstruction exitInst)
{
// start tallying stats for heuristics from then and else-if blocks
int maxStatements = 0, maxDepth = 0;
UpdateStats(ifInst.TrueInst, ref maxStatements, ref maxDepth);
// if (cond) { ... } exit;
if (ifInst.FalseInst.MatchNop()) {
// a separate heuristic tp ShouldReduceNesting as there is visual balancing to be performed based on number of statments
if (maxDepth < 2)
return false;
// ->
// if (!cond) exit;
// ...; exit;
EnsureEndPointUnreachable(ifInst.TrueInst, exitInst);
EnsureEndPointUnreachable(block, exitInst);
ConditionDetection.InvertIf(block, ifInst, context);
return true;
}
// else-if trees are considered as a single group from the root IfInstruction
if (GetElseIfParent(ifInst) != null)
return false;
// find the else block and tally stats for each else-if block
while (Block.Unwrap(ifInst.FalseInst) is IfInstruction elseIfInst) {
UpdateStats(elseIfInst.TrueInst, ref maxStatements, ref maxDepth);
ifInst = elseIfInst;
}
if (!ShouldReduceNesting(ifInst.FalseInst, maxStatements, maxDepth))
return false;
// extract the else block and insert exit points all the way up the else-if tree
do {
var elseIfInst = GetElseIfParent(ifInst);
// if (cond) { ... } else { ... } exit;
// ->
// if (cond) { ...; exit; }
// ...; exit;
EnsureEndPointUnreachable(ifInst.TrueInst, exitInst);
ExtractElseBlock(ifInst);
ifInst = elseIfInst;
} while (ifInst != null);
return true;
}
/// <summary>
/// Reduce Nesting in switch statements by replacing break; in cases with the block exit, and extracting the default case
/// Does not affect IL order
/// </summary>
private bool ReduceNesting(Block parentBlock, BlockContainer switchContainer, ILInstruction exitInst)
{
// break; from outer container cannot be brought inside the switch as the meaning would change
if (exitInst is Leave leave && !leave.IsLeavingFunction)
return false;
// find the default section, and ensure it has only one incoming edge
var switchInst = (SwitchInstruction)switchContainer.EntryPoint.Instructions.Single();
var defaultSection = switchInst.Sections.MaxBy(s => s.Labels.Count());
if (!defaultSection.Body.MatchBranch(out var defaultBlock) || defaultBlock.IncomingEdgeCount != 1)
return false;
// tally stats for heuristic from each case block
int maxStatements = 0, maxDepth = 0;
foreach (var section in switchInst.Sections)
if (section != defaultSection && section.Body.MatchBranch(out var caseBlock) && caseBlock.Parent == switchContainer)
UpdateStats(caseBlock, ref maxStatements, ref maxDepth);
if (!ShouldReduceNesting(defaultBlock, maxStatements, maxDepth))
return false;
Debug.Assert(defaultBlock.HasFlag(InstructionFlags.EndPointUnreachable));
// ensure the default case dominator tree has no exits (branches to other cases)
var cfg = new ControlFlowGraph(switchContainer, context.CancellationToken);
var defaultNode = cfg.GetNode(defaultBlock);
var defaultTree = TreeTraversal.PreOrder(defaultNode, n => n.DominatorTreeChildren).ToList();
if (defaultTree.SelectMany(n => n.Successors).Any(n => !defaultNode.Dominates(n)))
return false;
EnsureEndPointUnreachable(parentBlock, exitInst);
context.Step("Extract default case of switch", switchContainer);
// replace all break; statements with the exitInst
var leaveInstructions = switchContainer.Descendants.Where(inst => inst.MatchLeave(switchContainer));
foreach (var leaveInst in leaveInstructions.ToArray())
leaveInst.ReplaceWith(exitInst.Clone());
// replace the default section branch with a break;
defaultSection.Body.ReplaceWith(new Leave(switchContainer));
// remove all default blocks from the switch container
var defaultBlocks = defaultTree.Select(c => (Block)c.UserData).ToList();
foreach (var block in defaultBlocks)
switchContainer.Blocks.Remove(block);
// replace the parent block exit with the default case instructions
parentBlock.Instructions.RemoveLast();
parentBlock.Instructions.AddRange(defaultBlock.Instructions);
// add any additional blocks from the default case to the parent container
var parentContainer = (BlockContainer)parentBlock.Ancestors.First(p => p is BlockContainer);
int insertAt = parentContainer.Blocks.IndexOf(parentBlock) + 1;
foreach (var block in defaultBlocks.Skip(1))
parentContainer.Blocks.Insert(insertAt++, block);
return true;
}
/// <summary>
/// Checks if an exit is a duplicable keyword exit (return; break; continue;)
/// </summary>
private bool CanDuplicateExit(ILInstruction exit, Block continueTarget) =>
exit != null && (exit is Leave leave && leave.Value.MatchNop() || exit.MatchBranch(continueTarget));
/// <summary>
/// Ensures the end point of a block is unreachable by duplicating and appending the [exit] instruction following the end point
/// </summary>
/// <param name="inst">The instruction/block of interest</param>
/// <param name="fallthroughExit">The next instruction to be executed (provided inst does not exit)</param>
private void EnsureEndPointUnreachable(ILInstruction inst, ILInstruction fallthroughExit)
{
if (!(inst is Block block)) {
Debug.Assert(inst.HasFlag(InstructionFlags.EndPointUnreachable));
return;
}
if (!block.HasFlag(InstructionFlags.EndPointUnreachable)) {
context.Step("Duplicate block exit", fallthroughExit);
block.Instructions.Add(fallthroughExit.Clone());
}
}
/// <summary>
/// Removes a redundant block exit instruction.
/// </summary>
private void RemoveRedundantExit(Block block, ILInstruction implicitExit)
{
if (block.Instructions.Last().Match(implicitExit).Success) {
context.Step("Remove redundant exit", block.Instructions.Last());
block.Instructions.RemoveLast();
}
}
/// <summary>
/// Determines if an IfInstruction is an else-if and returns the preceeding (parent) IfInstruction
///
/// [else-]if (parent-cond) else { ifInst }
/// </summary>
private IfInstruction GetElseIfParent(IfInstruction ifInst)
{
Debug.Assert(ifInst.Parent is Block);
if (Block.Unwrap(ifInst.Parent) == ifInst && // only instruction in block
ifInst.Parent.Parent is IfInstruction elseIfInst && // parent of block is an IfInstruction
elseIfInst.FalseInst == ifInst.Parent) // part of the false branch not the true branch
return elseIfInst;
return null;
}
/// <summary>
/// Adds a code path to the current heuristic tally
/// </summary>
private void UpdateStats(ILInstruction inst, ref int maxStatements, ref int maxDepth)
{
int numStatements = 0;
ComputeStats(inst, ref numStatements, ref maxDepth, 0);
maxStatements = Math.Max(numStatements, maxStatements);
}
/// <summary>
/// Recursively computes the number of statements and maximum nested depth of an instruction
/// </summary>
private void ComputeStats(ILInstruction inst, ref int numStatements, ref int maxDepth, int currentDepth)
{
switch (inst) {
case Block block:
foreach (var i in block.Instructions)
ComputeStats(i, ref numStatements, ref maxDepth, currentDepth);
break;
case BlockContainer container:
numStatements++; // one statement for the container head (switch/loop)
var containerBody = container.EntryPoint;
if (container.Kind == ContainerKind.For || container.Kind == ContainerKind.While) {
if (!container.MatchConditionBlock(container.EntryPoint, out _, out containerBody))
throw new NotSupportedException("Invalid condition block in loop.");
}
// add the nested body
ComputeStats(containerBody, ref numStatements, ref maxDepth, currentDepth + 1);
break;
case IfInstruction ifInst:
numStatements++; // one statement for the if/condition itself
// nested then instruction
ComputeStats(ifInst.TrueInst, ref numStatements, ref maxDepth, currentDepth + 1);
// include all nested else-if instructions at the same depth
var elseInst = ifInst.FalseInst;
while (Block.Unwrap(elseInst) is IfInstruction elseIfInst) {
numStatements++;
ComputeStats(elseIfInst.TrueInst, ref numStatements, ref maxDepth, currentDepth + 1);
elseInst = elseIfInst.FalseInst;
}
// include all nested else instruction
ComputeStats(elseInst, ref numStatements, ref maxDepth, currentDepth + 1);
break;
case SwitchInstruction switchInst:
// one statement per case label
numStatements += switchInst.Sections.Count + 1;
// add all the case blocks at the current depth
// most formatters indent switch blocks twice, but we don't want this heuristic to be based on formatting
// so we remain conservative and only include the increase in depth from the container and not the labels
foreach (var section in switchInst.Sections)
if (section.Body.MatchBranch(out var caseBlock) && caseBlock.Parent == switchInst.Parent.Parent)
ComputeStats(caseBlock, ref numStatements, ref maxDepth, currentDepth);
break;
default:
// just a regular statement
numStatements++;
if (currentDepth > maxDepth)
maxDepth = currentDepth;
break;
}
}
/// <summary>
/// Heuristic to determine whether it is worth duplicating exits into the preceeding sibling blocks (then/else-if/case)
/// in order to reduce the nesting of inst by 1
/// </summary>
/// <param name="inst">The instruction heading the nested candidate block</param>
/// <param name="maxStatements">The number of statements in the largest sibling block</param>
/// <param name="maxDepth">The relative depth of the most nested statement in the sibling blocks</param>
/// <returns></returns>
private bool ShouldReduceNesting(ILInstruction inst, int maxStatements, int maxDepth)
{
int maxStatements2 = 0, maxDepth2 = 0;
UpdateStats(inst, ref maxStatements2, ref maxDepth2);
// if the max depth is 2, always reduce nesting (total depth 3 or more)
// if the max depth is 1, reduce nesting if this block is the largest
// otherwise reduce nesting only if this block is twice as large as any other
return maxDepth2 >= 2 || maxDepth2 >= 1 && maxStatements2 > maxStatements || maxStatements2 >= 2*maxStatements;
}
/// <summary>
/// if (cond) { ...; exit; } else { ... }
/// ...;
/// ->
/// if (cond) { ...; exit; }
/// ...;
/// ...;
/// </summary>
/// <param name="ifInst"></param>
private void ExtractElseBlock(IfInstruction ifInst)
{
Debug.Assert(ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable));
var block = (Block)ifInst.Parent;
var falseBlock = (Block)ifInst.FalseInst;
context.Step("Extract else block", ifInst);
int insertAt = block.Instructions.IndexOf(ifInst) + 1;
for (int i = 0; i < falseBlock.Instructions.Count; i++)
block.Instructions.Insert(insertAt++, falseBlock.Instructions[i]);
ifInst.FalseInst = new Nop();
}
}
}

2
ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs

@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
IType newType = null;
// Multiple store are possible in case of (c ? ref a : ref b) += 1, for example.
foreach (var stloc in v.StoreInstructions.OfType<StLoc>()) {
var inferredType = stloc.Value.InferType();
var inferredType = stloc.Value.InferType(context.TypeSystem);
// cancel, if types of values do not match exactly
if (newType != null && !newType.Equals(inferredType)) {
newType = SpecialType.UnknownType;

2
ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
for (int i = block.Instructions.Count - 1; i >= 0; i--) {
SwitchInstruction newSwitch;
if (MatchSwitchOnNullable(block.Instructions, i, out newSwitch)) {
newSwitch.ILRange = block.Instructions[i - 2].ILRange;
block.Instructions[i + 1].ReplaceWith(newSwitch);
block.Instructions.RemoveRange(i - 2, 3);
i -= 2;
@ -49,6 +50,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -49,6 +50,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
continue;
}
if (MatchRoslynSwitchOnNullable(block.Instructions, i, out newSwitch)) {
newSwitch.ILRange = block.Instructions[i - 1].ILRange;
block.Instructions[i - 1].ReplaceWith(newSwitch);
block.Instructions.RemoveRange(i, 2);
i--;

11
ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs

@ -219,14 +219,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -219,14 +219,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var inst = new SwitchInstruction(stringToInt);
inst.Sections.AddRange(sections);
if (extraLoad) {
inst.ILRange = instructions[i - 2].ILRange;
instructions[i - 2].ReplaceWith(inst);
instructions.RemoveRange(i - 1, 3);
i -= 2;
} else {
if (keepAssignmentBefore) {
inst.ILRange = instructions[i].ILRange;
instructions[i].ReplaceWith(inst);
instructions.RemoveAt(i + 1);
} else {
inst.ILRange = instructions[i - 1].ILRange;
instructions[i - 1].ReplaceWith(inst);
instructions.RemoveRange(i, 2);
i--;
@ -304,7 +307,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -304,7 +307,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var stringToInt = new StringToInt(switchValue, values.SelectArray(item => item.Item1));
var inst = new SwitchInstruction(stringToInt);
inst.Sections.AddRange(sections);
inst.ILRange = instructions[i - 1].ILRange;
instructions[i].ReplaceWith(inst);
instructions.RemoveAt(i + 1);
instructions.RemoveAt(i - 1);
@ -493,10 +497,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -493,10 +497,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
instructions[i + 1].ReplaceWith(inst);
if (keepAssignmentBefore) {
// delete if (comp(ldloc switchValueVar == ldnull))
inst.ILRange = instructions[i].ILRange;
instructions.RemoveAt(i);
i--;
} else {
// delete both the if and the assignment before
inst.ILRange = instructions[i - 1].ILRange;
instructions.RemoveRange(i - 1, 2);
i -= 2;
}
@ -711,6 +717,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -711,6 +717,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var stringToInt = new StringToInt(switchValue, stringValues);
var inst = new SwitchInstruction(stringToInt);
inst.Sections.AddRange(sections);
inst.ILRange = block.Instructions[i].ILRange;
block.Instructions[i].ReplaceWith(inst);
block.Instructions.RemoveRange(i + 1, 3);
info.Transformed = true;
@ -808,9 +815,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -808,9 +815,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
newSwitch.Sections.Add(new SwitchSection { Labels = defaultLabel, Body = defaultSection.Body });
instructions[i].ReplaceWith(newSwitch);
if (keepAssignmentBefore) {
newSwitch.ILRange = instructions[i - 1].ILRange;
instructions.RemoveAt(i - 1);
i--;
} else {
newSwitch.ILRange = instructions[i - 2].ILRange;
instructions.RemoveRange(i - 2, 2);
i -= 2;
}

34
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// in some cases it can be a compiler-generated local
if (inst == null || (inst.Variable.Kind != VariableKind.StackSlot && inst.Variable.Kind != VariableKind.Local))
return false;
if (IsImplicitTruncation(inst.Value, inst.Variable.Type)) {
if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) {
// 'stloc s' is implicitly truncating the value
return false;
}
@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!SemanticHelper.IsPure(stobj.Target.Flags) || inst.Variable.IsUsedWithin(stobj.Target))
return false;
var pointerType = stobj.Target.InferType();
var pointerType = stobj.Target.InferType(context.TypeSystem);
IType newType = stobj.Type;
if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointerType, stobj.Type)) {
if (pointerType is ByReferenceType byref)
@ -120,7 +120,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -120,7 +120,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
else if (pointerType is PointerType pointer)
newType = pointer.ElementType;
}
if (IsImplicitTruncation(inst.Value, newType)) {
if (IsImplicitTruncation(inst.Value, newType, context.TypeSystem)) {
// 'stobj' is implicitly truncating the value
return false;
}
@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!SemanticHelper.IsPure(arg.Flags) || inst.Variable.IsUsedWithin(arg))
return false;
}
if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type)) {
if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type, context.TypeSystem)) {
// setter call is implicitly truncating the value
return false;
}
@ -242,7 +242,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -242,7 +242,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// changes the return value of the expression, so this is only valid on block-level.
return false;
}
if (!IsCompoundStore(compoundStore, out var targetType, out var setterValue))
if (!IsCompoundStore(compoundStore, out var targetType, out var setterValue, context.TypeSystem))
return false;
// targetType = The type of the property/field/etc. being stored to.
// setterValue = The value being stored.
@ -342,11 +342,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -342,11 +342,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!nextInst.Value.MatchLdLoc(inst.Variable))
return false;
if (IsImplicitTruncation(inst.Value, inst.Variable.Type)) {
if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) {
// 'stloc s' is implicitly truncating the stack value
return false;
}
if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type)) {
if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type, context.TypeSystem)) {
// 'stloc l' is implicitly truncating the stack value
return false;
}
@ -371,7 +371,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -371,7 +371,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Gets whether 'stobj type(..., value)' would evaluate to a different value than 'value'
/// due to implicit truncation.
/// </summary>
static internal bool IsImplicitTruncation(ILInstruction value, IType type, bool allowNullableValue = false)
static internal bool IsImplicitTruncation(ILInstruction value, IType type, ICompilation compilation, bool allowNullableValue = false)
{
if (!type.IsSmallIntegerType()) {
// Implicit truncation in ILAst only happens for small integer types;
@ -401,10 +401,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -401,10 +401,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} else if (value is Comp) {
return false; // comp returns 0 or 1, which always fits
} else if (value is IfInstruction ifInst) {
return IsImplicitTruncation(ifInst.TrueInst, type, allowNullableValue)
|| IsImplicitTruncation(ifInst.FalseInst, type, allowNullableValue);
return IsImplicitTruncation(ifInst.TrueInst, type, compilation, allowNullableValue)
|| IsImplicitTruncation(ifInst.FalseInst, type, compilation, allowNullableValue);
} else {
IType inferredType = value.InferType();
IType inferredType = value.InferType(compilation);
if (allowNullableValue) {
inferredType = NullableType.GetUnderlyingType(inferredType);
}
@ -456,14 +456,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -456,14 +456,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Gets whether 'inst' is a possible store for use as a compound store.
/// </summary>
static bool IsCompoundStore(ILInstruction inst, out IType storeType, out ILInstruction value)
static bool IsCompoundStore(ILInstruction inst, out IType storeType, out ILInstruction value, ICompilation compilation)
{
value = null;
storeType = null;
if (inst is StObj stobj) {
// stobj.Type may just be 'int' (due to stind.i4) when we're actually operating on a 'ref MyEnum'.
// Try to determine the real type of the object we're modifying:
storeType = stobj.Target.InferType();
storeType = stobj.Target.InferType(compilation);
if (storeType is ByReferenceType refType) {
storeType = refType.ElementType;
} else if (storeType is PointerType pointerType) {
@ -530,7 +530,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -530,7 +530,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool TransformPostIncDecOperatorWithInlineStore(Block block, int pos)
{
var store = block.Instructions[pos];
if (!IsCompoundStore(store, out var targetType, out var value))
if (!IsCompoundStore(store, out var targetType, out var value, context.TypeSystem))
return false;
StLoc stloc;
var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction;
@ -555,7 +555,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -555,7 +555,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!IsMatchingCompoundLoad(stloc.Value, store, stloc.Variable))
return false;
if (IsImplicitTruncation(stloc.Value, stloc.Variable.Type))
if (IsImplicitTruncation(stloc.Value, stloc.Variable.Type, context.TypeSystem))
return false;
context.Step("TransformPostIncDecOperatorWithInlineStore", store);
if (binary != null) {
@ -585,9 +585,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -585,9 +585,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var store = block.Instructions.ElementAtOrDefault(i + 1);
if (inst == null || store == null)
return false;
if (!IsCompoundStore(store, out var targetType, out var value))
if (!IsCompoundStore(store, out var targetType, out var value, context.TypeSystem))
return false;
if (IsImplicitTruncation(inst.Value, targetType)) {
if (IsImplicitTruncation(inst.Value, targetType, context.TypeSystem)) {
// 'stloc l' is implicitly truncating the value
return false;
}

8
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -152,11 +152,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -152,11 +152,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!ReadParameters(instruction.Arguments[1], parameterList, parameterVariablesList, new SimpleTypeResolveContext(context.Function.Method)))
return (null, SpecialType.UnknownType);
var container = new BlockContainer();
container.ILRange = instruction.ILRange;
var functionType = instruction.Method.ReturnType.TypeArguments[0];
var returnType = functionType.GetDelegateInvokeMethod()?.ReturnType;
var function = new ILFunction(returnType, parameterList, context.Function.GenericContext, container);
function.DelegateType = functionType;
function.Variables.AddRange(parameterVariablesList);
function.ILRange = instruction.ILRange;
lambdaStack.Push(function);
var (bodyInstruction, type) = ConvertInstruction(instruction.Arguments[0]);
lambdaStack.Pop();
@ -611,7 +613,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -611,7 +613,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return (new Call(operatorMethod) { Arguments = { left, right } }, operatorMethod.ReturnType);
}
var resultType = context.TypeSystem.FindType(KnownTypeCode.Boolean);
return (new Comp(kind, NullableType.IsNullable(leftType) ? ComparisonLiftingKind.CSharp : ComparisonLiftingKind.None, leftType.GetStackType(), leftType.GetSign(), left, right), resultType);
var lifting = NullableType.IsNullable(leftType) ? ComparisonLiftingKind.CSharp : ComparisonLiftingKind.None;
var utype = NullableType.GetUnderlyingType(leftType);
return (new Comp(kind, lifting, utype.GetStackType(), utype.GetSign(), left, right), resultType);
}
(ILInstruction, IType) ConvertCondition(CallInstruction invocation)
@ -1065,7 +1069,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1065,7 +1069,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
value = call.Arguments[0];
if (call.Arguments.Count == 2)
return MatchGetTypeFromHandle(call.Arguments[1], out type);
type = value.InferType();
type = value.InferType(context.TypeSystem);
return true;
}
return false;

12
ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -156,5 +157,16 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -156,5 +157,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return compilation.FindType(attrType.GetTypeName());
}
public static KnownAttribute IsKnownAttributeType(this ITypeDefinition attributeType)
{
if (!attributeType.GetNonInterfaceBaseTypes().Any(t => t.IsKnownType(KnownTypeCode.Attribute)))
return KnownAttribute.None;
for (int i = 1; i < typeNames.Length; i++) {
if (typeNames[i] == attributeType.FullTypeName)
return (KnownAttribute)i;
}
return KnownAttribute.None;
}
}
}

2
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -332,7 +332,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -332,7 +332,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) {
implAttributes &= ~MethodImplAttributes.PreserveSig;
} else {
dllImport.AddNamedArg("PreserveSig", KnownTypeCode.Boolean, true);
dllImport.AddNamedArg("PreserveSig", KnownTypeCode.Boolean, false);
}
if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError)

5
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -525,5 +525,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -525,5 +525,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return method.Name == name && method.DeclaringType?.FullName == type;
}
public static KnownAttribute IsBuiltinAttribute(this ITypeDefinition type)
{
return KnownAttributes.IsKnownAttributeType(type);
}
}
}

22
ILSpy.AddIn/Commands/OpenILSpyCommand.cs

@ -12,18 +12,6 @@ using Mono.Cecil; @@ -12,18 +12,6 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
public class ILSpyParameters
{
public ILSpyParameters(IEnumerable<string> assemblyFileNames, params string[] arguments)
{
this.AssemblyFileNames = assemblyFileNames;
this.Arguments = arguments;
}
public IEnumerable<string> AssemblyFileNames { get; private set; }
public string[] Arguments { get; private set; }
}
public class DetectedReference
{
public DetectedReference(string name, string assemblyFile, bool isProjectReference)
@ -75,12 +63,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -75,12 +63,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
}
}
string commandLineArguments = Utils.ArgumentArrayToCommandLine(parameters.AssemblyFileNames.ToArray());
if (parameters.Arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(parameters.Arguments));
}
System.Diagnostics.Process.Start(GetILSpyPath(), commandLineArguments);
var ilspyExe = new ILSpyInstance(parameters);
ilspyExe.Start();
}
protected Dictionary<string, DetectedReference> GetReferences(Microsoft.CodeAnalysis.Project parentProject)
@ -140,7 +124,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -140,7 +124,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
protected override void OnExecute(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(GetILSpyPath());
new ILSpyInstance().Start();
}
internal static void Register(ILSpyAddInPackage owner)

3
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
<PackageReference Include="Microsoft.VisualStudio.Shell.14.0" Version="14.3.25407" />
<PackageReference Include="Microsoft.VisualStudio.Text.UI" Version="15.6.27740" />
<PackageReference Include="Microsoft.VisualStudio.Text.UI.Wpf" Version="15.6.27740" />
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
<PackageReference Include="VSLangProj" Version="7.0.3301" />
</ItemGroup>
@ -74,6 +74,7 @@ @@ -74,6 +74,7 @@
<Compile Include="Commands\OpenProjectOutputCommand.cs" />
<Compile Include="Commands\OpenReferenceCommand.cs" />
<Compile Include="Guids.cs" />
<Compile Include="ILSpyInstance.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

112
ILSpy.AddIn/ILSpyInstance.cs

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.ILSpy.AddIn
{
class ILSpyParameters
{
public ILSpyParameters(IEnumerable<string> assemblyFileNames, params string[] arguments)
{
this.AssemblyFileNames = assemblyFileNames;
this.Arguments = arguments;
}
public IEnumerable<string> AssemblyFileNames { get; private set; }
public string[] Arguments { get; private set; }
}
class ILSpyInstance
{
ILSpyParameters parameters;
public ILSpyInstance()
{
}
public ILSpyInstance(ILSpyParameters parameters)
{
this.parameters = parameters;
}
static string GetILSpyPath()
{
var basePath = Path.GetDirectoryName(typeof(ILSpyAddInPackage).Assembly.Location);
return Path.Combine(basePath, "ILSpy.exe");
}
public void Start()
{
var commandLineArguments = parameters.AssemblyFileNames?.Concat(parameters.Arguments);
var process = new Process() {
StartInfo = new ProcessStartInfo() {
FileName = GetILSpyPath(),
UseShellExecute = false
}
};
process.Start();
if ((commandLineArguments != null) && commandLineArguments.Any()) {
// Only need a message to started process if there are any parameters to pass
SendMessage(process, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true);
}
}
void SendMessage(Process ilspyProcess, string message, bool activate)
{
// We wait asynchronously until target window can be found and try to find it multiple times
Task.Run(async () => {
bool success = false;
int remainingAttempts = 20;
do {
NativeMethods.EnumWindows(
(hWnd, lParam) => {
string windowTitle = NativeMethods.GetWindowText(hWnd, 100);
if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) {
Debug.WriteLine("Found {0:x4}: {1}", hWnd, windowTitle);
IntPtr result = Send(hWnd, message);
Debug.WriteLine("WM_COPYDATA result: {0:x8}", result);
if (result == (IntPtr)1) {
if (activate)
NativeMethods.SetForegroundWindow(hWnd);
success = true;
return false; // stop enumeration
}
}
return true; // continue enumeration
}, IntPtr.Zero);
// Wait some time before next attempt
await Task.Delay(500);
remainingAttempts--;
} while (!success && (remainingAttempts > 0));
});
}
unsafe static IntPtr Send(IntPtr hWnd, string message)
{
const uint SMTO_NORMAL = 0;
CopyDataStruct lParam;
lParam.Padding = IntPtr.Zero;
lParam.Size = message.Length * 2;
fixed (char* buffer = message) {
lParam.Buffer = (IntPtr)buffer;
IntPtr result;
// SendMessage with 3s timeout (e.g. when the target process is stopped in the debugger)
if (NativeMethods.SendMessageTimeout(
hWnd, NativeMethods.WM_COPYDATA, IntPtr.Zero, ref lParam,
SMTO_NORMAL, 3000, out result) != IntPtr.Zero) {
return result;
} else {
return IntPtr.Zero;
}
}
}
}
}

2
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="3.9.0" />
<PackageReference Include="NUnit" Version="3.11.0" />
</ItemGroup>
<ItemGroup>

10
ILSpy.Tests/ILSpy.Tests.csproj

@ -42,11 +42,11 @@ @@ -42,11 +42,11 @@
<ItemGroup>
<PackageReference Include="DiffLib" Version="2017.7.26.1241" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="2.8.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.9.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="NUnit" Version="3.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="2.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.11.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="NUnit" Version="3.11.0" />
</ItemGroup>
<ItemGroup>

121
ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs

@ -18,10 +18,11 @@ @@ -18,10 +18,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
@ -31,10 +32,116 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -31,10 +32,116 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
if (!(analyzedSymbol is IEntity attributeEntity))
yield break;
if (!(analyzedSymbol is ITypeDefinition attributeType))
return Array.Empty<ISymbol>();
var scope = context.GetScopeOf(attributeEntity);
var scope = context.GetScopeOf(attributeType);
// TODO: DeclSecurity attributes are not supported.
if (!IsBuiltinAttribute(attributeType, out var knownAttribute)) {
return HandleCustomAttribute(attributeType, scope);
} else {
return HandleBuiltinAttribute(knownAttribute, scope).SelectMany(s => s);
}
}
bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute)
{
knownAttribute = attributeType.IsBuiltinAttribute();
switch (knownAttribute) {
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
case KnownAttribute.MarshalAs:
case KnownAttribute.PermissionSet:
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
case KnownAttribute.IndexerName:
return true;
default:
return false;
}
}
IEnumerable<IEnumerable<ISymbol>> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope)
{
IEnumerable<ISymbol> ScanTypes(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.Where(t => t.HasAttribute(attribute));
}
IEnumerable<ISymbol> ScanMethods(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Members.OfType<IMethod>())
.Where(m => m.HasAttribute(attribute))
.Select(m => m.AccessorOwner ?? m);
}
IEnumerable<ISymbol> ScanFields(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Fields)
.Where(f => f.HasAttribute(attribute));
}
IEnumerable<ISymbol> ScanProperties(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Properties)
.Where(p => p.HasAttribute(attribute));
}
IEnumerable<ISymbol> ScanParameters(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Members.OfType<IMethod>())
.Where(m => m.Parameters.Any(p => p.HasAttribute(attribute)))
.Select(m => m.AccessorOwner ?? m);
}
foreach (Decompiler.Metadata.PEFile module in scope.GetAllModules()) {
var ts = new DecompilerTypeSystem(module, module.GetAssemblyResolver());
switch (attribute) {
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
yield return ScanTypes(ts);
break;
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
yield return ScanMethods(ts);
break;
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
yield return ScanFields(ts);
break;
case KnownAttribute.MarshalAs:
yield return ScanFields(ts);
yield return ScanParameters(ts);
goto case KnownAttribute.Out;
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
yield return ScanParameters(ts);
break;
case KnownAttribute.IndexerName:
yield return ScanProperties(ts);
break;
}
}
}
IEnumerable<ISymbol> HandleCustomAttribute(ITypeDefinition attributeType, AnalyzerScope scope)
{
var genericContext = new GenericContext(); // type arguments do not matter for this analyzer.
foreach (var module in scope.GetAllModules()) {
@ -44,8 +151,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -44,8 +151,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var customAttribute = module.Metadata.GetCustomAttribute(h);
var attributeCtor = ts.MainModule.ResolveMethod(customAttribute.Constructor, genericContext);
if (attributeCtor.DeclaringTypeDefinition != null
&& attributeCtor.ParentModule.PEFile == attributeEntity.ParentModule.PEFile
&& attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeEntity.MetadataToken) {
&& attributeCtor.ParentModule.PEFile == attributeType.ParentModule.PEFile
&& attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeType.MetadataToken) {
if (customAttribute.Parent.Kind == HandleKind.Parameter) {
referencedParameters.Add((ParameterHandle)customAttribute.Parent);
} else {

3
ILSpy/Controls/GridViewColumnAutoSize.cs

@ -70,7 +70,8 @@ namespace ICSharpCode.ILSpy.Controls @@ -70,7 +70,8 @@ namespace ICSharpCode.ILSpy.Controls
{
string[] sizes = (sizeValue ?? "").Split(';');
Debug.Assert(sizes.Length == view.Columns.Count);
if (sizes.Length != view.Columns.Count)
return;
Dictionary<int, Func<double, double>> percentages = new Dictionary<int, Func<double, double>>();
double remainingWidth = fullWidth - 30; // 30 is a good offset for the scrollbar

16
ILSpy/Controls/ResourceObjectTable.xaml

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
<UserControl x:Class="ICSharpCode.ILSpy.Controls.ResourceObjectTable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.Controls"
Cursor="Arrow">
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
@ -36,25 +37,26 @@ @@ -36,25 +37,26 @@
Foreground="Black"
Grid.Row="1"
AlternationCount="2"
ItemContainerStyle="{StaticResource alternatingWithBinding}">
ItemContainerStyle="{StaticResource alternatingWithBinding}"
local:SortableGridViewColumn.SortMode="Automatic">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="{Binding Key}">
<local:SortableGridViewColumn DisplayMemberBinding="{Binding Key}" SortBy="Key">
<GridViewColumnHeader Content="Name"
HorizontalContentAlignment="Left"
FontWeight="Bold" />
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Value}">
</local:SortableGridViewColumn>
<local:SortableGridViewColumn DisplayMemberBinding="{Binding Value}" SortBy="Value">
<GridViewColumnHeader Content="Value (as string)"
HorizontalContentAlignment="Left"
FontWeight="Bold" />
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Type}">
</local:SortableGridViewColumn>
<local:SortableGridViewColumn DisplayMemberBinding="{Binding Type}" SortBy="Type">
<GridViewColumnHeader Content="Type"
HorizontalContentAlignment="Left"
FontWeight="Bold" />
</GridViewColumn>
</local:SortableGridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>

16
ILSpy/Controls/ResourceStringTable.xaml

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
<UserControl x:Class="ICSharpCode.ILSpy.Controls.ResourceStringTable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.Controls"
Cursor="Arrow">
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
@ -34,22 +35,23 @@ @@ -34,22 +35,23 @@
FontFamily="Segoe UI"
FontSize="9pt"
Foreground="Black"
Grid.Row="1"
AlternationCount="2"
ItemContainerStyle="{StaticResource alternatingWithBinding}">
Grid.Row="1"
AlternationCount="2"
ItemContainerStyle="{StaticResource alternatingWithBinding}"
local:SortableGridViewColumn.SortMode="Automatic">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="{Binding Key}">
<local:SortableGridViewColumn DisplayMemberBinding="{Binding Key}" SortBy="Key">
<GridViewColumnHeader Content="Name"
HorizontalContentAlignment="Left"
FontWeight="Bold" />
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Value}">
</local:SortableGridViewColumn>
<local:SortableGridViewColumn DisplayMemberBinding="{Binding Value}" SortBy="Value">
<GridViewColumnHeader Content="Value"
HorizontalContentAlignment="Left"
FontWeight="Bold" />
</GridViewColumn>
</local:SortableGridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>

2
ILSpy/ILSpy.csproj

@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="5.0.4" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.5.23" />
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
</ItemGroup>
<ItemGroup>

1
ILSpy/Languages/CSharpLanguage.cs

@ -110,6 +110,7 @@ namespace ICSharpCode.ILSpy @@ -110,6 +110,7 @@ namespace ICSharpCode.ILSpy
{
CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings);
decompiler.CancellationToken = options.CancellationToken;
decompiler.DebugInfoProvider = module.GetDebugInfoOrNull();
while (decompiler.AstTransforms.Count > transformCount)
decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1);
return decompiler;

22
ILSpy/MainWindow.xaml.cs

@ -48,6 +48,7 @@ namespace ICSharpCode.ILSpy @@ -48,6 +48,7 @@ namespace ICSharpCode.ILSpy
/// </summary>
partial class MainWindow : Window
{
bool refreshInProgress;
readonly NavigationHistory<NavigationState> history = new NavigationHistory<NavigationState>();
ILSpySettings spySettings;
internal SessionSettings sessionSettings;
@ -748,9 +749,14 @@ namespace ICSharpCode.ILSpy @@ -748,9 +749,14 @@ namespace ICSharpCode.ILSpy
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
try {
refreshInProgress = true;
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
} finally {
refreshInProgress = false;
}
}
void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e)
@ -775,6 +781,9 @@ namespace ICSharpCode.ILSpy @@ -775,6 +781,9 @@ namespace ICSharpCode.ILSpy
{
if (ignoreDecompilationRequests)
return;
if (treeView.SelectedItems.Count == 0 && refreshInProgress)
return;
if (recordHistory) {
var dtState = decompilerTextView.GetState();
@ -804,7 +813,12 @@ namespace ICSharpCode.ILSpy @@ -804,7 +813,12 @@ namespace ICSharpCode.ILSpy
public void RefreshDecompiledView()
{
DecompileSelectedNodes();
try {
refreshInProgress = true;
DecompileSelectedNodes();
} finally {
refreshInProgress = false;
}
}
public DecompilerTextView TextView {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save