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