2 // const.cs: Constant declarations.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2001 Ximian, Inc.
12 namespace Mono
.CSharp
{
15 using System
.Reflection
;
16 using System
.Reflection
.Emit
;
17 using System
.Collections
;
19 public interface IConstant
21 void CheckObsoleteness (Location loc
);
23 Constant Value { get; }
26 public class Const
: FieldMember
, IConstant
{
30 public const int AllowedModifiers
=
37 public Const (DeclSpace parent
, Expression constant_type
, string name
,
38 Expression expr
, int mod_flags
, Attributes attrs
, Location loc
)
39 : base (parent
, constant_type
, mod_flags
, AllowedModifiers
,
40 new MemberName (name
, loc
), attrs
)
43 ModFlags
|= Modifiers
.STATIC
;
46 protected override bool CheckBase ()
48 // Constant.Define can be called when the parent type hasn't yet been populated
49 // and it's base types need not have been populated. So, we defer this check
50 // to the second time Define () is called on this member.
51 if (ParentContainer
.BaseCache
== null)
53 return base.CheckBase ();
57 /// Defines the constant in the @parent
59 public override bool Define ()
61 // Make Define () idempotent, but ensure that the error check happens.
62 if (FieldBuilder
!= null)
63 return base.CheckBase ();
68 Type ttype
= MemberType
;
70 ttype
= TypeManager
.GetElementType (ttype
);
72 FieldAttributes field_attr
= FieldAttributes
.Static
| Modifiers
.FieldAttr (ModFlags
);
73 // Decimals cannot be emitted into the constant blob. So, convert to 'readonly'.
74 if (ttype
== TypeManager
.decimal_type
) {
75 field_attr
|= FieldAttributes
.InitOnly
;
76 ParentContainer
.RegisterFieldForInitialization (this);
79 field_attr
|= FieldAttributes
.Literal
;
82 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
, field_attr
);
84 TypeManager
.RegisterConstant (FieldBuilder
, this);
90 /// Emits the field value by evaluating the expression
92 public override void Emit ()
97 if (value.Type
== TypeManager
.decimal_type
) {
98 Decimal d
= ((DecimalConstant
)value).Value
;
99 int[] bits
= Decimal
.GetBits (d
);
100 object[] args
= new object[] { (byte)(bits [3] >> 16), (byte)(bits [3] >> 31), (uint)bits [2], (uint)bits [1], (uint)bits [0] }
;
101 CustomAttributeBuilder cab
= new CustomAttributeBuilder (TypeManager
.decimal_constant_attribute_ctor
, args
);
102 FieldBuilder
.SetCustomAttribute (cab
);
105 FieldBuilder
.SetConstant (value.GetTypedValue ());
111 public static void Error_ExpressionMustBeConstant (Location loc
, string e_name
)
113 Report
.Error (133, loc
, "The expression being assigned to `{0}' must be constant", e_name
);
116 public static void Error_CyclicDeclaration (MemberCore mc
)
118 Report
.Error (110, mc
.Location
, "The evaluation of the constant value for `{0}' involves a circular definition",
119 mc
.GetSignatureForError ());
122 public static void Error_ConstantCanBeInitializedWithNullOnly (Location loc
, string name
)
124 Report
.Error (134, loc
, "`{0}': the constant of reference type other than string can only be initialized with null",
128 #region IConstant Members
130 public bool ResolveValue ()
137 Error_CyclicDeclaration (this);
138 // Suppress cyclic errors
139 value = New
.Constantify (MemberType
);
144 // TODO: IResolveContext here
145 EmitContext ec
= new EmitContext (this, Parent
, Location
, null, MemberType
, ModFlags
);
146 value = initializer
.ResolveAsConstant (ec
, this);
152 value = value.ToType (MemberType
, Location
);
156 if (!MemberType
.IsValueType
&& MemberType
!= TypeManager
.string_type
&& !value.IsDefaultValue
) {
157 Error_ConstantCanBeInitializedWithNullOnly (Location
, GetSignatureForError ());
164 public Constant Value
{
173 public class ExternalConstant
: IConstant
178 public ExternalConstant (FieldInfo fi
)
183 private ExternalConstant (FieldInfo fi
, Constant
value):
190 // Decimal constants cannot be encoded in the constant blob, and thus are marked
191 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
192 // DecimalConstantAttribute metadata.
194 public static IConstant
CreateDecimal (FieldInfo fi
)
196 if (fi
is FieldBuilder
)
199 object[] attrs
= fi
.GetCustomAttributes (TypeManager
.decimal_constant_attribute_type
, false);
200 if (attrs
.Length
!= 1)
203 IConstant ic
= new ExternalConstant (fi
,
204 new DecimalConstant (((System
.Runtime
.CompilerServices
.DecimalConstantAttribute
) attrs
[0]).Value
, Location
.Null
));
209 #region IConstant Members
211 public void CheckObsoleteness (Location loc
)
213 ObsoleteAttribute oa
= AttributeTester
.GetMemberObsoleteAttribute (fi
);
218 AttributeTester
.Report_ObsoleteMessage (oa
, TypeManager
.GetFullNameSignature (fi
), loc
);
221 public bool ResolveValue ()
226 if (fi
.DeclaringType
.IsEnum
) {
227 value = Expression
.Constantify (fi
.GetValue (fi
), TypeManager
.EnumToUnderlying (fi
.FieldType
));
228 value = new EnumConstant (value, fi
.DeclaringType
);
232 value = Expression
.Constantify (fi
.GetValue (fi
), fi
.FieldType
);
236 public Constant Value
{