~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// field.cs: All field handlers
 
3
//
 
4
// Authors: Miguel de Icaza (miguel@gnu.org)
 
5
//          Martin Baulig (martin@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, 2002, 2003 Ximian, Inc (http://www.ximian.com)
 
11
// Copyright 2004-2008 Novell, Inc
 
12
// Copyright 2011 Xamarin Inc
 
13
//
 
14
 
 
15
using System;
 
16
using System.Collections.Generic;
 
17
using System.Runtime.InteropServices;
 
18
 
 
19
#if STATIC
 
20
using MetaType = IKVM.Reflection.Type;
 
21
using IKVM.Reflection;
 
22
using IKVM.Reflection.Emit;
 
23
#else
 
24
using MetaType = System.Type;
 
25
using System.Reflection;
 
26
using System.Reflection.Emit;
 
27
#endif
 
28
 
 
29
namespace Mono.CSharp
 
30
{
 
31
        public class FieldDeclarator
 
32
        {
 
33
                public FieldDeclarator (SimpleMemberName name, Expression initializer)
 
34
                {
 
35
                        this.Name = name;
 
36
                        this.Initializer = initializer;
 
37
                }
 
38
 
 
39
                #region Properties
 
40
 
 
41
                public SimpleMemberName Name { get; private set; }
 
42
                public Expression Initializer { get; private set; }
 
43
 
 
44
                #endregion
 
45
        }
 
46
 
 
47
        //
 
48
        // Abstract class for all fields
 
49
        //
 
50
        abstract public class FieldBase : MemberBase
 
51
        {
 
52
                protected FieldBuilder FieldBuilder;
 
53
                protected FieldSpec spec;
 
54
                public Status status;
 
55
                protected Expression initializer;
 
56
                protected List<FieldDeclarator> declarators;
 
57
 
 
58
                [Flags]
 
59
                public enum Status : byte {
 
60
                        HAS_OFFSET = 4          // Used by FieldMember.
 
61
                }
 
62
 
 
63
                static readonly string[] attribute_targets = new string [] { "field" };
 
64
 
 
65
                protected FieldBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
 
66
                        : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE, name, attrs)
 
67
                {
 
68
                        if ((mod & Modifiers.ABSTRACT) != 0)
 
69
                                Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
 
70
                }
 
71
 
 
72
                #region Properties
 
73
 
 
74
                public override AttributeTargets AttributeTargets {
 
75
                        get {
 
76
                                return AttributeTargets.Field;
 
77
                        }
 
78
                }
 
79
 
 
80
                public Expression Initializer {
 
81
                        get {
 
82
                                return initializer;
 
83
                        }
 
84
                        set {
 
85
                                this.initializer = value;
 
86
                        }
 
87
                }
 
88
 
 
89
                public string Name {
 
90
                        get {
 
91
                                return MemberName.Name;
 
92
                        }
 
93
                }
 
94
 
 
95
                public FieldSpec Spec {
 
96
                        get {
 
97
                                return spec;
 
98
                        }
 
99
                }
 
100
 
 
101
                public override string[] ValidAttributeTargets  {
 
102
                        get {
 
103
                                return attribute_targets;
 
104
                        }
 
105
                }
 
106
                
 
107
                public List<FieldDeclarator> Declarators {
 
108
                        get {
 
109
                                return this.declarators;
 
110
                        }
 
111
                }
 
112
                #endregion
 
113
 
 
114
                public void AddDeclarator (FieldDeclarator declarator)
 
115
                {
 
116
                        if (declarators == null)
 
117
                                declarators = new List<FieldDeclarator> (2);
 
118
 
 
119
                        declarators.Add (declarator);
 
120
 
 
121
                        Parent.AddNameToContainer (this, declarator.Name.Value);
 
122
                }
 
123
 
 
124
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
125
                {
 
126
                        if (a.Type == pa.FieldOffset) {
 
127
                                status |= Status.HAS_OFFSET;
 
128
 
 
129
                                if (!Parent.PartialContainer.HasExplicitLayout) {
 
130
                                        Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
 
131
                                        return;
 
132
                                }
 
133
 
 
134
                                if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
 
135
                                        Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
 
136
                                        return;
 
137
                                }
 
138
                        }
 
139
 
 
140
                        if (a.Type == pa.FixedBuffer) {
 
141
                                Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
 
142
                                return;
 
143
                        }
 
144
 
 
145
#if false
 
146
                        if (a.Type == pa.MarshalAs) {
 
147
                                UnmanagedMarshal marshal = a.GetMarshal (this);
 
148
                                if (marshal != null) {
 
149
                                        FieldBuilder.SetMarshal (marshal);
 
150
                                }
 
151
                                return;
 
152
                        }
 
153
#endif
 
154
                        if ((a.HasSecurityAttribute)) {
 
155
                                a.Error_InvalidSecurityParent ();
 
156
                                return;
 
157
                        }
 
158
 
 
159
                        if (a.Type == pa.Dynamic) {
 
160
                                a.Error_MisusedDynamicAttribute ();
 
161
                                return;
 
162
                        }
 
163
 
 
164
                        FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
 
165
                }
 
166
 
 
167
                public void SetCustomAttribute (MethodSpec ctor, byte[] data)
 
168
                {
 
169
                        FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data);
 
170
                }
 
171
 
 
172
                protected override bool CheckBase ()
 
173
                {
 
174
                        if (!base.CheckBase ())
 
175
                                return false;
 
176
 
 
177
                        MemberSpec candidate;
 
178
                        bool overrides = false;
 
179
                        var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
 
180
                        if (conflict_symbol == null)
 
181
                                conflict_symbol = candidate;
 
182
 
 
183
                        if (conflict_symbol == null) {
 
184
                                if ((ModFlags & Modifiers.NEW) != 0) {
 
185
                                        Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
 
186
                                                GetSignatureForError ());
 
187
                                }
 
188
                        } else {
 
189
                                if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) {
 
190
                                        Report.SymbolRelatedToPreviousError (conflict_symbol);
 
191
                                        Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
 
192
                                                GetSignatureForError (), conflict_symbol.GetSignatureForError ());
 
193
                                }
 
194
 
 
195
                                if (conflict_symbol.IsAbstract) {
 
196
                                        Report.SymbolRelatedToPreviousError (conflict_symbol);
 
197
                                        Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
 
198
                                                GetSignatureForError (), conflict_symbol.GetSignatureForError ());
 
199
                                }
 
200
                        }
 
201
 
 
202
                        return true;
 
203
                }
 
204
 
 
205
                public virtual Constant ConvertInitializer (ResolveContext rc, Constant expr)
 
206
                {
 
207
                        return expr.ConvertImplicitly (MemberType);
 
208
                }
 
209
 
 
210
                protected override void DoMemberTypeDependentChecks ()
 
211
                {
 
212
                        base.DoMemberTypeDependentChecks ();
 
213
 
 
214
                        if (MemberType.IsGenericParameter)
 
215
                                return;
 
216
 
 
217
                        if (MemberType.IsStatic)
 
218
                                Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType, Report);
 
219
 
 
220
                        CheckBase ();
 
221
                        IsTypePermitted ();
 
222
                }
 
223
 
 
224
                //
 
225
                //   Represents header string for documentation comment.
 
226
                //
 
227
                public override string DocCommentHeader {
 
228
                        get { return "F:"; }
 
229
                }
 
230
 
 
231
                public override void Emit ()
 
232
                {
 
233
                        if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
234
                                Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder);
 
235
                        } else if (!Parent.IsCompilerGenerated && member_type.HasDynamicElement) {
 
236
                                Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
 
237
                        }
 
238
 
 
239
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
 
240
                                Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
 
241
                        if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
 
242
                                Module.PredefinedAttributes.DebuggerBrowsable.EmitAttribute (FieldBuilder, System.Diagnostics.DebuggerBrowsableState.Never);
 
243
 
 
244
                        if (OptAttributes != null) {
 
245
                                OptAttributes.Emit ();
 
246
                        }
 
247
 
 
248
                        if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) {
 
249
                                Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ());
 
250
                        }
 
251
 
 
252
                        ConstraintChecker.Check (this, member_type, type_expr.Location);
 
253
 
 
254
                        base.Emit ();
 
255
                }
 
256
 
 
257
                public static void Error_VariableOfStaticClass (Location loc, string variable_name, TypeSpec static_class, Report Report)
 
258
                {
 
259
                        Report.SymbolRelatedToPreviousError (static_class);
 
260
                        Report.Error (723, loc, "`{0}': cannot declare variables of static types",
 
261
                                variable_name);
 
262
                }
 
263
 
 
264
                protected override bool VerifyClsCompliance ()
 
