X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconst.cs;h=1f082adb94bee259b43431e0a123ac1446d66985;hb=209eae257ac9c28f1c8361fd78b2933744dd19af;hp=7422b492b3f23be40c2771edca882855dc315718;hpb=53e266903ec6b2d822cf5b0c566f6374df5307a4;p=mono.git diff --git a/mcs/mcs/const.cs b/mcs/mcs/const.cs index 7422b492b3f..1f082adb94b 100644 --- a/mcs/mcs/const.cs +++ b/mcs/mcs/const.cs @@ -5,8 +5,8 @@ // Miguel de Icaza (miguel@ximian.com) // Marek Safar (marek.safar@seznam.cz) // -// (C) 2001 Ximian, Inc. -// +// Copyright 2001-2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. // namespace Mono.CSharp { @@ -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; + public class Const : FieldBase, IConstant { + protected Constant value; bool in_transit; + bool resolved; bool define_called; public const int AllowedModifiers = @@ -35,9 +36,9 @@ namespace Mono.CSharp { Modifiers.INTERNAL | Modifiers.PRIVATE; - public Const (DeclSpace parent, Expression constant_type, string name, + public Const (DeclSpace parent, FullNamedExpression type, string name, Expression expr, int mod_flags, Attributes attrs, Location loc) - : base (parent, constant_type, mod_flags, AllowedModifiers, + : base (parent, type, mod_flags, AllowedModifiers, new MemberName (name, loc), attrs) { initializer = expr; @@ -73,24 +74,28 @@ namespace Mono.CSharp { Type ttype = MemberType; if (!IsConstantTypeValid (ttype)) { Error_InvalidConstantType (ttype, Location); - return false; } - while (ttype.IsArray) - ttype = TypeManager.GetElementType (ttype); + // If the constant is private then we don't need any field the + // value is already inlined and cannot be referenced + //if ((ModFlags & Modifiers.PRIVATE) != 0 && RootContext.Optimize) + // return true; FieldAttributes field_attr = FieldAttributes.Static | Modifiers.FieldAttr (ModFlags); // Decimals cannot be emitted into the constant blob. So, convert to 'readonly'. if (ttype == TypeManager.decimal_type) { field_attr |= FieldAttributes.InitOnly; - Parent.PartialContainer.RegisterFieldForInitialization (this); } else { field_attr |= FieldAttributes.Literal; } FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, field_attr); - TypeManager.RegisterConstant (FieldBuilder, this); + Parent.MemberCache.AddMember (FieldBuilder, this); + + if ((field_attr & FieldAttributes.InitOnly) != 0) + Parent.PartialContainer.RegisterFieldForInitialization (this, + new FieldInitializer (FieldBuilder, initializer, this)); return true; } @@ -117,20 +122,52 @@ namespace Mono.CSharp { if (!ResolveValue ()) return; + if (FieldBuilder == null) + return; + if (value.Type == TypeManager.decimal_type) { - Decimal d = ((DecimalConstant)value).Value; - 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] }; - CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.decimal_constant_attribute_ctor, args); - FieldBuilder.SetCustomAttribute (cab); - } - else{ + EmitDecimalConstant (); + } else{ FieldBuilder.SetConstant (value.GetTypedValue ()); } base.Emit (); } + void EmitDecimalConstant () + { + ConstructorInfo ctor = TypeManager.decimal_constant_attribute_ctor; + if (ctor == null) { + if (TypeManager.decimal_constant_attribute_type == null) { + TypeManager.decimal_constant_attribute_type = TypeManager.CoreLookupType ( + "System.Runtime.CompilerServices", "DecimalConstantAttribute", Kind.Class, true); + + if (TypeManager.decimal_constant_attribute_type == null) + return; + } + + ctor = TypeManager.GetPredefinedConstructor (TypeManager.decimal_constant_attribute_type, Location, + TypeManager.byte_type, TypeManager.byte_type, + TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type); + + if (ctor == null) + return; + + TypeManager.decimal_constant_attribute_ctor = ctor; + } + + Decimal d = ((DecimalConstant) value).Value; + 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] + }; + + CustomAttributeBuilder cab = new CustomAttributeBuilder (ctor, args); + FieldBuilder.SetCustomAttribute (cab); + } + public static void Error_ExpressionMustBeConstant (Location loc, string e_name) { Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); @@ -142,10 +179,10 @@ namespace Mono.CSharp { mc.GetSignatureForError ()); } - public static void Error_ConstantCanBeInitializedWithNullOnly (Location loc, string name) + public static void Error_ConstantCanBeInitializedWithNullOnly (Type type, Location loc, string name) { - Report.Error (134, loc, "`{0}': the constant of reference type other than string can only be initialized with null", - name); + Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null", + name, TypeManager.CSharpName (type)); } public static void Error_InvalidConstantType (Type t, Location loc) @@ -157,42 +194,53 @@ namespace Mono.CSharp { public bool ResolveValue () { - if (value != null) - return true; + if (resolved) + return value != null; SetMemberIsUsed (); if (in_transit) { Error_CyclicDeclaration (this); // Suppress cyclic errors value = New.Constantify (MemberType); + resolved = true; return false; } in_transit = true; // TODO: IResolveContext here - EmitContext ec = new EmitContext (this, Parent, Location, null, MemberType, ModFlags); - value = initializer.ResolveAsConstant (ec, this); + EmitContext ec = new EmitContext ( + this, Parent, Location, null, MemberType, ModFlags); + ec.InEnumContext = this is EnumMember; + ec.IsAnonymousMethodAllowed = false; + value = DoResolveValue (ec); in_transit = false; + resolved = true; + return value != null; + } + protected virtual Constant DoResolveValue (EmitContext ec) + { + Constant value = initializer.ResolveAsConstant (ec, this); if (value == null) - return false; - - value = value.ImplicitConversionRequired (MemberType, Location); - if (value == null) - return false; + return null; - if (!MemberType.IsValueType && MemberType != TypeManager.string_type && !value.IsDefaultValue) { - Error_ConstantCanBeInitializedWithNullOnly (Location, GetSignatureForError ()); - return false; + Constant c = value.ConvertImplicitly (MemberType); + if (c == null) { + if (TypeManager.IsReferenceType (MemberType)) + Error_ConstantCanBeInitializedWithNullOnly (MemberType, Location, GetSignatureForError ()); + else + value.Error_ValueCannotBeConverted (ec, Location, MemberType, false); } - return true; + return c; } - public Constant Value { - get { - return value; - } + public virtual Constant CreateConstantReference (Location loc) + { + if (value == null) + return null; + + return Constant.CreateConstant (value.Type, value.GetValue(), loc); } #endregion @@ -201,14 +249,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; @@ -223,13 +271,16 @@ namespace Mono.CSharp { { if (fi is FieldBuilder) return null; - + + if (TypeManager.decimal_constant_attribute_type == null) + return null; + object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false); if (attrs.Length != 1) 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; } @@ -251,20 +302,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 (TypeManager.TypeToCoreType (fi.FieldType), value, loc); } #endregion