From caea72824d53d90e12a109453708135136fdc01c Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Thu, 19 Jun 2025 19:49:24 +0300 Subject: [PATCH] Add an option to not transform `Activator.CreateInstance()` to `new T()` --- .../ICSharpCode.Decompiler.Tests.csproj | 2 + .../NoGenericTypeInstantiation.Expected.cs | 17 ++ .../Ugly/NoGenericTypeInstantiation.cs | 15 ++ .../Ugly/NoGenericTypeInstantiation.il | 108 ++++++++++ ...NoGenericTypeInstantiation.net40.roslyn.il | 186 ++++++++++++++++++ .../Ugly/NoGenericTypeInstantiation.opt.il | 96 +++++++++ ...nericTypeInstantiation.opt.net40.roslyn.il | 167 ++++++++++++++++ .../NoGenericTypeInstantiation.opt.roslyn.il | 79 ++++++++ .../Ugly/NoGenericTypeInstantiation.roslyn.il | 92 +++++++++ .../UglyTestRunner.cs | 6 + .../ReplaceMethodCallsWithOperators.cs | 5 +- ICSharpCode.Decompiler/DecompilerSettings.cs | 23 ++- 12 files changed, 794 insertions(+), 2 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.Expected.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.net40.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.net40.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.roslyn.il diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 1a0d83379..b8c106f95 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -145,6 +145,8 @@ + + diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.Expected.cs new file mode 100644 index 000000000..af805e890 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.Expected.cs @@ -0,0 +1,17 @@ +using System; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly +{ + internal class NoGenericTypeInstantiation where TOnType : new() + { + public static TOnType CreateTOnType() + { + return Activator.CreateInstance(); + } + + public static TOnMethod CreateTOnMethod() where TOnMethod : new() + { + return Activator.CreateInstance(); + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.cs new file mode 100644 index 000000000..06cffa1a7 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.cs @@ -0,0 +1,15 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly +{ + internal class NoGenericTypeInstantiation where TOnType : new() + { + public static TOnType CreateTOnType() + { + return new TOnType(); + } + + public static TOnMethod CreateTOnMethod() where TOnMethod : new() + { + return new TOnMethod(); + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.il new file mode 100644 index 000000000..4f21fa536 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.il @@ -0,0 +1,108 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// 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 tmppi3wbt +{ + .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 tmppi3wbt.tmp +// MVID: {4130db71-37be-40af-9724-d988f7189866} +.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [mscorlib]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 39 (0x27) + .maxstack 1 + .locals init (!TOnType V_0, + !TOnType V_1) + IL_0000: nop + IL_0001: ldloca.s V_1 + IL_0003: initobj !TOnType + IL_0009: ldloc.1 + IL_000a: box !TOnType + IL_000f: brfalse.s IL_001c + + IL_0011: ldloca.s V_1 + IL_0013: initobj !TOnType + IL_0019: ldloc.1 + IL_001a: br.s IL_0021 + + IL_001c: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0021: nop + IL_0022: stloc.0 + IL_0023: br.s IL_0025 + + IL_0025: ldloc.0 + IL_0026: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 39 (0x27) + .maxstack 1 + .locals init (!!TOnMethod V_0, + !!TOnMethod V_1) + IL_0000: nop + IL_0001: ldloca.s V_1 + IL_0003: initobj !!TOnMethod + IL_0009: ldloc.1 + IL_000a: box !!TOnMethod + IL_000f: brfalse.s IL_001c + + IL_0011: ldloca.s V_1 + IL_0013: initobj !!TOnMethod + IL_0019: ldloc.1 + IL_001a: br.s IL_0021 + + IL_001c: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0021: nop + IL_0022: stloc.0 + IL_0023: br.s IL_0025 + + IL_0025: ldloc.0 + IL_0026: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.net40.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.net40.roslyn.il new file mode 100644 index 000000000..99236e576 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.net40.roslyn.il @@ -0,0 +1,186 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// 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 tmphku2gd +{ + .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 tmphku2gd.tmp +// MVID: {1307db53-f6c4-45d3-a995-8cb116ea8821} +.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) +.custom instance void System.Runtime.CompilerServices.RefSafetyRulesAttribute::.ctor(int32) = ( 01 00 0B 00 00 00 00 00 ) +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .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.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method EmbeddedAttribute::.ctor + +} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RefSafetyRulesAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 02 00 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 00 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .field public initonly int32 Version + .method public hidebysig specialname rtspecialname + instance void .ctor(int32 A_1) cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ldarg.0 + IL_0008: ldarg.1 + IL_0009: stfld int32 System.Runtime.CompilerServices.RefSafetyRulesAttribute::Version + IL_000e: ret + } // end of method RefSafetyRulesAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.RefSafetyRulesAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 FF 7F 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 01 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .method public hidebysig specialname rtspecialname + instance void .ctor(string featureName) cil managed + { + // Code size 9 (0x9) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: nop + IL_0008: ret + } // end of method CompilerFeatureRequiredAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + +.class private auto ansi beforefieldinit System.Runtime.CompilerServices.IsExternalInit + extends [mscorlib]System.Object +{ + .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 IsExternalInit::.ctor + +} // end of class System.Runtime.CompilerServices.IsExternalInit + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RequiredMemberAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 8C 01 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 00 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .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.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method RequiredMemberAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.RequiredMemberAttribute + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [mscorlib]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 11 (0xb) + .maxstack 1 + .locals init (!TOnType V_0) + IL_0000: nop + IL_0001: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 11 (0xb) + .maxstack 1 + .locals init (!!TOnMethod V_0) + IL_0000: nop + IL_0001: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.il new file mode 100644 index 000000000..03a347cb7 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.il @@ -0,0 +1,96 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// 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 tmp4sutck +{ + .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 tmp4sutck.tmp +// MVID: {8529154b-7a90-417c-b54f-0d5c900533db} +.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [mscorlib]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 32 (0x20) + .maxstack 1 + .locals init (!TOnType V_0, + !TOnType V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj !TOnType + IL_0008: ldloc.0 + IL_0009: box !TOnType + IL_000e: brfalse.s IL_001a + + IL_0010: ldloca.s V_1 + IL_0012: initobj !TOnType + IL_0018: ldloc.1 + IL_0019: ret + + IL_001a: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_001f: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 32 (0x20) + .maxstack 1 + .locals init (!!TOnMethod V_0, + !!TOnMethod V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj !!TOnMethod + IL_0008: ldloc.0 + IL_0009: box !!TOnMethod + IL_000e: brfalse.s IL_001a + + IL_0010: ldloca.s V_1 + IL_0012: initobj !!TOnMethod + IL_0018: ldloc.1 + IL_0019: ret + + IL_001a: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_001f: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.net40.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.net40.roslyn.il new file mode 100644 index 000000000..61d75dac2 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.net40.roslyn.il @@ -0,0 +1,167 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// 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 tmp2yw4m4 +{ + .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 tmp2yw4m4.tmp +// MVID: {1cd5c846-415a-403b-98cb-2fd0dd281694} +.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) +.custom instance void System.Runtime.CompilerServices.RefSafetyRulesAttribute::.ctor(int32) = ( 01 00 0B 00 00 00 00 00 ) +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .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.Attribute::.ctor() + IL_0006: ret + } // end of method EmbeddedAttribute::.ctor + +} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RefSafetyRulesAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 02 00 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 00 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .field public initonly int32 Version + .method public hidebysig specialname rtspecialname + instance void .ctor(int32 A_1) cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 System.Runtime.CompilerServices.RefSafetyRulesAttribute::Version + IL_000d: ret + } // end of method RefSafetyRulesAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.RefSafetyRulesAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 FF 7F 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 01 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .method public hidebysig specialname rtspecialname + instance void .ctor(string featureName) cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: ret + } // end of method CompilerFeatureRequiredAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + +.class private auto ansi beforefieldinit System.Runtime.CompilerServices.IsExternalInit + extends [mscorlib]System.Object +{ + .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 IsExternalInit::.ctor + +} // end of class System.Runtime.CompilerServices.IsExternalInit + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RequiredMemberAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 8C 01 00 00 02 00 54 02 0D 41 6C 6C 6F 77 // ........T..Allow + 4D 75 6C 74 69 70 6C 65 00 54 02 09 49 6E 68 65 // Multiple.T..Inhe + 72 69 74 65 64 00 ) // rited. + .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.Attribute::.ctor() + IL_0006: ret + } // end of method RequiredMemberAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.RequiredMemberAttribute + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [mscorlib]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 6 (0x6) + .maxstack 8 + IL_0000: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0005: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 6 (0x6) + .maxstack 8 + IL_0000: call !!0 [mscorlib]System.Activator::CreateInstance() + IL_0005: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.roslyn.il new file mode 100644 index 000000000..e28f5c4b6 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.opt.roslyn.il @@ -0,0 +1,79 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// Metadata version: v4.0.30319 +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 8:0:0:0 +} +.assembly tmpbfpzzx +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [System.Runtime]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 [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 ) + + .custom instance void [System.Runtime]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 18 2E 4E 45 54 43 6F 72 65 41 70 70 2C 56 // ....NETCoreApp,V + 65 72 73 69 6F 6E 3D 76 38 2E 30 01 00 54 0E 14 // ersion=v8.0..T.. + 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C 61 79 // FrameworkDisplay + 4E 61 6D 65 00 ) // Name. + .permissionset reqmin + = {[System.Runtime]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}} + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module tmpbfpzzx.tmp +// MVID: {5d4ee8e5-8c47-4519-bd9e-e6d2d3628bfc} +.custom instance void [System.Runtime]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) +.custom instance void [System.Runtime]System.Runtime.CompilerServices.RefSafetyRulesAttribute::.ctor(int32) = ( 01 00 0B 00 00 00 00 00 ) +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [System.Runtime]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 6 (0x6) + .maxstack 8 + IL_0000: call !!0 [System.Runtime]System.Activator::CreateInstance() + IL_0005: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 6 (0x6) + .maxstack 8 + IL_0000: call !!0 [System.Runtime]System.Activator::CreateInstance() + IL_0005: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // end of method NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.roslyn.il new file mode 100644 index 000000000..00886efd5 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoGenericTypeInstantiation.roslyn.il @@ -0,0 +1,92 @@ + +// .NET IL Disassembler. Version 9.0.4 + + + +// Metadata version: v4.0.30319 +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 8:0:0:0 +} +.assembly tmpw4dati +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [System.Runtime]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 [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .custom instance void [System.Runtime]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 18 2E 4E 45 54 43 6F 72 65 41 70 70 2C 56 // ....NETCoreApp,V + 65 72 73 69 6F 6E 3D 76 38 2E 30 01 00 54 0E 14 // ersion=v8.0..T.. + 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C 61 79 // FrameworkDisplay + 4E 61 6D 65 00 ) // Name. + .permissionset reqmin + = {[System.Runtime]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}} + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module tmpw4dati.tmp +// MVID: {901dcf98-cf20-4065-abc3-85086e5af113} +.custom instance void [System.Runtime]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) +.custom instance void [System.Runtime]System.Runtime.CompilerServices.RefSafetyRulesAttribute::.ctor(int32) = ( 01 00 0B 00 00 00 00 00 ) +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1<.ctor TOnType> + extends [System.Runtime]System.Object +{ + .method public hidebysig static !TOnType + CreateTOnType() cil managed + { + // Code size 11 (0xb) + .maxstack 1 + .locals init (!TOnType V_0) + IL_0000: nop + IL_0001: call !!0 [System.Runtime]System.Activator::CreateInstance() + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnType + + .method public hidebysig static !!TOnMethod + CreateTOnMethod<.ctor TOnMethod>() cil managed + { + // Code size 11 (0xb) + .maxstack 1 + .locals init (!!TOnMethod V_0) + IL_0000: nop + IL_0001: call !!0 [System.Runtime]System.Activator::CreateInstance() + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: ret + } // end of method NoGenericTypeInstantiation`1::CreateTOnMethod + + .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 [System.Runtime]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method NoGenericTypeInstantiation`1::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoGenericTypeInstantiation`1 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs index bc60f38c9..0b191cd5f 100644 --- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs @@ -132,6 +132,12 @@ namespace ICSharpCode.Decompiler.Tests }); } + [Test] + public async Task NoGenericTypeInstantiation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1)); + } + async Task RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) { await Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs index 36624535b..85ca13257 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs @@ -128,7 +128,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms break; */ case "System.Activator.CreateInstance": - if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0])) + if (context.Settings.GenericTypeInstantiation && + arguments.Length == 0 && + method.TypeArguments.Count == 1 && + IsInstantiableTypeParameter(method.TypeArguments[0])) { invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First()))); } diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 0ccfec2fa..6a1fd30b8 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -63,6 +63,7 @@ namespace ICSharpCode.Decompiler liftNullables = false; yieldReturn = false; useImplicitMethodGroupConversion = false; + genericTypeInstantiation = false; } if (languageVersion < CSharp.LanguageVersion.CSharp3) { @@ -203,7 +204,7 @@ namespace ICSharpCode.Decompiler if (anonymousTypes || objectCollectionInitializers || automaticProperties || queryExpressions || expressionTrees) return CSharp.LanguageVersion.CSharp3; - if (anonymousMethods || liftNullables || yieldReturn || useImplicitMethodGroupConversion) + if (anonymousMethods || liftNullables || yieldReturn || useImplicitMethodGroupConversion || genericTypeInstantiation) return CSharp.LanguageVersion.CSharp2; return CSharp.LanguageVersion.CSharp1; } @@ -961,6 +962,26 @@ namespace ICSharpCode.Decompiler } } + bool genericTypeInstantiation = true; + + /// + /// Gets/Sets whether to use generic type instantiation for generic types with new() constraint. + /// true: T t = new T(); + /// false: T t = Activator.CreateInstance<T>() + /// + [Category("C# 2.0 / VS 2005")] + [Description("DecompilerSettings.GenericTypeInstantiation")] + public bool GenericTypeInstantiation { + get { return genericTypeInstantiation; } + set { + if (genericTypeInstantiation != value) + { + genericTypeInstantiation = value; + OnPropertyChanged(); + } + } + } + bool alwaysCastTargetsOfExplicitInterfaceImplementationCalls = false; ///