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
;
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
,
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
)
47 protected override TypeExpr
DoResolveAsTypeStep (IMemberContext ec
)
49 type
= Enum
.CurrentType
!= null ? Enum
.CurrentType
: Enum
.TypeBuilder
;
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
));
68 get { return ResolveValue () ? value.GetValue () : null; }
71 public override bool Define ()
73 if (!ResolveMemberType ())
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);
83 protected override Constant
DoResolveValue (ResolveContext ec
)
85 if (ValueExpr
!= null) {
86 Constant c
= ValueExpr
.ResolveAsConstant (ec
, this);
90 if (c
is EnumConstant
)
91 c
= ((EnumConstant
)c
).Child
;
93 c
= c
.ImplicitConversionRequired (ec
, ParentEnum
.UnderlyingType
, Location
);
97 if (!IsValidEnumType (c
.Type
)) {
98 Enum
.Error_1008 (Location
, ec
.Report
);
102 return new EnumConstant (c
, MemberType
).Resolve (ec
);
105 if (prev_member
== null)
106 return new EnumConstant (New
.Constantify (ParentEnum
.UnderlyingType
), MemberType
).Resolve (ec
);
108 if (!prev_member
.ResolveValue ())
112 return ((EnumConstant
) prev_member
.value).Increment ();
113 } catch (OverflowException
) {
114 Report
.Error (543, Location
, "The enumerator value `{0}' is too " +
115 "large to fit in its type `{1}'", GetSignatureForError (),
116 TypeManager
.CSharpName (ParentEnum
.UnderlyingType
));
123 /// Enumeration container
125 public class Enum
: TypeContainer
127 public static readonly string UnderlyingValueField
= "value__";
131 const int AllowedModifiers
=
134 Modifiers
.PROTECTED
|
138 public Enum (NamespaceEntry ns
, DeclSpace parent
, TypeExpr type
,
139 int mod_flags
, MemberName name
, Attributes attrs
)
140 : base (ns
, parent
, name
, attrs
, Kind
.Enum
)
142 this.base_type
= type
;
143 int accmods
= IsTopLevel
? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
144 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
, accmods
, Location
, Report
);
147 public void AddEnumMember (EnumMember em
)
149 if (em
.Name
== UnderlyingValueField
) {
150 Report
.Error (76, em
.Location
, "An item in an enumeration cannot have an identifier `{0}'",
151 UnderlyingValueField
);
158 public static void Error_1008 (Location loc
, Report Report
)
160 Report
.Error (1008, loc
, "Type byte, sbyte, short, ushort, " +
161 "int, uint, long or ulong expected");
164 protected override bool DefineNestedTypes ()
166 if (!base.DefineNestedTypes ())
170 // Call MapToInternalType for corlib
172 TypeBuilder
.DefineField (UnderlyingValueField
, UnderlyingType
,
173 FieldAttributes
.Public
| FieldAttributes
.SpecialName
174 | FieldAttributes
.RTSpecialName
);
179 protected override bool DoDefineMembers ()
181 member_cache
= new MemberCache (TypeManager
.enum_type
, this);
182 DefineContainerMembers (constants
);
186 public override bool IsUnmanagedType ()
191 public Type UnderlyingType
{
193 return base_type
.Type
;
197 protected override bool VerifyClsCompliance ()
199 if (!base.VerifyClsCompliance ())
202 if (UnderlyingType
== TypeManager
.uint32_type
||
203 UnderlyingType
== TypeManager
.uint64_type
||
204 UnderlyingType
== TypeManager
.ushort_type
) {
205 Report
.Warning (3009, 1, Location
, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager
.CSharpName (UnderlyingType
));
211 public override AttributeTargets AttributeTargets
{
213 return AttributeTargets
.Enum
;
217 protected override TypeAttributes TypeAttr
{
219 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
220 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;