From 69c764722c080664af7658d3e0e51c09d5a96030 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 26 Nov 2017 12:10:00 +0100 Subject: [PATCH] Fix #989: Local variable naming conflict --- .../ICSharpCode.Decompiler.Tests.csproj | 2 + .../PrettyTestRunner.cs | 16 ++- .../TestCases/Pretty/VariableNaming.cs | 21 ++++ .../TestCases/Pretty/VariableNaming.il | 100 +++++++++++++++++ .../TestCases/Pretty/VariableNaming.opt.il | 96 ++++++++++++++++ .../Pretty/VariableNaming.opt.roslyn.il | 99 +++++++++++++++++ .../TestCases/Pretty/VariableNaming.roslyn.il | 105 ++++++++++++++++++ .../Pretty/VariableNamingWithoutSymbols.cs | 21 ++++ .../Pretty/VariableNamingWithoutSymbols.il | 100 +++++++++++++++++ .../VariableNamingWithoutSymbols.opt.il | 96 ++++++++++++++++ ...VariableNamingWithoutSymbols.opt.roslyn.il | 99 +++++++++++++++++ .../VariableNamingWithoutSymbols.roslyn.il | 105 ++++++++++++++++++ .../CSharp/Transforms/DeclareVariables.cs | 2 +- .../IL/Transforms/AssignVariableNames.cs | 51 ++++++--- 14 files changed, 895 insertions(+), 18 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.roslyn.il diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index be250db40..b4142d548 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -63,6 +63,8 @@ + + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 1c62772e5..30d62d94d 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -212,7 +212,19 @@ namespace ICSharpCode.Decompiler.Tests Run(cscOptions: cscOptions); } - void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None) + [Test] + public void VariableNaming([ValueSource("defaultOptions")] CompilerOptions cscOptions) + { + Run(cscOptions: cscOptions); + } + + [Test] + public void VariableNamingWithoutSymbols([ValueSource("defaultOptions")] CompilerOptions cscOptions) + { + Run(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings { UseDebugSymbols = false }); + } + + void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) { var ilFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il"; var csFile = Path.Combine(TestCasePath, testName + ".cs"); @@ -230,7 +242,7 @@ namespace ICSharpCode.Decompiler.Tests } var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library); - var decompiled = Tester.DecompileCSharp(executable); + var decompiled = Tester.DecompileCSharp(executable, decompilerSettings); CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs new file mode 100644 index 000000000..19ca0c8e1 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs @@ -0,0 +1,21 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal class VariableNaming + { + private class C + { + public string Name; + public string Text; + } + + private void Test(string text, C c) + { + string name = c.Name; + } + + private void Test2(string text, C c) + { + string text2 = c.Text; + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.il new file mode 100644 index 000000000..cad9efae2 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.il @@ -0,0 +1,100 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 sw5i42xa +{ + .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 sw5i42xa.dll +// MVID: {863C0756-F3DB-4C0E-BC40-5DDA3E7F1B18} +.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 +// Image base: 0x02C40000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Name + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNaming::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Text + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNaming::Test2 + + .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 VariableNaming::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\VariableNaming.res diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.il new file mode 100644 index 000000000..b7416f2b6 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.il @@ -0,0 +1,96 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 kt4vyfax +{ + .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 kt4vyfax.dll +// MVID: {2FDC68D5-1FEC-45A6-BADC-43373DBD141E} +.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 +// Image base: 0x05090000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Name + IL_0006: pop + IL_0007: ret + } // end of method VariableNaming::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Text + IL_0006: pop + IL_0007: ret + } // end of method VariableNaming::Test2 + + .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 VariableNaming::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\VariableNaming.opt.res diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.roslyn.il new file mode 100644 index 000000000..0a9636def --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.opt.roslyn.il @@ -0,0 +1,99 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 VariableNaming +{ + .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 VariableNaming.dll +// MVID: {9DEFE92E-9732-41C2-99CE-44CA361163E2} +.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 +// Image base: 0x046D0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Name + IL_0006: pop + IL_0007: ret + } // end of method VariableNaming::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Text + IL_0006: pop + IL_0007: ret + } // end of method VariableNaming::Test2 + + .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 VariableNaming::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.roslyn.il new file mode 100644 index 000000000..b9c171fba --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.roslyn.il @@ -0,0 +1,105 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 VariableNaming +{ + .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 VariableNaming.dll +// MVID: {E0E0C356-381B-487C-973F-FB9568F9D931} +.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 +// Image base: 0x03420000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Name + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNaming::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming/C::Text + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNaming::Test2 + + .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 VariableNaming::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNaming + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs new file mode 100644 index 000000000..9e9654962 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs @@ -0,0 +1,21 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal class VariableNamingWithoutSymbols + { + private class C + { + public string Name; + public string Text; + } + + private void Test(string text, C c) + { + string name = c.Name; + } + + private void Test2(string text, C c) + { + string text2 = c.Text; + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.il new file mode 100644 index 000000000..11981dd60 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.il @@ -0,0 +1,100 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 guxeth2f +{ + .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 guxeth2f.dll +// MVID: {D7E12634-3178-4FDA-B3F4-CE4846CACB94} +.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 +// Image base: 0x04ED0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Name + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNamingWithoutSymbols::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Text + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNamingWithoutSymbols::Test2 + + .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 VariableNamingWithoutSymbols::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\VariableNamingWithoutSymbols.res diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.il new file mode 100644 index 000000000..914f88157 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.il @@ -0,0 +1,96 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 wl1juwwv +{ + .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 wl1juwwv.dll +// MVID: {F60C4045-F949-4857-AE4D-AD0ED806A44F} +.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 +// Image base: 0x03250000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Name + IL_0006: pop + IL_0007: ret + } // end of method VariableNamingWithoutSymbols::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Text + IL_0006: pop + IL_0007: ret + } // end of method VariableNamingWithoutSymbols::Test2 + + .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 VariableNamingWithoutSymbols::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\VariableNamingWithoutSymbols.opt.res diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.roslyn.il new file mode 100644 index 000000000..8423d3d0f --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.opt.roslyn.il @@ -0,0 +1,99 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 VariableNamingWithoutSymbols +{ + .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 VariableNamingWithoutSymbols.dll +// MVID: {6DCCA4EB-C62E-49F5-9C21-5607777AD7D1} +.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 +// Image base: 0x00970000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Name + IL_0006: pop + IL_0007: ret + } // end of method VariableNamingWithoutSymbols::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.2 + IL_0001: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Text + IL_0006: pop + IL_0007: ret + } // end of method VariableNamingWithoutSymbols::Test2 + + .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 VariableNamingWithoutSymbols::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.roslyn.il new file mode 100644 index 000000000..a4d2676cf --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.roslyn.il @@ -0,0 +1,105 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// 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 VariableNamingWithoutSymbols +{ + .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 VariableNamingWithoutSymbols.dll +// MVID: {F6531449-0EBC-4EFD-BFD6-4FF158C836FF} +.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 +// Image base: 0x04C30000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + extends [mscorlib]System.Object +{ + .class auto ansi nested private beforefieldinit C + extends [mscorlib]System.Object + { + .field public string Name + .field public string Text + .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 C::.ctor + + } // end of class C + + .method private hidebysig instance void + Test(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Name + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNamingWithoutSymbols::Test + + .method private hidebysig instance void + Test2(string text, + class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C c) cil managed + { + // Code size 9 (0x9) + .maxstack 1 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.2 + IL_0002: ldfld string ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols/C::Text + IL_0007: stloc.0 + IL_0008: ret + } // end of method VariableNamingWithoutSymbols::Test2 + + .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 VariableNamingWithoutSymbols::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.VariableNamingWithoutSymbols + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 65d3d1034..355447889 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -161,7 +161,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var v = function.RegisterVariable( VariableKind.StackSlot, type, - AssignVariableNames.GenerateVariableName(function, type) + AssignVariableNames.GenerateVariableName(function, type, stmt.Expression.Annotations.OfType().Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault()) ); stmt.Expression = new AssignmentExpression( new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)), diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index 66f66407e..74587e328 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -158,6 +158,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } + /// + /// Must be in sync with . + /// + internal static bool IsSupportedInstruction(object arg) + { + switch (arg) { + case LdObj ldobj: + case LdFlda ldflda: + case LdsFlda ldsflda: + case CallInstruction call: + return true; + default: + return false; + } + } + bool ConflictWithLocal(ILVariable v) { if (v.Kind == VariableKind.UsingLocal || v.Kind == VariableKind.ForeachLocal) { @@ -420,18 +436,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms return variableType; } - internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null) + static Dictionary CollectReservedVariableNames(ILFunction function, ILVariable existingVariable) { - if (function == null) - throw new ArgumentNullException(nameof(function)); var reservedVariableNames = new Dictionary(); var rootFunction = function.Ancestors.OfType().Single(f => f.Parent == null); - foreach (var v in rootFunction.Descendants.OfType().SelectMany(m => m.Variables)) { - if (v != existingVariable) - AddExistingName(reservedVariableNames, v.Name); + foreach (var f in rootFunction.Descendants.OfType()) { + foreach (var p in rootFunction.Parameters) { + AddExistingName(reservedVariableNames, p.Name); + } + foreach (var v in f.Variables.Where(v => v.Kind != VariableKind.Parameter)) { + if (v != existingVariable) + AddExistingName(reservedVariableNames, v.Name); + } } foreach (var f in rootFunction.CecilMethod.DeclaringType.Fields.Select(f => f.Name)) AddExistingName(reservedVariableNames, f); + return reservedVariableNames; + } + + internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null) + { + if (function == null) + throw new ArgumentNullException(nameof(function)); + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable); string baseName = GetNameFromInstruction(valueContext); if (string.IsNullOrEmpty(baseName)) { @@ -467,19 +494,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - internal static string GenerateVariableName(ILFunction function, IType type, ILVariable existingVariable = null) + internal static string GenerateVariableName(ILFunction function, IType type, ILInstruction valueContext = null, ILVariable existingVariable = null) { if (function == null) throw new ArgumentNullException(nameof(function)); - var reservedVariableNames = new Dictionary(); - foreach (var v in function.Descendants.OfType().SelectMany(m => m.Variables)) { - if (v != existingVariable) - AddExistingName(reservedVariableNames, v.Name); - } - foreach (var f in function.CecilMethod.DeclaringType.Fields.Select(f => f.Name)) - AddExistingName(reservedVariableNames, f); + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable); - string baseName = GetNameByType(type); + string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string proposedName = "obj"; if (!string.IsNullOrEmpty(baseName)) {