X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconst.cs;h=b947e4d68f5485ee6552e1e4abb33d32d71d8459;hb=43b6678d45b2cf3705971998e1f04f67ef4d7667;hp=b094d580e51fdae7dd4292db088690e8f80c595b;hpb=7e18ed47c9606f3981e7b18cbc238d6781843153;p=mono.git diff --git a/mcs/mcs/const.cs b/mcs/mcs/const.cs index b094d580e51..b947e4d68f5 100644 --- a/mcs/mcs/const.cs +++ b/mcs/mcs/const.cs @@ -20,13 +20,13 @@ namespace Mono.CSharp { { void CheckObsoleteness (Location loc); bool ResolveValue (); - Constant Value { get; } + Constant CreateConstantReference (Location loc); } public class Const : FieldMember, IConstant { - Expression Expr; Constant value; bool in_transit; + bool define_called; public const int AllowedModifiers = Modifiers.NEW | @@ -35,12 +35,12 @@ namespace Mono.CSharp { Modifiers.INTERNAL | Modifiers.PRIVATE; - public Const (TypeContainer parent, Expression constant_type, string name, + public Const (DeclSpace parent, Expression constant_type, string name, Expression expr, int mod_flags, Attributes attrs, Location loc) : base (parent, constant_type, mod_flags, AllowedModifiers, - new MemberName (name, loc), expr, attrs) + new MemberName (name, loc), attrs) { - Expr = expr; + initializer = expr; ModFlags |= Modifiers.STATIC; } @@ -49,7 +49,7 @@ namespace Mono.CSharp { // Constant.Define can be called when the parent type hasn't yet been populated // and it's base types need not have been populated. So, we defer this check // to the second time Define () is called on this member. - if (Parent.BaseCache == null) + if (Parent.PartialContainer.BaseCache == null) return true; return base.CheckBase (); } @@ -59,14 +59,23 @@ namespace Mono.CSharp { /// public override bool Define () { - // Make Define () idempotent, but ensure that the error check happens. - if (FieldBuilder != null) - return base.CheckBase (); + // Because constant define can be called from other class + if (define_called) { + CheckBase (); + return FieldBuilder != null; + } + + define_called = true; if (!base.Define ()) return false; Type ttype = MemberType; + if (!IsConstantTypeValid (ttype)) { + Error_InvalidConstantType (ttype, Location); + return false; + } + while (ttype.IsArray) ttype = TypeManager.GetElementType (ttype); @@ -74,9 +83,8 @@ namespace Mono.CSharp { // Decimals cannot be emitted into the constant blob. So, convert to 'readonly'. if (ttype == TypeManager.decimal_type) { field_attr |= FieldAttributes.InitOnly; - Parent.RegisterFieldForInitialization (this); - } - else { + Parent.PartialContainer.RegisterFieldForInitialization (this); + } else { field_attr |= FieldAttributes.Literal; } @@ -86,7 +94,21 @@ namespace Mono.CSharp { return true; } - + + public static bool IsConstantTypeValid (Type t) + { + if (TypeManager.IsBuiltinOrEnum (t)) + return true; + + if (t.IsPointer || t.IsValueType) + return false; + + if (TypeManager.IsGenericParameter (t)) + return false; + + return true; + } + /// /// Emits the field value by evaluating the expression /// @@ -120,6 +142,17 @@ namespace Mono.CSharp { mc.GetSignatureForError ()); } + public static void Error_ConstantCanBeInitializedWithNullOnly (Location loc, string name) + { + Report.Error (134, loc, "`{0}': the constant of reference type other than string can only be initialized with null", + name); + } + + public static void Error_InvalidConstantType (Type t, Location loc) + { + Report.Error (283, loc, "The type `{0}' cannot be declared const", TypeManager.CSharpName (t)); + } + #region IConstant Members public bool ResolveValue () @@ -136,30 +169,32 @@ namespace Mono.CSharp { } in_transit = true; - EmitContext ec = new EmitContext (Parent, Location, null, MemberType, ModFlags); - value = Expr.ResolveAsConstant (ec, this); + // TODO: IResolveContext here + EmitContext ec = new EmitContext (this, Parent, Location, null, MemberType, ModFlags); + value = initializer.ResolveAsConstant (ec, this); in_transit = false; if (value == null) return false; - value = value.ToType (MemberType, Location); + value = value.ImplicitConversionRequired (MemberType, Location); if (value == null) return false; if (!MemberType.IsValueType && MemberType != TypeManager.string_type && !value.IsDefaultValue) { - Report.Error (134, Location, "`{0}': A const of reference other than string can only be initialized with null", - GetSignatureForError ()); + Error_ConstantCanBeInitializedWithNullOnly (Location, GetSignatureForError ()); return false; } return true; } - public Constant Value { - get { - return value; - } + public Constant CreateConstantReference (Location loc) + { + if (value == null) + return null; + + return Constant.CreateConstant (value.Type, value.GetValue(), loc); } #endregion @@ -168,14 +203,14 @@ namespace Mono.CSharp { public class ExternalConstant : IConstant { FieldInfo fi; - Constant value; + object value; public ExternalConstant (FieldInfo fi) { this.fi = fi; } - private ExternalConstant (FieldInfo fi, Constant value): + private ExternalConstant (FieldInfo fi, object value): this (fi) { this.value = value; @@ -196,7 +231,7 @@ namespace Mono.CSharp { return null; IConstant ic = new ExternalConstant (fi, - new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value, Location.Null)); + ((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value); return ic; } @@ -218,20 +253,13 @@ namespace Mono.CSharp { if (value != null) return true; - if (fi.DeclaringType.IsEnum) { - value = Expression.Constantify (fi.GetValue (fi), TypeManager.EnumToUnderlying (fi.FieldType)); - value = new EnumConstant (value, fi.DeclaringType); - return true; - } - - value = Expression.Constantify (fi.GetValue (fi), fi.FieldType); + value = fi.GetValue (fi); return true; } - public Constant Value { - get { - return value; - } + public Constant CreateConstantReference (Location loc) + { + return Constant.CreateConstant (fi.FieldType, value, loc); } #endregion