2
// enum.cs: Enum handling.
4
// Author: Miguel de Icaza (miguel@gnu.org)
5
// Ravi Pratap (ravi@ximian.com)
6
// Marek Safar (marek.safar@seznam.cz)
8
// Dual licensed under the terms of the MIT X11 or GNU GPL
10
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
11
// Copyright 2003-2003 Novell, Inc (http://www.novell.com)
12
// Copyright 2011 Xamarin Inc
18
using MetaType = IKVM.Reflection.Type;
19
using IKVM.Reflection;
21
using MetaType = System.Type;
22
using System.Reflection;
25
namespace Mono.CSharp {
27
public class EnumMember : Const
29
class EnumTypeExpr : TypeExpr
31
public override TypeSpec ResolveAsType (IMemberContext ec)
33
type = ec.CurrentType;
34
eclass = ExprClass.Type;
39
public EnumMember (Enum parent, MemberName name, Attributes attrs)
40
: base (parent, new EnumTypeExpr (), Modifiers.PUBLIC, name, attrs)
44
static bool IsValidEnumType (TypeSpec t)
46
switch (t.BuiltinType) {
47
case BuiltinTypeSpec.Type.Int:
48
case BuiltinTypeSpec.Type.UInt:
49
case BuiltinTypeSpec.Type.Long:
50
case BuiltinTypeSpec.Type.Byte:
51
case BuiltinTypeSpec.Type.SByte:
52
case BuiltinTypeSpec.Type.Short:
53
case BuiltinTypeSpec.Type.UShort:
54
case BuiltinTypeSpec.Type.ULong:
55
case BuiltinTypeSpec.Type.Char:
62
public override Constant ConvertInitializer (ResolveContext rc, Constant expr)
64
if (expr is EnumConstant)
65
expr = ((EnumConstant) expr).Child;
67
var underlying = ((Enum) Parent).UnderlyingType;
69
expr = expr.ImplicitConversionRequired (rc, underlying, Location);
70
if (expr != null && !IsValidEnumType (expr.Type)) {
71
Enum.Error_1008 (Location, Report);
77
expr = New.Constantify (underlying, Location);
79
return new EnumConstant (expr, MemberType);
82
public override bool Define ()
84
if (!ResolveMemberType ())
87
const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
88
FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr);
89
spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer);
91
Parent.MemberCache.AddMember (spec);
95
public override void Accept (StructuralVisitor visitor)
103
/// Enumeration container
105
public class Enum : TypeDefinition
108
// Implicit enum member initializer, used when no constant value is provided
110
sealed class ImplicitInitializer : Expression
112
readonly EnumMember prev;
113
readonly EnumMember current;
115
public ImplicitInitializer (EnumMember current, EnumMember prev)
117
this.current = current;
121
public override bool ContainsEmitWithAwait ()
126
public override Expression CreateExpressionTree (ResolveContext ec)
128
throw new NotSupportedException ("Missing Resolve call");
131
protected override Expression DoResolve (ResolveContext rc)
133
// We are the first member
135
return New.Constantify (current.Parent.Definition, Location);
138
var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant;
140
return c.Increment ();
141
} catch (OverflowException) {
142
rc.Report.Error (543, current.Location,
143
"The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'",
144
current.GetSignatureForError (), ((Enum) current.Parent).UnderlyingType.GetSignatureForError ());
146
return New.Constantify (current.Parent.Definition, current.Location);
150
public override void Emit (EmitContext ec)
152
throw new NotSupportedException ("Missing Resolve call");
156
public static readonly string UnderlyingValueField = "value__";
158
const Modifiers AllowedModifiers =
161
Modifiers.PROTECTED |
165
readonly FullNamedExpression underlying_type_expr;
167
public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
168
: base (parent, name, attrs, MemberKind.Enum)
170
underlying_type_expr = type;
171
var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
172
ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report);
173
spec = new EnumSpec (null, this, null, null, ModFlags);
178
public override AttributeTargets AttributeTargets {
180
return AttributeTargets.Enum;
184
public FullNamedExpression BaseTypeExpression {
186
return underlying_type_expr;
190
protected override TypeAttributes TypeAttr {
192
return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed;
196
public TypeSpec UnderlyingType {
198
return ((EnumSpec) spec).UnderlyingType;
204
public override void Accept (StructuralVisitor visitor)
206
visitor.Visit (this);
209
public void AddEnumMember (EnumMember em)
211
if (em.Name == UnderlyingValueField) {
212
Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'",
213
UnderlyingValueField);
220
public static void Error_1008 (Location loc, Report Report)
222
Report.Error (1008, loc,
223
"Type byte, sbyte, short, ushort, int, uint, long or ulong expected");
226
protected override void DoDefineContainer ()
228
((EnumSpec) spec).UnderlyingType = underlying_type_expr == null ? Compiler.BuiltinTypes.Int : underlying_type_expr.Type;
230
TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (),
231
FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
236
protected override bool DoDefineMembers ()
238
for (int i = 0; i < Members.Count; ++i) {
239
EnumMember em = (EnumMember) Members[i];
240
if (em.Initializer == null) {
241
em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) Members[i - 1]);
250
public override bool IsUnmanagedType ()
255
protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
257
base_type = Compiler.BuiltinTypes.Enum;
262
protected override bool VerifyClsCompliance ()
264
if (!base.VerifyClsCompliance ())
267
switch (UnderlyingType.BuiltinType) {
268
case BuiltinTypeSpec.Type.UInt:
269
case BuiltinTypeSpec.Type.ULong:
270
case BuiltinTypeSpec.Type.UShort:
271
Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
272
GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
280
class EnumSpec : TypeSpec
284
public EnumSpec (TypeSpec declaringType, ITypeDefinition definition, TypeSpec underlyingType, MetaType info, Modifiers modifiers)
285
: base (MemberKind.Enum, declaringType, definition, info, modifiers | Modifiers.SEALED)
287
this.underlying = underlyingType;
290
public TypeSpec UnderlyingType {
295
if (underlying != null)
296
throw new InternalErrorException ("UnderlyingType reset");
302
public static TypeSpec GetUnderlyingType (TypeSpec t)
304
return ((EnumSpec) t.GetDefinition ()).UnderlyingType;
307
public static bool IsValidUnderlyingType (TypeSpec type)
309
switch (type.BuiltinType) {
310
case BuiltinTypeSpec.Type.Int:
311
case BuiltinTypeSpec.Type.UInt:
312
case BuiltinTypeSpec.Type.Long:
313
case BuiltinTypeSpec.Type.Byte:
314
case BuiltinTypeSpec.Type.SByte:
315
case BuiltinTypeSpec.Type.Short:
316
case BuiltinTypeSpec.Type.UShort:
317
case BuiltinTypeSpec.Type.ULong: