Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[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 //
12 //
13
14 using System;
15 using System.Text;
16 using System.Collections.Generic;
17 using System.Globalization;
18 using System.Reflection.Emit;
19 using System.Reflection;
20
21 #if NET_2_1
22 using XmlElement = System.Object;
23 #else
24 using System.Xml;
25 #endif
26
27 namespace Mono.CSharp {
28
29         //
30         // Better name would be DottenName
31         //
32         public class MemberName {
33                 public readonly string Name;
34                 public readonly TypeArguments TypeArguments;
35
36                 public readonly MemberName Left;
37                 public readonly Location Location;
38
39                 public static readonly MemberName Null = new MemberName ("");
40
41                 bool is_double_colon;
42
43                 private MemberName (MemberName left, string name, bool is_double_colon,
44                                     Location loc)
45                 {
46                         this.Name = name;
47                         this.Location = loc;
48                         this.is_double_colon = is_double_colon;
49                         this.Left = left;
50                 }
51
52                 private MemberName (MemberName left, string name, bool is_double_colon,
53                                     TypeArguments args, Location loc)
54                         : this (left, name, is_double_colon, loc)
55                 {
56                         if (args != null && args.Count > 0)
57                                 this.TypeArguments = args;
58                 }
59
60                 public MemberName (string name)
61                         : this (name, Location.Null)
62                 { }
63
64                 public MemberName (string name, Location loc)
65                         : this (null, name, false, loc)
66                 { }
67
68                 public MemberName (string name, TypeArguments args, Location loc)
69                         : this (null, name, false, args, loc)
70                 { }
71
72                 public MemberName (MemberName left, string name)
73                         : this (left, name, left != null ? left.Location : Location.Null)
74                 { }
75
76                 public MemberName (MemberName left, string name, Location loc)
77                         : this (left, name, false, loc)
78                 { }
79
80                 public MemberName (MemberName left, string name, TypeArguments args, Location loc)
81                         : this (left, name, false, args, loc)
82                 { }
83
84                 public MemberName (string alias, string name, TypeArguments args, Location loc)
85                         : this (new MemberName (alias, loc), name, true, args, loc)
86                 { }
87
88                 public MemberName (MemberName left, MemberName right)
89                         : this (left, right, right.Location)
90                 { }
91
92                 public MemberName (MemberName left, MemberName right, Location loc)
93                         : this (null, right.Name, false, right.TypeArguments, loc)
94                 {
95                         if (right.is_double_colon)
96                                 throw new InternalErrorException ("Cannot append double_colon member name");
97                         this.Left = (right.Left == null) ? left : new MemberName (left, right.Left);
98                 }
99
100                 // TODO: Remove
101                 public string GetName ()
102                 {
103                         return GetName (false);
104                 }
105
106                 public bool IsGeneric {
107                         get {
108                                 if (TypeArguments != null)
109                                         return true;
110                                 else if (Left != null)
111                                         return Left.IsGeneric;
112                                 else
113                                         return false;
114                         }
115                 }
116
117                 public string GetName (bool is_generic)
118                 {
119                         string name = is_generic ? Basename : Name;
120                         if (Left != null)
121                                 return Left.GetName (is_generic) + (is_double_colon ? "::" : ".") + name;
122
123                         return name;
124                 }
125
126                 public ATypeNameExpression GetTypeExpression ()
127                 {
128                         if (Left == null) {
129                                 if (TypeArguments != null)
130                                         return new SimpleName (Basename, TypeArguments, Location);
131                                 
132                                 return new SimpleName (Name, Location);
133                         }
134
135                         if (is_double_colon) {
136                                 if (Left.Left != null)
137                                         throw new InternalErrorException ("The left side of a :: should be an identifier");
138                                 return new QualifiedAliasMember (Left.Name, Name, TypeArguments, Location);
139                         }
140
141                         Expression lexpr = Left.GetTypeExpression ();
142                         return new MemberAccess (lexpr, Name, TypeArguments, Location);
143                 }
144
145                 public MemberName Clone ()
146                 {
147                         MemberName left_clone = Left == null ? null : Left.Clone ();
148                         return new MemberName (left_clone, Name, is_double_colon, TypeArguments, Location);
149                 }
150
151                 public string Basename {
152                         get {
153                                 if (TypeArguments != null)
154                                         return MakeName (Name, TypeArguments);
155                                 return Name;
156                         }
157                 }
158
159                 public string GetSignatureForError ()
160                 {
161                         string append = TypeArguments == null ? "" : "<" + TypeArguments.GetSignatureForError () + ">";
162                         if (Left == null)
163                                 return Name + append;
164                         string connect = is_double_colon ? "::" : ".";
165                         return Left.GetSignatureForError () + connect + Name + append;
166                 }
167
168                 public override bool Equals (object other)
169                 {
170                         return Equals (other as MemberName);
171                 }
172
173                 public bool Equals (MemberName other)
174                 {
175                         if (this == other)
176                                 return true;
177                         if (other == null || Name != other.Name)
178                                 return false;
179                         if (is_double_colon != other.is_double_colon)
180                                 return false;
181
182                         if ((TypeArguments != null) &&
183                             (other.TypeArguments == null || TypeArguments.Count != other.TypeArguments.Count))
184                                 return false;
185
186                         if ((TypeArguments == null) && (other.TypeArguments != null))
187                                 return false;
188
189                         if (Left == null)
190                                 return other.Left == null;
191
192                         return Left.Equals (other.Left);
193                 }
194
195                 public override int GetHashCode ()
196                 {
197                         int hash = Name.GetHashCode ();
198                         for (MemberName n = Left; n != null; n = n.Left)
199                                 hash ^= n.Name.GetHashCode ();
200                         if (is_double_colon)
201                                 hash ^= 0xbadc01d;
202
203                         if (TypeArguments != null)
204                                 hash ^= TypeArguments.Count << 5;
205
206                         return hash & 0x7FFFFFFF;
207                 }
208
209                 public int CountTypeArguments {
210                         get {
211                                 if (TypeArguments != null)
212                                         return TypeArguments.Count;
213                                 else if (Left != null)
214                                         return Left.CountTypeArguments; 
215                                 else
216                                         return 0;
217                         }
218                 }
219
220                 public static string MakeName (string name, TypeArguments args)
221                 {
222                         if (args == null)
223                                 return name;
224
225                         return name + "`" + args.Count;
226                 }
227
228                 public static string MakeName (string name, int count)
229                 {
230                         return name + "`" + count;
231                 }
232         }
233
234         public class SimpleMemberName
235         {
236                 public string Value;
237                 public Location Location;
238
239                 public SimpleMemberName (string name, Location loc)
240                 {
241                         this.Value = name;
242                         this.Location = loc;
243                 }
244         }
245
246         /// <summary>
247         ///   Base representation for members.  This is used to keep track
248         ///   of Name, Location and Modifier flags, and handling Attributes.
249         /// </summary>
250         public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition
251         {
252                 /// <summary>
253                 ///   Public name
254                 /// </summary>
255
256                 protected string cached_name;
257                 // TODO: Remove in favor of MemberName
258                 public string Name {
259                         get {
260                                 if (cached_name == null)
261                                         cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method));
262                                 return cached_name;
263                         }
264                 }
265
266                 // Is not readonly because of IndexerName attribute
267                 private MemberName member_name;
268                 public MemberName MemberName {
269                         get { return member_name; }
270                 }
271
272                 /// <summary>
273                 ///   Modifier flags that the user specified in the source code
274                 /// </summary>
275                 private Modifiers mod_flags;
276                 public Modifiers ModFlags {
277                         set {
278                                 mod_flags = value;
279                                 if ((value & Modifiers.COMPILER_GENERATED) != 0)
280                                         caching_flags = Flags.IsUsed | Flags.IsAssigned;
281                         }
282                         get {
283                                 return mod_flags;
284                         }
285                 }
286
287                 public /*readonly*/ DeclSpace Parent;
288
289                 /// <summary>
290                 ///   Location where this declaration happens
291                 /// </summary>
292                 public Location Location {
293                         get { return member_name.Location; }
294                 }
295
296                 /// <summary>
297                 ///   XML documentation comment
298                 /// </summary>
299                 protected string comment;
300
301                 /// <summary>
302                 ///   Represents header string for documentation comment 
303                 ///   for each member types.
304                 /// </summary>
305                 public abstract string DocCommentHeader { get; }
306
307                 [Flags]
308                 public enum Flags {
309                         Obsolete_Undetected = 1,                // Obsolete attribute has not been detected yet
310                         Obsolete = 1 << 1,                      // Type has obsolete attribute
311                         ClsCompliance_Undetected = 1 << 2,      // CLS Compliance has not been detected yet
312                         ClsCompliant = 1 << 3,                  // Type is CLS Compliant
313                         CloseTypeCreated = 1 << 4,              // Tracks whether we have Closed the type
314                         HasCompliantAttribute_Undetected = 1 << 5,      // Presence of CLSCompliantAttribute has not been detected
315                         HasClsCompliantAttribute = 1 << 6,                      // Type has CLSCompliantAttribute
316                         ClsCompliantAttributeTrue = 1 << 7,                     // Type has CLSCompliant (true)
317                         Excluded_Undetected = 1 << 8,           // Conditional attribute has not been detected yet
318                         Excluded = 1 << 9,                                      // Method is conditional
319                         MethodOverloadsExist = 1 << 10,         // Test for duplication must be performed
320                         IsUsed = 1 << 11,
321                         IsAssigned = 1 << 12,                           // Field is assigned
322                         HasExplicitLayout       = 1 << 13,
323                         PartialDefinitionExists = 1 << 14,      // Set when corresponding partial method definition exists
324                         HasStructLayout         = 1 << 15                       // Has StructLayoutAttribute
325                 }
326
327                 /// <summary>
328                 ///   MemberCore flags at first detected then cached
329                 /// </summary>
330                 internal Flags caching_flags;
331
332                 public MemberCore (DeclSpace parent, MemberName name, Attributes attrs)
333                 {
334                         this.Parent = parent;
335                         member_name = name;
336                         caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
337                         AddAttributes (attrs, this);
338                 }
339
340                 protected virtual void SetMemberName (MemberName new_name)
341                 {
342                         member_name = new_name;
343                         cached_name = null;
344                 }
345
346                 protected bool CheckAbstractAndExtern (bool has_block)
347                 {
348                         if (Parent.PartialContainer.Kind == MemberKind.Interface)
349                                 return true;
350
351                         if (has_block) {
352                                 if ((ModFlags & Modifiers.EXTERN) != 0) {
353                                         Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
354                                                 GetSignatureForError ());
355                                         return false;
356                                 }
357
358                                 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
359                                         Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
360                                                 GetSignatureForError ());
361                                         return false;
362                                 }
363                         } else {
364                                 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) {
365                                         if (RootContext.Version >= LanguageVersion.V_3) {
366                                                 Property.PropertyMethod pm = this as Property.PropertyMethod;
367                                                 if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod)
368                                                         pm = null;
369
370                                                 if (pm != null && (pm.Property.Get.IsDummy || pm.Property.Set.IsDummy)) {
371                                                         Report.Error (840, Location,
372                                                                 "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors",
373                                                                 GetSignatureForError ());
374                                                         return false;
375                                                 }
376                                         }
377
378                                         Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial",
379                                                       GetSignatureForError ());
380                                         return false;
381                                 }
382                         }
383
384                         return true;
385                 }
386
387                 protected void CheckProtectedModifier ()
388                 {
389                         if ((ModFlags & Modifiers.PROTECTED) == 0)
390                                 return;
391
392                         if (Parent.PartialContainer.Kind == MemberKind.Struct) {
393                                 Report.Error (666, Location, "`{0}': Structs cannot contain protected members",
394                                         GetSignatureForError ());
395                                 return;
396                         }
397
398                         if ((Parent.ModFlags & Modifiers.STATIC) != 0) {
399                                 Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members",
400                                         GetSignatureForError ());
401                                 return;
402                         }
403
404                         if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 &&
405                                 !(this is Destructor)) {
406                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class",
407                                         GetSignatureForError ());
408                                 return;
409                         }
410                 }
411
412                 public abstract bool Define ();
413
414                 public virtual string DocComment {
415                         get {
416                                 return comment;
417                         }
418                         set {
419                                 comment = value;
420                         }
421                 }
422
423                 // 
424                 // Returns full member name for error message
425                 //
426                 public virtual string GetSignatureForError ()
427                 {
428                         if (Parent == null || Parent.Parent == null)
429                                 return member_name.GetSignatureForError ();
430
431                         return Parent.GetSignatureForError () + "." + member_name.GetSignatureForError ();
432                 }
433
434                 /// <summary>
435                 /// Base Emit method. This is also entry point for CLS-Compliant verification.
436                 /// </summary>
437                 public virtual void Emit ()
438                 {
439                         if (!RootContext.VerifyClsCompliance)
440                                 return;
441
442                         if (Report.WarningLevel > 0)
443                                 VerifyClsCompliance ();
444                 }
445
446                 public bool IsCompilerGenerated {
447                         get     {
448                                 if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0)
449                                         return true;
450
451                                 return Parent == null ? false : Parent.IsCompilerGenerated;
452                         }
453                 }
454
455                 public virtual bool IsUsed {
456                         get { return (caching_flags & Flags.IsUsed) != 0; }
457                 }
458
459                 protected Report Report {
460                         get {
461                                 return Compiler.Report;
462                         }
463                 }
464
465                 public void SetIsUsed ()
466                 {
467                         caching_flags |= Flags.IsUsed;
468                 }
469
470                 /// <summary>
471                 /// Returns instance of ObsoleteAttribute for this MemberCore
472                 /// </summary>
473                 public virtual ObsoleteAttribute GetObsoleteAttribute ()
474                 {
475                         if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0)
476                                 return null;
477
478                         caching_flags &= ~Flags.Obsolete_Undetected;
479
480                         if (OptAttributes == null)
481                                 return null;
482
483                         Attribute obsolete_attr = OptAttributes.Search (PredefinedAttributes.Get.Obsolete);
484                         if (obsolete_attr == null)
485                                 return null;
486
487                         caching_flags |= Flags.Obsolete;
488
489                         ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute ();
490                         if (obsolete == null)
491                                 return null;
492
493                         return obsolete;
494                 }
495
496                 /// <summary>
497                 /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements
498                 /// </summary>
499                 public virtual void CheckObsoleteness (Location loc)
500                 {
501                         ObsoleteAttribute oa = GetObsoleteAttribute ();
502                         if (oa != null)
503                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, Report);
504                 }
505
506                 //
507                 // Returns the access level for type `t'
508                 //
509                 static Modifiers GetAccessLevelFromType (Type type)
510                 {
511                         var ma = type.Attributes;
512                         Modifiers mod;
513                         switch (ma & TypeAttributes.VisibilityMask) {
514                         case TypeAttributes.Public:
515                         case TypeAttributes.NestedPublic:
516                                 mod = Modifiers.PUBLIC;
517                                 break;
518                         case TypeAttributes.NestedPrivate:
519                                 mod = Modifiers.PRIVATE;
520                                 break;
521                         case TypeAttributes.NestedFamily:
522                                 mod = Modifiers.PROTECTED;
523                                 break;
524                         case TypeAttributes.NestedFamORAssem:
525                                 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
526                                 break;
527                         default:
528                                 mod = Modifiers.INTERNAL;
529                                 break;
530                         }
531
532                         return mod;
533                 }
534
535                 //
536                 // Checks whether the type P is as accessible as this member
537                 //
538                 public bool IsAccessibleAs (Type p)
539                 {
540                         //
541                         // if M is private, its accessibility is the same as this declspace.
542                         // we already know that P is accessible to T before this method, so we
543                         // may return true.
544                         //
545                         if ((mod_flags & Modifiers.PRIVATE) != 0)
546                                 return true;
547
548                         while (TypeManager.HasElementType (p))
549                                 p = TypeManager.GetElementType (p);
550
551                         if (TypeManager.IsGenericParameter (p))
552                                 return true;
553
554                         if (TypeManager.IsGenericType (p)) {
555                                 foreach (Type t in TypeManager.GetTypeArguments (p)) {
556                                         if (!IsAccessibleAs (t))
557                                                 return false;
558                                 }
559                         }
560
561                         for (Type p_parent = null; p != null; p = p_parent) {
562                                 p_parent = p.DeclaringType;
563                                 var pAccess = GetAccessLevelFromType (p);
564                                 if (pAccess == Modifiers.PUBLIC)
565                                         continue;
566
567                                 bool same_access_restrictions = false;
568                                 for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) {
569                                         var al = mc.ModFlags & Modifiers.AccessibilityMask;
570                                         switch (pAccess) {
571                                         case Modifiers.INTERNAL:
572                                                 if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL)
573                                                         same_access_restrictions = TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
574                                                 
575                                                 break;
576
577                                         case Modifiers.PROTECTED:
578                                                 if (al == Modifiers.PROTECTED) {
579                                                         same_access_restrictions = mc.Parent.IsBaseType (p_parent);
580                                                         break;
581                                                 }
582
583                                                 if (al == Modifiers.PRIVATE) {
584                                                         //
585                                                         // When type is private and any of its parents derives from
586                                                         // protected type then the type is accessible
587                                                         //
588                                                         while (mc.Parent != null) {
589                                                                 if (mc.Parent.IsBaseType (p_parent))
590                                                                         same_access_restrictions = true;
591                                                                 mc = mc.Parent; 
592                                                         }
593                                                 }
594                                                 
595                                                 break;
596
597                                         case Modifiers.PROTECTED | Modifiers.INTERNAL:
598                                                 if (al == Modifiers.INTERNAL)
599                                                         same_access_restrictions = TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
600                                                 else if (al == Modifiers.PROTECTED)
601                                                         same_access_restrictions = mc.Parent.IsBaseType (p_parent);
602                                                 else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
603                                                         same_access_restrictions = mc.Parent.IsBaseType (p_parent) &&
604                                                                 TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
605                                                 break;
606
607                                         case Modifiers.PRIVATE:
608                                                 //
609                                                 // Both are private and share same parent
610                                                 //
611                                                 if (al == Modifiers.PRIVATE) {
612                                                         var decl = mc.Parent;
613                                                         do {
614                                                                 same_access_restrictions = TypeManager.IsEqual (decl.TypeBuilder, p_parent);
615                                                         } while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null);
616                                                 }
617                                                 
618                                                 break;
619                                                 
620                                         default:
621                                                 throw new InternalErrorException (al.ToString ());
622                                         }
623                                 }
624                                 
625                                 if (!same_access_restrictions)
626                                         return false;
627                         }
628
629                         return true;
630                 }
631
632                 /// <summary>
633                 /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
634                 /// </summary>
635                 public override bool IsClsComplianceRequired ()
636                 {
637                         if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
638                                 return (caching_flags & Flags.ClsCompliant) != 0;
639
640                         if (GetClsCompliantAttributeValue () && IsExposedFromAssembly ()) {
641                                 caching_flags &= ~Flags.ClsCompliance_Undetected;
642                                 caching_flags |= Flags.ClsCompliant;
643                                 return true;
644                         }
645
646                         caching_flags &= ~Flags.ClsCompliance_Undetected;
647                         return false;
648                 }
649
650                 /// <summary>
651                 /// Returns true when MemberCore is exposed from assembly.
652                 /// </summary>
653                 public bool IsExposedFromAssembly ()
654                 {
655                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
656                                 return false;
657                         
658                         DeclSpace parentContainer = Parent.PartialContainer;
659                         while (parentContainer != null && parentContainer.ModFlags != 0) {
660                                 if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
661                                         return false;
662                                 parentContainer = parentContainer.Parent;
663                         }
664                         return true;
665                 }
666
667                 public virtual ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
668                 {
669                         return Parent.LookupExtensionMethod (extensionType, name, loc);
670                 }
671
672                 public virtual FullNamedExpression LookupNamespaceAlias (string name)
673                 {
674                         return Parent.NamespaceEntry.LookupNamespaceAlias (name);
675                 }
676
677                 public virtual FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
678                 {
679                         return Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
680                 }
681
682                 /// <summary>
683                 /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
684                 /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
685                 /// </summary>
686                 public virtual bool GetClsCompliantAttributeValue ()
687                 {
688                         if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
689                                 return (caching_flags & Flags.ClsCompliantAttributeTrue) != 0;
690
691                         caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
692
693                         if (OptAttributes != null) {
694                                 Attribute cls_attribute = OptAttributes.Search (
695                                         PredefinedAttributes.Get.CLSCompliant);
696                                 if (cls_attribute != null) {
697                                         caching_flags |= Flags.HasClsCompliantAttribute;
698                                         bool value = cls_attribute.GetClsCompliantAttributeValue ();
699                                         if (value)
700                                                 caching_flags |= Flags.ClsCompliantAttributeTrue;
701                                         return value;
702                                 }
703                         }
704                         
705                         // It's null for TypeParameter
706                         if (Parent == null)
707                                 return false;                   
708
709                         if (Parent.GetClsCompliantAttributeValue ()) {
710                                 caching_flags |= Flags.ClsCompliantAttributeTrue;
711                                 return true;
712                         }
713                         return false;
714                 }
715
716                 /// <summary>
717                 /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
718                 /// </summary>
719                 protected bool HasClsCompliantAttribute {
720                         get {
721                                 if ((caching_flags & Flags.HasCompliantAttribute_Undetected) != 0)
722                                         GetClsCompliantAttributeValue ();
723                                 
724                                 return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
725                         }
726                 }
727
728                 /// <summary>
729                 /// Returns true when a member supports multiple overloads (methods, indexers, etc)
730                 /// </summary>
731                 public virtual bool EnableOverloadChecks (MemberCore overload)
732                 {
733                         return false;
734                 }
735
736                 /// <summary>
737                 /// The main virtual method for CLS-Compliant verifications.
738                 /// The method returns true if member is CLS-Compliant and false if member is not
739                 /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
740                 /// and add their extra verifications.
741                 /// </summary>
742                 protected virtual bool VerifyClsCompliance ()
743                 {
744                         if (!IsClsComplianceRequired ()) {
745                                 if (HasClsCompliantAttribute && Report.WarningLevel >= 2) {
746                                         if (!IsExposedFromAssembly ()) {
747                                                 Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant);
748                                                 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 ());
749                                         }
750
751                                         if (!CodeGen.Assembly.IsClsCompliant) {
752                                                 Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant);
753                                                 Report.Warning (3021, 2, a.Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ());
754                                         }
755                                 }
756                                 return false;
757                         }
758
759                         if (HasClsCompliantAttribute) {
760                                 if (CodeGen.Assembly.ClsCompliantAttribute == null && !CodeGen.Assembly.IsClsCompliant) {
761                                         Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant);
762                                         Report.Warning (3014, 1, a.Location,
763                                                 "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
764                                                 GetSignatureForError ());
765                                         return false;
766                                 }
767
768                                 if (!Parent.IsClsComplianceRequired ()) {
769                                         Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant);
770                                         Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", 
771                                                 GetSignatureForError (), Parent.GetSignatureForError ());
772                                         return false;
773                                 }
774                         }
775
776                         if (member_name.Name [0] == '_') {
777                                 Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () );
778                         }
779                         return true;
780                 }
781
782                 //
783                 // Raised (and passed an XmlElement that contains the comment)
784                 // when GenerateDocComment is writing documentation expectedly.
785                 //
786                 internal virtual void OnGenerateDocComment (XmlElement intermediateNode)
787                 {
788                 }
789
790                 //
791                 // Returns a string that represents the signature for this 
792                 // member which should be used in XML documentation.
793                 //
794                 public virtual string GetDocCommentName (DeclSpace ds)
795                 {
796                         if (ds == null || this is DeclSpace)
797                                 return DocCommentHeader + Name;
798                         else
799                                 return String.Concat (DocCommentHeader, ds.Name, ".", Name);
800                 }
801
802                 //
803                 // Generates xml doc comments (if any), and if required,
804                 // handle warning report.
805                 //
806                 internal virtual void GenerateDocComment (DeclSpace ds)
807                 {
808                         try {
809                                 DocUtil.GenerateDocComment (this, ds, Report);
810                         } catch (Exception e) {
811                                 throw new InternalErrorException (this, e);
812                         }
813                 }
814
815                 #region IMemberContext Members
816
817                 public virtual CompilerContext Compiler {
818                         get { return Parent.Module.Compiler; }
819                 }
820
821                 public virtual Type CurrentType {
822                         get { return Parent.CurrentType; }
823                 }
824
825                 public virtual TypeContainer CurrentTypeDefinition {
826                         get { return Parent.CurrentTypeDefinition; }
827                 }
828
829                 public virtual TypeParameter[] CurrentTypeParameters {
830                         get { return null; }
831                 }
832
833                 public bool IsObsolete {
834                         get {
835                                 if (GetObsoleteAttribute () != null)
836                                         return true;
837
838                                 return Parent == null ? false : Parent.IsObsolete;
839                         }
840                 }
841
842                 public bool IsUnsafe {
843                         get {
844                                 if ((ModFlags & Modifiers.UNSAFE) != 0)
845                                         return true;
846
847                                 return Parent == null ? false : Parent.IsUnsafe;
848                         }
849                 }
850
851                 public bool IsStatic {
852                         get { return (ModFlags & Modifiers.STATIC) != 0; }
853                 }
854
855                 #endregion
856         }
857
858         //
859         // Base member specification. A member specification contains
860         // member details which can alter in the context (e.g. generic instances)
861         //
862         public abstract class MemberSpec
863         {
864                 [Flags]
865                 protected enum StateFlags
866                 {
867                         Obsolete_Undetected = 1,        // Obsolete attribute has not been detected yet
868                         Obsolete = 1 << 1                       // Member has obsolete attribute
869                 }
870
871                 readonly Modifiers modifiers;
872                 readonly string name;
873                 protected StateFlags state;
874                 protected IMemberDefinition definition;
875                 public readonly MemberKind Kind;
876
877                 protected MemberSpec (MemberKind kind, IMemberDefinition definition, string name, Modifiers modifiers)
878                 {
879                         this.definition = definition;
880                         this.name = name;
881                         this.modifiers = modifiers;
882
883                         state = StateFlags.Obsolete_Undetected;
884                 }
885
886                 public abstract Type DeclaringType { get; }
887
888                 public ObsoleteAttribute GetObsoleteAttribute ()
889                 {
890                         if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0)
891                                 return null;
892
893                         state &= ~StateFlags.Obsolete_Undetected;
894
895                         var oa = definition.GetObsoleteAttribute ();
896                         if (oa != null)
897                                 state |= StateFlags.Obsolete;
898
899                         return oa;
900                 }
901
902                 public IMemberDefinition MemberDefinition {
903                         get { return definition; }
904                 }
905
906                 public Modifiers Modifiers {
907                         get { return modifiers; }
908                 }
909                 
910                 public string Name {
911                         get { return name; }
912                 }
913
914                 public bool IsStatic {
915                         get { return (modifiers & Modifiers.STATIC) != 0; }
916                 }
917         }
918
919         //
920         // Member details which are same between all member
921         // specifications
922         //
923         public interface IMemberDefinition
924         {
925                 ObsoleteAttribute GetObsoleteAttribute ();
926                 void SetIsUsed ();
927         }
928
929         /// <summary>
930         ///   Base class for structs, classes, enumerations and interfaces.  
931         /// </summary>
932         /// <remarks>
933         ///   They all create new declaration spaces.  This
934         ///   provides the common foundation for managing those name
935         ///   spaces.
936         /// </remarks>
937         public abstract class DeclSpace : MemberCore {
938                 /// <summary>
939                 ///   This points to the actual definition that is being
940                 ///   created with System.Reflection.Emit
941                 /// </summary>
942                 public TypeBuilder TypeBuilder;
943
944                 /// <summary>
945                 ///   If we are a generic type, this is the type we are
946                 ///   currently defining.  We need to lookup members on this
947                 ///   instead of the TypeBuilder.
948                 /// </summary>
949                 protected Type currentType;
950
951                 //
952                 // This is the namespace in which this typecontainer
953                 // was declared.  We use this to resolve names.
954                 //
955                 public NamespaceEntry NamespaceEntry;
956
957                 private Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
958                 
959                 public readonly string Basename;
960                 
961                 protected Dictionary<string, MemberCore> defined_names;
962
963                 public TypeContainer PartialContainer;          
964
965                 protected readonly bool is_generic;
966                 readonly int count_type_params;
967                 protected TypeParameter[] type_params;
968                 TypeParameter[] type_param_list;
969
970                 //
971                 // Whether we are Generic
972                 //
973                 public bool IsGeneric {
974                         get {
975                                 if (is_generic)
976                                         return true;
977                                 else if (Parent != null)
978                                         return Parent.IsGeneric;
979                                 else
980                                         return false;
981                         }
982                 }
983
984                 static string[] attribute_targets = new string [] { "type" };
985
986                 public DeclSpace (NamespaceEntry ns, DeclSpace parent, MemberName name,
987                                   Attributes attrs)
988                         : base (parent, name, attrs)
989                 {
990                         NamespaceEntry = ns;
991                         Basename = name.Basename;
992                         defined_names = new Dictionary<string, MemberCore> ();
993                         PartialContainer = null;
994                         if (name.TypeArguments != null) {
995                                 is_generic = true;
996                                 count_type_params = name.TypeArguments.Count;
997                         }
998                         if (parent != null)
999                                 count_type_params += parent.count_type_params;
1000                 }
1001
1002                 /// <summary>
1003                 /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
1004                 /// </summary>
1005                 protected virtual bool AddToContainer (MemberCore symbol, string name)
1006                 {
1007                         MemberCore mc;
1008                         if (!defined_names.TryGetValue (name, out mc)) {
1009                                 defined_names.Add (name, symbol);
1010                                 return true;
1011                         }
1012
1013                         if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
1014                                 return true;
1015
1016                         if (symbol.EnableOverloadChecks (mc))
1017                                 return true;
1018
1019                         InterfaceMemberBase im = mc as InterfaceMemberBase;
1020                         if (im != null && im.IsExplicitImpl)
1021                                 return true;
1022
1023                         Report.SymbolRelatedToPreviousError (mc);
1024                         if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
1025                                 Error_MissingPartialModifier (symbol);
1026                                 return false;
1027                         }
1028
1029                         if (this is ModuleContainer) {
1030                                 Report.Error (101, symbol.Location, 
1031                                         "The namespace `{0}' already contains a definition for `{1}'",
1032                                         ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
1033                         } else if (symbol is TypeParameter) {
1034                                 Report.Error (692, symbol.Location,
1035                                         "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
1036                         } else {
1037                                 Report.Error (102, symbol.Location,
1038                                               "The type `{0}' already contains a definition for `{1}'",
1039                                               GetSignatureForError (), symbol.MemberName.Name);
1040                         }
1041
1042                         return false;
1043                 }
1044
1045                 protected void RemoveFromContainer (string name)
1046                 {
1047                         defined_names.Remove (name);
1048                 }
1049                 
1050                 /// <summary>
1051                 ///   Returns the MemberCore associated with a given name in the declaration
1052                 ///   space. It doesn't return method based symbols !!
1053                 /// </summary>
1054                 /// 
1055                 public MemberCore GetDefinition (string name)
1056                 {
1057                         MemberCore mc = null;
1058                         defined_names.TryGetValue (name, out mc);
1059                         return mc;
1060                 }
1061
1062                 public bool IsStaticClass {
1063                         get { return (ModFlags & Modifiers.STATIC) != 0; }
1064                 }
1065                 
1066                 // 
1067                 // root_types contains all the types.  All TopLevel types
1068                 // hence have a parent that points to `root_types', that is
1069                 // why there is a non-obvious test down here.
1070                 //
1071                 public bool IsTopLevel {
1072                         get { return (Parent != null && Parent.Parent == null); }
1073                 }
1074
1075                 public virtual bool IsUnmanagedType ()
1076                 {
1077                         return false;
1078                 }
1079
1080                 public virtual void CloseType ()
1081                 {
1082                         if ((caching_flags & Flags.CloseTypeCreated) == 0){
1083                                 try {
1084                                         TypeBuilder.CreateType ();
1085                                 } catch {
1086                                         //
1087                                         // The try/catch is needed because
1088                                         // nested enumerations fail to load when they
1089                                         // are defined.
1090                                         //
1091                                         // Even if this is the right order (enumerations
1092                                         // declared after types).
1093                                         //
1094                                         // Note that this still creates the type and
1095                                         // it is possible to save it
1096                                 }
1097                                 caching_flags |= Flags.CloseTypeCreated;
1098                         }
1099                 }
1100
1101                 protected virtual TypeAttributes TypeAttr {
1102                         get { return Module.DefaultCharSetType; }
1103                 }
1104
1105                 /// <remarks>
1106                 ///  Should be overriten by the appropriate declaration space
1107                 /// </remarks>
1108                 public abstract TypeBuilder DefineType ();
1109
1110                 protected void Error_MissingPartialModifier (MemberCore type)
1111                 {
1112                         Report.Error (260, type.Location,
1113                                 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
1114                                 type.GetSignatureForError ());
1115                 }
1116
1117                 public override void Emit ()
1118                 {
1119                         if (type_params != null) {
1120                                 int offset = count_type_params - type_params.Length;
1121                                 for (int i = offset; i < type_params.Length; i++)
1122                                         CurrentTypeParameters [i - offset].Emit ();
1123                         }
1124
1125                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1126                                 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (TypeBuilder);
1127
1128                         base.Emit ();
1129                 }
1130
1131                 public override string GetSignatureForError ()
1132                 {       
1133                         return MemberName.GetSignatureForError ();
1134                 }
1135                 
1136                 public bool CheckAccessLevel (Type check_type)
1137                 {
1138                         Type tb = TypeBuilder;
1139
1140                         if (this is GenericMethod) {
1141                                 tb = Parent.TypeBuilder;
1142
1143                                 // FIXME: Generic container does not work with nested generic
1144                                 // anonymous method stories
1145                                 if (TypeBuilder == null)
1146                                         return true;
1147                         }
1148
1149                         check_type = TypeManager.DropGenericTypeArguments (check_type);
1150                         if (check_type == tb)
1151                                 return true;
1152
1153                         // TODO: When called from LocalUsingAliasEntry tb is null
1154                         // because we are in RootDeclSpace
1155                         if (tb == null)
1156                                 tb = typeof (RootDeclSpace);
1157
1158                         //
1159                         // Broken Microsoft runtime, return public for arrays, no matter what 
1160                         // the accessibility is for their underlying class, and they return 
1161                         // NonPublic visibility for pointers
1162                         //
1163                         if (TypeManager.HasElementType (check_type))
1164                                 return CheckAccessLevel (TypeManager.GetElementType (check_type));
1165
1166                         if (TypeManager.IsGenericParameter (check_type))
1167                                 return true;
1168
1169                         TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask;
1170
1171                         switch (check_attr){
1172                         case TypeAttributes.Public:
1173                                 return true;
1174
1175                         case TypeAttributes.NotPublic:
1176                                 return TypeManager.IsThisOrFriendAssembly (Module.Assembly, check_type.Assembly);
1177                                 
1178                         case TypeAttributes.NestedPublic:
1179                                 return CheckAccessLevel (check_type.DeclaringType);
1180
1181                         case TypeAttributes.NestedPrivate:
1182                                 Type declaring = check_type.DeclaringType;
1183                                 return tb == declaring || TypeManager.IsNestedChildOf (tb, declaring);  
1184
1185                         case TypeAttributes.NestedFamily:
1186                                 //
1187                                 // Only accessible to methods in current type or any subtypes
1188                                 //
1189                                 return FamilyAccessible (tb, check_type);
1190
1191                         case TypeAttributes.NestedFamANDAssem:
1192                                 return TypeManager.IsThisOrFriendAssembly (Module.Assembly, check_type.Assembly) && 
1193                                         FamilyAccessible (tb, check_type);
1194
1195                         case TypeAttributes.NestedFamORAssem:
1196                                 return FamilyAccessible (tb, check_type) ||
1197                                         TypeManager.IsThisOrFriendAssembly (Module.Assembly, check_type.Assembly);
1198
1199                         case TypeAttributes.NestedAssembly:
1200                                 return TypeManager.IsThisOrFriendAssembly (Module.Assembly, check_type.Assembly);
1201                         }
1202
1203                         throw new NotImplementedException (check_attr.ToString ());
1204                 }
1205
1206                 static bool FamilyAccessible (Type tb, Type check_type)
1207                 {
1208                         Type declaring = check_type.DeclaringType;
1209                         return TypeManager.IsNestedFamilyAccessible (tb, declaring);
1210                 }
1211
1212                 public bool IsBaseType (Type baseType)
1213                 {
1214                         // We are called from RootDeclspace
1215                         if (TypeBuilder == null)
1216                                 return false;
1217
1218                         return TypeManager.IsSubclassOf (TypeBuilder, baseType);
1219                 }
1220
1221                 private Type LookupNestedTypeInHierarchy (string name)
1222                 {
1223                         Type t = null;
1224                         // if the member cache has been created, lets use it.
1225                         // the member cache is MUCH faster.
1226                         if (MemberCache != null) {
1227                                 t = MemberCache.FindNestedType (name);
1228                                 if (t == null)
1229                                         return null;
1230                         }
1231
1232                         //
1233                         // FIXME: This hack is needed because member cache does not work
1234                         // with nested base generic types, it does only type name copy and
1235                         // not type construction
1236                         //
1237
1238                         // no member cache. Do it the hard way -- reflection
1239                         for (Type current_type = TypeBuilder;
1240                              current_type != null && current_type != TypeManager.object_type;
1241                              current_type = current_type.BaseType) {
1242
1243                                 Type ct = TypeManager.DropGenericTypeArguments (current_type);
1244                                 if (ct is TypeBuilder) {
1245                                         TypeContainer tc = ct == TypeBuilder
1246                                                 ? PartialContainer : TypeManager.LookupTypeContainer (ct);
1247                                         if (tc != null)
1248                                                 t = tc.FindNestedType (name);
1249                                 } else {
1250                                         t = TypeManager.GetNestedType (ct, name);
1251                                 }
1252
1253                                 if ((t == null) || !CheckAccessLevel (t))
1254                                         continue;
1255
1256                                 if (!TypeManager.IsGenericType (current_type))
1257                                         return t;
1258
1259                                 Type[] args = TypeManager.GetTypeArguments (current_type);
1260                                 Type[] targs = TypeManager.GetTypeArguments (t);
1261                                 for (int i = 0; i < args.Length; i++)
1262                                         targs [i] = TypeManager.TypeToCoreType (args [i]);
1263
1264                                 return t.MakeGenericType (targs);
1265                         }
1266
1267                         return null;
1268                 }
1269
1270                 //
1271                 // Public function used to locate types.
1272                 //
1273                 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
1274                 //
1275                 // Returns: Type or null if they type can not be found.
1276                 //
1277                 public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
1278                 {
1279                         FullNamedExpression e;
1280                         if (Cache.TryGetValue (name, out e))
1281                                 return e;
1282
1283                         e = null;
1284                         int errors = Report.Errors;
1285
1286                         TypeParameter[] tp = CurrentTypeParameters;
1287                         if (tp != null) {
1288                                 TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name);
1289                                 if (tparam != null)
1290                                         e = new TypeParameterExpr (tparam, Location.Null);
1291                         }
1292
1293                         if (e == null) {
1294                                 Type t = LookupNestedTypeInHierarchy (name);
1295
1296                                 if (t != null)
1297                                         e = new TypeExpression (t, Location.Null);
1298                                 else if (Parent != null)
1299                                         e = Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
1300                                 else
1301                                         e = NamespaceEntry.LookupNamespaceOrType (name, loc, ignore_cs0104);
1302                         }
1303
1304                         if (errors == Report.Errors)
1305                                 Cache [name] = e;
1306                         
1307                         return e;
1308                 }
1309
1310                 /// <remarks>
1311                 ///   This function is broken and not what you're looking for.  It should only
1312                 ///   be used while the type is still being created since it doesn't use the cache
1313                 ///   and relies on the filter doing the member name check.
1314                 /// </remarks>
1315                 ///
1316                 // [Obsolete ("Only MemberCache approach should be used")]
1317                 public virtual MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1318                                                         MemberFilter filter, object criteria)
1319                 {
1320                         throw new NotSupportedException ();
1321                 }
1322
1323                 /// <remarks>
1324                 ///   If we have a MemberCache, return it.  This property may return null if the
1325                 ///   class doesn't have a member cache or while it's still being created.
1326                 /// </remarks>
1327                 public abstract MemberCache MemberCache {
1328                         get;
1329                 }
1330
1331                 public virtual ModuleContainer Module {
1332                         get { return Parent.Module; }
1333                 }
1334
1335                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1336                 {
1337                         if (a.Type == pa.Required) {
1338                                 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
1339                                 return;
1340                         }
1341                         TypeBuilder.SetCustomAttribute (cb);
1342                 }
1343
1344                 TypeParameter[] initialize_type_params ()
1345                 {
1346                         if (type_param_list != null)
1347                                 return type_param_list;
1348
1349                         DeclSpace the_parent = Parent;
1350                         if (this is GenericMethod)
1351                                 the_parent = null;
1352
1353                         var list = new List<TypeParameter> ();
1354                         if (the_parent != null && the_parent.IsGeneric) {
1355                                 // FIXME: move generics info out of DeclSpace
1356                                 TypeParameter[] parent_params = the_parent.TypeParameters;
1357                                 list.AddRange (parent_params);
1358                         }
1359  
1360                         int count = type_params != null ? type_params.Length : 0;
1361                         for (int i = 0; i < count; i++) {
1362                                 TypeParameter param = type_params [i];
1363                                 list.Add (param);
1364                                 if (Parent.CurrentTypeParameters != null) {
1365                                         foreach (TypeParameter tp in Parent.CurrentTypeParameters) {
1366                                                 if (tp.Name != param.Name)                              
1367                                                         continue;
1368
1369                                                 Report.SymbolRelatedToPreviousError (tp.Location, null);
1370                                                 Report.Warning (693, 3, param.Location,
1371                                                         "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'",
1372                                                         param.Name, Parent.GetSignatureForError ());
1373                                         }
1374                                 }
1375                         }
1376
1377                         type_param_list = new TypeParameter [list.Count];
1378                         list.CopyTo (type_param_list, 0);
1379                         return type_param_list;
1380                 }
1381
1382                 public virtual void SetParameterInfo (List<Constraints> constraints_list)
1383                 {
1384                         if (!is_generic) {
1385                                 if (constraints_list != null) {
1386                                         Report.Error (
1387                                                 80, Location, "Constraints are not allowed " +
1388                                                 "on non-generic declarations");
1389                                 }
1390
1391                                 return;
1392                         }
1393
1394                         TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
1395                         type_params = new TypeParameter [names.Length];
1396
1397                         //
1398                         // Register all the names
1399                         //
1400                         for (int i = 0; i < type_params.Length; i++) {
1401                                 TypeParameterName name = names [i];
1402
1403                                 Constraints constraints = null;
1404                                 if (constraints_list != null) {
1405                                         int total = constraints_list.Count;
1406                                         for (int ii = 0; ii < total; ++ii) {
1407                                                 Constraints constraints_at = (Constraints)constraints_list[ii];
1408                                                 // TODO: it is used by iterators only
1409                                                 if (constraints_at == null) {
1410                                                         constraints_list.RemoveAt (ii);
1411                                                         --total;
1412                                                         continue;
1413                                                 }
1414                                                 if (constraints_at.TypeParameter.Value == name.Name) {
1415                                                         constraints = constraints_at;
1416                                                         constraints_list.RemoveAt(ii);
1417                                                         break;
1418                                                 }
1419                                         }
1420                                 }
1421
1422                                 Variance variance = name.Variance;
1423                                 if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) {
1424                                         Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates");
1425                                         variance = Variance.None;
1426                                 }
1427
1428                                 type_params [i] = new TypeParameter (
1429                                         Parent, this, name.Name, constraints, name.OptAttributes, variance, Location);
1430
1431                                 AddToContainer (type_params [i], name.Name);
1432                         }
1433
1434                         if (constraints_list != null && constraints_list.Count > 0) {
1435                                 foreach (Constraints constraint in constraints_list) {
1436                                         Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", 
1437                                                 GetSignatureForError (), constraint.TypeParameter.Value);
1438                                 }
1439                         }
1440                 }
1441
1442                 public TypeParameter[] TypeParameters {
1443                         get {
1444                                 if (!IsGeneric)
1445                                         throw new InvalidOperationException ();
1446                                 if ((PartialContainer != null) && (PartialContainer != this))
1447                                         return PartialContainer.TypeParameters;
1448                                 if (type_param_list == null)
1449                                         initialize_type_params ();
1450
1451                                 return type_param_list;
1452                         }
1453                 }
1454
1455                 public override Type CurrentType {
1456                         get { return currentType != null ? currentType : TypeBuilder; }
1457                 }
1458
1459                 public override TypeContainer CurrentTypeDefinition {
1460                         get { return PartialContainer; }
1461                 }
1462
1463                 public int CountTypeParameters {
1464                         get {
1465                                 return count_type_params;
1466                         }
1467                 }
1468
1469                 // Used for error reporting only
1470                 public virtual Type LookupAnyGeneric (string typeName)
1471                 {
1472                         return NamespaceEntry.NS.LookForAnyGenericType (typeName);
1473                 }
1474
1475                 public override string[] ValidAttributeTargets {
1476                         get { return attribute_targets; }
1477                 }
1478
1479                 protected override bool VerifyClsCompliance ()
1480                 {
1481                         if (!base.VerifyClsCompliance ()) {
1482                                 return false;
1483                         }
1484
1485                         if (type_params != null) {
1486                                 foreach (TypeParameter tp in type_params) {
1487                                         if (tp.Constraints == null)
1488                                                 continue;
1489
1490                                         tp.Constraints.VerifyClsCompliance (Report);
1491                                 }
1492                         }
1493
1494                         var cache = TypeManager.AllClsTopLevelTypes;
1495                         if (cache == null)
1496                                 return true;
1497
1498                         string lcase = Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
1499                         if (!cache.ContainsKey (lcase)) {
1500                                 cache.Add (lcase, this);
1501                                 return true;
1502                         }
1503
1504                         object val = cache [lcase];
1505                         if (val == null) {
1506                                 Type t = AttributeTester.GetImportedIgnoreCaseClsType (lcase);
1507                                 if (t == null)
1508                                         return true;
1509                                 Report.SymbolRelatedToPreviousError (t);
1510                         }
1511                         else {
1512                                 Report.SymbolRelatedToPreviousError ((DeclSpace)val);
1513                         }
1514
1515                         Report.Warning (3005, 1, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ());
1516                         return true;
1517                 }
1518         }
1519 }