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 (IResolveContext ec
)
49 type
= Enum
.CurrentType
!= null ? Enum
.CurrentType
: Enum
.TypeBuilder
;
53 public override TypeExpr
ResolveAsTypeTerminal (IResolveContext 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 (EmitContext 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
);
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 ())
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
));
124 /// Enumeration container
126 public class Enum
: TypeContainer
128 public static readonly string UnderlyingValueField
= "value__";
132 const int AllowedModifiers
=
135 Modifiers
.PROTECTED
|
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
);
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 ())
171 // Call MapToInternalType for corlib
173 TypeBuilder
.DefineField (UnderlyingValueField
, UnderlyingType
,
174 FieldAttributes
.Public
| FieldAttributes
.SpecialName
175 | FieldAttributes
.RTSpecialName
);
180 public override bool Define ()
182 member_cache
= new MemberCache (TypeManager
.enum_type
, this);
183 DefineContainerMembers (constants
);
187 public override bool IsUnmanagedType ()
192 public Type UnderlyingType
{
194 return base_type
.Type
;
198 protected override bool VerifyClsCompliance ()
200 if (!base.VerifyClsCompliance ())
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
));
212 public override AttributeTargets AttributeTargets
{
214 return AttributeTargets
.Enum
;
218 protected override TypeAttributes TypeAttr
{
220 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
221 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;