Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / mcs / decl.cs
1 //
2 // decl.cs: Declaration base class for structs, classes, enums and interfaces.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Marek Safar (marek.safar@seznam.cz)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2004-2008 Novell, Inc
11 // Copyright 2011 Xamarin Inc
12 //
13 //
14
15 using System;
16 using System.Collections.Generic;
17 using System.Diagnostics;
18 using System.Text;
19 using Mono.CompilerServices.SymbolWriter;
20
21 #if MOBILE
22 using XmlElement = System.Object;
23 #else
24 using System.Xml;
25 #endif
26
27 #if STATIC
28 using IKVM.Reflection;
29 using IKVM.Reflection.Emit;
30 #else
31 using System.Reflection;
32 using System.Reflection.Emit;
33 #endif
34
35 namespace Mono.CSharp {
36
37         //
38         // Better name would be DottenName
39         //
40         [DebuggerDisplay ("{GetSignatureForError()}")]
41         public class MemberName
42         {
43                 public static readonly MemberName Null = new MemberName ("");
44
45                 public readonly string Name;
46                 public TypeParameters TypeParameters;
47                 public readonly FullNamedExpression ExplicitInterface;
48                 public readonly Location Location;
49
50                 public readonly MemberName Left;
51
52                 public MemberName (string name)
53                         : this (name, Location.Null)
54                 { }
55
56                 public MemberName (string name, Location loc)
57                         : this (null, name, loc)
58                 { }
59
60                 public MemberName (string name, TypeParameters tparams, Location loc)
61                 {
62                         this.Name = name;
63                         this.Location = loc;
64
65                         this.TypeParameters = tparams;
66                 }
67
68                 public MemberName (string name, TypeParameters tparams, FullNamedExpression explicitInterface, Location loc)
69                         : this (name, tparams, loc)
70                 {
71                         this.ExplicitInterface = explicitInterface;
72                 }
73
74                 public MemberName (MemberName left, string name, Location loc)
75                 {
76                         this.Name = name;
77                         this.Location = loc;
78                         this.Left = left;
79                 }
80
81                 public MemberName (MemberName left, string name, FullNamedExpression explicitInterface, Location loc)
82                         : this (left, name, loc)
83                 {
84                         this.ExplicitInterface = explicitInterface;
85                 }
86
87                 public MemberName (MemberName left, MemberName right)
88                 {
89                         this.Name = right.Name;
90                         this.Location = right.Location;
91                         this.TypeParameters = right.TypeParameters;
92                         this.Left = left;
93                 }
94
95                 public int Arity {
96                         get {
97                                 return TypeParameters == null ? 0 : TypeParameters.Count;
98                         }
99                 }
100
101                 public bool IsGeneric {
102                         get {
103                                 return TypeParameters != null;
104                         }
105                 }
106
107                 public string Basename {
108                         get {
109                                 if (TypeParameters != null)
110                                         return MakeName (Name, TypeParameters);
111                                 return Name;
112                         }
113                 }
114
115                 public void CreateMetadataName (StringBuilder sb)
116                 {
117                         if (Left != null)
118                                 Left.CreateMetadataName (sb);
119
120                         if (sb.Length != 0) {
121                                 sb.Append (".");
122                         }
123
124                         sb.Append (Basename);
125                 }
126
127                 public string GetSignatureForDocumentation ()
128                 {
129                         var s = Basename;
130
131                         if (ExplicitInterface != null)
132                                 s = ExplicitInterface.GetSignatureForError () + "." + s;
133
134                         if (Left == null)
135                                 return s;
136
137                         return Left.GetSignatureForDocumentation () + "." + s;
138                 }
139
140                 public string GetSignatureForError ()
141                 {
142                         string s = TypeParameters == null ? null : "<" + TypeParameters.GetSignatureForError () + ">";
143                         s = Name + s;
144
145                         if (ExplicitInterface != null)
146                                 s = ExplicitInterface.GetSignatureForError () + "." + s;
147
148                         if (Left == null)
149                                 return s;
150
151                         return Left.GetSignatureForError () + "." + s;
152                 }
153
154                 public override bool Equals (object other)
155                 {
156                         return Equals (other as MemberName);
157                 }
158
159                 public bool Equals (MemberName other)
160                 {
161                         if (this == other)
162                                 return true;
163                         if (other == null || Name != other.Name)
164                                 return false;
165
166                         if ((TypeParameters != null) &&
167                             (other.TypeParameters == null || TypeParameters.Count != other.TypeParameters.Count))
168                                 return false;
169
170                         if ((TypeParameters == null) && (other.TypeParameters != null))
171                                 return false;
172
173                         if (Left == null)
174                                 return other.Left == null;
175
176                         return Left.Equals (other.Left);
177                 }
178
179                 public override int GetHashCode ()
180                 {
181                         int hash = Name.GetHashCode ();
182                         for (MemberName n = Left; n != null; n = n.Left)
183                                 hash ^= n.Name.GetHashCode ();
184
185                         if (TypeParameters != null)
186                                 hash ^= TypeParameters.Count << 5;
187
188                         return hash & 0x7FFFFFFF;
189                 }
190
191                 public static string MakeName (string name, TypeParameters args)
192                 {
193                         if (args == null)
194                                 return name;
195
196                         return name + "`" + args.Count;
197                 }
198         }
199
200         public class SimpleMemberName
201         {
202                 public string Value;
203                 public Location Location;
204
205                 public SimpleMemberName (string name, Location loc)
206                 {
207                         this.Value = name;
208                         this.Location = loc;
209                 }
210         }
211
212         /// <summary>
213         ///   Base representation for members.  This is used to keep track
214         ///   of Name, Location and Modifier flags, and handling Attributes.
215         /// </summary>
216         [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")]
217         public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition
218         {
219                 string IMemberDefinition.Name {
220                         get {
221                                 return member_name.Name;
222                         }
223                 }
224
225                 // Is not readonly because of IndexerName attribute
226                 private MemberName member_name;
227                 public MemberName MemberName {
228                         get { return member_name; }
229                 }
230
231                 /// <summary>
232                 ///   Modifier flags that the user specified in the source code
233                 /// </summary>
234                 private Modifiers mod_flags;
235                 public Modifiers ModFlags {
236                         set {
237                                 mod_flags = value;
238                                 if ((value & Modifiers.COMPILER_GENERATED) != 0)
239                                         caching_flags = Flags.IsUsed | Flags.IsAssigned;
240                         }
241                         get {
242                                 return mod_flags;
243                         }
244                 }
245
246                 public virtual ModuleContainer Module {
247                         get {
248                                 return Parent.Module;
249                         }
250                 }
251
252                 public /*readonly*/ TypeContainer Parent;
253
254                 /// <summary>
255                 ///   Location where this declaration happens
256                 /// </summary>
257                 public Location Location {
258                         get { return member_name.Location; }
259                 }
260
261                 /// <summary>
262                 ///   XML documentation comment
263                 /// </summary>
264                 protected string comment;
265
266                 /// <summary>
267                 ///   Represents header string for documentation comment 
268                 ///   for each member types.
269                 /// </summary>
270                 public abstract string DocCommentHeader { get; }
271
272                 [Flags]
273                 public enum Flags {
274                         Obsolete_Undetected = 1,                // Obsolete attribute has not been detected yet
275                         Obsolete = 1 << 1,                      // Type has obsolete attribute
276                         ClsCompliance_Undetected = 1 << 2,      // CLS Compliance has not been detected yet
277                         ClsCompliant = 1 << 3,                  // Type is CLS Compliant
278                         CloseTypeCreated = 1 << 4,              // Tracks whether we have Closed the type
279                         HasCompliantAttribute_Undetected = 1 << 5,      // Presence of CLSCompliantAttribute has not been detected
280                         HasClsCompliantAttribute = 1 << 6,                      // Type has CLSCompliantAttribute
281                         ClsCompliantAttributeFalse = 1 << 7,                    // Member has CLSCompliant(false)
282                         Excluded_Undetected = 1 << 8,           // Conditional attribute has not been detected yet
283                         Excluded = 1 << 9,                                      // Method is conditional
284                         MethodOverloadsExist = 1 << 10,         // Test for duplication must be performed
285                         IsUsed = 1 << 11,
286                         IsAssigned = 1 << 12,                           // Field is assigned
287                         HasExplicitLayout       = 1 << 13,
288                         PartialDefinitionExists = 1 << 14,      // Set when corresponding partial method definition exists
289                         HasStructLayout = 1 << 15,                      // Has StructLayoutAttribute
290                         HasInstanceConstructor = 1 << 16,
291                         HasUserOperators = 1 << 17,
292                         CanBeReused = 1 << 18,
293                         InterfacesExpanded = 1 << 19,
294                         HasInstanceField = 1 << 20
295                 }
296
297                 /// <summary>
298                 ///   MemberCore flags at first detected then cached
299                 /// </summary>
300                 internal Flags caching_flags;
301
302                 protected MemberCore (TypeContainer parent, MemberName name, Attributes attrs)
303                 {
304                         this.Parent = parent;
305                         member_name = name;
306                         caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
307                         AddAttributes (attrs, this);
308                 }
309
310                 protected virtual void SetMemberName (MemberName new_name)
311                 {
312                         member_name = new_name;
313                 }
314
315                 public virtual void Accept (StructuralVisitor visitor)
316                 {
317                         visitor.Visit (this);
318                 }
319
320                 protected bool CheckAbstractAndExtern (bool has_block)
321                 {
322                         if (Parent.PartialContainer.Kind == MemberKind.Interface)
323                                 return true;
324
325                         if (has_block) {
326                                 if ((ModFlags & Modifiers.EXTERN) != 0) {
327                                         Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
328                                                 GetSignatureForError ());
329                                         return false;
330                                 }
331
332                                 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
333                                         Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
334                                                 GetSignatureForError ());
335                                         return false;
336                                 }
337                         } else {
338                                 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) {
339                                         if (Compiler.Settings.Version >= LanguageVersion.V_3) {
340                                                 Property.PropertyMethod pm = this as Property.PropertyMethod;
341                                                 if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod)
342                                                         pm = null;
343
344                                                 if (pm != null && pm.Property.AccessorSecond == null) {
345                                                         Report.Error (840, Location,
346                                                                 "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors",
347                                                                 GetSignatureForError ());
348                                                         return false;
349                                                 }
350                                         }
351
352                                         Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial",
353                                                       GetSignatureForError ());
354                                         return false;
355                                 }
356                         }
357
358                         return true;
359                 }
360
361                 protected void CheckProtectedModifier ()
362                 {
363                         if ((ModFlags & Modifiers.PROTECTED) == 0)
364                                 return;
365
366                         if (Parent.PartialContainer.Kind == MemberKind.Struct) {
367                                 Report.Error (666, Location, "`{0}': Structs cannot contain protected members",
368                                         GetSignatureForError ());
369                                 return;
370                         }
371
372                         if ((Parent.ModFlags & Modifiers.STATIC) != 0) {
373                                 Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members",
374                                         GetSignatureForError ());
375                                 return;
376                         }
377
378                         if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 &&
379                                 !(this is Destructor)) {
380                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class",
381                                         GetSignatureForError ());
382                                 return;
383                         }
384                 }
385
386                 public abstract bool Define ();
387
388                 public virtual string DocComment {
389                         get {
390                                 return comment;
391                         }
392                         set {
393                                 comment = value;
394                         }
395                 }
396
397                 // 
398                 // Returns full member name for error message
399                 //
400                 public virtual string GetSignatureForError ()
401                 {
402                         var parent = Parent.GetSignatureForError ();
403                         if (parent == null)
404                                 return member_name.GetSignatureForError ();
405
406                         return parent + "." + member_name.GetSignatureForError ();
407                 }
408
409                 /// <summary>
410                 /// Base Emit method. This is also entry point for CLS-Compliant verification.
411                 /// </summary>
412                 public virtual void Emit ()
413                 {
414                         if (!Compiler.Settings.VerifyClsCompliance)
415                                 return;
416
417                         VerifyClsCompliance ();
418                 }
419
420                 public bool IsAvailableForReuse {
421                         get {
422                                 return (caching_flags & Flags.CanBeReused) != 0;
423                         }
424                         set {
425                                 caching_flags = value ? (caching_flags | Flags.CanBeReused) : (caching_flags & ~Flags.CanBeReused);
426                         }
427                 }
428
429                 public bool IsCompilerGenerated {
430                         get     {
431                                 if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0)
432                                         return true;
433
434                                 return Parent != null && Parent.IsCompilerGenerated;
435                         }
436                 }
437
438                 public bool IsImported {
439                         get {
440                                 return false;
441                         }
442                 }
443
444                 public virtual bool IsUsed {
445                         get {
446                                 return (caching_flags & Flags.IsUsed) != 0;
447                         }
448                 }
449
450                 protected Report Report {
451                         get {
452                                 return Compiler.Report;
453                         }
454                 }
455
456                 public void SetIsUsed ()
457                 {
458                         caching_flags |= Flags.IsUsed;
459                 }
460
461                 public void SetIsAssigned ()
462                 {
463                         caching_flags |= Flags.IsAssigned;
464                 }
465
466                 public virtual void SetConstraints (List<Constraints> constraints_list)
467                 {
468                         var tparams = member_name.TypeParameters;
469                         if (tparams == null) {
470                                 Report.Error (80, Location, "Constraints are not allowed on non-generic declarations");
471                                 return;
472                         }
473
474                         foreach (var c in constraints_list) {
475                                 var tp = tparams.Find (c.TypeParameter.Value);
476                                 if (tp == null) {
477                                         Report.Error (699, c.Location, "`{0}': A constraint references nonexistent type parameter `{1}'",
478                                                 GetSignatureForError (), c.TypeParameter.Value);
479                                         continue;
480                                 }
481
482                                 tp.Constraints = c;
483                         }
484                 }
485
486                 /// <summary>
487                 /// Returns instance of ObsoleteAttribute for this MemberCore
488                 /// </summary>
489                 public virtual ObsoleteAttribute GetAttributeObsolete ()
490                 {
491                         if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0)
492                                 return null;
493
494                         caching_flags &= ~Flags.Obsolete_Undetected;
495
496                         if (OptAttributes == null)
497                                 return null;
498
499                         Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete);
500                         if (obsolete_attr == null)
501                                 return null;
502
503                         caching_flags |= Flags.Obsolete;
504
505                         ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute ();
506                         if (obsolete == null)
507                                 return null;
508
509                         return obsolete;
510                 }
511
512                 //
513                 // Checks whether the type P is as accessible as this member
514                 //
515                 public bool IsAccessibleAs (TypeSpec p)
516                 {
517                         //
518                         // if M is private, its accessibility is the same as this declspace.
519                         // we already know that P is accessible to T before this method, so we
520                         // may return true.
521                         //
522                         if ((mod_flags & Modifiers.PRIVATE) != 0)
523                                 return true;
524
525                         while (TypeManager.HasElementType (p))
526                                 p = TypeManager.GetElementType (p);
527
528                         if (p.BuiltinType != BuiltinTypeSpec.Type.None)
529                                 return true;
530
531                         if (p.IsGenericParameter)
532                                 return true;
533
534                         for (TypeSpec p_parent; p != null; p = p_parent) {
535                                 p_parent = p.DeclaringType;
536
537                                 if (p.IsGeneric) {
538                                         foreach (TypeSpec t in p.TypeArguments) {
539                                                 if (!IsAccessibleAs (t))
540                                                         return false;
541                                         }
542                                 }
543
544                                 var pAccess = p.Modifiers & Modifiers.AccessibilityMask;
545                                 if (pAccess == Modifiers.PUBLIC)
546                                         continue;
547
548                                 bool same_access_restrictions = false;
549                                 for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) {
550                                         var tc = mc as TypeContainer;
551                                         if (tc != null && tc.PartialContainer != null)
552                                                 mc = tc.PartialContainer;
553
554                                         var al = mc.ModFlags & Modifiers.AccessibilityMask;
555                                         switch (pAccess) {
556                                         case Modifiers.INTERNAL:
557                                                 if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL)
558                                                         same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
559                                                 
560                                                 break;
561
562                                         case Modifiers.PROTECTED:
563                                                 if (al == Modifiers.PROTECTED) {
564                                                         same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent);
565                                                         break;
566                                                 }
567
568                                                 if (al == Modifiers.PRIVATE) {
569                                                         //
570                                                         // When type is private and any of its parents derives from
571                                                         // protected type then the type is accessible
572                                                         //
573                                                         while (mc.Parent != null && mc.Parent.PartialContainer != null) {
574                                                                 if (mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent)) {
575                                                                         same_access_restrictions = true;
576                                                                         break;
577                                                                 }
578
579                                                                 mc = mc.Parent; 
580                                                         }
581                                                 }
582                                                 
583                                                 break;
584
585                                         case Modifiers.PROTECTED | Modifiers.INTERNAL:
586                                                 if (al == Modifiers.INTERNAL)
587                                                         same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
588                                                 else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
589                                                         same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
590                                                 else if (al == Modifiers.PROTECTED)
591                                                         goto case Modifiers.PROTECTED;
592                                                 else if (al == Modifiers.PRIVATE) {
593                                                         if (p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly)) {
594                                                                 same_access_restrictions = true;
595                                                         } else {
596                                                                 goto case Modifiers.PROTECTED;
597                                                         }
598                                                 }
599
600                                                 break;
601
602                                         case Modifiers.PRIVATE:
603                                                 //
604                                                 // Both are private and share same parent
605                                                 //
606                                                 if (al == Modifiers.PRIVATE) {
607                                                         var decl = mc.Parent;
608                                                         do {
609                                                                 same_access_restrictions = decl.CurrentType.MemberDefinition == p_parent.MemberDefinition;
610                                                         } while (!same_access_restrictions && !decl.PartialContainer.IsTopLevel && (decl = decl.Parent) != null);
611                                                 }
612                                                 
613                                                 break;
614                                                 
615                                         default:
616                                                 throw new InternalErrorException (al.ToString ());
617                                         }
618                                 }
619                                 
620                                 if (!same_access_restrictions)
621                                         return false;
622                         }
623
624                         return true;
625                 }
626
627                 /// <summary>
628                 /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
629                 /// </summary>
630                 public override bool IsClsComplianceRequired ()
631                 {
632                         if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
633                                 return (caching_flags & Flags.ClsCompliant) != 0;
634
635                         caching_flags &= ~Flags.ClsCompliance_Undetected;
636
637                         if (HasClsCompliantAttribute) {
638                                 if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0)
639                                         return false;
640
641                                 caching_flags |= Flags.ClsCompliant;
642                                 return true;
643                         }
644
645                         if (Parent.IsClsComplianceRequired ()) {
646                                 caching_flags |= Flags.ClsCompliant;
647                                 return true;
648                         }
649
650                         return false;
651                 }
652
653                 public virtual string[] ConditionalConditions ()
654                 {
655                         return null;
656                 }
657
658                 /// <summary>
659                 /// Returns true when MemberCore is exposed from assembly.
660                 /// </summary>
661                 public bool IsExposedFromAssembly ()
662                 {
663                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
664                                 return this is NamespaceContainer;
665                         
666                         var parentContainer = Parent.PartialContainer;
667                         while (parentContainer != null) {
668                                 if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
669                                         return false;
670
671                                 parentContainer = parentContainer.Parent.PartialContainer;
672                         }
673
674                         return true;
675                 }
676
677                 //
678                 // Does extension methods look up to find a method which matches name and extensionType.
679                 // Search starts from this namespace and continues hierarchically up to top level.
680                 //
681                 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
682                 {
683                         var m = Parent;
684                         do {
685                                 var ns = m as NamespaceContainer;
686                                 if (ns != null)
687                                         return ns.LookupExtensionMethod (this, name, arity, 0);
688
689                                 m = m.Parent;
690                         } while (m != null);
691
692                         return null;
693                 }
694
695                 public virtual FullNamedExpression LookupNamespaceAlias (string name)
696                 {
697                         return Parent.LookupNamespaceAlias (name);
698                 }
699
700                 public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
701                 {
702                         return Parent.LookupNamespaceOrType (name, arity, mode, loc);
703                 }
704
705                 /// <summary>
706                 /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
707                 /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
708                 /// </summary>
709                 public bool? CLSAttributeValue {
710                         get {
711                                 if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) {
712                                         if ((caching_flags & Flags.HasClsCompliantAttribute) == 0)
713                                                 return null;
714
715                                         return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0;
716                                 }
717
718                                 caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
719
720                                 if (OptAttributes != null) {
721                                         Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
722                                         if (cls_attribute != null) {
723                                                 caching_flags |= Flags.HasClsCompliantAttribute;
724                                                 if (cls_attribute.GetClsCompliantAttributeValue ())
725                                                         return true;
726
727                                                 caching_flags |= Flags.ClsCompliantAttributeFalse;
728                                                 return false;
729                                         }
730                                 }
731
732                                 return null;
733                         }
734                 }
735
736                 /// <summary>
737                 /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
738                 /// </summary>
739                 protected bool HasClsCompliantAttribute {
740                         get {
741                                 return CLSAttributeValue.HasValue;
742                         }
743                 }
744
745                 /// <summary>
746                 /// Returns true when a member supports multiple overloads (methods, indexers, etc)
747                 /// </summary>
748                 public virtual bool EnableOverloadChecks (MemberCore overload)
749                 {
750                         return false;
751                 }
752
753                 /// <summary>
754                 /// The main virtual method for CLS-Compliant verifications.
755                 /// The method returns true if member is CLS-Compliant and false if member is not
756                 /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
757                 /// and add their extra verifications.
758                 /// </summary>
759                 protected virtual bool VerifyClsCompliance ()
760                 {
761                         if (HasClsCompliantAttribute) {
762                                 if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) {
763                                         Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
764                                         if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
765                                                 Report.Warning (3021, 2, a.Location,
766                                                         "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant",
767                                                         GetSignatureForError ());
768                                         } else {
769                                                 Report.Warning (3014, 1, a.Location,
770                                                         "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
771                                                         GetSignatureForError ());
772                                         }
773                                         return false;
774                                 }
775
776                                 if (!IsExposedFromAssembly ()) {
777                                         Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
778                                         Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ());
779                                         return false;
780                                 }
781
782                                 if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
783                                         if (Parent is Interface && Parent.IsClsComplianceRequired ()) {
784                                                 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
785                                         } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) {
786                                                 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
787                                         }
788
789                                         return false;
790                                 }
791
792                                 if (Parent.Kind != MemberKind.Namespace && Parent.Kind != 0 && !Parent.IsClsComplianceRequired ()) {
793                                         Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
794                                         Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
795                                                 GetSignatureForError (), Parent.GetSignatureForError ());
796                                         return false;
797                                 }
798                         } else {
799                                 if (!IsExposedFromAssembly ())
800                                         return false;
801
802                                 if (!Parent.IsClsComplianceRequired ())
803                                         return false;
804                         }
805
806                         if (member_name.Name [0] == '_') {
807                                 Warning_IdentifierNotCompliant ();
808                         }
809
810                         if (member_name.TypeParameters != null)
811                                 member_name.TypeParameters.VerifyClsCompliance ();
812
813                         return true;
814                 }
815
816                 protected void Warning_IdentifierNotCompliant ()
817                 {
818                         Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ());
819                 }
820
821                 public virtual string GetCallerMemberName ()
822                 {
823                         return MemberName.Name;
824                 }
825
826                 //
827                 // Returns a string that represents the signature for this 
828                 // member which should be used in XML documentation.
829                 //
830                 public abstract string GetSignatureForDocumentation ();
831
832                 public virtual void GetCompletionStartingWith (string prefix, List<string> results)
833                 {
834                         Parent.GetCompletionStartingWith (prefix, results);
835                 }
836
837                 //
838                 // Generates xml doc comments (if any), and if required,
839                 // handle warning report.
840                 //
841                 internal virtual void GenerateDocComment (DocumentationBuilder builder)
842                 {
843                         if (DocComment == null) {
844                                 if (IsExposedFromAssembly ()) {
845                                         Constructor c = this as Constructor;
846                                         if (c == null || !c.IsDefault ())
847                                                 Report.Warning (1591, 4, Location,
848                                                         "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ());
849                                 }
850
851                                 return;
852                         }
853
854                         try {
855                                 builder.GenerateDocumentationForMember (this);
856                         } catch (Exception e) {
857                                 throw new InternalErrorException (this, e);
858                         }
859                 }
860
861                 public virtual void WriteDebugSymbol (MonoSymbolFile file)
862                 {
863                 }
864
865                 #region IMemberContext Members
866
867                 public virtual CompilerContext Compiler {
868                         get {
869                                 return Module.Compiler;
870                         }
871                 }
872
873                 public virtual TypeSpec CurrentType {
874                         get { return Parent.CurrentType; }
875                 }
876
877                 public MemberCore CurrentMemberDefinition {
878                         get { return this; }
879                 }
880
881                 public virtual TypeParameters CurrentTypeParameters {
882                         get { return null; }
883                 }
884
885                 public bool IsObsolete {
886                         get {
887                                 if (GetAttributeObsolete () != null)
888                                         return true;
889
890                                 return Parent != null && Parent.IsObsolete;
891                         }
892                 }
893
894                 public bool IsUnsafe {
895                         get {
896                                 if ((ModFlags & Modifiers.UNSAFE) != 0)
897                                         return true;
898
899                                 return Parent != null && Parent.IsUnsafe;
900                         }
901                 }
902
903                 public bool IsStatic {
904                         get {
905                                 return (ModFlags & Modifiers.STATIC) != 0;
906                         }
907                 }
908
909                 #endregion
910         }
911
912         //
913         // Base member specification. A member specification contains
914         // member details which can alter in the context (e.g. generic instances)
915         //
916         public abstract class MemberSpec
917         {
918                 [Flags]
919                 public enum StateFlags
920                 {
921                         Obsolete_Undetected = 1,        // Obsolete attribute has not been detected yet
922                         Obsolete = 1 << 1,                      // Member has obsolete attribute
923                         CLSCompliant_Undetected = 1 << 2,       // CLSCompliant attribute has not been detected yet
924                         CLSCompliant = 1 << 3,          // Member is CLS Compliant
925                         MissingDependency_Undetected = 1 << 4,
926                         MissingDependency = 1 << 5,
927                         HasDynamicElement = 1 << 6,
928                         ConstraintsChecked = 1 << 7,
929                         HasNamedTupleElement = 1 << 8,
930
931                         IsAccessor = 1 << 9,            // Method is an accessor
932                         IsGeneric = 1 << 10,            // Member contains type arguments
933
934                         PendingMetaInflate = 1 << 12,
935                         PendingMakeMethod = 1 << 13,
936                         PendingMemberCacheMembers = 1 << 14,
937                         PendingBaseTypeInflate = 1 << 15,
938                         InterfacesExpanded = 1 << 16,
939                         IsNotCSharpCompatible = 1 << 17,
940                         SpecialRuntimeType = 1 << 18,
941                         InflatedExpressionType = 1 << 19,
942                         InflatedNullableType = 1 << 20,
943                         GenericIterateInterface = 1 << 21,
944                         GenericTask = 1 << 22,
945                         InterfacesImported = 1 << 23,
946                         Tuple = 1 << 24
947                 }
948
949                 //
950                 // Some flags can be copied directly from other member
951                 //
952                 protected const StateFlags SharedStateFlags =
953                         StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
954                         StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
955                         StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
956                         StateFlags.HasDynamicElement | StateFlags.HasNamedTupleElement;
957
958                 protected Modifiers modifiers;
959                 public StateFlags state;
960                 protected IMemberDefinition definition;
961                 public readonly MemberKind Kind;
962                 protected TypeSpec declaringType;
963
964 #if DEBUG
965                 static int counter;
966                 public int ID = counter++;
967 #endif
968
969                 protected MemberSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, Modifiers modifiers)
970                 {
971                         this.Kind = kind;
972                         this.declaringType = declaringType;
973                         this.definition = definition;
974                         this.modifiers = modifiers;
975
976                         if (kind == MemberKind.MissingType)
977                                 state = StateFlags.MissingDependency;
978                         else
979                                 state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected;
980                 }
981
982                 #region Properties
983
984                 public virtual int Arity {
985                         get {
986                                 return 0;
987                         }
988                 }
989
990                 public TypeSpec DeclaringType {
991                         get {
992                                 return declaringType;
993                         }
994                         set {
995                                 declaringType = value;
996                         }
997                 }
998
999                 public IMemberDefinition MemberDefinition {
1000                         get {
1001                                 return definition;
1002                         }
1003                 }
1004
1005                 public Modifiers Modifiers {
1006                         get {
1007                                 return modifiers;
1008                         }
1009                         set {
1010                                 modifiers = value;
1011                         }
1012                 }
1013                 
1014                 public virtual string Name {
1015                         get {
1016                                 return definition.Name;
1017                         }
1018                 }
1019
1020                 public bool IsAbstract {
1021                         get { return (modifiers & Modifiers.ABSTRACT) != 0; }
1022                 }
1023
1024                 public bool IsAccessor {
1025                         get {
1026                                 return (state & StateFlags.IsAccessor) != 0;
1027                         }
1028                         set {
1029                                 state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor;
1030                         }
1031                 }
1032
1033                 //
1034                 // Return true when this member is a generic in C# terms
1035                 // A nested non-generic type of generic type will return false
1036                 //
1037                 public bool IsGeneric {
1038                         get {
1039                                 return (state & StateFlags.IsGeneric) != 0;
1040                         }
1041                         set {
1042                                 state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric;
1043                         }
1044                 }
1045
1046                 //
1047                 // Returns true for imported members which are not compatible with C# language
1048                 //
1049                 public bool IsNotCSharpCompatible {
1050                         get {
1051                                 return (state & StateFlags.IsNotCSharpCompatible) != 0;
1052                         }
1053                         set {
1054                                 state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible;
1055                         }
1056                 }
1057
1058                 public bool IsPrivate {
1059                         get { return (modifiers & Modifiers.PRIVATE) != 0; }
1060                 }
1061
1062                 public bool IsPublic {
1063                         get { return (modifiers & Modifiers.PUBLIC) != 0; }
1064                 }
1065
1066                 public bool IsStatic {
1067                         get { 
1068                                 return (modifiers & Modifiers.STATIC) != 0;
1069                         }
1070                 }
1071
1072                 #endregion
1073
1074                 public virtual void CheckObsoleteness (IMemberContext mc, Location loc)
1075                 {
1076                         var oa = GetAttributeObsolete ();
1077                         if (oa == null)
1078                                 return;
1079
1080                         if (!mc.IsObsolete)
1081                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, mc.Module.Compiler.Report);
1082                 }
1083
1084                 public virtual ObsoleteAttribute GetAttributeObsolete ()
1085                 {
1086                         if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0)
1087                                 return null;
1088
1089                         state &= ~StateFlags.Obsolete_Undetected;
1090
1091                         var oa = definition.GetAttributeObsolete ();
1092                         if (oa != null)
1093                                 state |= StateFlags.Obsolete;
1094
1095                         return oa;
1096                 }
1097
1098                 //
1099                 // Returns a list of missing dependencies of this member. The list
1100                 // will contain types only but it can have numerous values for members
1101                 // like methods where both return type and all parameters are checked
1102                 //
1103                 public List<MissingTypeSpecReference> GetMissingDependencies ()
1104                 {
1105                         return GetMissingDependencies (this);
1106                 }
1107
1108                 public List<MissingTypeSpecReference> GetMissingDependencies (MemberSpec caller)
1109                 {
1110                         if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0)
1111                                 return null;
1112
1113                         state &= ~StateFlags.MissingDependency_Undetected;
1114
1115                         var imported = definition as ImportedDefinition;
1116                         List<MissingTypeSpecReference> missing;
1117                         if (imported != null) {
1118                                 missing = ResolveMissingDependencies (caller);
1119                         } else if (this is ElementTypeSpec) {
1120                                 missing = ((ElementTypeSpec) this).Element.GetMissingDependencies (caller);
1121                         } else {
1122                                 missing = null;
1123                         }
1124
1125                         if (missing != null) {
1126                                 state |= StateFlags.MissingDependency;
1127                         }
1128
1129                         return missing;
1130                 }
1131
1132                 public abstract List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller);
1133
1134                 protected virtual bool IsNotCLSCompliant (out bool attrValue)
1135                 {
1136                         var cls = MemberDefinition.CLSAttributeValue;
1137                         attrValue = cls ?? false;
1138                         return cls == false;
1139                 }
1140
1141                 public virtual string GetSignatureForDocumentation ()
1142                 {
1143                         return DeclaringType.GetSignatureForDocumentation () + "." + Name;
1144                 }
1145
1146                 public virtual string GetSignatureForError ()
1147                 {
1148                         var bf = MemberDefinition as Property.BackingFieldDeclaration;
1149                         string name;
1150                         if (bf == null) {
1151                                 name = Name;
1152                         } else {
1153                                 name = bf.OriginalProperty.MemberName.Name;
1154                         }
1155
1156                         return DeclaringType.GetSignatureForError () + "." + name;
1157                 }
1158
1159                 public virtual MemberSpec InflateMember (TypeParameterInflator inflator)
1160                 {
1161                         var inflated = (MemberSpec) MemberwiseClone ();
1162                         inflated.declaringType = inflator.TypeInstance;
1163                         if (DeclaringType.IsGenericOrParentIsGeneric)
1164                                 inflated.state |= StateFlags.PendingMetaInflate;
1165 #if DEBUG
1166                         inflated.ID += 1000000;
1167 #endif
1168                         return inflated;
1169                 }
1170
1171                 //
1172                 // Is this member accessible from invocation context
1173                 //
1174                 public bool IsAccessible (IMemberContext ctx)
1175                 {
1176                         var ma = Modifiers & Modifiers.AccessibilityMask;
1177                         if (ma == Modifiers.PUBLIC)
1178                                 return true;
1179
1180                         var parentType = /* this as TypeSpec ?? */ DeclaringType;
1181                         var ctype = ctx.CurrentType;
1182
1183                         if (ma == Modifiers.PRIVATE) {
1184                                 if (ctype == null || parentType == null)
1185                                         return false;
1186                                 //
1187                                 // It's only accessible to the current class or children
1188                                 //
1189                                 if (parentType.MemberDefinition == ctype.MemberDefinition)
1190                                         return true;
1191
1192                                 return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition);
1193                         }
1194
1195                         if ((ma & Modifiers.INTERNAL) != 0) {
1196                                 bool b;
1197                                 var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly;
1198
1199                                 if (parentType == null) {
1200                                         b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly);
1201                                 } else {
1202                                         b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly);
1203                                 }
1204
1205                                 if (b || ma == Modifiers.INTERNAL)
1206                                         return b;
1207                         }
1208
1209                         //
1210                         // Checks whether `ctype' is a subclass or nested child of `parentType'.
1211                         //
1212                         while (ctype != null) {
1213                                 if (TypeManager.IsFamilyAccessible (ctype, parentType))
1214                                         return true;
1215
1216                                 // Handle nested types.
1217                                 ctype = ctype.DeclaringType;    // TODO: Untested ???
1218                         }
1219
1220                         return false;
1221                 }
1222
1223                 //
1224                 // Returns member CLS compliance based on full member hierarchy
1225                 //
1226                 public bool IsCLSCompliant ()
1227                 {
1228                         if ((state & StateFlags.CLSCompliant_Undetected) != 0) {
1229                                 state &= ~StateFlags.CLSCompliant_Undetected;
1230
1231                                 bool compliant;
1232                                 if (IsNotCLSCompliant (out compliant))
1233                                         return false;
1234
1235                                 if (!compliant) {
1236                                         if (DeclaringType != null) {
1237                                                 compliant = DeclaringType.IsCLSCompliant ();
1238                                         } else {
1239                                                 compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
1240                                         }
1241                                 }
1242
1243                                 if (compliant)
1244                                         state |= StateFlags.CLSCompliant;
1245                         }
1246
1247                         return (state & StateFlags.CLSCompliant) != 0;
1248                 }
1249
1250                 public bool IsConditionallyExcluded (IMemberContext ctx)
1251                 {
1252                         if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
1253                                 return false;
1254
1255                         var conditions = MemberDefinition.ConditionalConditions ();
1256                         if (conditions == null)
1257                                 return false;
1258
1259                         var m = ctx.CurrentMemberDefinition;
1260                         CompilationSourceFile unit = null;
1261                         while (m != null && unit == null) {
1262                                 unit = m as CompilationSourceFile;
1263                                 m = m.Parent;
1264                         }
1265
1266                         if (unit != null) {
1267                                 foreach (var condition in conditions) {
1268                                         if (unit.IsConditionalDefined (condition))
1269                                                 return false;
1270                                 }
1271                         }
1272
1273                         return true;
1274                 }
1275
1276                 public override string ToString ()
1277                 {
1278                         return GetSignatureForError ();
1279                 }
1280         }
1281
1282         //
1283         // Member details which are same between all member
1284         // specifications
1285         //
1286         public interface IMemberDefinition
1287         {
1288                 bool? CLSAttributeValue { get; }
1289                 string Name { get; }
1290                 bool IsImported { get; }
1291
1292                 string[] ConditionalConditions ();
1293                 ObsoleteAttribute GetAttributeObsolete ();
1294                 void SetIsAssigned ();
1295                 void SetIsUsed ();
1296         }
1297
1298         public interface IMethodDefinition : IMemberDefinition
1299         {
1300                 MethodBase Metadata { get; }
1301         }
1302
1303         public interface IParametersMember : IInterfaceMemberSpec
1304         {
1305                 AParametersCollection Parameters { get; }
1306         }
1307
1308         public interface IInterfaceMemberSpec
1309         {
1310                 TypeSpec MemberType { get; }
1311         }
1312 }