From f1f70d0ded7ee2c3c84c11b21c67ac155336082d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 Jul 2018 21:20:48 +0200 Subject: [PATCH] Fix #1148: Do not use hexadecimal display in enums if the value is negative. --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../PrettyTestRunner.cs | 6 ++ .../TestCases/Pretty/TypeTests.cs | 35 ++++++++++ .../TestCases/Pretty/TypeTests.il | 65 +++++++++++++++++ .../TestCases/Pretty/TypeTests.opt.il | 65 +++++++++++++++++ .../TestCases/Pretty/TypeTests.opt.roslyn.il | 69 ++++++++++++++++++ .../TestCases/Pretty/TypeTests.roslyn.il | 70 +++++++++++++++++++ .../CSharp/CSharpDecompiler.cs | 2 +- 8 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.roslyn.il diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index f419e96af..bf4a8ba3a 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -68,6 +68,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 6aa225bca..ac6081054 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -338,6 +338,12 @@ namespace ICSharpCode.Decompiler.Tests RunForLibrary(cscOptions: cscOptions); } + [Test] + public void TypeTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions) + { + RunForLibrary(cscOptions: cscOptions); + } + void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CSharpCompilerOptions cscOptions = CSharpCompilerOptions.None, DecompilerSettings decompilerSettings = null) { Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CSharpCompilerOptions.Library, decompilerSettings); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.cs new file mode 100644 index 000000000..41c3fdef6 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.cs @@ -0,0 +1,35 @@ +// 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; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal class TypeTests + { + [Flags] + public enum NegativeValueWithFlags + { + Value = -2147483647 + } + public enum NegativeValueWithoutFlags + { + Value = -2147483647 + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.il new file mode 100644 index 000000000..6bb34fe36 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.il @@ -0,0 +1,65 @@ + + + + +// 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 TypeTests +{ + .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 TypeTests.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested public NegativeValueWithFlags + extends [mscorlib]System.Enum + { + .custom instance void [mscorlib]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithFlags Value = int32(0x80000001) + } // end of class NegativeValueWithFlags + + .class auto ansi sealed nested public NegativeValueWithoutFlags + extends [mscorlib]System.Enum + { + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithoutFlags Value = int32(0x80000001) + } // end of class NegativeValueWithoutFlags + + .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 TypeTests::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.il new file mode 100644 index 000000000..c954a8d9c --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.il @@ -0,0 +1,65 @@ + + + + +// 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 TypeTests.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 TypeTests.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested public NegativeValueWithFlags + extends [mscorlib]System.Enum + { + .custom instance void [mscorlib]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithFlags Value = int32(0x80000001) + } // end of class NegativeValueWithFlags + + .class auto ansi sealed nested public NegativeValueWithoutFlags + extends [mscorlib]System.Enum + { + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithoutFlags Value = int32(0x80000001) + } // end of class NegativeValueWithoutFlags + + .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 TypeTests::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.roslyn.il new file mode 100644 index 000000000..ab2e421ac --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.opt.roslyn.il @@ -0,0 +1,69 @@ + + + + +// 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 TypeTests +{ + .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 TypeTests.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested public NegativeValueWithFlags + extends [mscorlib]System.Enum + { + .custom instance void [mscorlib]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithFlags Value = int32(0x80000001) + } // end of class NegativeValueWithFlags + + .class auto ansi sealed nested public NegativeValueWithoutFlags + extends [mscorlib]System.Enum + { + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithoutFlags Value = int32(0x80000001) + } // end of class NegativeValueWithoutFlags + + .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 TypeTests::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.roslyn.il new file mode 100644 index 000000000..6d86be30f --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeTests.roslyn.il @@ -0,0 +1,70 @@ + + + + +// 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 TypeTests +{ + .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 TypeTests.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 private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested public NegativeValueWithFlags + extends [mscorlib]System.Enum + { + .custom instance void [mscorlib]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithFlags Value = int32(0x80000001) + } // end of class NegativeValueWithFlags + + .class auto ansi sealed nested public NegativeValueWithoutFlags + extends [mscorlib]System.Enum + { + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests/NegativeValueWithoutFlags Value = int32(0x80000001) + } // end of class NegativeValueWithoutFlags + + .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 TypeTests::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeTests + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 41ef97f9a..c52d56d45 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1170,7 +1170,7 @@ namespace ICSharpCode.Decompiler.CSharp 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 - && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags) + && 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}");