X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fenum.cs;h=22a10381ca0783939d4cdae9568f0991e4cda111;hb=09625a5c5e5f84824d55b38967c982afb0ce075d;hp=c6f613bfadff70ecc972304d77c7c3a8f5f0c36e;hpb=c7cfb1e7236af539cb992e125d29524e60e4d7ea;p=mono.git diff --git a/mcs/gmcs/enum.cs b/mcs/gmcs/enum.cs index c6f613bfadf..22a10381ca0 100755 --- a/mcs/gmcs/enum.cs +++ b/mcs/gmcs/enum.cs @@ -13,9 +13,92 @@ using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; +using System.Globalization; namespace Mono.CSharp { + // Maybe can be usefull to derive from MemberCore + class EnumMember: Attributable { + string name; + Enum parent; + Location loc; + + static string[] attribute_targets = new string [] { "field" }; + + public FieldBuilder builder; + + public EnumMember (string name, Enum parent, Location loc, Attributes attrs): + base (attrs) + { + this.name = name; + this.parent = parent; + this.loc = loc; + } + + public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb) + { + if (a.Type == TypeManager.marshal_as_attr_type) { + UnmanagedMarshal marshal = a.GetMarshal (); + if (marshal != null) { + builder.SetMarshal (marshal); + return; + } + Report.Warning_T (-24, a.Location); + return; + } + + builder.SetCustomAttribute (cb); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Field; + } + } + + public override bool IsClsCompliaceRequired(DeclSpace ds) + { + return parent.IsClsCompliaceRequired (ds); + } + + public void DefineMember (TypeBuilder tb) + { + FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static + | FieldAttributes.Literal; + + builder = tb.DefineField (name, tb, attr); + } + + public void Emit (EmitContext ec) + { + if (OptAttributes != null) + OptAttributes.Emit (ec, this); + } + + // TODO: caching would be usefull + public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec) + { + if (OptAttributes == null) + return null; + + Attribute obsolete_attr = OptAttributes.Search (TypeManager.obsolete_attribute_type, ec); + if (obsolete_attr == null) + return null; + + ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (ec.DeclSpace); + if (obsolete == null) + return null; + + return obsolete; + } + + protected override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + /// /// Enumeration container /// @@ -23,7 +106,6 @@ namespace Mono.CSharp { ArrayList ordered_enums; public Expression BaseType; - public Attributes OptAttributes; public Type UnderlyingType; @@ -42,6 +124,9 @@ namespace Mono.CSharp { ArrayList field_builders; + + Hashtable name_to_member; + public const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | @@ -49,19 +134,21 @@ namespace Mono.CSharp { Modifiers.INTERNAL | Modifiers.PRIVATE; - public Enum (TypeContainer parent, Expression type, int mod_flags, string name, Attributes attrs, Location l) - : base (parent, name, l) + public Enum (NamespaceEntry ns, TypeContainer parent, Expression type, + int mod_flags, MemberName name, Attributes attrs, Location l) + : base (ns, parent, name, attrs, l) { this.BaseType = type; ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, l); - OptAttributes = attrs; ordered_enums = new ArrayList (); member_to_location = new Hashtable (); member_to_value = new Hashtable (); in_transit = new Hashtable (); field_builders = new ArrayList (); + + name_to_member = new Hashtable (); } /// @@ -89,6 +176,8 @@ namespace Mono.CSharp { member_to_attributes.Add (name, opt_attrs); + name_to_member.Add (name, new EnumMember (name, this, loc, opt_attrs)); + return AdditionResult.Success; } @@ -133,6 +222,13 @@ namespace Mono.CSharp { attr |= TypeAttributes.Class | TypeAttributes.Sealed; + if (!(BaseType is TypeLookupExpression)) { + Report.Error (1008, Location, + "Type byte, sbyte, short, ushort, int, uint, " + + "long, or ulong expected (got: `{0}')", BaseType); + return null; + } + UnderlyingType = ResolveType (BaseType, false, Location); if (UnderlyingType != TypeManager.int32_type && @@ -142,10 +238,9 @@ namespace Mono.CSharp { UnderlyingType != TypeManager.short_type && UnderlyingType != TypeManager.ushort_type && UnderlyingType != TypeManager.byte_type && - UnderlyingType != TypeManager.char_type && UnderlyingType != TypeManager.sbyte_type) { Report.Error (1008, Location, - "Type byte, sbyte, short, char, ushort, int, uint, " + + "Type byte, sbyte, short, ushort, int, uint, " + "long, or ulong expected (got: " + TypeManager.CSharpName (UnderlyingType) + ")"); return null; @@ -155,7 +250,7 @@ namespace Mono.CSharp { if (TypeManager.NamespaceClash (Name, Location)) return null; - ModuleBuilder builder = CodeGen.ModuleBuilder; + ModuleBuilder builder = CodeGen.Module.Builder; TypeBuilder = builder.DefineType (Name, attr, TypeManager.enum_type); } else { @@ -502,10 +597,8 @@ namespace Mono.CSharp { } } - FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static - | FieldAttributes.Literal; - - FieldBuilder fb = TypeBuilder.DefineField (name, TypeBuilder, attr); + EnumMember em = name_to_member [name] as EnumMember; + em.DefineMember (TypeBuilder); bool fail; default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail); @@ -514,18 +607,13 @@ namespace Mono.CSharp { return null; } - fb.SetConstant (default_value); - field_builders.Add (fb); + em.builder.SetConstant (default_value); + field_builders.Add (em.builder); member_to_value [name] = default_value; - if (!TypeManager.RegisterFieldValue (fb, default_value)) + if (!TypeManager.RegisterFieldValue (em.builder, default_value)) return null; - // - // Now apply attributes - // - Attribute.ApplyAttributes (ec, fb, fb, (Attributes) member_to_attributes [name]); - return default_value; } @@ -548,9 +636,6 @@ namespace Mono.CSharp { object default_value = 0; - FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static - | FieldAttributes.Literal; - foreach (string name in ordered_enums) { // @@ -572,8 +657,10 @@ namespace Mono.CSharp { return false; } - FieldBuilder fb = TypeBuilder.DefineField ( - name, TypeBuilder, attr); + EnumMember em = name_to_member [name] as EnumMember; + + em.DefineMember (TypeBuilder); + FieldBuilder fb = em.builder; if (default_value == null) { Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " + @@ -594,21 +681,71 @@ namespace Mono.CSharp { if (!TypeManager.RegisterFieldValue (fb, default_value)) return false; - - // - // Apply attributes on the enum member - // - Attribute.ApplyAttributes (ec, fb, fb, (Attributes) member_to_attributes [name]); } default_value = GetNextDefaultValue (default_value); } + + return true; + } - Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes); + public override void Emit (TypeContainer tc) + { + EmitContext ec = new EmitContext (tc, this, Location, null, null, ModFlags, false); + + if (OptAttributes != null) { + OptAttributes.Emit (ec, this); + } + + foreach (EnumMember em in name_to_member.Values) { + em.Emit (ec); + } + + base.Emit (tc); + } + + protected override bool IsIdentifierClsCompliant (DeclSpace ds) + { + if (!base.IsIdentifierClsCompliant (ds)) + return false; + + for (int i = 1; i < ordered_enums.Count; ++i) { + string checked_name = ordered_enums [i] as string; + for (int ii = 0; ii < ordered_enums.Count; ++ii) { + if (ii == i) + continue; + + string enumerator_name = ordered_enums [ii] as string; + if (String.Compare (checked_name, enumerator_name, true, CultureInfo.InvariantCulture) == 0) { + Report.SymbolRelatedToPreviousError ((Location)member_to_location [enumerator_name], enumerator_name); + Report.Error_T (3005, (Location)member_to_location [checked_name], GetEnumeratorName (checked_name)); + break; + } + } + } + return true; + } + + protected override bool VerifyClsCompliance (DeclSpace ds) + { + if (!base.VerifyClsCompliance (ds)) + return false; + + if (!AttributeTester.IsClsCompliant (UnderlyingType)) { + Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (UnderlyingType)); + } return true; } + /// + /// Returns full enum name. + /// + string GetEnumeratorName (string valueName) + { + return String.Concat (Name, ".", valueName); + } + // // IMemberFinder // @@ -650,5 +787,39 @@ namespace Mono.CSharp { return (Expression) defined_names [name]; } } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Enum; + } + } + + protected override void VerifyObsoleteAttribute() + { + // UnderlyingType is never obsolete + } + + /// + /// Returns ObsoleteAttribute for both enum type and enum member + /// + public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec, string identifier) + { + if ((caching_flags & Flags.Obsolete_Undetected) == 0 && (caching_flags & Flags.Obsolete) == 0) { + return null; + } + + ObsoleteAttribute oa = GetObsoleteAttribute (ec.DeclSpace); + if (oa != null) + return oa; + + EnumMember em = (EnumMember)name_to_member [identifier]; + oa = em.GetObsoleteAttribute (ec); + + if (oa == null) + return null; + + caching_flags |= Flags.Obsolete; + return oa; + } } }