X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fenum.cs;h=7a025bb6c347e4a2574a788aa94744c8650aa9ec;hb=a299db4b1e987d3a41ec5b561815ff1b29839b76;hp=36d5ab10b9c2eb7c9ce5d35c4923bd14e15b0b1a;hpb=0e3361865d53648229b8700c8d76e6af93f1e062;p=mono.git diff --git a/mcs/mcs/enum.cs b/mcs/mcs/enum.cs index 36d5ab10b9c..7a025bb6c34 100644 --- a/mcs/mcs/enum.cs +++ b/mcs/mcs/enum.cs @@ -5,404 +5,320 @@ // Ravi Pratap (ravi@ximian.com) // Marek Safar (marek.safar@seznam.cz) // -// Licensed under the terms of the GNU GPL +// Dual licensed under the terms of the MIT X11 or GNU GPL // -// (C) 2001 Ximian, Inc (http://www.ximian.com) +// 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.Collections; -using System.Collections.Specialized; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; using System.Reflection; -using System.Reflection.Emit; -using System.Globalization; +#endif namespace Mono.CSharp { - public class EnumMember: MemberCore, IConstant { - static string[] attribute_targets = new string [] { "field" }; - - public FieldBuilder builder; - - readonly Enum parent_enum; - readonly Expression ValueExpr; - readonly EnumMember prev_member; - - Constant value; - bool in_transit; + public class EnumMember : Const + { + class EnumTypeExpr : TypeExpr + { + public override TypeSpec ResolveAsType (IMemberContext ec) + { + type = ec.CurrentType; + eclass = ExprClass.Type; + return type; + } + } - public EnumMember (Enum parent_enum, EnumMember prev_member, Expression expr, - MemberName name, Attributes attrs): - base (parent_enum.Parent, name, attrs) + public EnumMember (Enum parent, MemberName name, Attributes attrs) + : base (parent, new EnumTypeExpr (), Modifiers.PUBLIC, name, attrs) { - this.parent_enum = parent_enum; - this.ModFlags = parent_enum.ModFlags; - this.ValueExpr = expr; - this.prev_member = prev_member; } - public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) + static bool IsValidEnumType (TypeSpec t) { - if (a.Type == TypeManager.marshal_as_attr_type) { - UnmanagedMarshal marshal = a.GetMarshal (this); - if (marshal != null) { - builder.SetMarshal (marshal); - } - return; + 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; } + } - if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) { - a.Error_InvalidSecurityParent (); - return; + public override Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + if (expr is EnumConstant) + expr = ((EnumConstant) expr).Child; + + var underlying = ((Enum) Parent).UnderlyingType; + if (expr != null) { + expr = expr.ImplicitConversionRequired (rc, underlying, Location); + if (expr != null && !IsValidEnumType (expr.Type)) { + Enum.Error_1008 (Location, Report); + expr = null; + } } - builder.SetCustomAttribute (cb); - } + if (expr == null) + expr = New.Constantify (underlying, Location); - public override AttributeTargets AttributeTargets { - get { - return AttributeTargets.Field; - } + return new EnumConstant (expr, MemberType); } - bool IsValidEnumType (Type 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 || - t.IsEnum); - } - public override bool Define () { + if (!ResolveMemberType ()) + return false; + const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; - TypeBuilder tb = parent_enum.TypeBuilder; - builder = tb.DefineField (Name, tb, attr); + FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr); + spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer); - TypeManager.RegisterConstant (builder, this); + Parent.MemberCache.AddMember (spec); return true; } - - public bool ResolveValue () + + public override void Accept (StructuralVisitor visitor) { - if (value != null) - return true; - - if (in_transit) { - // suppress cyclic errors - value = new EnumConstant (New.Constantify (parent_enum.UnderlyingType), parent_enum.TypeBuilder); - Const.Error_CyclicDeclaration (this); - return false; - } - - if (ValueExpr != null) { - in_transit = true; + visitor.Visit (this); + } - Constant c = ValueExpr.ResolveAsConstant (parent_enum.EmitContext, this); - if (c == null) - return false; + } - if (c is EnumConstant) - c = ((EnumConstant)c).Child; - - c = c.ToType (parent_enum.UnderlyingType, Location); - if (c == null) - return false; + /// + /// Enumeration container + /// + public class Enum : TypeDefinition + { + // + // Implicit enum member initializer, used when no constant value is provided + // + sealed class ImplicitInitializer : Expression + { + readonly EnumMember prev; + readonly EnumMember current; - if (!IsValidEnumType (c.Type)) { - Report.Error (1008, Location, "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); - return false; - } + public ImplicitInitializer (EnumMember current, EnumMember prev) + { + this.current = current; + this.prev = prev; + } - in_transit = false; - value = new EnumConstant (c, parent_enum.TypeBuilder); - return true; + public override bool ContainsEmitWithAwait () + { + return false; } - if (prev_member == null) { - value = new EnumConstant (New.Constantify (parent_enum.UnderlyingType), parent_enum.TypeBuilder); - return true; + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); } - if (!prev_member.ResolveValue ()) - return false; + protected override Expression DoResolve (ResolveContext rc) + { + // We are the first member + if (prev == null) { + return New.Constantify (current.Parent.Definition, Location); + } - in_transit = true; + var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant; + try { + 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 ()); - try { - value = prev_member.value.Increment (); - } - catch (OverflowException) { - Report.Error (543, Location, "The enumerator value `{0}' is too large to fit in its type `{1}'", - GetSignatureForError (), TypeManager.CSharpName (parent_enum.UnderlyingType)); - return false; + return New.Constantify (current.Parent.Definition, current.Location); + } } - in_transit = false; - return true; + public override void Emit (EmitContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); + } } - public void Emit (EmitContext ec) - { - if (OptAttributes != null) - OptAttributes.Emit (ec, this); + public static readonly string UnderlyingValueField = "value__"; - if (ResolveValue ()) - builder.SetConstant (value.GetValue ()); + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; - Emit (); - } + readonly FullNamedExpression underlying_type_expr; - public override string GetSignatureForError() + public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, name, attrs, MemberKind.Enum) { - return String.Concat (parent_enum.GetSignatureForError (), '.', Name); + 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 override string[] ValidAttributeTargets { + #region Properties + + public override AttributeTargets AttributeTargets { get { - return attribute_targets; + return AttributeTargets.Enum; } } - protected override bool VerifyClsCompliance(DeclSpace ds) - { - // Because parent is TypeContainer and we have only DeclSpace parent. - // Parameter replacing is required - return base.VerifyClsCompliance (parent_enum); - } - - // There is no base type - protected override void VerifyObsoleteAttribute() - { + public FullNamedExpression BaseTypeExpression { + get { + return underlying_type_expr; + } } - public override string DocCommentHeader { - get { return "F:"; } + protected override TypeAttributes TypeAttr { + get { + return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed; + } } - #region IConstant Members - - public Constant Value { + public TypeSpec UnderlyingType { get { - return value; + return ((EnumSpec) spec).UnderlyingType; } } #endregion - } - /// - /// Enumeration container - /// - public class Enum : DeclSpace { - Expression BaseType; - public Type UnderlyingType; - - static MemberList no_list = new MemberList (new object[0]); - - public const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE; - - public Enum (NamespaceEntry ns, TypeContainer parent, Expression type, - int mod_flags, MemberName name, Attributes attrs) - : base (ns, parent, name, attrs) + public override void Accept (StructuralVisitor visitor) { - this.BaseType = type; - ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, - IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, name.Location); + visitor.Visit (this); } public void AddEnumMember (EnumMember em) { - if (em.Name == "value__") { - Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `value__'"); + if (em.Name == UnderlyingValueField) { + Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'", + UnderlyingValueField); return; } - if (!AddToContainer (em, em.Name)) - return; + AddMember (em); } - - public override TypeBuilder DefineType () - { - if (TypeBuilder != null) - return TypeBuilder; - ec = new EmitContext (this, this, Location, null, null, ModFlags, false); - ec.InEnumContext = true; - - if (!(BaseType is TypeLookupExpression)) { - Report.Error (1008, Location, - "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); - return null; - } - - TypeExpr ute = ResolveBaseTypeExpr (BaseType, false, Location); - UnderlyingType = ute.Type; - - if (UnderlyingType != TypeManager.int32_type && - UnderlyingType != TypeManager.uint32_type && - UnderlyingType != TypeManager.int64_type && - UnderlyingType != TypeManager.uint64_type && - UnderlyingType != TypeManager.short_type && - UnderlyingType != TypeManager.ushort_type && - UnderlyingType != TypeManager.byte_type && - UnderlyingType != TypeManager.sbyte_type) { - Report.Error (1008, Location, - "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); - return null; - } - - if (IsTopLevel) { - if (TypeManager.NamespaceClash (Name, Location)) - return null; - - ModuleBuilder builder = CodeGen.Module.Builder; - - TypeBuilder = builder.DefineType (Name, TypeAttr, TypeManager.enum_type); - } else { - TypeBuilder builder = Parent.TypeBuilder; + public static void Error_1008 (Location loc, Report Report) + { + Report.Error (1008, loc, + "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); + } - TypeBuilder = builder.DefineNestedType ( - Basename, TypeAttr, TypeManager.enum_type); - } + protected override void DoDefineContainer () + { + ((EnumSpec) spec).UnderlyingType = underlying_type_expr == null ? Compiler.BuiltinTypes.Int : underlying_type_expr.Type; - ec.ContainerType = TypeBuilder; + TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (), + FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); - // - // Call MapToInternalType for corlib - // - TypeBuilder.DefineField ("value__", UnderlyingType, - FieldAttributes.Public | FieldAttributes.SpecialName - | FieldAttributes.RTSpecialName); + DefineBaseTypes (); + } - TypeManager.AddUserType (Name, this); + protected override bool DoDefineMembers () + { + 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]); + } - foreach (EnumMember em in defined_names.Values) { - if (!em.Define ()) - return null; + em.Define (); } - return TypeBuilder; - } - - public override bool Define () - { return true; } - public override void Emit () + public override bool IsUnmanagedType () { - if (OptAttributes != null) { - OptAttributes.Emit (ec, this); - } - - foreach (EnumMember em in defined_names.Values) { - em.Emit (ec); - } - - base.Emit (); + return true; } - // - // IMemberFinder - // - public override MemberList FindMembers (MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) { - if ((mt & MemberTypes.Field) == 0) - return no_list; - - EnumMember em = defined_names [criteria] as EnumMember; - if (em == null) - return no_list; - - FieldBuilder[] fb = new FieldBuilder[] { em.builder }; - return new MemberList (fb); + base_type = Compiler.BuiltinTypes.Enum; + base_class = null; + return null; } - void VerifyClsName () - { - HybridDictionary dict = new HybridDictionary (defined_names.Count, true); - foreach (EnumMember em in defined_names.Values) { - if (!em.IsClsCompliaceRequired (this)) - continue; - - try { - dict.Add (em.Name, em); - } - catch (ArgumentException) { - Report.SymbolRelatedToPreviousError (em); - MemberCore col = (MemberCore)dict [em.Name]; - Report.Error (3005, col.Location, "Identifier `{0}' differing only in case is not CLS-compliant", col.GetSignatureForError ()); - } - } - } - - protected override bool VerifyClsCompliance (DeclSpace ds) + protected override bool VerifyClsCompliance () { - if (!base.VerifyClsCompliance (ds)) + if (!base.VerifyClsCompliance ()) return false; - VerifyClsName (); - - if (UnderlyingType == TypeManager.uint32_type || - UnderlyingType == TypeManager.uint64_type || - UnderlyingType == TypeManager.ushort_type) { - Report.Error (3009, 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 (), TypeManager.CSharpName (UnderlyingType)); + break; } return true; - } - + } + } - public override MemberCache MemberCache { - get { - return null; - } + class EnumSpec : TypeSpec + { + TypeSpec underlying; + + public EnumSpec (TypeSpec declaringType, ITypeDefinition definition, TypeSpec underlyingType, MetaType info, Modifiers modifiers) + : base (MemberKind.Enum, declaringType, definition, info, modifiers | Modifiers.SEALED) + { + this.underlying = underlyingType; } - public override AttributeTargets AttributeTargets { + public TypeSpec UnderlyingType { get { - return AttributeTargets.Enum; + return underlying; } - } + set { + if (underlying != null) + throw new InternalErrorException ("UnderlyingType reset"); - protected override TypeAttributes TypeAttr { - get { - return Modifiers.TypeAttr (ModFlags, IsTopLevel) | - TypeAttributes.Class | TypeAttributes.Sealed | - base.TypeAttr; + underlying = value; } } - protected override void VerifyObsoleteAttribute() + public static TypeSpec GetUnderlyingType (TypeSpec t) { - // UnderlyingType is never obsolete + return ((EnumSpec) t.GetDefinition ()).UnderlyingType; } - // - // Generates xml doc comments (if any), and if required, - // handle warning report. - // - internal override void GenerateDocComment (DeclSpace ds) + public static bool IsValidUnderlyingType (TypeSpec type) { - base.GenerateDocComment (ds); - - foreach (EnumMember em in defined_names.Values) { - em.GenerateDocComment (this); + 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; } - } - // - // Represents header string for documentation comment. - // - public override string DocCommentHeader { - get { return "T:"; } + return false; } } }