// 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 {
}
public class Const : FieldBase, IConstant {
- Constant value;
+ protected Constant value;
bool in_transit;
+ bool resolved;
bool define_called;
public const int AllowedModifiers =
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;
Type ttype = MemberType;
if (!IsConstantTypeValid (ttype)) {
Error_InvalidConstantType (ttype, Location);
- return false;
}
// If the constant is private then we don't need any field the
//if ((ModFlags & Modifiers.PRIVATE) != 0 && RootContext.Optimize)
// return true;
- while (ttype.IsArray)
- ttype = TypeManager.GetElementType (ttype);
-
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) {
FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, field_attr);
TypeManager.RegisterConstant (FieldBuilder, this);
+ Parent.MemberCache.AddMember (FieldBuilder, this);
- if (ttype == TypeManager.decimal_type)
+ if ((field_attr & FieldAttributes.InitOnly) != 0)
Parent.PartialContainer.RegisterFieldForInitialization (this,
- new FieldInitializer (FieldBuilder, initializer, Parent));
+ new FieldInitializer (FieldBuilder, initializer, this));
return true;
}
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);
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)
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;
+ return null;
- Constant c = value.ConvertImplicitly (MemberType);
+ Constant c = value.ConvertImplicitly (MemberType);
if (c == null) {
- if (!MemberType.IsValueType && MemberType != TypeManager.string_type && !value.IsDefaultValue)
- Error_ConstantCanBeInitializedWithNullOnly (Location, GetSignatureForError ());
+ if (TypeManager.IsReferenceType (MemberType))
+ Error_ConstantCanBeInitializedWithNullOnly (MemberType, Location, GetSignatureForError ());
else
- value.Error_ValueCannotBeConverted (null, Location, MemberType, false);
- return false;
+ value.Error_ValueCannotBeConverted (ec, Location, MemberType, false);
}
- value = c;
- return true;
+ return c;
}
- public Constant CreateConstantReference (Location loc)
+ public virtual Constant CreateConstantReference (Location loc)
{
if (value == null)
return null;
{
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;
public Constant CreateConstantReference (Location loc)
{
- return Constant.CreateConstant (fi.FieldType, value, loc);
+ return Constant.CreateConstant (TypeManager.TypeToCoreType (fi.FieldType), value, loc);
}
#endregion