[mcs] Correctly import metadata constant with mismatched type and value. Fixes #24675
authorMarek Safar <marek.safar@gmail.com>
Fri, 6 Feb 2015 16:53:05 +0000 (17:53 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 6 Feb 2015 16:54:59 +0000 (17:54 +0100)
mcs/mcs/import.cs
mcs/tests/test-912-lib.il [new file with mode: 0644]
mcs/tests/test-912.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index cc9b68cd5a2ad1ebafcf58da66533e2d0542ab06..98254207136904fa18e8867abc8b3fe401c1cf0e 100644 (file)
@@ -208,7 +208,7 @@ namespace Mono.CSharp
                        if ((fa & FieldAttributes.Literal) != 0) {
                                Constant c = field_type.Kind == MemberKind.MissingType ?
                                        new NullConstant (InternalType.ErrorType, Location.Null) :
-                                       Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null);
+                                       CreateConstantFromValue (field_type, fi);
                                return new ConstSpec (declaringType, definition, field_type, fi, mod, c);
                        }
 
@@ -242,6 +242,25 @@ namespace Mono.CSharp
                        return new FieldSpec (declaringType, definition, field_type, fi, mod);
                }
 
+               Constant CreateConstantFromValue (TypeSpec fieldType, FieldInfo fi)
+               {
+                       var value = fi.GetRawConstantValue ();
+                       //
+                       // Metadata value can be encoded using different constant value type
+                       // than is actual field type
+                       //
+                       // e.g. unsigned int16 CONSTANT = int16 (0x0000ffff)
+                       //
+                       if (value != null && !fieldType.IsEnum) {
+                               var c = ImportConstant (value);
+                               if (c != null) {
+                                       return fieldType == c.Type ? c : c.ConvertExplicitly (false, fieldType);
+                               }
+                       }
+
+                       return Constant.CreateConstantFromValue (fieldType, value, Location.Null);
+               }
+
                public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
                {
                        add.IsAccessor = true;
@@ -531,7 +550,7 @@ namespace Mono.CSharp
                                                        if (value == null) {
                                                                default_value = Constant.CreateConstantFromValue (ptype, null, Location.Null);
                                                        } else {
-                                                               default_value = ImportParameterConstant (value);
+                                                               default_value = ImportConstant (value);
 
                                                                if (ptype.IsEnum) {
                                                                        default_value = new EnumConstant ((Constant) default_value, ptype);
@@ -557,7 +576,7 @@ namespace Mono.CSharp
                                                } else if (value == null) {
                                                        default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
                                                } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
-                                                       default_value = ImportParameterConstant (value);
+                                                       default_value = ImportConstant (value);
                                                }
                                        }
                                }
@@ -1109,7 +1128,7 @@ namespace Mono.CSharp
                                spec.TypeArguments = tparams.ToArray ();
                }
 
-               Constant ImportParameterConstant (object value)
+               Constant ImportConstant (object value)
                {
                        //
                        // Get type of underlying value as int constant can be used for object
diff --git a/mcs/tests/test-912-lib.il b/mcs/tests/test-912-lib.il
new file mode 100644 (file)
index 0000000..be90537
--- /dev/null
@@ -0,0 +1,17 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly 'test-912-lib'
+{
+}
+
+.module 'test-912-lib.dll'
+
+.namespace TypeLib
+{
+  .class public auto ansi abstract Foo extends [mscorlib]System.Object
+  {
+    .field public static literal  unsigned int16 CONSTANT = int16(0x0000ffff)
+  }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-912.cs b/mcs/tests/test-912.cs
new file mode 100644 (file)
index 0000000..3cda7a0
--- /dev/null
@@ -0,0 +1,18 @@
+// Compiler options: -r:test-912-lib.dll
+
+using System;
+using TypeLib;
+
+public class Bar
+{
+       public const ushort FIELD = Foo.CONSTANT;
+
+       public static int Main ()
+       {
+               Console.WriteLine (FIELD);
+               if (FIELD != 65535)
+                       return 1;
+
+               return 0;
+       }
+}
\ No newline at end of file
index c3deae6d6c8d8aa226fbfd7c3195359f2c952d1b..3ab494c30448603887312ea00dbdd69944ef8194 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-912.cs">\r
+    <type name="Bar">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>20</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-92.cs">\r
     <type name="Outer">\r
       <method name="Void .ctor()" attrs="6278">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-anon-173.cs">\r
+    <type name="MainClass">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>36</size>\r
+      </method>\r
+      <method name="Void SomeMethod(System.Action)" attrs="145">\r
+        <size>2</size>\r
+      </method>\r
+      <method name="Void &lt;Main&gt;m__0()" attrs="145">\r
+        <size>36</size>\r
+      </method>\r
+      <method name="Int32 &lt;Main&gt;m__1(Int32)" attrs="145">\r
+        <size>9</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-anon-18.cs">\r
     <type name="A">\r
       <method name="Void Invoke()" attrs="454">\r