X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconst.cs;h=b947e4d68f5485ee6552e1e4abb33d32d71d8459;hb=43b6678d45b2cf3705971998e1f04f67ef4d7667;hp=3282d6f24bf7ac4517b973687025af49294a0da7;hpb=7efb90a210ca6ea8839ad2572734cfbfe2b7d802;p=mono.git diff --git a/mcs/mcs/const.cs b/mcs/mcs/const.cs index 3282d6f24bf..b947e4d68f5 100644 --- a/mcs/mcs/const.cs +++ b/mcs/mcs/const.cs @@ -20,12 +20,13 @@ namespace Mono.CSharp { { void CheckObsoleteness (Location loc); bool ResolveValue (); - Constant Value { get; } + Constant CreateConstantReference (Location loc); } public class Const : FieldMember, IConstant { Constant value; bool in_transit; + bool define_called; public const int AllowedModifiers = Modifiers.NEW | @@ -48,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 (ParentContainer.BaseCache == null) + if (Parent.PartialContainer.BaseCache == null) return true; return base.CheckBase (); } @@ -58,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); @@ -73,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; - ParentContainer.RegisterFieldForInitialization (this); - } - else { + Parent.PartialContainer.RegisterFieldForInitialization (this); + } else { field_attr |= FieldAttributes.Literal; } @@ -85,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 /// @@ -108,13 +131,8 @@ namespace Mono.CSharp { base.Emit (); } - public static void Error_ExpressionMustBeConstant (Type constantType, Location loc, string e_name) + public static void Error_ExpressionMustBeConstant (Location loc, string e_name) { - if (constantType != null && TypeManager.IsValueType (constantType) && - !TypeManager.IsBuiltinOrEnum (constantType)) { - Report.Error (283, loc, "The type `{0}' cannot be declared const", TypeManager.CSharpName (constantType)); - return; - } Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); } @@ -130,6 +148,11 @@ namespace Mono.CSharp { 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 () @@ -154,7 +177,7 @@ namespace Mono.CSharp { if (value == null) return false; - value = value.ToType (MemberType, Location); + value = value.ImplicitConversionRequired (MemberType, Location); if (value == null) return false; @@ -166,10 +189,12 @@ namespace Mono.CSharp { 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 @@ -178,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; @@ -206,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; } @@ -228,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