//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2003 Novell, Inc (http://www.novell.com)
+// Copyright 2011 Xamarin Inc
//
using System;
using System.Reflection;
#endif
-namespace Mono.CSharp {
+namespace Mono.CSharp
+{
public class EnumMember : Const
{
- class EnumTypeExpr : TypeExpr
+#if !STATIC
+ class MemberTypeDelegator : TypeDelegator
{
- protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
+ Type underlyingType;
+
+ public MemberTypeDelegator (Type delegatingType, Type underlyingType)
+ : base (delegatingType)
{
- type = ec.CurrentType;
- return this;
+ this.underlyingType = underlyingType;
+ }
+
+ public override Type GetEnumUnderlyingType ()
+ {
+ return underlyingType;
}
- public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
+ public override Type UnderlyingSystemType {
+ get {
+ return underlyingType;
+ }
+ }
+ }
+#endif
+
+ class EnumTypeExpr : TypeExpr
+ {
+ public override TypeSpec ResolveAsType (IMemberContext ec, bool allowUnboundTypeArguments)
{
- return DoResolveAsTypeStep (ec);
+ type = ec.CurrentType;
+ eclass = ExprClass.Type;
+ return type;
}
}
static bool IsValidEnumType (TypeSpec t)
{
- return (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.int64_type ||
- t == TypeManager.byte_type || t == TypeManager.sbyte_type || t == TypeManager.short_type ||
- t == TypeManager.ushort_type || t == TypeManager.uint64_type || t == TypeManager.char_type ||
- TypeManager.IsEnumType (t));
+ switch (t.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Char:
+ return true;
+ default:
+ return t.IsEnum;
+ }
}
public override Constant ConvertInitializer (ResolveContext rc, Constant expr)
if (expr is EnumConstant)
expr = ((EnumConstant) expr).Child;
- var underlying = ((Enum) Parent).UnderlyingType;
+ var en = (Enum)Parent;
+ var underlying = en.UnderlyingType;
if (expr != null) {
- expr = expr.ImplicitConversionRequired (rc, underlying, Location);
+ expr = expr.ImplicitConversionRequired (rc, underlying);
if (expr != null && !IsValidEnumType (expr.Type)) {
- Enum.Error_1008 (Location, Report);
+ en.Error_UnderlyingType (Location);
expr = null;
}
}
if (expr == null)
expr = New.Constantify (underlying, Location);
- return new EnumConstant (expr, MemberType).Resolve (rc);
+ return new EnumConstant (expr, MemberType);
}
public override bool Define ()
if (!ResolveMemberType ())
return false;
+ MetaType ftype = MemberType.GetMetaInfo ();
+#if !STATIC
+ //
+ // Workaround for .net SRE limitation which cannot define field of unbaked enum type
+ // which is how all enums are declared
+ //
+ ftype = new MemberTypeDelegator (ftype, ((Enum)Parent).UnderlyingType.GetMetaInfo ());
+#endif
+
const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
- FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr);
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name, ftype, attr);
spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer);
Parent.MemberCache.AddMember (spec);
return true;
}
+
+ public override void Accept (StructuralVisitor visitor)
+ {
+ visitor.Visit (this);
+ }
+
}
/// <summary>
/// Enumeration container
/// </summary>
- public class Enum : TypeContainer
+ public class Enum : TypeDefinition
{
//
// Implicit enum member initializer, used when no constant value is provided
//
- class ImplicitInitializer : Expression
+ sealed class ImplicitInitializer : Expression
{
readonly EnumMember prev;
readonly EnumMember current;
this.prev = prev;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return false;
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotSupportedException ("Missing Resolve call");
{
// We are the first member
if (prev == null) {
- return New.Constantify (current.Parent.Definition, Location).Resolve (rc);
+ return New.Constantify (current.Parent.Definition, Location);
}
var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant;
try {
- return c.Increment ().Resolve (rc);
+ return c.Increment ();
} catch (OverflowException) {
rc.Report.Error (543, current.Location,
"The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'",
current.GetSignatureForError (), ((Enum) current.Parent).UnderlyingType.GetSignatureForError ());
- return New.Constantify (current.Parent.Definition, current.Location).Resolve (rc);
+ return New.Constantify (current.Parent.Definition, current.Location);
}
}
Modifiers.INTERNAL |
Modifiers.PRIVATE;
- public Enum (NamespaceEntry ns, DeclSpace parent, TypeExpression type,
- Modifiers mod_flags, MemberName name, Attributes attrs)
- : base (ns, parent, name, attrs, MemberKind.Enum)
+ readonly FullNamedExpression underlying_type_expr;
+
+ public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
+ : base (parent, name, attrs, MemberKind.Enum)
{
- base_type_expr = type;
+ underlying_type_expr = type;
var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report);
spec = new EnumSpec (null, this, null, null, ModFlags);
}
}
- public TypeExpr BaseTypeExpression {
+ public FullNamedExpression BaseTypeExpression {
get {
- return base_type_expr;
+ return underlying_type_expr;
}
}
protected override TypeAttributes TypeAttr {
get {
- return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) |
- TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr;
+ return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed;
}
}
#endregion
+ public override void Accept (StructuralVisitor visitor)
+ {
+ visitor.Visit (this);
+ }
+
public void AddEnumMember (EnumMember em)
{
if (em.Name == UnderlyingValueField) {
return;
}
- AddConstant (em);
+ AddMember (em);
}
- public static void Error_1008 (Location loc, Report Report)
+ public void Error_UnderlyingType (Location loc)
{
Report.Error (1008, loc,
"Type byte, sbyte, short, ushort, int, uint, long or ulong expected");
}
- protected override bool DefineNestedTypes ()
+ protected override void DoDefineContainer ()
{
- ((EnumSpec) spec).UnderlyingType = base_type_expr == null ? TypeManager.int32_type : base_type_expr.Type;
+ TypeSpec ut;
+ if (underlying_type_expr != null) {
+ ut = underlying_type_expr.ResolveAsType (this);
+ if (!EnumSpec.IsValidUnderlyingType (ut)) {
+ Error_UnderlyingType (underlying_type_expr.Location);
+ ut = null;
+ }
+ } else {
+ ut = null;
+ }
+
+ if (ut == null)
+ ut = Compiler.BuiltinTypes.Int;
+
+ ((EnumSpec) spec).UnderlyingType = ut;
TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (),
FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
- return true;
+ DefineBaseTypes ();
}
protected override bool DoDefineMembers ()
{
- if (constants != null) {
- for (int i = 0; i < constants.Count; ++i) {
- EnumMember em = (EnumMember) constants [i];
- if (em.Initializer == null) {
- em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) constants[i - 1]);
- }
-
- em.Define ();
+ for (int i = 0; i < Members.Count; ++i) {
+ EnumMember em = (EnumMember) Members[i];
+ if (em.Initializer == null) {
+ em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) Members[i - 1]);
}
+
+ em.Define ();
}
return true;
return true;
}
- protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
+ protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
{
- base_type = TypeManager.enum_type;
- base_class = base_type_expr;
+ base_type = Compiler.BuiltinTypes.Enum;
+ base_class = null;
return null;
}
if (!base.VerifyClsCompliance ())
return false;
- if (UnderlyingType == TypeManager.uint32_type ||
- UnderlyingType == TypeManager.uint64_type ||
- UnderlyingType == TypeManager.ushort_type) {
- Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
+ switch (UnderlyingType.BuiltinType) {
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.UShort:
+ Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
+ GetSignatureForError (), UnderlyingType.GetSignatureForError ());
+ break;
}
return true;
{
return ((EnumSpec) t.GetDefinition ()).UnderlyingType;
}
+
+ public static bool IsValidUnderlyingType (TypeSpec type)
+ {
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.ULong:
+ return true;
+ }
+
+ return false;
+ }
}
}