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