[Microsoft.Build.Tasks] Fix a net 2.0 failure.
[mono.git] / mcs / mcs / const.cs
index 6b502c04f2b2986eb189a973afd4b72362c157ae..eef90b34603c80175df19f75373cc6c0502e6b62 100644 (file)
@@ -9,31 +9,26 @@
 // Copyright 2003-2008 Novell, Inc.
 //
 
-using System;
+#if STATIC
+using IKVM.Reflection;
+#else
 using System.Reflection;
-using System.Reflection.Emit;
+#endif
 
 namespace Mono.CSharp {
 
        public class Const : FieldBase
        {
-               Constant value;
-
-               public const Modifiers AllowedModifiers =
+               const Modifiers AllowedModifiers =
                        Modifiers.NEW |
                        Modifiers.PUBLIC |
                        Modifiers.PROTECTED |
                        Modifiers.INTERNAL |
                        Modifiers.PRIVATE;
 
-               public Const (DeclSpace parent, FullNamedExpression type, string name,
-                             Expression expr, Modifiers mod_flags, Attributes attrs, Location loc)
-                       : base (parent, type, mod_flags, AllowedModifiers,
-                               new MemberName (name, loc), attrs)
+               public Const (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
+                       : base (parent, type, mod_flags, AllowedModifiers, name, attrs)
                {
-                       if (expr != null)
-                               initializer = new ConstInitializer (this, expr);
-
                        ModFlags |= Modifiers.STATIC;
                }
 
@@ -45,14 +40,13 @@ namespace Mono.CSharp {
                        if (!base.Define ())
                                return false;
 
-                       TypeSpec ttype = MemberType;
-                       if (!ttype.IsConstantCompatible) {
-                               Error_InvalidConstantType (ttype, Location, Report);
+                       if (!member_type.IsConstantCompatible) {
+                               Error_InvalidConstantType (member_type, Location, Report);
                        }
 
                        FieldAttributes field_attr = FieldAttributes.Static | ModifiersExtensions.FieldAttr (ModFlags);
                        // Decimals cannot be emitted into the constant blob.  So, convert to 'readonly'.
-                       if (ttype == TypeManager.decimal_type) {
+                       if (member_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
                                field_attr |= FieldAttributes.InitOnly;
                        } else {
                                field_attr |= FieldAttributes.Literal;
@@ -65,17 +59,26 @@ namespace Mono.CSharp {
 
                        if ((field_attr & FieldAttributes.InitOnly) != 0)
                                Parent.PartialContainer.RegisterFieldForInitialization (this,
-                                       new FieldInitializer (this, initializer, this));
+                                       new FieldInitializer (this, initializer, Location));
+
+                       if (declarators != null) {
+                               var t = new TypeExpression (MemberType, TypeExpression.Location);
+                               foreach (var d in declarators) {
+                                       var c = new Const (Parent, t, ModFlags & ~Modifiers.STATIC, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
+                                       c.initializer = d.Initializer;
+                                       ((ConstInitializer) c.initializer).Name = d.Name.Value;
+                                       c.Define ();
+                                       Parent.PartialContainer.Members.Add (c);
+                               }
+                       }
 
                        return true;
                }
 
-               public Constant DefineValue ()
+               public void DefineValue ()
                {
-                       if (value == null)
-                               value = initializer.Resolve (new ResolveContext (this)) as Constant;
-
-                       return value;
+                       var rc = new ResolveContext (this);
+                       ((ConstSpec) spec).GetConstant (rc);
                }
 
                /// <summary>
@@ -83,44 +86,31 @@ namespace Mono.CSharp {
                /// </summary>
                public override void Emit ()
                {
-                       if (value.Type == TypeManager.decimal_type) {
-                               FieldBuilder.SetCustomAttribute (CreateDecimalConstantAttribute (value));
-                       } else{
-                               FieldBuilder.SetConstant (value.GetTypedValue ());
+                       var c = ((ConstSpec) spec).Value as Constant;
+                       if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
+                               Module.PredefinedAttributes.DecimalConstant.EmitAttribute (FieldBuilder, (decimal) c.GetValue (), c.Location);
+                       } else {
+                               FieldBuilder.SetConstant (c.GetValue ());
                        }
 
                        base.Emit ();
                }
 
-               public static CustomAttributeBuilder CreateDecimalConstantAttribute (Constant c)
-               {
-                       PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant;
-                       if (pa.Constructor == null &&
-                               !pa.ResolveConstructor (c.Location, TypeManager.byte_type, TypeManager.byte_type,
-                                       TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
-                               return null;
-
-                       Decimal d = (Decimal) c.GetValue ();
-                       int [] bits = Decimal.GetBits (d);
-                       object [] args = new object [] { 
-                               (byte) (bits [3] >> 16),
-                               (byte) (bits [3] >> 31),
-                               (uint) bits [2], (uint) bits [1], (uint) bits [0]
-                       };
-
-                       return new CustomAttributeBuilder (pa.Constructor, args);
-               }
-
                public static void Error_InvalidConstantType (TypeSpec t, Location loc, Report Report)
                {
                        if (t.IsGenericParameter) {
                                Report.Error (1959, loc,
-                                       "Type parameter `{0}' cannot be declared const", TypeManager.CSharpName (t));
+                                       "Type parameter `{0}' cannot be declared const", t.GetSignatureForError ());
                        } else {
                                Report.Error (283, loc,
-                                       "The type `{0}' cannot be declared const", TypeManager.CSharpName (t));
+                                       "The type `{0}' cannot be declared const", t.GetSignatureForError ());
                        }
                }
+
+               public override void Accept (StructuralVisitor visitor)
+               {
+                       visitor.Visit (this);
+               }
        }
 
        public class ConstSpec : FieldSpec
@@ -133,30 +123,42 @@ namespace Mono.CSharp {
                        this.value = value;
                }
 
+               //
+               // This expresion is guarantee to be a constant at emit phase only
+               //
                public Expression Value {
                        get {
                                return value;
                        }
-                       private set {
-                               this.value = value;
-                       }
+               }
+
+               //
+               // For compiled constants we have to resolve the value as there could be constant dependecies. This
+               // is needed for imported constants too to get the right context type
+               //
+               public Constant GetConstant (ResolveContext rc)
+               {
+                       if (value.eclass != ExprClass.Value)
+                               value = value.Resolve (rc);
+
+                       return (Constant) value;
                }
        }
 
-       class ConstInitializer : ShimExpression
+       public class ConstInitializer : ShimExpression
        {
                bool in_transit;
-               protected readonly FieldBase field;
+               readonly FieldBase field;
 
-               public ConstInitializer (FieldBase field, Expression value)
+               public ConstInitializer (FieldBase field, Expression value, Location loc)
                        : base (value)
                {
-                       if (value != null)
-                               this.loc = value.Location;
-
+                       this.loc = loc;
                        this.field = field;
                }
 
+               public string Name { get; set; }
+
                protected override Expression DoResolve (ResolveContext unused)
                {
                        if (type != null)
@@ -180,9 +182,9 @@ namespace Mono.CSharp {
                protected virtual Expression DoResolveInitializer (ResolveContext rc)
                {
                        if (in_transit) {
-                               field.Compiler.Report.Error (110, field.Location,
+                               field.Compiler.Report.Error (110, expr.Location,
                                        "The evaluation of the constant value for `{0}' involves a circular definition",
-                                       field.GetSignatureForError ());
+                                       GetSignatureForError ());
 
                                expr = null;
                        } else {
@@ -198,19 +200,19 @@ namespace Mono.CSharp {
                                        c = field.ConvertInitializer (rc, c);
 
                                if (c == null) {
-                                       if (TypeManager.IsReferenceType (field.MemberType))
-                                               Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, loc, field.GetSignatureForError ());
+                                       if (TypeSpec.IsReferenceType (field.MemberType))
+                                               Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, expr.Location, GetSignatureForError ());
                                        else if (!(expr is Constant))
-                                               Error_ExpressionMustBeConstant (rc, field.Location, field.GetSignatureForError ());
+                                               Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ());
                                        else
-                                               expr.Error_ValueCannotBeConverted (rc, loc, field.MemberType, false);
+                                               expr.Error_ValueCannotBeConverted (rc, field.MemberType, false);
                                }
 
                                expr = c;
                        }
 
                        if (expr == null) {
-                               expr = New.Constantify (field.MemberType);
+                               expr = New.Constantify (field.MemberType, Location);
                                if (expr == null)
                                        expr = Constant.CreateConstantFromValue (field.MemberType, null, Location);
                                expr = expr.Resolve (rc);
@@ -218,5 +220,18 @@ namespace Mono.CSharp {
 
                        return expr;
                }
+
+               public override string GetSignatureForError ()
+               {
+                       if (Name == null)
+                               return field.GetSignatureForError ();
+
+                       return field.Parent.GetSignatureForError () + "." + Name;
+               }
+
+               public override object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
        }
 }