265
                {
 
266
                        if (!base.VerifyClsCompliance ())
 
267
                                return false;
 
268
 
 
269
                        if (!MemberType.IsCLSCompliant () || this is FixedField) {
 
270
                                Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
 
271
                                        GetSignatureForError ());
 
272
                        }
 
273
                        return true;
 
274
                }
 
275
        }
 
276
 
 
277
        //
 
278
        // Field specification
 
279
        //
 
280
        public class FieldSpec : MemberSpec, IInterfaceMemberSpec
 
281
        {
 
282
                FieldInfo metaInfo;
 
283
                TypeSpec memberType;
 
284
 
 
285
                public FieldSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo info, Modifiers modifiers)
 
286
                        : base (MemberKind.Field, declaringType, definition, modifiers)
 
287
                {
 
288
                        this.metaInfo = info;
 
289
                        this.memberType = memberType;
 
290
                }
 
291
 
 
292
                #region Properties
 
293
 
 
294
                public bool IsReadOnly {
 
295
                        get {
 
296
                                return (Modifiers & Modifiers.READONLY) != 0;
 
297
                        }
 
298
                }
 
299
 
 
300
                public TypeSpec MemberType {
 
301
                        get {
 
302
                                return memberType;
 
303
                        }
 
304
                }
 
305
 
 
306
#endregion
 
307
 
 
308
                public FieldInfo GetMetaInfo ()
 
309
                {
 
310
                        if ((state & StateFlags.PendingMetaInflate) != 0) {
 
311
                                var decl_meta = DeclaringType.GetMetaInfo ();
 
312
                                if (DeclaringType.IsTypeBuilder) {
 
313
                                        metaInfo = TypeBuilder.GetField (decl_meta, metaInfo);
 
314
                                } else {
 
315
                                        var orig_token = metaInfo.MetadataToken;
 
316
                                        metaInfo = decl_meta.GetField (Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
 
317
                                        if (metaInfo.MetadataToken != orig_token)
 
318
                                                throw new NotImplementedException ("Resolved to wrong meta token");
 
319
 
 
320
                                        // What a stupid API, does not work because field handle is imported
 
321
                                        // metaInfo = FieldInfo.GetFieldFromHandle (metaInfo.FieldHandle, DeclaringType.MetaInfo.TypeHandle);
 
322
                                }
 
323
 
 
324
                                state &= ~StateFlags.PendingMetaInflate;
 
325
                        }
 
326
 
 
327
                        return metaInfo;
 
328
                }
 
329
 
 
330
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
 
331
                {
 
332
                        var fs = (FieldSpec) base.InflateMember (inflator);
 
333
                        fs.memberType = inflator.Inflate (memberType);
 
334
                        return fs;
 
335
                }
 
336
 
 
337
                public FieldSpec Mutate (TypeParameterMutator mutator)
 
338
                {
 
339
                        var decl = DeclaringType;
 
340
                        if (DeclaringType.IsGenericOrParentIsGeneric)
 
341
                                decl = mutator.Mutate (decl);
 
342
 
 
343
                        if (decl == DeclaringType)
 
344
                                return this;
 
345
 
 
346
                        var fs = (FieldSpec) MemberwiseClone ();
 
347
                        fs.declaringType = decl;
 
348
                        fs.state |= StateFlags.PendingMetaInflate;
 
349
 
 
350
                        // Gets back FieldInfo in case of metaInfo was inflated
 
351
                        fs.metaInfo = MemberCache.GetMember (TypeParameterMutator.GetMemberDeclaringType (DeclaringType), this).metaInfo;
 
352
                        return fs;
 
353
                }
 
354
 
 
355
                public override List<TypeSpec> ResolveMissingDependencies ()
 
356
                {
 
357
                        return memberType.ResolveMissingDependencies ();
 
358
                }
 
359
        }
 
360
 
 
361
        /// <summary>
 
362
        /// Fixed buffer implementation
 
363
        /// </summary>
 
364
        public class FixedField : FieldBase
 
365
        {
 
366
                public const string FixedElementName = "FixedElementField";
 
367
                static int GlobalCounter = 0;
 
368
 
 
369
                TypeBuilder fixed_buffer_type;
 
370
 
 
371
                const Modifiers AllowedModifiers =
 
372
                        Modifiers.NEW |
 
373
                        Modifiers.PUBLIC |
 
374
                        Modifiers.PROTECTED |
 
375
                        Modifiers.INTERNAL |
 
376
                        Modifiers.PRIVATE |
 
377
                        Modifiers.UNSAFE;
 
378
 
 
379
                public FixedField (TypeDefinition parent, FullNamedExpression type, Modifiers mod, MemberName name, Attributes attrs)
 
380
                        : base (parent, type, mod, AllowedModifiers, name, attrs)
 
381
                {
 
382
                }
 
383
 
 
384
                #region Properties
 
385
 
 
386
                //
 
387
                // Explicit struct layout set by parent
 
388
                //
 
389
                public CharSet? CharSet {
 
390
                        get; set;
 
391
                }               
 
392
 
 
393
                #endregion
 
394
 
 
395
                public override Constant ConvertInitializer (ResolveContext rc, Constant expr)
 
396
                {
 
397
                        return expr.ImplicitConversionRequired (rc, rc.BuiltinTypes.Int, Location);
 
398
                }
 
399
 
 
400
                public override bool Define ()
 
401
                {
 
402
                        if (!base.Define ())
 
403
                                return false;
 
404
 
 
405
                        if (!BuiltinTypeSpec.IsPrimitiveType (MemberType)) {
 
406
                                Report.Error (1663, Location,
 
407
                                        "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double",
 
408
                                        GetSignatureForError ());
 
409
                        } else if (declarators != null) {
 
410
                                var t = new TypeExpression (MemberType, TypeExpression.Location);
 
411
                                foreach (var d in declarators) {
 
412
                                        var f = new FixedField (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
 
413
                                        f.initializer = d.Initializer;
 
414
                                        ((ConstInitializer) f.initializer).Name = d.Name.Value;
 
415
                                        f.Define ();
 
416
                                        Parent.PartialContainer.Members.Add (f);
 
417
                                }
 
418
                        }
 
419
                        
 
420
                        // Create nested fixed buffer container
 
421
                        string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
 
422
                        fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
 
423
                                TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit,
 
424
                                Compiler.BuiltinTypes.ValueType.GetMetaInfo ());
 
425
 
 
426
                        var ffield = fixed_buffer_type.DefineField (FixedElementName, MemberType.GetMetaInfo (), FieldAttributes.Public);
 
427
                        
 
428
                        FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, ModifiersExtensions.FieldAttr (ModFlags));
 
429
 
 
430
                        var element_spec = new FieldSpec (null, this, MemberType, ffield, ModFlags);
 
431
                        spec = new FixedFieldSpec (Module, Parent.Definition, this, FieldBuilder, element_spec, ModFlags);
 
432
 
 
433
                        Parent.MemberCache.AddMember (spec);
 
434
                        return true;
 
435
                }
 
436
 
 
437
                protected override void DoMemberTypeIndependentChecks ()
 
438
                {
 
439
                        base.DoMemberTypeIndependentChecks ();
 
440
 
 
441
                        if (!IsUnsafe)
 
442
                                Expression.UnsafeError (Report, Location);
 
443
 
 
444
                        if (Parent.PartialContainer.Kind != MemberKind.Struct) {
 
445
                                Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
 
446
                                        GetSignatureForError ());
 
447
                        }
 
448
                }
 
449
                
 
450
                public override void Accept (StructuralVisitor visitor)
 
451
                {
 
452
                        visitor.Visit (this);
 
453
                }
 
454
 
 
455
                public override void Emit()
 
456
                {
 
457
                        ResolveContext rc = new ResolveContext (this);
 
458
                        IntConstant buffer_size_const = initializer.Resolve (rc) as IntConstant;
 
459
                        if (buffer_size_const == null)
 
460
                                return;
 
461
 
 
462
                        int buffer_size = buffer_size_const.Value;
 
463
 
 
464
                        if (buffer_size <= 0) {
 
465
                                Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
 
466
                                return;
 
467
                        }
 
468
 
 
469
                        EmitFieldSize (buffer_size);
 
470
 
 
471
#if STATIC
 
472
                        if (Module.HasDefaultCharSet)
 
473
                                fixed_buffer_type.__SetAttributes (fixed_buffer_type.Attributes | Module.DefaultCharSetType);
 
474
#endif
 
475
 
 
476
                        Module.PredefinedAttributes.UnsafeValueType.EmitAttribute (fixed_buffer_type);
 
477
                        Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (fixed_buffer_type);
 
478
                        fixed_buffer_type.CreateType ();
 
479
 
 
480
                        base.Emit ();
 
481
                }
 
482
 
 
483
                void EmitFieldSize (int buffer_size)
 
484
                {
 
485
                        int type_size = BuiltinTypeSpec.GetSize (MemberType);
 
486
 
 
487
                        if (buffer_size > int.MaxValue / type_size) {
 
488
                                Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
 
489
                                        GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
 
490
                                return;
 
491
                        }
 
492
 
 
493
                        AttributeEncoder encoder;
 
494
 
 
495
                        var ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location);
 
496
                        if (ctor == null)
 
497
                                return;
 
498
 
 
499
                        var field_size = Module.PredefinedMembers.StructLayoutSize.Resolve (Location);
 
500
                        var field_charset = Module.PredefinedMembers.StructLayoutCharSet.Resolve (Location);
 
501
                        if (field_size == null || field_charset == null)
 
502
                                return;
 
503
 
 
504
                        var char_set = CharSet ?? Module.DefaultCharSet ?? 0;
 
505
 
 
506
                        encoder = new AttributeEncoder ();
 
507
                        encoder.Encode ((short)LayoutKind.Sequential);
 
508
                        encoder.EncodeNamedArguments (
 
509
                                new [] { field_size, field_charset },
 
510
                                new Constant [] { 
 
511
                                        new IntConstant (Compiler.BuiltinTypes, buffer_size * type_size, Location),
 
512
                                        new IntConstant (Compiler.BuiltinTypes, (int) char_set, Location)
 
513
                                }
 
514
                        );
 
515
 
 
516
                        fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
517
 
 
518
                        //
 
519
                        // Don't emit FixedBufferAttribute attribute for private types
 
520
                        //
 
521
                        if ((ModFlags & Modifiers.PRIVATE) != 0)
 
522
                                return;
 
523
 
 
524
                        ctor = Module.PredefinedMembers.FixedBufferAttributeCtor.Resolve (Location);
 
525
                        if (ctor == null)
 
526
                                return;
 
527
 
 
528
                        encoder = new AttributeEncoder ();
 
529
                        encoder.EncodeTypeName (MemberType);
 
530
                        encoder.Encode (buffer_size);
 
531
                        encoder.EncodeEmptyNamedArguments ();
 
532
 
 
533
                        FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
534
                }
 
535
        }
 
536
 
 
537
        class FixedFieldSpec : FieldSpec
 
538
        {
 
539
                readonly FieldSpec element;
 
540
 
 
541
                public FixedFieldSpec (ModuleContainer module, TypeSpec declaringType, IMemberDefinition definition, FieldInfo info, FieldSpec element, Modifiers modifiers)
 
542
                        : base (declaringType, definition, PointerContainer.MakeType (module, element.MemberType), info, modifiers)
 
543
                {
 
544
                        this.element = element;
 
545
 
 
546
                        // It's never CLS-Compliant
 
547
                        state &= ~StateFlags.CLSCompliant_Undetected;
 
548
                }
 
549
 
 
550
                public FieldSpec Element {
 
551
                        get {
 
552
                                return element;
 
553
                        }
 
554
                }
 
555
                
 
556
                public TypeSpec ElementType {
 
557
                        get {
 
558
                                return element.MemberType;
 
559
                        }
 
560
                }
 
561
        }
 
562
 
 
563
        //
 
564
        // The Field class is used to represents class/struct fields during parsing.
 
565
        //
 
