Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2922-DataCompletenessChartPerf/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/enum.cs

Last change on this file was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 8.2 KB
Line 
1//
2// enum.cs: Enum handling.
3//
4// Author: Miguel de Icaza (miguel@gnu.org)
5//         Ravi Pratap     (ravi@ximian.com)
6//         Marek Safar     (marek.safar@seznam.cz)
7//
8// Dual licensed under the terms of the MIT X11 or GNU GPL
9//
10// Copyright 2001 Ximian, Inc (http://www.ximian.com)
11// Copyright 2003-2003 Novell, Inc (http://www.novell.com)
12// Copyright 2011 Xamarin Inc
13//
14
15using System;
16
17#if STATIC
18using MetaType = IKVM.Reflection.Type;
19using IKVM.Reflection;
20#else
21using MetaType = System.Type;
22using System.Reflection;
23#endif
24
25namespace Mono.CSharp {
26
27  public class EnumMember : Const
28  {
29    class EnumTypeExpr : TypeExpr
30    {
31      public override TypeSpec ResolveAsType (IMemberContext ec, bool allowUnboundTypeArguments)
32      {
33        type = ec.CurrentType;
34        eclass = ExprClass.Type;
35        return type;
36      }
37    }
38
39    public EnumMember (Enum parent, MemberName name, Attributes attrs)
40      : base (parent, new EnumTypeExpr (), Modifiers.PUBLIC, name, attrs)
41    {
42    }
43
44    static bool IsValidEnumType (TypeSpec t)
45    {
46      switch (t.BuiltinType) {
47      case BuiltinTypeSpec.Type.Int:
48      case BuiltinTypeSpec.Type.UInt:
49      case BuiltinTypeSpec.Type.Long:
50      case BuiltinTypeSpec.Type.Byte:
51      case BuiltinTypeSpec.Type.SByte:
52      case BuiltinTypeSpec.Type.Short:
53      case BuiltinTypeSpec.Type.UShort:
54      case BuiltinTypeSpec.Type.ULong:
55      case BuiltinTypeSpec.Type.Char:
56        return true;
57      default:
58        return t.IsEnum;
59      }
60    }
61
62    public override Constant ConvertInitializer (ResolveContext rc, Constant expr)
63    {
64      if (expr is EnumConstant)
65        expr = ((EnumConstant) expr).Child;
66
67      var en = (Enum)Parent;
68      var underlying = en.UnderlyingType;
69      if (expr != null) {
70        expr = expr.ImplicitConversionRequired (rc, underlying);
71        if (expr != null && !IsValidEnumType (expr.Type)) {
72          en.Error_UnderlyingType (Location);
73          expr = null;
74        }
75      }
76
77      if (expr == null)
78        expr = New.Constantify (underlying, Location);
79
80      return new EnumConstant (expr, MemberType);
81    }
82
83    public override bool Define ()
84    {
85      if (!ResolveMemberType ())
86        return false;
87
88      const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
89      FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr);
90      spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer);
91
92      Parent.MemberCache.AddMember (spec);
93      return true;
94    }
95   
96    public override void Accept (StructuralVisitor visitor)
97    {
98      visitor.Visit (this);
99    }
100
101  }
102
103  /// <summary>
104  ///   Enumeration container
105  /// </summary>
106  public class Enum : TypeDefinition
107  {
108    //
109    // Implicit enum member initializer, used when no constant value is provided
110    //
111    sealed class ImplicitInitializer : Expression
112    {
113      readonly EnumMember prev;
114      readonly EnumMember current;
115
116      public ImplicitInitializer (EnumMember current, EnumMember prev)
117      {
118        this.current = current;
119        this.prev = prev;
120      }
121
122      public override bool ContainsEmitWithAwait ()
123      {
124        return false;
125      }
126
127      public override Expression CreateExpressionTree (ResolveContext ec)
128      {
129        throw new NotSupportedException ("Missing Resolve call");
130      }
131
132      protected override Expression DoResolve (ResolveContext rc)
133      {
134        // We are the first member
135        if (prev == null) {
136          return New.Constantify (current.Parent.Definition, Location);
137        }
138
139        var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant;
140        try {
141          return c.Increment ();
142        } catch (OverflowException) {
143          rc.Report.Error (543, current.Location,
144            "The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'",
145            current.GetSignatureForError (), ((Enum) current.Parent).UnderlyingType.GetSignatureForError ());
146
147          return New.Constantify (current.Parent.Definition, current.Location);
148        }
149      }
150
151      public override void Emit (EmitContext ec)
152      {
153        throw new NotSupportedException ("Missing Resolve call");
154      }
155    }
156
157    public static readonly string UnderlyingValueField = "value__";
158
159    const Modifiers AllowedModifiers =
160      Modifiers.NEW |
161      Modifiers.PUBLIC |
162      Modifiers.PROTECTED |
163      Modifiers.INTERNAL |
164      Modifiers.PRIVATE;
165
166    readonly FullNamedExpression underlying_type_expr;
167
168    public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
169      : base (parent, name, attrs, MemberKind.Enum)
170    {
171      underlying_type_expr = type;
172      var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
173      ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report);
174      spec = new EnumSpec (null, this, null, null, ModFlags);
175    }
176
177    #region Properties
178
179    public override AttributeTargets AttributeTargets {
180      get {
181        return AttributeTargets.Enum;
182      }
183    }
184
185    public FullNamedExpression BaseTypeExpression {
186      get {
187        return underlying_type_expr;
188      }
189    }
190
191    protected override TypeAttributes TypeAttr {
192      get {
193        return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed;
194      }
195    }
196
197    public TypeSpec UnderlyingType {
198      get {
199        return ((EnumSpec) spec).UnderlyingType;
200      }
201    }
202
203    #endregion
204
205    public override void Accept (StructuralVisitor visitor)
206    {
207      visitor.Visit (this);
208    }
209
210    public void AddEnumMember (EnumMember em)
211    {
212      if (em.Name == UnderlyingValueField) {
213        Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'",
214          UnderlyingValueField);
215        return;
216      }
217
218      AddMember (em);
219    }
220
221    public void Error_UnderlyingType (Location loc)
222    {
223      Report.Error (1008, loc,
224        "Type byte, sbyte, short, ushort, int, uint, long or ulong expected");
225    }
226
227    protected override void DoDefineContainer ()
228    {
229      TypeSpec ut;
230      if (underlying_type_expr != null) {
231        ut = underlying_type_expr.ResolveAsType (this);
232        if (!EnumSpec.IsValidUnderlyingType (ut)) {
233          Error_UnderlyingType (underlying_type_expr.Location);
234          ut = null;
235        }
236      } else {
237        ut = null;
238      }
239
240      if (ut == null)
241        ut = Compiler.BuiltinTypes.Int;
242
243      ((EnumSpec) spec).UnderlyingType = ut;
244
245      TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (),
246        FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
247
248      DefineBaseTypes ();
249    }
250
251    protected override bool DoDefineMembers ()
252    {
253      for (int i = 0; i < Members.Count; ++i) {
254        EnumMember em = (EnumMember) Members[i];
255        if (em.Initializer == null) {
256          em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) Members[i - 1]);
257        }
258
259        em.Define ();
260      }
261
262      return true;
263    }
264
265    public override bool IsUnmanagedType ()
266    {
267      return true;
268    }
269
270    protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
271    {
272      base_type = Compiler.BuiltinTypes.Enum;
273      base_class = null;
274      return null;
275    }
276   
277    protected override bool VerifyClsCompliance ()
278    {
279      if (!base.VerifyClsCompliance ())
280        return false;
281
282      switch (UnderlyingType.BuiltinType) {
283      case BuiltinTypeSpec.Type.UInt:
284      case BuiltinTypeSpec.Type.ULong:
285      case BuiltinTypeSpec.Type.UShort:
286        Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
287          GetSignatureForError (), UnderlyingType.GetSignatureForError ());
288        break;
289      }
290
291      return true;
292    }
293  }
294
295  class EnumSpec : TypeSpec
296  {
297    TypeSpec underlying;
298
299    public EnumSpec (TypeSpec declaringType, ITypeDefinition definition, TypeSpec underlyingType, MetaType info, Modifiers modifiers)
300      : base (MemberKind.Enum, declaringType, definition, info, modifiers | Modifiers.SEALED)
301    {
302      this.underlying = underlyingType;
303    }
304
305    public TypeSpec UnderlyingType {
306      get {
307        return underlying;
308      }
309      set {
310        if (underlying != null)
311          throw new InternalErrorException ("UnderlyingType reset");
312
313        underlying = value;
314      }
315    }
316
317    public static TypeSpec GetUnderlyingType (TypeSpec t)
318    {
319      return ((EnumSpec) t.GetDefinition ()).UnderlyingType;
320    }
321
322    public static bool IsValidUnderlyingType (TypeSpec type)
323    {
324      switch (type.BuiltinType) {
325      case BuiltinTypeSpec.Type.Int:
326      case BuiltinTypeSpec.Type.UInt:
327      case BuiltinTypeSpec.Type.Long:
328      case BuiltinTypeSpec.Type.Byte:
329      case BuiltinTypeSpec.Type.SByte:
330      case BuiltinTypeSpec.Type.Short:
331      case BuiltinTypeSpec.Type.UShort:
332      case BuiltinTypeSpec.Type.ULong:
333        return true;
334      }
335
336      return false;
337    }
338  }
339}
Note: See TracBrowser for help on using the repository browser.