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)
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Globalization
;
20 namespace Mono
.CSharp
{
22 public class EnumMember
: Const
24 class EnumTypeExpr
: TypeExpr
26 public readonly Enum Enum
;
28 public EnumTypeExpr (Enum e
)
33 protected override TypeExpr
DoResolveAsTypeStep (IMemberContext ec
)
35 type
= Enum
.CurrentType
!= null ? Enum
.CurrentType
: Enum
.TypeBuilder
;
39 public override TypeExpr
ResolveAsTypeTerminal (IMemberContext ec
, bool silent
)
41 return DoResolveAsTypeStep (ec
);
45 public EnumMember (Enum parent
, EnumMember prev_member
, string name
, Expression expr
,
46 Attributes attrs
, Location loc
)
47 : base (parent
, new EnumTypeExpr (parent
), name
, null, Modifiers
.PUBLIC
,
50 initializer
= new EnumInitializer (this, expr
, prev_member
);
53 static bool IsValidEnumType (Type t
)
55 return (t
== TypeManager
.int32_type
|| t
== TypeManager
.uint32_type
|| t
== TypeManager
.int64_type
||
56 t
== TypeManager
.byte_type
|| t
== TypeManager
.sbyte_type
|| t
== TypeManager
.short_type
||
57 t
== TypeManager
.ushort_type
|| t
== TypeManager
.uint64_type
|| t
== TypeManager
.char_type
||
58 TypeManager
.IsEnumType (t
));
61 public override Constant
ConvertInitializer (ResolveContext rc
, Constant expr
)
63 if (expr
is EnumConstant
)
64 expr
= ((EnumConstant
) expr
).Child
;
66 var underlying
= ((Enum
) Parent
).UnderlyingType
;
68 expr
= expr
.ImplicitConversionRequired (rc
, underlying
, Location
);
69 if (expr
!= null && !IsValidEnumType (expr
.Type
)) {
70 Enum
.Error_1008 (Location
, Report
);
76 expr
= New
.Constantify (underlying
);
78 return new EnumConstant (expr
, MemberType
).Resolve (rc
);
81 public override bool Define ()
83 if (!ResolveMemberType ())
86 const FieldAttributes attr
= FieldAttributes
.Public
| FieldAttributes
.Static
| FieldAttributes
.Literal
;
87 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
, attr
);
88 spec
= new ConstSpec (this, FieldBuilder
, ModFlags
, initializer
);
90 Parent
.MemberCache
.AddMember (FieldBuilder
, spec
);
91 TypeManager
.RegisterConstant (FieldBuilder
, (ConstSpec
) spec
);
97 class EnumInitializer
: ConstInitializer
101 public EnumInitializer (Const field
, Expression init
, EnumMember prev
)
107 protected override Expression
DoResolveInitializer (ResolveContext rc
)
110 return base.DoResolveInitializer (rc
);
113 return field
.ConvertInitializer (rc
, null);
116 var ec
= prev
.Initializer
.Resolve (rc
) as EnumConstant
;
117 expr
= ec
.Increment ().Resolve (rc
);
118 } catch (OverflowException
) {
119 rc
.Report
.Error (543, field
.Location
,
120 "The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'",
121 field
.GetSignatureForError (),
122 TypeManager
.CSharpName (((Enum
) field
.Parent
).UnderlyingType
));
124 expr
= field
.ConvertInitializer (rc
, null);
132 /// Enumeration container
134 public class Enum
: TypeContainer
136 public static readonly string UnderlyingValueField
= "value__";
140 const Modifiers AllowedModifiers
=
143 Modifiers
.PROTECTED
|
147 public Enum (NamespaceEntry ns
, DeclSpace parent
, TypeExpr type
,
148 Modifiers mod_flags
, MemberName name
, Attributes attrs
)
149 : base (ns
, parent
, name
, attrs
, MemberKind
.Enum
)
151 this.base_type
= type
;
152 var accmods
= IsTopLevel
? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
153 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod_flags
, accmods
, Location
, Report
);
156 public void AddEnumMember (EnumMember em
)
158 if (em
.Name
== UnderlyingValueField
) {
159 Report
.Error (76, em
.Location
, "An item in an enumeration cannot have an identifier `{0}'",
160 UnderlyingValueField
);
167 public static void Error_1008 (Location loc
, Report Report
)
169 Report
.Error (1008, loc
, "Type byte, sbyte, short, ushort, " +
170 "int, uint, long or ulong expected");
173 protected override bool DefineNestedTypes ()
175 if (!base.DefineNestedTypes ())
179 // Call MapToInternalType for corlib
181 TypeBuilder
.DefineField (UnderlyingValueField
, UnderlyingType
,
182 FieldAttributes
.Public
| FieldAttributes
.SpecialName
183 | FieldAttributes
.RTSpecialName
);
188 protected override bool DoDefineMembers ()
190 member_cache
= new MemberCache (TypeManager
.enum_type
, this);
191 DefineContainerMembers (constants
);
195 public override bool IsUnmanagedType ()
200 public Type UnderlyingType
{
202 return base_type
.Type
;
206 protected override bool VerifyClsCompliance ()
208 if (!base.VerifyClsCompliance ())
211 if (UnderlyingType
== TypeManager
.uint32_type
||
212 UnderlyingType
== TypeManager
.uint64_type
||
213 UnderlyingType
== TypeManager
.ushort_type
) {
214 Report
.Warning (3009, 1, Location
, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager
.CSharpName (UnderlyingType
));
220 public override AttributeTargets AttributeTargets
{
222 return AttributeTargets
.Enum
;
226 protected override TypeAttributes TypeAttr
{
228 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) |
229 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;
234 public class EnumSpec
: TypeSpec
236 public EnumSpec (MemberKind kind
, ITypeDefinition definition
, TypeSpec underlyingType
, Type info
, string name
, Modifiers modifiers
)
237 : base (kind
, definition
, info
, name
, modifiers
)
239 this.UnderlyingType
= underlyingType
;
242 public TypeSpec UnderlyingType { get; private set; }