diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 4af2803c0..50dc56748 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -71,6 +71,8 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
index ce61445ed..16fadeecf 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
@@ -42,6 +42,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Test();
Test(5);
Test(10, "Hello World!");
+
+ Decimal();
+ Decimal(5m);
}
private void Conflicts()
@@ -124,6 +127,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
+ private void Decimal(decimal d = 10m)
+ {
+ }
+
private void OnlyDifferenceIsLastArgument(int a, int b, string c = null)
{
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il
index 5a6e1b7af..cc01fe3db 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il
@@ -76,8 +76,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
- // Code size 43 (0x2b)
- .maxstack 8
+ // Code size 70 (0x46)
+ .maxstack 3
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 10
@@ -97,7 +97,17 @@
IL_0024: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0029: nop
- IL_002a: ret
+ IL_002a: ldarg.0
+ IL_002b: ldc.i4.s 10
+ IL_002d: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_0032: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0037: nop
+ IL_0038: ldarg.0
+ IL_0039: ldc.i4.5
+ IL_003a: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0044: nop
+ IL_0045: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@@ -400,6 +410,22 @@
IL_0001: ret
} // end of method OptionalArguments::Test
+ .method private hidebysig instance void
+ Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ret
+ } // end of method OptionalArguments::Decimal
+
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il
index d15e2c21a..e34d0deb9 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il
@@ -69,8 +69,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
- // Code size 39 (0x27)
- .maxstack 8
+ // Code size 64 (0x40)
+ .maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.s 10
IL_0003: ldstr "Test"
@@ -86,7 +86,15 @@
IL_001c: ldstr "Hello World!"
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
- IL_0026: ret
+ IL_0026: ldarg.0
+ IL_0027: ldc.i4.s 10
+ IL_0029: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_002e: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0033: ldarg.0
+ IL_0034: ldc.i4.5
+ IL_0035: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_003a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_003f: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@@ -358,6 +366,21 @@
IL_0000: ret
} // end of method OptionalArguments::Test
+ .method private hidebysig instance void
+ Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 1 (0x1)
+ .maxstack 8
+ IL_0000: ret
+ } // end of method OptionalArguments::Decimal
+
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il
index c30b296a7..179bc8bff 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il
@@ -73,8 +73,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
- // Code size 39 (0x27)
- .maxstack 8
+ // Code size 64 (0x40)
+ .maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.s 10
IL_0003: ldstr "Test"
@@ -90,7 +90,15 @@
IL_001c: ldstr "Hello World!"
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
- IL_0026: ret
+ IL_0026: ldarg.0
+ IL_0027: ldc.i4.s 10
+ IL_0029: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_002e: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0033: ldarg.0
+ IL_0034: ldc.i4.5
+ IL_0035: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_003a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_003f: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@@ -334,6 +342,21 @@
IL_0000: ret
} // end of method OptionalArguments::Test
+ .method private hidebysig instance void
+ Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 1 (0x1)
+ .maxstack 8
+ IL_0000: ret
+ } // end of method OptionalArguments::Decimal
+
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
@@ -400,15 +423,15 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
- .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002D2C
- .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002D3C
+ .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002DC4
+ .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002DD4
} // end of class ''
// =============================================================
-.data cil I_00002D2C = bytearray (
+.data cil I_00002DC4 = bytearray (
0A 00 00 00 09 00 00 00 08 00 00 00)
-.data cil I_00002D3C = bytearray (
+.data cil I_00002DD4 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il
index ea483f7eb..f8f4f8145 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il
@@ -78,8 +78,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
- // Code size 43 (0x2b)
- .maxstack 8
+ // Code size 70 (0x46)
+ .maxstack 3
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 10
@@ -99,7 +99,17 @@
IL_0024: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0029: nop
- IL_002a: ret
+ IL_002a: ldarg.0
+ IL_002b: ldc.i4.s 10
+ IL_002d: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_0032: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0037: nop
+ IL_0038: ldarg.0
+ IL_0039: ldc.i4.5
+ IL_003a: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
+ IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
+ IL_0044: nop
+ IL_0045: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@@ -375,6 +385,22 @@
IL_0001: ret
} // end of method OptionalArguments::Test
+ .method private hidebysig instance void
+ Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ret
+ } // end of method OptionalArguments::Decimal
+
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
@@ -446,16 +472,15 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
- .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002D58
- .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002D68
+ .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002DF4
+ .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002E04
} // end of class ''
// =============================================================
-.data cil I_00002D58 = bytearray (
+.data cil I_00002DF4 = bytearray (
0A 00 00 00 09 00 00 00 08 00 00 00)
-.data cil I_00002D64 = int8[4]
-.data cil I_00002D68 = bytearray (
+.data cil I_00002E04 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs
new file mode 100644
index 000000000..50c053240
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs
@@ -0,0 +1,14 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
+{
+ public class NoDecimalConstants
+ {
+ [DecimalConstant(1, 0, 0u, 0u, 10u)]
+ private static readonly decimal constant = 1.0m;
+ private void MethodWithOptionalParameter([Optional] [DecimalConstant(1, 0, 0u, 0u, 10u)] decimal parameter)
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.cs
new file mode 100644
index 000000000..a18aea7a8
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.cs
@@ -0,0 +1,31 @@
+// 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.Ugly
+{
+ public class NoDecimalConstants
+ {
+ private const decimal constant = 1.0m;
+
+ private void MethodWithOptionalParameter(decimal parameter = 1.0m)
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.opt.roslyn.il
new file mode 100644
index 000000000..6f97629f2
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.opt.roslyn.il
@@ -0,0 +1,95 @@
+
+
+
+
+// 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 NoDecimalConstants
+{
+ .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 NoDecimalConstants.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 auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
+ extends [mscorlib]System.Object
+{
+ .field private static initonly valuetype [mscorlib]System.Decimal constant
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ .method private hidebysig instance void
+ MethodWithOptionalParameter([opt] valuetype [mscorlib]System.Decimal parameter) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 1 (0x1)
+ .maxstack 8
+ IL_0000: ret
+ } // end of method NoDecimalConstants::MethodWithOptionalParameter
+
+ .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 NoDecimalConstants::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 17 (0x11)
+ .maxstack 8
+ IL_0000: ldc.i4.s 10
+ IL_0002: ldc.i4.0
+ IL_0003: ldc.i4.0
+ IL_0004: ldc.i4.0
+ IL_0005: ldc.i4.1
+ IL_0006: newobj instance void [mscorlib]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+ IL_000b: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants::constant
+ IL_0010: ret
+ } // end of method NoDecimalConstants::.cctor
+
+} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.roslyn.il
new file mode 100644
index 000000000..ea109cfe6
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.roslyn.il
@@ -0,0 +1,97 @@
+
+
+
+
+// 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 NoDecimalConstants
+{
+ .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 NoDecimalConstants.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 auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
+ extends [mscorlib]System.Object
+{
+ .field private static initonly valuetype [mscorlib]System.Decimal constant
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ .method private hidebysig instance void
+ MethodWithOptionalParameter([opt] valuetype [mscorlib]System.Decimal parameter) cil managed
+ {
+ .param [1]
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ uint32,
+ uint32,
+ uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
+ 00 00 )
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ret
+ } // end of method NoDecimalConstants::MethodWithOptionalParameter
+
+ .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 NoDecimalConstants::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 17 (0x11)
+ .maxstack 8
+ IL_0000: ldc.i4.s 10
+ IL_0002: ldc.i4.0
+ IL_0003: ldc.i4.0
+ IL_0004: ldc.i4.0
+ IL_0005: ldc.i4.1
+ IL_0006: newobj instance void [mscorlib]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+ IL_000b: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants::constant
+ IL_0010: ret
+ } // end of method NoDecimalConstants::.cctor
+
+} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
index dd8945797..2469e2555 100644
--- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
+++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
@@ -658,6 +658,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual(4, p.ConstantValue);
}
@@ -670,6 +671,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsFalse(p.HasConstantValueInSignature);
// explicit optional parameter appears in type system if it's read from C#, but not when read from IL
//Assert.AreEqual(1, p.GetAttributes().Count());
}
@@ -682,6 +684,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue);
}
@@ -694,6 +697,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsNull(p.ConstantValue);
}
@@ -706,6 +710,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue);
Assert.AreEqual(typeof(long), p.ConstantValue.GetType());
}
@@ -718,10 +723,24 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue);
Assert.AreEqual(typeof(long), p.ConstantValue.GetType());
}
+ [Test]
+ public void MethodWithOptionalDecimalParameter()
+ {
+ IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalDecimalParameter").Parameters.Single();
+ Assert.IsTrue(p.IsOptional);
+ Assert.IsFalse(p.IsRef);
+ Assert.IsFalse(p.IsOut);
+ Assert.IsFalse(p.IsParams);
+ Assert.IsTrue(p.HasConstantValueInSignature);
+ Assert.AreEqual(1M, p.ConstantValue);
+ Assert.AreEqual(typeof(decimal), p.ConstantValue.GetType());
+ }
+
[Test]
public void VarArgsMethod()
{
diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
index 4a0c50fe5..6c36c9128 100644
--- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
+++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
@@ -162,6 +162,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void MethodWithOptionalNullableParameter(int? x = null) { }
public void MethodWithOptionalLongParameter(long x = 1) { }
public void MethodWithOptionalNullableLongParameter(long? x = 1) { }
+ public void MethodWithOptionalDecimalParameter(decimal x = 1) { }
public void VarArgsMethod(__arglist) { }
}
diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
index b91485a02..30230bda5 100644
--- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
@@ -75,6 +75,14 @@ namespace ICSharpCode.Decompiler.Tests
});
}
+ [Test]
+ public void NoDecimalConstants([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
+ {
+ RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
+ DecimalConstants = false
+ });
+ }
+
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/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
index 8c99c6a33..54a6021dd 100644
--- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
@@ -933,7 +933,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (this.ShowParameterNames) {
decl.Name = parameter.Name;
}
- if (parameter.IsOptional && this.ShowConstantValues) {
+ if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) {
decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue);
}
return decl;
diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs
index 1d8ce6a56..4642290a0 100644
--- a/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs
+++ b/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs
@@ -50,6 +50,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public void Run(AstNode rootNode, TransformContext context)
{
+ if (!context.Settings.DecimalConstants)
+ return;
rootNode.AcceptVisitor(this);
}
}
diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
index 49a4de71d..ef08fa1ac 100644
--- a/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ b/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -221,6 +221,21 @@ namespace ICSharpCode.Decompiler
}
}
+ bool decimalConstants = true;
+
+ ///
+ /// Decompile [DecimalConstant(...)] as simple literal values.
+ ///
+ public bool DecimalConstants {
+ get { return decimalConstants; }
+ set {
+ if (decimalConstants != value) {
+ decimalConstants = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
bool fixedBuffers = true;
///
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 9033f3bac..a284f6442 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -349,6 +349,7 @@
+
diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
index c944ef851..362fd07e5 100644
--- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
@@ -71,11 +71,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Also, some code in the decompiler expects to be able to compare type/member definitions by reference equality,
/// and thus will fail with uncached type systems.
///
- Uncached = 0x10,
+ Uncached = 16,
+ ///
+ /// If this option is active, [DecimalConstantAttribute] is removed and constant values are transformed into simple decimal literals.
+ ///
+ DecimalConstants = 32,
///
/// Default settings: all features enabled.
///
- Default = Dynamic | Tuple | ExtensionMethods
+ Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants
}
///
@@ -95,6 +99,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeSystemOptions |= TypeSystemOptions.Tuple;
if (settings.ExtensionMethods)
typeSystemOptions |= TypeSystemOptions.ExtensionMethods;
+ if (settings.DecimalConstants)
+ typeSystemOptions |= TypeSystemOptions.DecimalConstants;
return typeSystemOptions;
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs
index 06d777f0f..553d8f029 100644
--- a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs
@@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+using System.Runtime.CompilerServices;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem
@@ -48,6 +49,22 @@ namespace ICSharpCode.Decompiler.TypeSystem
///
bool IsOptional { get; }
+ ///
+ /// Gets whether this parameter has a constant value when presented in method signature.
+ ///
+ ///
+ /// This can only be true if the parameter is optional, and it's true for most
+ /// optional parameters. However it is possible to compile a parameter without a default value,
+ /// and some parameters handle their default values in an special way.
+ ///
+ /// For example, does not use normal constants,
+ /// so when is false
+ /// we expose DecimalConstantAttribute directly instead of a constant value.
+ ///
+ /// On the call sites, though, we can still use the value inferred from the attribute.
+ ///
+ bool HasConstantValueInSignature { get; }
+
///
/// Gets the owner of this parameter.
/// May return null; for example when parameters belong to lambdas or anonymous methods.
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
index 055ef5cbc..5e53daafb 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
@@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
case "ExtensionAttribute":
return (options & TypeSystemOptions.ExtensionMethods) != 0;
case "DecimalConstantAttribute":
- return true;
+ return (options & TypeSystemOptions.DecimalConstants) != 0;
default:
return false;
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs
new file mode 100644
index 000000000..b65fdb5ef
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs
@@ -0,0 +1,72 @@
+// Copyright (c) 2018 Daniel Grunwald
+//
+// 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.Reflection.Metadata;
+
+namespace ICSharpCode.Decompiler.TypeSystem.Implementation
+{
+ static class DecimalConstantHelper
+ {
+ public static bool AllowsDecimalConstants(MetadataModule module)
+ {
+ return ((module.TypeSystemOptions & TypeSystemOptions.DecimalConstants) == TypeSystemOptions.DecimalConstants);
+ }
+
+ public static bool IsDecimalConstant(MetadataModule module, CustomAttributeHandleCollection attributeHandles)
+ {
+ return attributeHandles.HasKnownAttribute(module.metadata, KnownAttribute.DecimalConstant);
+ }
+
+ public static object GetDecimalConstantValue(MetadataModule module, CustomAttributeHandleCollection attributeHandles)
+ {
+ var metadata = module.metadata;
+ foreach (var attributeHandle in attributeHandles) {
+ var attribute = metadata.GetCustomAttribute(attributeHandle);
+ if (attribute.IsKnownAttribute(metadata, KnownAttribute.DecimalConstant))
+ return TryDecodeDecimalConstantAttribute(module, attribute);
+ }
+ return null;
+ }
+
+ static decimal? TryDecodeDecimalConstantAttribute(MetadataModule module, System.Reflection.Metadata.CustomAttribute attribute)
+ {
+ var attrValue = attribute.DecodeValue(module.TypeProvider);
+ if (attrValue.FixedArguments.Length != 5)
+ return null;
+ // DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
+ // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
+ if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
+ return null;
+ unchecked {
+ if (attrValue.FixedArguments[2].Value is uint hi
+ && attrValue.FixedArguments[3].Value is uint mid
+ && attrValue.FixedArguments[4].Value is uint lo) {
+ return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
+ }
+ }
+ {
+ if (attrValue.FixedArguments[2].Value is int hi
+ && attrValue.FixedArguments[3].Value is int mid
+ && attrValue.FixedArguments[4].Value is int lo) {
+ return new decimal(lo, mid, hi, sign != 0, scale);
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
index 28d0873d5..7642ad98c 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
@@ -102,6 +102,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return false; }
}
+ public bool HasConstantValueInSignature {
+ get { return IsOptional; }
+ }
+
public object ConstantValue {
get { return defaultValue; }
}
@@ -123,7 +127,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Append(parameter.Name);
b.Append(':');
b.Append(parameter.Type.ReflectionName);
- if (parameter.IsOptional) {
+ if (parameter.IsOptional && parameter.HasConstantValueInSignature) {
b.Append(" = ");
if (parameter.ConstantValue != null)
b.Append(parameter.ConstantValue.ToString());
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
index cc3e9ac79..d345d472f 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
@@ -78,6 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
ParamArray,
In,
Out,
+ Optional,
CallerMemberName,
CallerFilePath,
CallerLineNumber,
@@ -133,6 +134,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(InAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OutAttribute)),
+ new TopLevelTypeName("System.Runtime.InteropServices", nameof(OptionalAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerMemberNameAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerFilePathAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerLineNumberAttribute)),
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
index d7c942730..ac1aa6c3f 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
@@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
object constantValue;
IType type;
bool isVolatile; // initialized together with this.type
- byte decimalConstant; // 0=no, 1=yes, 2=unknown
+ bool? isDecimalConstant;
internal MetadataField(MetadataModule module, FieldDefinitionHandle handle)
{
@@ -52,8 +52,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.handle = handle;
var def = module.metadata.GetFieldDefinition(handle);
this.attributes = def.Attributes;
- if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) == (FieldAttributes.Static | FieldAttributes.InitOnly)) {
- decimalConstant = 2; // may be decimal constant
+
+ if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) != (FieldAttributes.Static | FieldAttributes.InitOnly)) {
+ isDecimalConstant = false;
}
}
@@ -187,19 +188,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return LazyInit.GetOrSet(ref this.type, ty);
}
- public bool IsConst => (attributes & FieldAttributes.Literal) != 0 || IsDecimalConstant;
+ public bool IsConst => (attributes & FieldAttributes.Literal) != 0
+ || (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module));
bool IsDecimalConstant {
get {
- if (decimalConstant == 2) {
- var metadata = module.metadata;
- var fieldDef = metadata.GetFieldDefinition(handle);
- if (fieldDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.DecimalConstant))
- decimalConstant = 1;
- else
- decimalConstant = 0;
+ if (isDecimalConstant == null) {
+ var fieldDef = module.metadata.GetFieldDefinition(handle);
+ isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, fieldDef.GetCustomAttributes());
}
- return decimalConstant == 1;
+ return (bool)isDecimalConstant;
}
}
@@ -210,13 +208,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return val;
var metadata = module.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
- if (IsDecimalConstant) {
- foreach (var attrHandle in fieldDef.GetCustomAttributes()) {
- var attribute = metadata.GetCustomAttribute(attrHandle);
- if (attribute.IsKnownAttribute(metadata, KnownAttribute.DecimalConstant)) {
- val = TryDecodeDecimalConstantAttribute(attribute);
- }
- }
+ if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) {
+ val = DecimalConstantHelper.GetDecimalConstantValue(module, fieldDef.GetCustomAttributes());
} else {
var constantHandle = fieldDef.GetDefaultValue();
if (constantHandle.IsNil)
@@ -229,32 +222,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
- decimal? TryDecodeDecimalConstantAttribute(System.Reflection.Metadata.CustomAttribute attribute)
- {
- var attrValue = attribute.DecodeValue(module.TypeProvider);
- if (attrValue.FixedArguments.Length != 5)
- return null;
- // DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
- // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
- if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
- return null;
- unchecked {
- if (attrValue.FixedArguments[2].Value is uint hi
- && attrValue.FixedArguments[3].Value is uint mid
- && attrValue.FixedArguments[4].Value is uint lo) {
- return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
- }
- }
- {
- if (attrValue.FixedArguments[2].Value is int hi
- && attrValue.FixedArguments[3].Value is int mid
- && attrValue.FixedArguments[4].Value is int lo) {
- return new decimal(lo, mid, hi, sign != 0, scale);
- }
- }
- return null;
- }
-
public override bool Equals(object obj)
{
if (obj is MetadataField f) {
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
index 1dad96af7..426e238d0 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
@@ -37,6 +37,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded:
string name;
+ bool? hasConstantValueInSignature;
+ bool? isDecimalConstant;
internal MetadataParameter(MetadataModule module, IParameterizedMember owner, IType type, ParameterHandle handle)
{
@@ -47,6 +49,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var param = module.metadata.GetParameter(handle);
this.attributes = param.Attributes;
+ if (!IsOptional)
+ isDecimalConstant = false; // only optional parameters can be constants
}
public EntityHandle MetadataToken => handle;
@@ -58,6 +62,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = module.metadata;
var parameter = metadata.GetParameter(handle);
+ if (IsOptional && !HasConstantValueInSignature)
+ b.Add(KnownAttribute.Optional);
+
if (!IsOut) {
if ((attributes & ParameterAttributes.In) == ParameterAttributes.In)
b.Add(KnownAttribute.In);
@@ -102,16 +109,44 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public object ConstantValue {
get {
var metadata = module.metadata;
- var propertyDef = metadata.GetParameter(handle);
- var constantHandle = propertyDef.GetDefaultValue();
+ var parameterDef = metadata.GetParameter(handle);
+ if (IsDecimalConstant)
+ return DecimalConstantHelper.GetDecimalConstantValue(module, parameterDef.GetCustomAttributes());
+
+ var constantHandle = parameterDef.GetDefaultValue();
if (constantHandle.IsNil)
return null;
+
var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value);
return blobReader.ReadConstant(constant.TypeCode);
}
}
+ public bool HasConstantValueInSignature {
+ get {
+ if (hasConstantValueInSignature == null) {
+ if (IsDecimalConstant) {
+ hasConstantValueInSignature = DecimalConstantHelper.AllowsDecimalConstants(module);
+ }
+ else {
+ hasConstantValueInSignature = !module.metadata.GetParameter(handle).GetDefaultValue().IsNil;
+ }
+ }
+ return (bool)hasConstantValueInSignature;
+ }
+ }
+
+ bool IsDecimalConstant {
+ get {
+ if (isDecimalConstant == null) {
+ var parameterDef = module.metadata.GetParameter(handle);
+ isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, parameterDef.GetCustomAttributes());
+ }
+ return (bool)isDecimalConstant;
+ }
+ }
+
SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter;
public override string ToString()
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
index bca6f3075..bd34dbe92 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
@@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IParameter.IsOut => baseParameter.IsOut;
bool IParameter.IsParams => baseParameter.IsParams;
bool IParameter.IsOptional => baseParameter.IsOptional;
+ bool IParameter.HasConstantValueInSignature => baseParameter.HasConstantValueInSignature;
IParameterizedMember IParameter.Owner => newOwner;
string IVariable.Name => baseParameter.Name;
string ISymbol.Name => baseParameter.Name;