2009-09-04 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / mcs / enum.cs
blob451761eee0dc5fd4167dc5e52f5ac70d03ca4c62
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 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2003 Novell, Inc (http://www.novell.com)
14 using System;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Globalization;
21 namespace Mono.CSharp {
23 public class EnumMember : Const {
24 protected readonly Enum ParentEnum;
25 protected readonly Expression ValueExpr;
26 readonly EnumMember prev_member;
28 public EnumMember (Enum parent, EnumMember prev_member, string name, Expression expr,
29 Attributes attrs, Location loc)
30 : base (parent, new EnumTypeExpr (parent), name, expr, Modifiers.PUBLIC,
31 attrs, loc)
33 this.ParentEnum = parent;
34 this.ValueExpr = expr;
35 this.prev_member = prev_member;
38 protected class EnumTypeExpr : TypeExpr
40 public readonly Enum Enum;
42 public EnumTypeExpr (Enum e)
44 this.Enum = e;
47 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
49 type = Enum.CurrentType != null ? Enum.CurrentType : Enum.TypeBuilder;
50 return this;
53 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
55 return DoResolveAsTypeStep (ec);
59 static bool IsValidEnumType (Type t)
61 return (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.int64_type ||
62 t == TypeManager.byte_type || t == TypeManager.sbyte_type || t == TypeManager.short_type ||
63 t == TypeManager.ushort_type || t == TypeManager.uint64_type || t == TypeManager.char_type ||
64 TypeManager.IsEnumType (t));
67 public object Value {
68 get { return ResolveValue () ? value.GetValue () : null; }
71 public override bool Define ()
73 if (!ResolveMemberType ())
74 return false;
76 const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
77 FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, attr);
78 Parent.MemberCache.AddMember (FieldBuilder, this);
79 TypeManager.RegisterConstant (FieldBuilder, this);
80 return true;
83 protected override Constant DoResolveValue (ResolveContext ec)
85 if (ValueExpr != null) {
86 Constant c = ValueExpr.ResolveAsConstant (ec, this);
87 if (c == null)
88 return null;
90 if (c is EnumConstant)
91 c = ((EnumConstant)c).Child;
93 c = c.ImplicitConversionRequired (ec, ParentEnum.UnderlyingType, Location);
94 if (c == null)
95 return null;
97 if (!IsValidEnumType (c.Type)) {
98 Enum.Error_1008 (Location);
99 return null;
102 return new EnumConstant (c, MemberType);
105 if (prev_member == null)
106 return new EnumConstant (
107 New.Constantify (ParentEnum.UnderlyingType), MemberType);
109 if (!prev_member.ResolveValue ())
110 return null;
112 try {
113 return (EnumConstant) prev_member.value.Increment ();
114 } catch (OverflowException) {
115 Report.Error (543, Location, "The enumerator value `{0}' is too " +
116 "large to fit in its type `{1}'", GetSignatureForError (),
117 TypeManager.CSharpName (ParentEnum.UnderlyingType));
118 return null;
123 /// <summary>
124 /// Enumeration container
125 /// </summary>
126 public class Enum : TypeContainer
128 public static readonly string UnderlyingValueField = "value__";
130 TypeExpr base_type;
132 const int AllowedModifiers =
133 Modifiers.NEW |
134 Modifiers.PUBLIC |
135 Modifiers.PROTECTED |
136 Modifiers.INTERNAL |
137 Modifiers.PRIVATE;
139 public Enum (NamespaceEntry ns, DeclSpace parent, TypeExpr type,
140 int mod_flags, MemberName name, Attributes attrs)
141 : base (ns, parent, name, attrs, Kind.Enum)
143 this.base_type = type;
144 int accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
145 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, accmods, Location);
148 public void AddEnumMember (EnumMember em)
150 if (em.Name == UnderlyingValueField) {
151 Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'",
152 UnderlyingValueField);
153 return;
156 AddConstant (em);
159 public static void Error_1008 (Location loc)
161 Report.Error (1008, loc, "Type byte, sbyte, short, ushort, " +
162 "int, uint, long or ulong expected");
165 protected override bool DefineNestedTypes ()
167 if (!base.DefineNestedTypes ())
168 return false;
171 // Call MapToInternalType for corlib
173 TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType,
174 FieldAttributes.Public | FieldAttributes.SpecialName
175 | FieldAttributes.RTSpecialName);
177 return true;
180 public override bool Define ()
182 member_cache = new MemberCache (TypeManager.enum_type, this);
183 DefineContainerMembers (constants);
184 return true;
187 public override bool IsUnmanagedType ()
189 return true;
192 public Type UnderlyingType {
193 get {
194 return base_type.Type;
198 protected override bool VerifyClsCompliance ()
200 if (!base.VerifyClsCompliance ())
201 return false;
203 if (UnderlyingType == TypeManager.uint32_type ||
204 UnderlyingType == TypeManager.uint64_type ||
205 UnderlyingType == TypeManager.ushort_type) {
206 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
209 return true;
212 public override AttributeTargets AttributeTargets {
213 get {
214 return AttributeTargets.Enum;
218 protected override TypeAttributes TypeAttr {
219 get {
220 return Modifiers.TypeAttr (ModFlags, IsTopLevel) |
221 TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr;