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