Add initial reflection dependant code
[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.Collections.Generic;
16 using System.Reflection.Emit;
17 using System.Reflection;
18
19 #if NET_2_1
20 using XmlElement = System.Object;
21 #else
22 using System.Xml;
23 #endif
24
25 namespace Mono.CSharp {
26
27         //
28         // Better name would be DottenName
29         //
30         public class MemberName {
31                 public readonly string Name;
32                 public TypeArguments TypeArguments;
33
34                 public readonly MemberName Left;
35                 public readonly Location Location;
36
37                 public static readonly MemberName Null = new MemberName ("");
38
39                 bool is_double_colon;
40
41                 private MemberName (MemberName left, string name, bool is_double_colon,
42                                     Location loc)
43                 {
44                         this.Name = name;
45                         this.Location = loc;
46                         this.is_double_colon = is_double_colon;
47                         this.Left = left;
48                 }
49
50                 private MemberName (MemberName left, string name, bool is_double_colon,
51                                     TypeArguments args, Location loc)
52                         : this (left, name, is_double_colon, loc)
53                 {
54                         if (args != null && args.Count > 0)
55                                 this.TypeArguments = args;
56                 }
57
58                 public MemberName (string name)
59                         : this (name, Location.Null)
60                 { }
61
62                 public MemberName (string name, Location loc)
63                         : this (null, name, false, loc)
64                 { }
65
66                 public MemberName (string name, TypeArguments args, Location loc)
67                         : this (null, name, false, args, loc)
68                 { }
69
70                 public MemberName (MemberName left, string name)
71                         : this (left, name, left != null ? left.Location : Location.Null)
72                 { }
73
74                 public MemberName (MemberName left, string name, Location loc)
75                         : this (left, name, false, loc)
76                 { }
77
78                 public MemberName (MemberName left, string name, TypeArguments args, Location loc)
79                         : this (left, name, false, args, loc)
80                 { }
81
82                 public MemberName (string alias, string name, TypeArguments args, Location loc)
83                         : this (new MemberName (alias, loc), name, true, args, loc)
84                 { }
85
86                 public MemberName (MemberName left, MemberName right)
87                         : this (left, right, right.Location)
88                 { }
89
90                 public MemberName (MemberName left, MemberName right, Location loc)
91                         : this (null, right.Name, false, right.TypeArguments, loc)
92                 {
93                         if (right.is_double_colon)
94                                 throw new InternalErrorException ("Cannot append double_colon member name");
95                         this.Left = (right.Left == null) ? left : new MemberName (left, right.Left);
96                 }
97
98                 // TODO: Remove
99                 public string GetName ()
100                 {
101                         return GetName (false);
102                 }
103
104                 public int Arity {
105                         get {
106                                 return TypeArguments == null ? 0 : TypeArguments.Count;
107                         }
108                 }
109
110                 public bool IsGeneric {
111                         get {
112                                 if (TypeArguments != null)
113                                         return true;
114                                 else if (Left != null)
115                                         return Left.IsGeneric;
116                                 else
117                                         return false;
118                         }
119                 }
120
121                 public string GetName (bool is_generic)
122                 {
123                         string name = is_generic ? Basename : Name;
124                         if (Left != null)
125                                 return Left.GetName (is_generic) + (is_double_colon ? "::" : ".") + name;
126
127                         return name;
128                 }
129
130                 public ATypeNameExpression GetTypeExpression ()
131                 {
132                         if (Left == null) {
133                                 if (TypeArguments != null)
134                                         return new SimpleName (Name, TypeArguments, Location);
135                                 
136                                 return new SimpleName (Name, Location);
137                         }
138
139                         if (is_double_colon) {
140                                 if (Left.Left != null)
141                                         throw new InternalErrorException ("The left side of a :: should be an identifier");
142                                 return new QualifiedAliasMember (Left.Name, Name, TypeArguments, Location);
143                         }
144
145                         Expression lexpr = Left.GetTypeExpression ();
146                         return new MemberAccess (lexpr, Name, TypeArguments, Location);
147                 }
148
149                 public MemberName Clone ()
150                 {
151                         MemberName left_clone = Left == null ? null : Left.Clone ();
152                         return new MemberName (left_clone, Name, is_double_colon, TypeArguments, Location);
153                 }
154
155                 public string Basename {
156                         get {
157                                 if (TypeArguments != null)
158                                         return MakeName (Name, TypeArguments);
159                                 return Name;
160                         }
161                 }
162
163                 public string GetSignatureForError ()
164                 {
165                         string append = TypeArguments == null ? "" : "<" + TypeArguments.GetSignatureForError () + ">";
166                         if (Left == null)
167                                 return Name + append;
168                         string connect = is_double_colon ? "::" : ".";
169                         return Left.GetSignatureForError () + connect + Name + append;
170                 }
171
172                 public override bool Equals (object other)
173                 {
174                         return Equals (other as MemberName);
175                 }
176
177                 public bool Equals (MemberName other)
178                 {
179                         if (this == other)
180                                 return true;
181                         if (other == null || Name != other.Name)
182                                 return false;
183                         if (is_double_colon != other.is_double_colon)
184                                 return false;
185
186                         if ((TypeArguments != null) &&
187                             (other.TypeArguments == null || TypeArguments.Count != other.TypeArguments.Count))
188                                 return false;
189
190                         if ((TypeArguments == null) && (other.TypeArguments != null))
191                                 return false;
192
193                         if (Left == null)
194                                 return other.Left == null;
195
196                         return Left.Equals (other.Left);
197                 }
198
199                 public override int GetHashCode ()
200                 {
201                         int hash = Name.GetHashCode ();
202                         for (MemberName n = Left; n != null; n = n.Left)
203                                 hash ^= n.Name.GetHashCode ();
204                         if (is_double_colon)
205                                 hash ^= 0xbadc01d;
206
207                         if (TypeArguments != null)
208                                 hash ^= TypeArguments.Count << 5;
209
210                         return hash & 0x7FFFFFFF;
211                 }
212
213                 public int CountTypeArguments {
214                         get {
215                                 if (TypeArguments != null)
216                                         return TypeArguments.Count;
217                                 else if (Left != null)
218                                         return Left.CountTypeArguments; 
219                                 else
220                                         return 0;
221                         }
222                 }
223
224                 public static string MakeName (string name, TypeArguments args)
225                 {
226                         if (args == null)
227                                 return name;
228
229                         return name + "`" + args.Count;
230                 }
231
232                 public static string MakeName (string name, int count)
233                 {
234                         return name + "`" + count;
235                 }
236         }
237
238         public class SimpleMemberName
239         {
240                 public string Value;
241                 public Location Location;
242
243                 public SimpleMemberName (string name, Location loc)
244                 {
245                         this.Value = name;
246                         this.Location = loc;
247                 }
248         }
249
250         /// <summary>
251         ///   Base representation for members.  This is used to keep track
252         ///   of Name, Location and Modifier flags, and handling Attributes.
253         /// </summary>
254         [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")]
255         public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition
256         {
257                 /// <summary>
258                 ///   Public name
259                 /// </summary>
260
261                 protected string cached_name;
262                 // TODO: Remove in favor of MemberName
263                 public string Name {
264                         get {
265                                 if (cached_name == null)
266                                         cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method));
267                                 return cached_name;
268                         }
269                 }
270
271                 string IMemberDefinition.Name {
272                         get {
273                                 return member_name.Name;
274                         }
275                 }
276
277                 // Is not readonly because of IndexerName attribute
278                 private MemberName member_name;
279                 public MemberName MemberName {
280                         get { return member_name; }
281                 }
282
283                 /// <summary>
284                 ///   Modifier flags that the user specified in the source code
285                 /// </summary>
286                 private Modifiers mod_flags;
287                 public Modifiers ModFlags {
288                         set {
289                                 mod_flags = value;
290                                 if ((value & Modifiers.COMPILER_GENERATED) != 0)
291                                         caching_flags = Flags.IsUsed | Flags.IsAssigned;
292                         }
293                         get {
294                                 return mod_flags;
295                         }
296                 }
297
298                 public virtual ModuleContainer Module {
299                         get {
300                                 return Parent.Module;
301                         }
302                 }
303
304                 public /*readonly*/ TypeContainer Parent;
305
306                 /// <summary>
307                 ///   Location where this declaration happens
308                 /// </summary>
309                 public Location Location {
310                         get { return member_name.Location; }
311                 }
312
313                 /// <summary>
314                 ///   XML documentation comment
315                 /// </summary>
316                 protected string comment;
317
318                 /// <summary>
319                 ///   Represents header string for documentation comment 
320                 ///   for each member types.
321                 /// </summary>
322                 public abstract string DocCommentHeader { get; }
323
324                 [Flags]
325                 public enum Flags {
326                         Obsolete_Undetected = 1,                // Obsolete attribute has not been detected yet
327                         Obsolete = 1 << 1,                      // Type has obsolete attribute
328                         ClsCompliance_Undetected = 1 << 2,      // CLS Compliance has not been detected yet
329                         ClsCompliant = 1 << 3,                  // Type is CLS Compliant
330                         CloseTypeCreated = 1 << 4,              // Tracks whether we have Closed the type
331                         HasCompliantAttribute_Undetected = 1 << 5,      // Presence of CLSCompliantAttribute has not been detected
332                         HasClsCompliantAttribute = 1 << 6,                      // Type has CLSCompliantAttribute
333                         ClsCompliantAttributeFalse = 1 << 7,                    // Member has CLSCompliant(false)
334                         Excluded_Undetected = 1 << 8,           // Conditional attribute has not been detected yet
335                         Excluded = 1 << 9,                                      // Method is conditional
336                         MethodOverloadsExist = 1 << 10,         // Test for duplication must be performed
337                         IsUsed = 1 << 11,
338                         IsAssigned = 1 << 12,                           // Field is assigned
339                         HasExplicitLayout       = 1 << 13,
340                         PartialDefinitionExists = 1 << 14,      // Set when corresponding partial method definition exists
341                         HasStructLayout         = 1 << 15                       // Has StructLayoutAttribute
342                 }
343
344                 /// <summary>
345                 ///   MemberCore flags at first detected then cached
346                 /// </summary>
347                 internal Flags caching_flags;
348
349                 public MemberCore (DeclSpace parent, MemberName name, Attributes attrs)
350                 {
351                         this.Parent = parent as TypeContainer;
352                         member_name = name;
353                         caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
354                         AddAttributes (attrs, this);
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 = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
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 = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
601                                                 else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
602                                                         same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
603                                                 else
604                                                         goto case Modifiers.PROTECTED;
605
606                                                 break;
607
608                                         case Modifiers.PRIVATE:
609                                                 //
610                                                 // Both are private and share same parent
611                                                 //
612                                                 if (al == Modifiers.PRIVATE) {
613                                                         var decl = mc.Parent;
614                                                         do {
615                                                                 same_access_restrictions = decl.CurrentType == p_parent;
616                                                         } while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null);
617                                                 }
618                                                 
619                                                 break;
620                                                 
621                                         default:
622                                                 throw new InternalErrorException (al.ToString ());
623                                         }
624                                 }
625                                 
626                                 if (!same_access_restrictions)
627                                         return false;
628                         }
629
630                         return true;
631                 }
632
633                 /// <summary>
634                 /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
635                 /// </summary>
636                 public override bool IsClsComplianceRequired ()
637                 {
638                         if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
639                                 return (caching_flags & Flags.ClsCompliant) != 0;
640
641                         caching_flags &= ~Flags.ClsCompliance_Undetected;
642
643                         if (HasClsCompliantAttribute) {
644                                 if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0)
645                                         return false;
646
647                                 caching_flags |= Flags.ClsCompliant;
648                                 return true;
649                         }
650
651                         if (Parent.PartialContainer.IsClsComplianceRequired ()) {
652                                 caching_flags |= Flags.ClsCompliant;
653                                 return true;
654                         }
655
656                         return false;
657                 }
658
659                 public virtual string[] ConditionalConditions ()
660                 {
661                         return null;
662                 }
663
664                 /// <summary>
665                 /// Returns true when MemberCore is exposed from assembly.
666                 /// </summary>
667                 public bool IsExposedFromAssembly ()
668                 {
669                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
670                                 return false;
671                         
672                         DeclSpace parentContainer = Parent.PartialContainer;
673                         while (parentContainer != null && parentContainer.ModFlags != 0) {
674                                 if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
675                                         return false;
676                                 parentContainer = parentContainer.Parent;
677                         }
678                         return true;
679                 }
680
681                 public virtual IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
682                 {
683                         return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope);
684                 }
685
686                 public virtual FullNamedExpression LookupNamespaceAlias (string name)
687                 {
688                         return Parent.NamespaceEntry.LookupNamespaceAlias (name);
689                 }
690
691                 public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
692                 {
693                         return Parent.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
694                 }
695
696                 /// <summary>
697                 /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
698                 /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
699                 /// </summary>
700                 public bool IsNotCLSCompliant ()
701                 {
702                         if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
703                                 return (caching_flags & Flags.ClsCompliantAttributeFalse) != 0;
704
705                         caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
706
707                         if (OptAttributes != null) {
708                                 Attribute cls_attribute = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
709                                 if (cls_attribute != null) {
710                                         caching_flags |= Flags.HasClsCompliantAttribute;
711                                         if (cls_attribute.GetClsCompliantAttributeValue ())
712                                                 return false;
713
714                                         caching_flags |= Flags.ClsCompliantAttributeFalse;
715                                         return true;
716                                 }
717                         }
718
719                         return false;
720                 }
721
722                 /// <summary>
723                 /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
724                 /// </summary>
725                 protected bool HasClsCompliantAttribute {
726                         get {
727                                 if ((caching_flags & Flags.HasCompliantAttribute_Undetected) != 0)
728                                         IsNotCLSCompliant ();
729                                 
730                                 return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
731                         }
732                 }
733
734                 /// <summary>
735                 /// Returns true when a member supports multiple overloads (methods, indexers, etc)
736                 /// </summary>
737                 public virtual bool EnableOverloadChecks (MemberCore overload)
738                 {
739                         return false;
740                 }
741
742                 /// <summary>
743                 /// The main virtual method for CLS-Compliant verifications.
744                 /// The method returns true if member is CLS-Compliant and false if member is not
745                 /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
746                 /// and add their extra verifications.
747                 /// </summary>
748                 protected virtual bool VerifyClsCompliance ()
749                 {
750                         if (HasClsCompliantAttribute) {
751                                 if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) {
752                                         Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
753                                         if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
754                                                 Report.Warning (3021, 2, a.Location,
755                                                         "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant",
756                                                         GetSignatureForError ());
757                                         } else {
758                                                 Report.Warning (3014, 1, a.Location,
759                                                         "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
760                                                         GetSignatureForError ());
761                                         }
762                                         return false;
763                                 }
764
765                                 if (!IsExposedFromAssembly ()) {
766                                         Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
767                                         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 ());
768                                         return false;
769                                 }
770
771                                 if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
772                                         if (Parent.Kind == MemberKind.Interface && Parent.IsClsComplianceRequired ()) {
773                                                 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
774                                         } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) {
775                                                 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
776                                         }
777
778                                         return false;
779                                 }
780
781                                 if (Parent.Parent != null && !Parent.IsClsComplianceRequired ()) {
782                                         Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
783                                         Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
784                                                 GetSignatureForError (), Parent.GetSignatureForError ());
785                                         return false;
786                                 }
787                         } else {
788                                 if (!IsExposedFromAssembly ())
789                                         return false;
790
791                                 if (!Parent.PartialContainer.IsClsComplianceRequired ())
792                                         return false;
793                         }
794
795                         if (member_name.Name [0] == '_') {
796                                 Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () );
797                         }
798
799                         return true;
800                 }
801
802                 //
803                 // Raised (and passed an XmlElement that contains the comment)
804                 // when GenerateDocComment is writing documentation expectedly.
805                 //
806                 internal virtual void OnGenerateDocComment (XmlElement intermediateNode)
807                 {
808                 }
809
810                 //
811                 // Returns a string that represents the signature for this 
812                 // member which should be used in XML documentation.
813                 //
814                 public virtual string GetDocCommentName (DeclSpace ds)
815                 {
816                         if (ds == null || this is DeclSpace)
817                                 return DocCommentHeader + Name;
818                         else
819                                 return String.Concat (DocCommentHeader, ds.Name, ".", Name);
820                 }
821
822                 //
823                 // Generates xml doc comments (if any), and if required,
824                 // handle warning report.
825                 //
826                 internal virtual void GenerateDocComment (DeclSpace ds)
827                 {
828                         try {
829                                 DocUtil.GenerateDocComment (this, ds, Report);
830                         } catch (Exception e) {
831                                 throw new InternalErrorException (this, e);
832                         }
833                 }
834
835                 #region IMemberContext Members
836
837                 public virtual CompilerContext Compiler {
838                         get { return Parent.Compiler; }
839                 }
840
841                 public virtual TypeSpec CurrentType {
842                         get { return Parent.CurrentType; }
843                 }
844
845                 public MemberCore CurrentMemberDefinition {
846                         get { return this; }
847                 }
848
849                 public virtual TypeParameter[] CurrentTypeParameters {
850                         get { return null; }
851                 }
852
853                 public virtual bool HasUnresolvedConstraints {
854                         get { return false; }
855                 }
856
857                 public bool IsObsolete {
858                         get {
859                                 if (GetAttributeObsolete () != null)
860                                         return true;
861
862                                 return Parent == null ? false : Parent.IsObsolete;
863                         }
864                 }
865
866                 public bool IsUnsafe {
867                         get {
868                                 if ((ModFlags & Modifiers.UNSAFE) != 0)
869                                         return true;
870
871                                 return Parent == null ? false : Parent.IsUnsafe;
872                         }
873                 }
874
875                 public bool IsStatic {
876                         get {
877                                 return (ModFlags & Modifiers.STATIC) != 0;
878                         }
879                 }
880
881                 #endregion
882         }
883
884         //
885         // Base member specification. A member specification contains
886         // member details which can alter in the context (e.g. generic instances)
887         //
888         public abstract class MemberSpec
889         {
890                 [Flags]
891                 public enum StateFlags
892                 {
893                         Obsolete_Undetected = 1,        // Obsolete attribute has not been detected yet
894                         Obsolete = 1 << 1,                      // Member has obsolete attribute
895                         CLSCompliant_Undetected = 1 << 3,       // CLSCompliant attribute has not been detected yet
896                         CLSCompliant = 1 << 4,          // Member is CLS Compliant
897                         HasDynamicElement = 1 << 5,
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                 public 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 virtual int Arity {
934                         get {
935                                 return 0;
936                         }
937                 }
938
939                 public TypeSpec DeclaringType {
940                         get {
941                                 return declaringType;
942                         }
943                         set {
944                                 declaringType = value;
945                         }
946                 }
947
948                 public IMemberDefinition MemberDefinition {
949                         get {
950                                 return definition;
951                         }
952                 }
953
954                 public Modifiers Modifiers {
955                         get {
956                                 return modifiers;
957                         }
958                         set {
959                                 modifiers = value;
960                         }
961                 }
962                 
963                 public virtual string Name {
964                         get {
965                                 return definition.Name;
966                         }
967                 }
968
969                 public bool IsAbstract {
970                         get { return (modifiers & Modifiers.ABSTRACT) != 0; }
971                 }
972
973                 public bool IsAccessor {
974                         get {
975                                 return (state & StateFlags.IsAccessor) != 0;
976                         }
977                         set {
978                                 state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor;
979                         }
980                 }
981
982                 //
983                 // Return true when this member is a generic in C# terms
984                 // A nested non-generic type of generic type will return false
985                 //
986                 public bool IsGeneric {
987                         get {
988                                 return (state & StateFlags.IsGeneric) != 0;
989                         }
990                         set {
991                                 state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric;
992                         }
993                 }
994
995                 public bool IsPrivate {
996                         get { return (modifiers & Modifiers.PRIVATE) != 0; }
997                 }
998
999                 public bool IsPublic {
1000                         get { return (modifiers & Modifiers.PUBLIC) != 0; }
1001                 }
1002
1003                 public bool IsStatic {
1004                         get { 
1005                                 return (modifiers & Modifiers.STATIC) != 0;
1006                         }
1007                 }
1008
1009                 #endregion
1010
1011                 public virtual ObsoleteAttribute GetAttributeObsolete ()
1012                 {
1013                         if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0)
1014                                 return null;
1015
1016                         state &= ~StateFlags.Obsolete_Undetected;
1017
1018                         var oa = definition.GetAttributeObsolete ();
1019                         if (oa != null)
1020                                 state |= StateFlags.Obsolete;
1021
1022                         return oa;
1023                 }
1024
1025                 protected virtual bool IsNotCLSCompliant ()
1026                 {
1027                         return MemberDefinition.IsNotCLSCompliant ();
1028                 }
1029
1030                 public virtual string GetSignatureForError ()
1031                 {
1032                         var bf = MemberDefinition as Property.BackingField;
1033                         var name = bf == null ? Name : bf.OriginalName;
1034                         return DeclaringType.GetSignatureForError () + "." + name;
1035                 }
1036
1037                 public virtual MemberSpec InflateMember (TypeParameterInflator inflator)
1038                 {
1039                         var inflated = (MemberSpec) MemberwiseClone ();
1040                         inflated.declaringType = inflator.TypeInstance;
1041                         inflated.state |= StateFlags.PendingMetaInflate;
1042 #if DEBUG
1043                         if (inflated.ID > 0)
1044                                 inflated.ID = -inflated.ID;
1045 #endif
1046                         return inflated;
1047                 }
1048
1049                 //
1050                 // Is this member accessible from invocationType
1051                 //
1052                 public bool IsAccessible (TypeSpec invocationType)
1053                 {
1054                         var ma = Modifiers & Modifiers.AccessibilityMask;
1055                         if (ma == Modifiers.PUBLIC)
1056                                 return true;
1057
1058                         var parentType = /* this as TypeSpec ?? */ DeclaringType;
1059
1060                         // It's null for module context
1061                         if (invocationType == null)
1062                                 invocationType = InternalType.FakeInternalType;
1063                 
1064                         //
1065                         // If only accessible to the current class or children
1066                         //
1067                         if (ma == Modifiers.PRIVATE)
1068                                 return invocationType.MemberDefinition == parentType.MemberDefinition ||
1069                                         TypeManager.IsNestedChildOf (invocationType, parentType);
1070
1071                         if ((ma & Modifiers.INTERNAL) != 0) {
1072                                 bool b;
1073                                 var assembly = invocationType == InternalType.FakeInternalType ?
1074                                         RootContext.ToplevelTypes.DeclaringAssembly :
1075                                         invocationType.MemberDefinition.DeclaringAssembly;
1076
1077                                 if (parentType == null) {
1078                                         b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly);
1079                                 } else {
1080                                         b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly);
1081                                 }
1082
1083                                 if (b || ma == Modifiers.INTERNAL)
1084                                         return b;
1085                         }
1086
1087                         // PROTECTED
1088                         if (!TypeManager.IsNestedFamilyAccessible (invocationType, parentType))
1089                                 return false;
1090
1091                         return true;
1092                 }
1093
1094                 //
1095                 // Returns member CLS compliance based on full member hierarchy
1096                 //
1097                 public bool IsCLSCompliant ()
1098                 {
1099                         if ((state & StateFlags.CLSCompliant_Undetected) != 0) {
1100                                 state &= ~StateFlags.CLSCompliant_Undetected;
1101
1102                                 if (IsNotCLSCompliant ())
1103                                         return false;
1104
1105                                 bool compliant;
1106                                 if (DeclaringType != null) {
1107                                         compliant = DeclaringType.IsCLSCompliant ();
1108                                 } else {
1109                                         compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
1110                                 }
1111
1112                                 if (compliant)
1113                                         state |= StateFlags.CLSCompliant;
1114                         }
1115
1116                         return (state & StateFlags.CLSCompliant) != 0;
1117                 }
1118
1119                 public bool IsConditionallyExcluded (Location loc)
1120                 {
1121                         if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
1122                                 return false;
1123
1124                         var conditions = MemberDefinition.ConditionalConditions ();
1125                         if (conditions == null)
1126                                 return false;
1127
1128                         foreach (var condition in conditions) {
1129                                 if (loc.CompilationUnit.IsConditionalDefined (condition))
1130                                         return false;
1131                         }
1132
1133                         return true;
1134                 }
1135
1136                 public override string ToString ()
1137                 {
1138                         return GetSignatureForError ();
1139                 }
1140         }
1141
1142         //
1143         // Member details which are same between all member
1144         // specifications
1145         //
1146         public interface IMemberDefinition
1147         {
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                 public readonly string Basename;
1187                 
1188                 protected Dictionary<string, MemberCore> defined_names;
1189
1190                 public TypeContainer PartialContainer;          
1191
1192                 protected readonly bool is_generic;
1193                 readonly int count_type_params;
1194                 protected TypeParameter[] type_params;
1195                 TypeParameter[] type_param_list;
1196
1197                 //
1198                 // Whether we are Generic
1199                 //
1200                 public bool IsGeneric {
1201                         get {
1202                                 if (is_generic)
1203                                         return true;
1204                                 else if (Parent != null)
1205                                         return Parent.IsGeneric;
1206                                 else
1207                                         return false;
1208                         }
1209                 }
1210
1211                 static string[] attribute_targets = new string [] { "type" };
1212
1213                 public DeclSpace (NamespaceEntry ns, DeclSpace parent, MemberName name,
1214                                   Attributes attrs)
1215                         : base (parent, name, attrs)
1216                 {
1217                         NamespaceEntry = ns;
1218                         Basename = name.Basename;
1219                         defined_names = new Dictionary<string, MemberCore> ();
1220                         PartialContainer = null;
1221                         if (name.TypeArguments != null) {
1222                                 is_generic = true;
1223                                 count_type_params = name.TypeArguments.Count;
1224                         }
1225                         if (parent != null)
1226                                 count_type_params += parent.count_type_params;
1227                 }
1228
1229                 /// <summary>
1230                 /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
1231                 /// </summary>
1232                 protected virtual bool AddToContainer (MemberCore symbol, string name)
1233                 {
1234                         MemberCore mc;
1235                         if (!defined_names.TryGetValue (name, out mc)) {
1236                                 defined_names.Add (name, symbol);
1237                                 return true;
1238                         }
1239
1240                         if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
1241                                 return true;
1242
1243                         if (symbol.EnableOverloadChecks (mc))
1244                                 return true;
1245
1246                         InterfaceMemberBase im = mc as InterfaceMemberBase;
1247                         if (im != null && im.IsExplicitImpl)
1248                                 return true;
1249
1250                         Report.SymbolRelatedToPreviousError (mc);
1251                         if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
1252                                 Error_MissingPartialModifier (symbol);
1253                                 return false;
1254                         }
1255
1256                         if (this is ModuleContainer) {
1257                                 Report.Error (101, symbol.Location, 
1258                                         "The namespace `{0}' already contains a definition for `{1}'",
1259                                         ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
1260                         } else if (symbol is TypeParameter) {
1261                                 Report.Error (692, symbol.Location,
1262                                         "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
1263                         } else {
1264                                 Report.Error (102, symbol.Location,
1265                                               "The type `{0}' already contains a definition for `{1}'",
1266                                               GetSignatureForError (), symbol.MemberName.Name);
1267                         }
1268
1269                         return false;
1270                 }
1271
1272                 protected void RemoveFromContainer (string name)
1273                 {
1274                         defined_names.Remove (name);
1275                 }
1276                 
1277                 /// <summary>
1278                 ///   Returns the MemberCore associated with a given name in the declaration
1279                 ///   space. It doesn't return method based symbols !!
1280                 /// </summary>
1281                 /// 
1282                 public MemberCore GetDefinition (string name)
1283                 {
1284                         MemberCore mc = null;
1285                         defined_names.TryGetValue (name, out mc);
1286                         return mc;
1287                 }
1288         
1289                 // 
1290                 // root_types contains all the types.  All TopLevel types
1291                 // hence have a parent that points to `root_types', that is
1292                 // why there is a non-obvious test down here.
1293                 //
1294                 public bool IsTopLevel {
1295                         get { return (Parent != null && Parent.Parent == null); }
1296                 }
1297
1298                 public virtual bool IsUnmanagedType ()
1299                 {
1300                         return false;
1301                 }
1302
1303                 protected virtual TypeAttributes TypeAttr {
1304                         get { return Module.DefaultCharSetType; }
1305                 }
1306
1307                 /// <remarks>
1308                 ///  Should be overriten by the appropriate declaration space
1309                 /// </remarks>
1310                 public abstract void DefineType ();
1311
1312                 protected void Error_MissingPartialModifier (MemberCore type)
1313                 {
1314                         Report.Error (260, type.Location,
1315                                 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
1316                                 type.GetSignatureForError ());
1317                 }
1318
1319                 public override string GetSignatureForError ()
1320                 {
1321                         return MemberName.GetSignatureForError ();
1322                 }
1323                 
1324                 TypeParameter[] initialize_type_params ()
1325                 {
1326                         if (type_param_list != null)
1327                                 return type_param_list;
1328
1329                         DeclSpace the_parent = Parent;
1330                         if (this is GenericMethod)
1331                                 the_parent = null;
1332
1333                         var list = new List<TypeParameter> ();
1334                         if (the_parent != null && the_parent.IsGeneric) {
1335                                 // FIXME: move generics info out of DeclSpace
1336                                 TypeParameter[] parent_params = the_parent.TypeParameters;
1337                                 list.AddRange (parent_params);
1338                         }
1339  
1340                         int count = type_params != null ? type_params.Length : 0;
1341                         for (int i = 0; i < count; i++) {
1342                                 TypeParameter param = type_params [i];
1343                                 list.Add (param);
1344                                 if (Parent.CurrentTypeParameters != null) {
1345                                         foreach (TypeParameter tp in Parent.CurrentTypeParameters) {
1346                                                 if (tp.Name != param.Name)                              
1347                                                         continue;
1348
1349                                                 Report.SymbolRelatedToPreviousError (tp.Location, null);
1350                                                 Report.Warning (693, 3, param.Location,
1351                                                         "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'",
1352                                                         param.Name, Parent.GetSignatureForError ());
1353                                         }
1354                                 }
1355                         }
1356
1357                         type_param_list = new TypeParameter [list.Count];
1358                         list.CopyTo (type_param_list, 0);
1359                         return type_param_list;
1360                 }
1361
1362                 public virtual void SetParameterInfo (List<Constraints> constraints_list)
1363                 {
1364                         if (!is_generic) {
1365                                 if (constraints_list != null) {
1366                                         Report.Error (
1367                                                 80, Location, "Constraints are not allowed " +
1368                                                 "on non-generic declarations");
1369                                 }
1370
1371                                 return;
1372                         }
1373
1374                         TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
1375                         type_params = new TypeParameter [names.Length];
1376
1377                         //
1378                         // Register all the names
1379                         //
1380                         for (int i = 0; i < type_params.Length; i++) {
1381                                 TypeParameterName name = names [i];
1382
1383                                 Constraints constraints = null;
1384                                 if (constraints_list != null) {
1385                                         int total = constraints_list.Count;
1386                                         for (int ii = 0; ii < total; ++ii) {
1387                                                 Constraints constraints_at = (Constraints)constraints_list[ii];
1388                                                 // TODO: it is used by iterators only
1389                                                 if (constraints_at == null) {
1390                                                         constraints_list.RemoveAt (ii);
1391                                                         --total;
1392                                                         continue;
1393                                                 }
1394                                                 if (constraints_at.TypeParameter.Value == name.Name) {
1395                                                         constraints = constraints_at;
1396                                                         constraints_list.RemoveAt(ii);
1397                                                         break;
1398                                                 }
1399                                         }
1400                                 }
1401
1402                                 Variance variance = name.Variance;
1403                                 if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) {
1404                                         Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates");
1405                                         variance = Variance.None;
1406                                 }
1407
1408                                 type_params [i] = new TypeParameter (
1409                                         Parent, i, new MemberName (name.Name, Location), constraints, name.OptAttributes, variance);
1410
1411                                 AddToContainer (type_params [i], name.Name);
1412                         }
1413
1414                         if (constraints_list != null && constraints_list.Count > 0) {
1415                                 foreach (Constraints constraint in constraints_list) {
1416                                         Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", 
1417                                                 GetSignatureForError (), constraint.TypeParameter.Value);
1418                                 }
1419                         }
1420                 }
1421
1422                 protected TypeParameter[] TypeParameters {
1423                         get {
1424                                 if (!IsGeneric)
1425                                         throw new InvalidOperationException ();
1426                                 if ((PartialContainer != null) && (PartialContainer != this))
1427                                         return PartialContainer.TypeParameters;
1428                                 if (type_param_list == null)
1429                                         initialize_type_params ();
1430
1431                                 return type_param_list;
1432                         }
1433                 }
1434
1435                 public int CountTypeParameters {
1436                         get {
1437                                 return count_type_params;
1438                         }
1439                 }
1440
1441                 public override string[] ValidAttributeTargets {
1442                         get { return attribute_targets; }
1443                 }
1444
1445                 protected override bool VerifyClsCompliance ()
1446                 {
1447                         if (!base.VerifyClsCompliance ()) {
1448                                 return false;
1449                         }
1450
1451                         if (type_params != null) {
1452                                 foreach (TypeParameter tp in type_params) {
1453                                         tp.VerifyClsCompliance ();
1454                                 }
1455                         }
1456
1457                         return true;
1458                 }
1459         }
1460 }