566
        public class Field : FieldBase {
 
567
                // <summary>
 
568
                //   Modifiers allowed in a class declaration
 
569
                // </summary>
 
570
                const Modifiers AllowedModifiers =
 
571
                        Modifiers.NEW |
 
572
                        Modifiers.PUBLIC |
 
573
                        Modifiers.PROTECTED |
 
574
                        Modifiers.INTERNAL |
 
575
                        Modifiers.PRIVATE |
 
576
                        Modifiers.STATIC |
 
577
                        Modifiers.VOLATILE |
 
578
                        Modifiers.UNSAFE |
 
579
                        Modifiers.READONLY;
 
580
 
 
581
                public Field (TypeDefinition parent, FullNamedExpression type, Modifiers mod, MemberName name, Attributes attrs)
 
582
                        : base (parent, type, mod, AllowedModifiers, name, attrs)
 
583
                {
 
584
                }
 
585
 
 
586
                bool CanBeVolatile ()
 
587
                {
 
588
                        switch (MemberType.BuiltinType) {
 
589
                        case BuiltinTypeSpec.Type.Bool:
 
590
                        case BuiltinTypeSpec.Type.Char:
 
591
                        case BuiltinTypeSpec.Type.SByte:
 
592
                        case BuiltinTypeSpec.Type.Byte:
 
593
                        case BuiltinTypeSpec.Type.Short:
 
594
                        case BuiltinTypeSpec.Type.UShort:
 
595
                        case BuiltinTypeSpec.Type.Int:
 
596
                        case BuiltinTypeSpec.Type.UInt:
 
597
                        case BuiltinTypeSpec.Type.Float:
 
598
                        case BuiltinTypeSpec.Type.UIntPtr:
 
599
                        case BuiltinTypeSpec.Type.IntPtr:
 
600
                                return true;
 
601
                        }
 
602
 
 
603
                        if (TypeSpec.IsReferenceType (MemberType))
 
604
                                return true;
 
605
 
 
606
                        if (MemberType.IsEnum)
 
607
                                return true;
 
608
 
 
609
                        return false;
 
610
                }
 
611
 
 
612
                public override void Accept (StructuralVisitor visitor)
 
613
                {
 
614
                        visitor.Visit (this);
 
615
                }
 
616
                
 
617
                public override bool Define ()
 
618
                {
 
619
                        if (!base.Define ())
 
620
                                return false;
 
621
 
 
622
                        MetaType[] required_modifier = null;
 
623
                        if ((ModFlags & Modifiers.VOLATILE) != 0) {
 
624
                                var mod = Module.PredefinedTypes.IsVolatile.Resolve ();
 
625
                                if (mod != null)
 
626
                                        required_modifier = new MetaType[] { mod.GetMetaInfo () };
 
627
                        }
 
628
 
 
629
                        FieldBuilder = Parent.TypeBuilder.DefineField (
 
630
                                Name, member_type.GetMetaInfo (), required_modifier, null, ModifiersExtensions.FieldAttr (ModFlags));
 
631
 
 
632
                        spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags);
 
633
 
 
634
                        //
 
635
                        // Don't cache inaccessible fields except for struct where we
 
636
                        // need them for definitive assignment checks
 
637
                        //
 
638
                        if ((ModFlags & Modifiers.BACKING_FIELD) == 0 || Parent.Kind == MemberKind.Struct) {
 
639
                                Parent.MemberCache.AddMember (spec);
 
640
                        }
 
641
 
 
642
                        if (initializer != null) {
 
643
                                Parent.RegisterFieldForInitialization (this, new FieldInitializer (this, initializer, TypeExpression.Location));
 
644
                        }
 
645
 
 
646
                        if (declarators != null) {
 
647
                                foreach (var d in declarators) {
 
648
                                        var t = new TypeExpression (MemberType, d.Name.Location);
 
649
                                        var f = new Field (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
 
650
                                        if (d.Initializer != null)
 
651
                                                f.initializer = d.Initializer;
 
652
 
 
653
                                        f.Define ();
 
654
                                        Parent.PartialContainer.Members.Add (f);
 
655
                                }
 
656
                        }
 
657
 
 
658
                        return true;
 
659
                }
 
660
 
 
661
                protected override void DoMemberTypeDependentChecks ()
 
662
                {
 
663
                        if ((ModFlags & Modifiers.BACKING_FIELD) != 0)
 
664
                                return;
 
665
 
 
666
                        base.DoMemberTypeDependentChecks ();
 
667
 
 
668
                        if ((ModFlags & Modifiers.VOLATILE) != 0) {
 
669
                                if (!CanBeVolatile ()) {
 
670
                                        Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
 
671
                                                GetSignatureForError (), TypeManager.CSharpName (MemberType));
 
672
                                }
 
673
 
 
674
                                if ((ModFlags & Modifiers.READONLY) != 0) {
 
675
                                        Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
 
676
                                                GetSignatureForError ());
 
677
                                }
 
678
                        }
 
679
                }
 
680
 
 
681
                protected override bool VerifyClsCompliance ()
 
682
                {
 
683
                        if (!base.VerifyClsCompliance ())
 
684
                                return false;
 
685
 
 
686
                        if ((ModFlags & Modifiers.VOLATILE) != 0) {
 
687
                                Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
 
688
                        }
 
689
 
 
690
                        return true;
 
691
                }
 
692
        }
 
693
}