* DataGrid.cs: remove the XXX'ed check at the top of
[mcs.git] / mcs / enum.cs
blobbb80a71aeb3b48de84855603abd946e6c68e52f4
1 //
2 // enum.cs: Enum handling.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 using System;
14 using System.Collections;
15 using System.Collections.Specialized;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Globalization;
20 namespace Mono.CSharp {
22 public class EnumMember : Const {
23 protected readonly Enum ParentEnum;
24 protected readonly Expression ValueExpr;
25 readonly EnumMember prev_member;
27 public EnumMember (Enum parent, EnumMember prev_member, string name, Expression expr,
28 Attributes attrs, Location loc)
29 : base (parent, new EnumTypeExpr (parent), name, expr, Modifiers.PUBLIC,
30 attrs, loc)
32 this.ParentEnum = parent;
33 this.ValueExpr = expr;
34 this.prev_member = prev_member;
37 protected class EnumTypeExpr : TypeExpr
39 public readonly Enum Enum;
41 public EnumTypeExpr (Enum e)
43 this.Enum = e;
46 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
48 type = Enum.CurrentType != null ? Enum.CurrentType : Enum.TypeBuilder;
49 return this;
52 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
54 return DoResolveAsTypeStep (ec);
57 public override string Name {
58 get { return Enum.Name; }
61 public override string FullName {
62 get { return Enum.Name; }
66 static bool IsValidEnumType (Type t)
68 return (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.int64_type ||
69 t == TypeManager.byte_type || t == TypeManager.sbyte_type || t == TypeManager.short_type ||
70 t == TypeManager.ushort_type || t == TypeManager.uint64_type || t == TypeManager.char_type ||
71 t.IsEnum);
74 public object Value {
75 get { return value.GetValue (); }
78 public override bool Define ()
80 const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
81 FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, attr);
82 TypeManager.RegisterConstant (FieldBuilder, this);
83 return true;
86 protected override Constant DoResolveValue (EmitContext ec)
88 if (ValueExpr != null) {
89 Constant c = ValueExpr.ResolveAsConstant (ec, this);
90 if (c == null)
91 return null;
93 if (c is EnumConstant)
94 c = ((EnumConstant)c).Child;
96 c = c.ImplicitConversionRequired (ParentEnum.UnderlyingType, Location);
97 if (c == null)
98 return null;
100 if (!IsValidEnumType (c.Type)) {
101 Enum.Error_1008 (Location);
102 return null;
105 return new EnumConstant (c, MemberType);
108 if (prev_member == null) {
109 return new EnumConstant (
110 New.Constantify (ParentEnum.UnderlyingType), MemberType);
113 if (!prev_member.ResolveValue ()) {
114 prev_member.value = new EnumConstant (
115 New.Constantify (ParentEnum.UnderlyingType), MemberType);
116 return null;
119 try {
120 return (EnumConstant) prev_member.value.Increment ();
121 } catch (OverflowException) {
122 Report.Error (543, Location, "The enumerator value `{0}' is too " +
123 "large to fit in its type `{1}'", GetSignatureForError (),
124 TypeManager.CSharpName (ParentEnum.UnderlyingType));
125 return null;
130 /// <summary>
131 /// Enumeration container
132 /// </summary>
133 public class Enum : TypeContainer
135 Expression base_type;
137 public Type UnderlyingType;
139 public const int AllowedModifiers =
140 Modifiers.NEW |
141 Modifiers.PUBLIC |
142 Modifiers.PROTECTED |
143 Modifiers.INTERNAL |
144 Modifiers.PRIVATE;
146 public Enum (NamespaceEntry ns, DeclSpace parent, Expression type,
147 int mod_flags, MemberName name, Attributes attrs)
148 : base (ns, parent, name, attrs, Kind.Enum)
150 this.base_type = type;
151 int accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
152 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, accmods, Location);
155 public void AddEnumMember (EnumMember em)
157 if (em.Name == "value__") {
158 Report.Error (76, em.Location, "An item in an enumeration cannot " +
159 "have an identifier `value__'");
160 return;
163 AddConstant (em);
166 public static void Error_1008 (Location loc)
168 Report.Error (1008, loc, "Type byte, sbyte, short, ushort, " +
169 "int, uint, long or ulong expected");
172 protected override bool DefineNestedTypes ()
174 if (!base.DefineNestedTypes ())
175 return false;
177 if (!(base_type is TypeLookupExpression)) {
178 Error_1008 (Location);
179 return false;
182 TypeExpr ute = base_type.ResolveAsTypeTerminal (this, false);
183 UnderlyingType = ute.Type;
185 if (UnderlyingType != TypeManager.int32_type &&
186 UnderlyingType != TypeManager.uint32_type &&
187 UnderlyingType != TypeManager.int64_type &&
188 UnderlyingType != TypeManager.uint64_type &&
189 UnderlyingType != TypeManager.short_type &&
190 UnderlyingType != TypeManager.ushort_type &&
191 UnderlyingType != TypeManager.byte_type &&
192 UnderlyingType != TypeManager.sbyte_type) {
193 Error_1008 (Location);
194 return false;
198 // Call MapToInternalType for corlib
200 TypeBuilder.DefineField ("value__", UnderlyingType,
201 FieldAttributes.Public | FieldAttributes.SpecialName
202 | FieldAttributes.RTSpecialName);
204 return true;
208 // Used for error reporting only
210 public EnumMember GetDefinition (object value)
212 foreach (EnumMember e in defined_names.Values) {
213 if (e.Value.Equals (value))
214 return e;
217 throw new ArgumentOutOfRangeException (value.ToString ());
220 protected override bool VerifyClsCompliance ()
222 if (!base.VerifyClsCompliance ())
223 return false;
225 if (UnderlyingType == TypeManager.uint32_type ||
226 UnderlyingType == TypeManager.uint64_type ||
227 UnderlyingType == TypeManager.ushort_type) {
228 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
231 return true;
234 public override AttributeTargets AttributeTargets {
235 get {
236 return AttributeTargets.Enum;
240 protected override TypeAttributes TypeAttr {
241 get {
242 return Modifiers.TypeAttr (ModFlags, IsTopLevel) |
243 TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr;