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 protected override TypeExpr
DoResolveAsTypeStep (IMemberContext ec
)
28 type
= ec
.CurrentType
;
32 public override TypeExpr
ResolveAsTypeTerminal (IMemberContext ec
, bool silent
)
34 return DoResolveAsTypeStep (ec
);
38 public EnumMember (Enum parent
, EnumMember prev_member
, string name
, Expression expr
,
39 Attributes attrs
, Location loc
)
40 : base (parent
, new EnumTypeExpr (), name
, null, Modifiers
.PUBLIC
,
43 initializer
= new EnumInitializer (this, expr
, prev_member
);
46 static bool IsValidEnumType (TypeSpec t
)
48 return (t
== TypeManager
.int32_type
|| t
== TypeManager
.uint32_type
|| t
== TypeManager
.int64_type
||
49 t
== TypeManager
.byte_type
|| t
== TypeManager
.sbyte_type
|| t
== TypeManager
.short_type
||
50 t
== TypeManager
.ushort_type
|| t
== TypeManager
.uint64_type
|| t
== TypeManager
.char_type
||
51 TypeManager
.IsEnumType (t
));
54 public override Constant
ConvertInitializer (ResolveContext rc
, Constant expr
)
56 if (expr
is EnumConstant
)
57 expr
= ((EnumConstant
) expr
).Child
;
59 var underlying
= ((Enum
) Parent
).UnderlyingType
;
61 expr
= expr
.ImplicitConversionRequired (rc
, underlying
, Location
);
62 if (expr
!= null && !IsValidEnumType (expr
.Type
)) {
63 Enum
.Error_1008 (Location
, Report
);
69 expr
= New
.Constantify (underlying
);
71 return new EnumConstant (expr
, MemberType
).Resolve (rc
);
74 public override bool Define ()
76 if (!ResolveMemberType ())
79 const FieldAttributes attr
= FieldAttributes
.Public
| FieldAttributes
.Static
| FieldAttributes
.Literal
;
80 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
.GetMetaInfo (), attr
);
81 spec
= new ConstSpec (Parent
.Definition
, this, MemberType
, FieldBuilder
, ModFlags
, initializer
);
83 Parent
.MemberCache
.AddMember (spec
);
88 class EnumInitializer
: ConstInitializer
92 public EnumInitializer (Const field
, Expression init
, EnumMember prev
)
98 protected override Expression
DoResolveInitializer (ResolveContext rc
)
101 return base.DoResolveInitializer (rc
);
104 return field
.ConvertInitializer (rc
, null);
107 var ec
= prev
.DefineValue () as EnumConstant
;
108 expr
= ec
.Increment ().Resolve (rc
);
109 } catch (OverflowException
) {
110 rc
.Report
.Error (543, field
.Location
,
111 "The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'",
112 field
.GetSignatureForError (),
113 TypeManager
.CSharpName (((Enum
) field
.Parent
).UnderlyingType
));
115 expr
= field
.ConvertInitializer (rc
, null);
123 /// Enumeration container
125 public class Enum
: TypeContainer
127 public static readonly string UnderlyingValueField
= "value__";
129 const Modifiers AllowedModifiers
=
132 Modifiers
.PROTECTED
|
136 public Enum (NamespaceEntry ns
, DeclSpace parent
, TypeExpression type
,
137 Modifiers mod_flags
, MemberName name
, Attributes attrs
)
138 : base (ns
, parent
, name
, attrs
, MemberKind
.Enum
)
140 base_type_expr
= type
;
141 var accmods
= IsTopLevel
? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
142 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod_flags
, accmods
, Location
, Report
);
143 spec
= new EnumSpec (null, this, null, null, ModFlags
);
148 public override AttributeTargets AttributeTargets
{
150 return AttributeTargets
.Enum
;
154 public TypeExpr BaseTypeExpression
{
156 return base_type_expr
;
160 protected override TypeAttributes TypeAttr
{
162 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) |
163 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;
167 public TypeSpec UnderlyingType
{
169 return ((EnumSpec
) spec
).UnderlyingType
;
175 public void AddEnumMember (EnumMember em
)
177 if (em
.Name
== UnderlyingValueField
) {
178 Report
.Error (76, em
.Location
, "An item in an enumeration cannot have an identifier `{0}'",
179 UnderlyingValueField
);
186 public static void Error_1008 (Location loc
, Report Report
)
188 Report
.Error (1008, loc
,
189 "Type byte, sbyte, short, ushort, int, uint, long or ulong expected");
192 protected override bool DefineNestedTypes ()
194 ((EnumSpec
) spec
).UnderlyingType
= base_type_expr
== null ? TypeManager
.int32_type
: base_type_expr
.Type
;
196 TypeBuilder
.DefineField (UnderlyingValueField
, UnderlyingType
.GetMetaInfo (),
197 FieldAttributes
.Public
| FieldAttributes
.SpecialName
| FieldAttributes
.RTSpecialName
);
199 if (!RootContext
.StdLib
)
200 RootContext
.hack_corlib_enums
.Add (this);
205 protected override bool DoDefineMembers ()
207 DefineContainerMembers (constants
);
211 public override bool IsUnmanagedType ()
216 protected override TypeExpr
[] ResolveBaseTypes (out TypeExpr base_class
)
218 base_type
= TypeManager
.enum_type
;
219 base_class
= base_type_expr
;
223 protected override bool VerifyClsCompliance ()
225 if (!base.VerifyClsCompliance ())
228 if (UnderlyingType
== TypeManager
.uint32_type
||
229 UnderlyingType
== TypeManager
.uint64_type
||
230 UnderlyingType
== TypeManager
.ushort_type
) {
231 Report
.Warning (3009, 1, Location
, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager
.CSharpName (UnderlyingType
));
238 class EnumSpec
: TypeSpec
242 public EnumSpec (TypeSpec declaringType
, ITypeDefinition definition
, TypeSpec underlyingType
, Type info
, Modifiers modifiers
)
243 : base (MemberKind
.Enum
, declaringType
, definition
, info
, modifiers
| Modifiers
.SEALED
)
245 this.underlying
= underlyingType
;
248 public TypeSpec UnderlyingType
{
253 if (underlying
!= null)
254 throw new InternalErrorException ("UnderlyingType reset");
260 public static TypeSpec
GetUnderlyingType (TypeSpec t
)
262 return ((EnumSpec
) t
.GetDefinition ()).UnderlyingType
;