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
{
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
,
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
)
46 protected override TypeExpr
DoResolveAsTypeStep (IMemberContext ec
)
48 type
= Enum
.CurrentType
!= null ? Enum
.CurrentType
: Enum
.TypeBuilder
;
52 public override TypeExpr
ResolveAsTypeTerminal (IMemberContext ec
, bool silent
)
54 return DoResolveAsTypeStep (ec
);
58 static bool IsValidEnumType (Type t
)
60 return (t
== TypeManager
.int32_type
|| t
== TypeManager
.uint32_type
|| t
== TypeManager
.int64_type
||
61 t
== TypeManager
.byte_type
|| t
== TypeManager
.sbyte_type
|| t
== TypeManager
.short_type
||
62 t
== TypeManager
.ushort_type
|| t
== TypeManager
.uint64_type
|| t
== TypeManager
.char_type
||
63 TypeManager
.IsEnumType (t
));
67 get { return ResolveValue () ? value.GetValue () : null; }
70 public override bool Define ()
72 if (!ResolveMemberType ())
75 const FieldAttributes attr
= FieldAttributes
.Public
| FieldAttributes
.Static
| FieldAttributes
.Literal
;
76 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
, attr
);
77 Parent
.MemberCache
.AddMember (FieldBuilder
, this);
78 TypeManager
.RegisterConstant (FieldBuilder
, this);
82 protected override Constant
DoResolveValue (ResolveContext ec
)
84 if (ValueExpr
!= null) {
85 Constant c
= ValueExpr
.ResolveAsConstant (ec
, this);
89 if (c
is EnumConstant
)
90 c
= ((EnumConstant
)c
).Child
;
92 c
= c
.ImplicitConversionRequired (ec
, ParentEnum
.UnderlyingType
, Location
);
96 if (!IsValidEnumType (c
.Type
)) {
97 Enum
.Error_1008 (Location
, ec
.Report
);
101 return new EnumConstant (c
, MemberType
).Resolve (ec
);
104 if (prev_member
== null)
105 return new EnumConstant (New
.Constantify (ParentEnum
.UnderlyingType
), MemberType
).Resolve (ec
);
107 if (!prev_member
.ResolveValue ())
111 return ((EnumConstant
) prev_member
.value).Increment ();
112 } catch (OverflowException
) {
113 Report
.Error (543, Location
, "The enumerator value `{0}' is too " +
114 "large to fit in its type `{1}'", GetSignatureForError (),
115 TypeManager
.CSharpName (ParentEnum
.UnderlyingType
));
122 /// Enumeration container
124 public class Enum
: TypeContainer
126 public static readonly string UnderlyingValueField
= "value__";
130 const Modifiers AllowedModifiers
=
133 Modifiers
.PROTECTED
|
137 public Enum (NamespaceEntry ns
, DeclSpace parent
, TypeExpr type
,
138 Modifiers mod_flags
, MemberName name
, Attributes attrs
)
139 : base (ns
, parent
, name
, attrs
, Kind
.Enum
)
141 this.base_type
= type
;
142 var accmods
= IsTopLevel
? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
143 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod_flags
, accmods
, Location
, Report
);
146 public void AddEnumMember (EnumMember em
)
148 if (em
.Name
== UnderlyingValueField
) {
149 Report
.Error (76, em
.Location
, "An item in an enumeration cannot have an identifier `{0}'",
150 UnderlyingValueField
);
157 public static void Error_1008 (Location loc
, Report Report
)
159 Report
.Error (1008, loc
, "Type byte, sbyte, short, ushort, " +
160 "int, uint, long or ulong expected");
163 protected override bool DefineNestedTypes ()
165 if (!base.DefineNestedTypes ())
169 // Call MapToInternalType for corlib
171 TypeBuilder
.DefineField (UnderlyingValueField
, UnderlyingType
,
172 FieldAttributes
.Public
| FieldAttributes
.SpecialName
173 | FieldAttributes
.RTSpecialName
);
178 protected override bool DoDefineMembers ()
180 member_cache
= new MemberCache (TypeManager
.enum_type
, this);
181 DefineContainerMembers (constants
);
185 public override bool IsUnmanagedType ()
190 public Type UnderlyingType
{
192 return base_type
.Type
;
196 protected override bool VerifyClsCompliance ()
198 if (!base.VerifyClsCompliance ())
201 if (UnderlyingType
== TypeManager
.uint32_type
||
202 UnderlyingType
== TypeManager
.uint64_type
||
203 UnderlyingType
== TypeManager
.ushort_type
) {
204 Report
.Warning (3009, 1, Location
, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager
.CSharpName (UnderlyingType
));
210 public override AttributeTargets AttributeTargets
{
212 return AttributeTargets
.Enum
;
216 protected override TypeAttributes TypeAttr
{
218 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) |
219 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;