{
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 |
// 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 ();
}
/// </summary>
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);
// 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;
}
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;
+ }
+
/// <summary>
/// Emits the field value by evaluating the expression
/// </summary>
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);
}
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 ()
if (value == null)
return false;
- value = value.ToType (MemberType, Location);
+ value = value.ImplicitConversionRequired (MemberType, Location);
if (value == null)
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
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;
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;
}
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