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