2006-03-22 Marek Safar <marek.safar@seznam.cz>
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@ximian.com)
6 //          Marek Safar (marek.safar@seznam.cz)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // (C) 2004 Novell, Inc
12 //
13 //
14 //  2002-10-11  Miguel de Icaza  <miguel@ximian.com>
15 //
16 //      * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 //      have fixed a remaining problem: not every AddXXXX was adding a
18 //      fully qualified name.  
19 //
20 //      Now everyone registers a fully qualified name in the DeclSpace as
21 //      being defined instead of the partial name.  
22 //
23 //      Downsides: we are slower than we need to be due to the excess
24 //      copies and the names being registered this way.  
25 //
26 //      The reason for this is that we currently depend (on the corlib
27 //      bootstrap for instance) that types are fully qualified, because
28 //      we dump all the types in the namespace, and we should really have
29 //      types inserted into the proper namespace, so we can only store the
30 //      basenames in the defined_names array.
31 //
32 //
33 #define CACHE
34 using System;
35 using System.Collections;
36 using System.Collections.Specialized;
37 using System.Reflection;
38 using System.Reflection.Emit;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Security;
42 using System.Security.Permissions;
43 using System.Text;
44
45 #if BOOTSTRAP_WITH_OLDLIB
46 using XmlElement = System.Object;
47 #else
48 using System.Xml;
49 #endif
50
51 using Mono.CompilerServices.SymbolWriter;
52
53 namespace Mono.CSharp {
54
55         public enum Kind {
56                 Root,
57                 Struct,
58                 Class,
59                 Interface
60         }
61
62         /// <summary>
63         ///   This is the base class for structs and classes.  
64         /// </summary>
65         public abstract class TypeContainer : DeclSpace, IMemberContainer {
66
67                 public class MemberCoreArrayList: ArrayList
68                 {
69                         /// <summary>
70                         ///   Defines the MemberCore objects that are in this array
71                         /// </summary>
72                         public virtual void DefineContainerMembers ()
73                         {
74                                 foreach (MemberCore mc in this) {
75                                         mc.Define ();
76                                 }
77                         }
78
79                         public virtual void Emit ()
80                         {
81                                 foreach (MemberCore mc in this)
82                                         mc.Emit ();
83                         }
84                 }
85
86                 public class MethodArrayList : MemberCoreArrayList
87                 {
88                         [Flags]
89                         enum CachedMethods {
90                                 Equals                  = 1,
91                                 GetHashCode             = 1 << 1
92                         }
93  
94                         CachedMethods cached_method;
95                         TypeContainer container;
96
97                         public MethodArrayList (TypeContainer container)
98                         {
99                                 this.container = container;
100                         }
101  
102                         /// <summary>
103                         /// Method container contains Equals method
104                         /// </summary>
105                         public bool HasEquals {
106                                 set {
107                                         cached_method |= CachedMethods.Equals;
108                                 }
109  
110                                 get {
111                                         return (cached_method & CachedMethods.Equals) != 0;
112                                 }
113                         }
114  
115                         /// <summary>
116                         /// Method container contains GetHashCode method
117                         /// </summary>
118                         public bool HasGetHashCode {
119                                 set {
120                                         cached_method |= CachedMethods.GetHashCode;
121                                 }
122  
123                                 get {
124                                         return (cached_method & CachedMethods.GetHashCode) != 0;
125                                 }
126                         }
127  
128                         public override void DefineContainerMembers ()
129                         {
130                                 base.DefineContainerMembers ();
131  
132                                 if (HasEquals && !HasGetHashCode) {
133                                         Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
134                                 }
135                         }
136  
137                 }
138
139                 public sealed class IndexerArrayList : MemberCoreArrayList
140                 {
141                         /// <summary>
142                         /// The indexer name for this container
143                         /// </summary>
144                         public string IndexerName = DefaultIndexerName;
145
146                         bool seen_normal_indexers = false;
147
148                         TypeContainer container;
149
150                         public IndexerArrayList (TypeContainer container)
151                         {
152                                 this.container = container;
153                         }
154
155                         /// <summary>
156                         /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
157                         /// class is consistent.  Either it is `Item' or it is the name defined by all the
158                         /// indexers with the `IndexerName' attribute.
159                         ///
160                         /// Turns out that the IndexerNameAttribute is applied to each indexer,
161                         /// but it is never emitted, instead a DefaultMember attribute is attached
162                         /// to the class.
163                         /// </summary>
164                         public override void DefineContainerMembers()
165                         {
166                                 base.DefineContainerMembers ();
167
168                                 string class_indexer_name = null;
169
170                                 //
171                                 // If there's both an explicit and an implicit interface implementation, the
172                                 // explicit one actually implements the interface while the other one is just
173                                 // a normal indexer.  See bug #37714.
174                                 //
175
176                                 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
177                                 foreach (Indexer i in this) {
178                                         if (i.InterfaceType != null) {
179                                                 if (seen_normal_indexers)
180                                                         throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
181                                                 continue;
182                                         }
183
184                                         seen_normal_indexers = true;
185
186                                         if (class_indexer_name == null) {
187                                                 class_indexer_name = i.ShortName;
188                                                 continue;
189                                         }
190
191                                         if (i.ShortName != class_indexer_name)
192                                                 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
193                                 }
194
195                                 if (class_indexer_name != null)
196                                         IndexerName = class_indexer_name;
197                         }
198
199                         public override void Emit ()
200                         {
201                                 base.Emit ();
202
203                                 if (!seen_normal_indexers)
204                                         return;
205
206                                 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
207                                 container.TypeBuilder.SetCustomAttribute (cb);
208                         }
209                 }
210
211                 public class OperatorArrayList: MemberCoreArrayList
212                 {
213                         TypeContainer container;
214
215                         public OperatorArrayList (TypeContainer container)
216                         {
217                                 this.container = container;
218                         }
219
220                         //
221                         // Operator pair checking
222                         //
223                         class OperatorEntry
224                         {
225                                 public int flags;
226                                 public Type ret_type;
227                                 public Type type1, type2;
228                                 public Operator op;
229                                 public Operator.OpType ot;
230                                 
231                                 public OperatorEntry (int f, Operator o)
232                                 {
233                                         flags = f;
234
235                                         ret_type = o.OperatorMethod.ReturnType;
236                                         Type [] pt = o.OperatorMethod.ParameterTypes;
237                                         type1 = pt [0];
238                                         type2 = pt [1];
239                                         op = o;
240                                         ot = o.OperatorType;
241                                 }
242
243                                 public override int GetHashCode ()
244                                 {       
245                                         return ret_type.GetHashCode ();
246                                 }
247
248                                 public override bool Equals (object o)
249                                 {
250                                         OperatorEntry other = (OperatorEntry) o;
251
252                                         if (other.ret_type != ret_type)
253                                                 return false;
254                                         if (other.type1 != type1)
255                                                 return false;
256                                         if (other.type2 != type2)
257                                                 return false;
258                                         return true;
259                                 }
260                         }
261                                 
262                         //
263                         // Checks that some operators come in pairs:
264                         //  == and !=
265                         // > and <
266                         // >= and <=
267                         // true and false
268                         //
269                         // They are matched based on the return type and the argument types
270                         //
271                         void CheckPairedOperators ()
272                         {
273                                 IDictionary pairs = new HybridDictionary ();
274                                 Operator true_op = null;
275                                 Operator false_op = null;
276                                 bool has_equality_or_inequality = false;
277                                 
278                                 // Register all the operators we care about.
279                                 foreach (Operator op in this){
280                                         int reg = 0;
281
282                                         // Skip erroneous code.
283                                         if (op.OperatorMethod == null)
284                                                 continue;
285
286                                         switch (op.OperatorType){
287                                         case Operator.OpType.Equality:
288                                                 reg = 1;
289                                                 has_equality_or_inequality = true;
290                                                 break;
291                                         case Operator.OpType.Inequality:
292                                                 reg = 2;
293                                                 has_equality_or_inequality = true;
294                                                 break;
295
296                                         case Operator.OpType.True:
297                                                 true_op = op;
298                                                 break;
299                                         case Operator.OpType.False:
300                                                 false_op = op;
301                                                 break;
302                                                 
303                                         case Operator.OpType.GreaterThan:
304                                                 reg = 1; break;
305                                         case Operator.OpType.LessThan:
306                                                 reg = 2; break;
307                                                 
308                                         case Operator.OpType.GreaterThanOrEqual:
309                                                 reg = 1; break;
310                                         case Operator.OpType.LessThanOrEqual:
311                                                 reg = 2; break;
312                                         }
313                                         if (reg == 0)
314                                                 continue;
315
316                                         OperatorEntry oe = new OperatorEntry (reg, op);
317
318                                         object o = pairs [oe];
319                                         if (o == null)
320                                                 pairs [oe] = oe;
321                                         else {
322                                                 oe = (OperatorEntry) o;
323                                                 oe.flags |= reg;
324                                         }
325                                 }
326
327                                 if (true_op != null){
328                                         if (false_op == null)
329                                                 Report.Error (216, true_op.Location, "The operator `{0}' requires a matching operator `false' to also be defined",
330                                                         true_op.GetSignatureForError ());
331                                 } else if (false_op != null)
332                                         Report.Error (216, false_op.Location, "The operator `{0}' requires a matching operator `true' to also be defined",
333                                                 false_op.GetSignatureForError ());
334                                 
335                                 //
336                                 // Look for the mistakes.
337                                 //
338                                 foreach (DictionaryEntry de in pairs){
339                                         OperatorEntry oe = (OperatorEntry) de.Key;
340
341                                         if (oe.flags == 3)
342                                                 continue;
343
344                                         string s = "";
345                                         switch (oe.ot){
346                                         case Operator.OpType.Equality:
347                                                 s = "!=";
348                                                 break;
349                                         case Operator.OpType.Inequality: 
350                                                 s = "==";
351                                                 break;
352                                         case Operator.OpType.GreaterThan: 
353                                                 s = "<";
354                                                 break;
355                                         case Operator.OpType.LessThan:
356                                                 s = ">";
357                                                 break;
358                                         case Operator.OpType.GreaterThanOrEqual:
359                                                 s = "<=";
360                                                 break;
361                                         case Operator.OpType.LessThanOrEqual:
362                                                 s = ">=";
363                                                 break;
364                                         }
365                                         Report.Error (216, oe.op.Location,
366                                                 "The operator `{0}' requires a matching operator `{1}' to also be defined",
367                                                 oe.op.GetSignatureForError (), s);
368                                 }
369
370                                 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
371                                         if (container.Methods == null || !container.Methods.HasEquals)
372                                                 Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
373  
374                                         if (container.Methods == null || !container.Methods.HasGetHashCode)
375                                                 Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
376                                 }
377                         }
378
379                         public override void DefineContainerMembers ()
380                         {
381                                 base.DefineContainerMembers ();
382                                 CheckPairedOperators ();
383                         }
384                 }
385
386
387                 // Whether this is a struct, class or interface
388                 public readonly Kind Kind;
389
390                 // Holds a list of classes and structures
391                 protected ArrayList types;
392
393                 // Holds the list of properties
394                 MemberCoreArrayList properties;
395
396                 // Holds the list of enumerations
397                 MemberCoreArrayList enums;
398
399                 // Holds the list of delegates
400                 MemberCoreArrayList delegates;
401                 
402                 // Holds the list of constructors
403                 protected MemberCoreArrayList instance_constructors;
404
405                 // Holds the list of fields
406                 MemberCoreArrayList fields;
407
408                 // Holds a list of fields that have initializers
409                 protected ArrayList initialized_fields;
410
411                 // Holds a list of static fields that have initializers
412                 protected ArrayList initialized_static_fields;
413
414                 // Holds the list of constants
415                 MemberCoreArrayList constants;
416
417                 // Holds the list of
418                 MemberCoreArrayList interfaces;
419
420                 // Holds the methods.
421                 MethodArrayList methods;
422
423                 // Holds the events
424                 protected MemberCoreArrayList events;
425
426                 // Holds the indexers
427                 IndexerArrayList indexers;
428
429                 // Holds the operators
430                 MemberCoreArrayList operators;
431
432                 // Holds the iterators
433                 ArrayList iterators;
434
435                 //
436                 // Pointers to the default constructor and the default static constructor
437                 //
438                 Constructor default_constructor;
439                 Constructor default_static_constructor;
440
441                 //
442                 // Points to the first non-static field added to the container.
443                 //
444                 // This is an arbitrary choice.  We are interested in looking at _some_ non-static field,
445                 // and the first one's as good as any.
446                 //
447                 FieldBase first_nonstatic_field = null;
448
449                 //
450                 // This one is computed after we can distinguish interfaces
451                 // from classes from the arraylist `type_bases' 
452                 //
453                 TypeExpr base_type;
454                 TypeExpr[] iface_exprs;
455
456                 ArrayList type_bases;
457
458                 bool members_defined;
459                 bool members_defined_ok;
460
461                 // The interfaces we implement.
462                 protected Type[] ifaces;
463
464                 // The base member cache and our member cache
465                 MemberCache base_cache;
466                 MemberCache member_cache;
467
468                 public const string DefaultIndexerName = "Item";
469
470                 public TypeContainer PartialContainer;
471                 ArrayList partial_parts;
472
473                 /// <remarks>
474                 ///  The pending methods that need to be implemented
475                 //   (interfaces or abstract methods)
476                 /// </remarks>
477                 PendingImplementation pending;
478
479                 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
480                                       Attributes attrs, Kind kind)
481                         : base (ns, parent, name, attrs)
482                 {
483                         if (parent != null && parent != RootContext.Tree.Types && parent.NamespaceEntry != ns)
484                                 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
485
486                         this.Kind = kind;
487                         this.PartialContainer = this;
488                 }
489
490                 public bool AddToMemberContainer (MemberCore symbol)
491                 {
492                         return AddToContainer (symbol, symbol.Name);
493                 }
494
495                 protected virtual bool AddToTypeContainer (DeclSpace ds)
496                 {
497                         return AddToContainer (ds, ds.Basename);
498                 }
499
500                 public void AddConstant (Const constant)
501                 {
502                         if (!AddToMemberContainer (constant))
503                                 return;
504
505                         if (constants == null)
506                                 constants = new MemberCoreArrayList ();
507                         
508                         constants.Add (constant);
509                 }
510
511                 public void AddEnum (Mono.CSharp.Enum e)
512                 {
513                         if (!AddToTypeContainer (e))
514                                 return;
515
516                         if (enums == null)
517                                 enums = new MemberCoreArrayList ();
518
519                         enums.Add (e);
520                 }
521                 
522                 public bool AddClassOrStruct (TypeContainer c)
523                 {
524                         if (!AddToTypeContainer (c))
525                                 return false;
526
527                         if (types == null)
528                                 types = new ArrayList (2);
529
530                         RootContext.Tree.RecordDecl (c.NamespaceEntry.NS, c.MemberName, c);
531                         types.Add (c);
532                         return true;
533                 }
534
535                 public virtual TypeContainer AddPartial (TypeContainer nextPart)
536                 {
537                         return AddPartial (nextPart, nextPart.Basename);
538                 }
539
540                 protected TypeContainer AddPartial (TypeContainer nextPart, string name)
541                 {
542                         nextPart.ModFlags |= Modifiers.PARTIAL;
543                         TypeContainer tc = defined_names [name] as TypeContainer;
544
545                         if (tc == null) {
546                                 if (nextPart is Interface)
547                                         AddInterface (nextPart);
548                                 else
549                                         AddClassOrStruct (nextPart);
550                                 return nextPart;
551                         }
552
553                         if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
554                                 Report.SymbolRelatedToPreviousError (tc);
555                                 Error_MissingPartialModifier (nextPart);
556                                 return tc;
557                         }
558
559                         if (tc.Kind != nextPart.Kind) {
560                                 Report.SymbolRelatedToPreviousError (tc);
561                                 Report.Error (261, nextPart.Location,
562                                         "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
563                                         nextPart.GetSignatureForError ());
564                                 return tc;
565                         }
566
567                         if ((tc.ModFlags & Modifiers.Accessibility) != (nextPart.ModFlags & Modifiers.Accessibility)) {
568                                 Report.SymbolRelatedToPreviousError (tc);
569                                 Report.Error (262, nextPart.Location,
570                                         "Partial declarations of `{0}' have conflicting accessibility modifiers",
571                                         nextPart.GetSignatureForError ());
572                                 return tc;
573                         }
574
575                         if (tc.partial_parts == null)
576                                 tc.partial_parts = new ArrayList (1);
577
578                         tc.ModFlags |= nextPart.ModFlags;
579                         if (nextPart.attributes != null) {
580                                 if (tc.attributes == null)
581                                         tc.attributes = nextPart.attributes;
582                                 else
583                                         tc.attributes.AddAttributes (nextPart.attributes.Attrs);
584                         }
585
586                         nextPart.PartialContainer = tc;
587                         tc.partial_parts.Add (nextPart);
588                         return tc;
589                 }
590
591                 public void AddDelegate (Delegate d)
592                 {
593                         if (!AddToTypeContainer (d))
594                                 return;
595
596                         if (delegates == null)
597                                 delegates = new MemberCoreArrayList ();
598                         
599                         delegates.Add (d);
600                 }
601
602                 public void AddMethod (Method method)
603                 {
604                         if (!AddToMemberContainer (method))
605                                 return;
606
607                         if (methods == null)
608                                 methods = new MethodArrayList (this);
609                         
610                         if (method.MemberName.Left != null)
611                                 methods.Insert (0, method);
612                         else 
613                                 methods.Add (method);
614                 }
615
616                 //
617                 // Do not use this method: use AddMethod.
618                 //
619                 // This is only used by iterators.
620                 //
621                 public void AppendMethod (Method method)
622                 {
623                         if (!AddToMemberContainer (method))
624                                 return;
625
626                         if (methods == null)
627                                 methods = new MethodArrayList (this);
628
629                         methods.Add (method);
630                 }
631
632                 public void AddConstructor (Constructor c)
633                 {
634                         if (c.Name != Basename)  {
635                                 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
636                         }
637
638                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
639                         
640                         if (is_static){
641                                 if (default_static_constructor != null) {
642                                         Report.SymbolRelatedToPreviousError (default_static_constructor);
643                                         Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
644                                         return;
645                                 }
646
647                                 default_static_constructor = c;
648                         } else {
649                                 if (c.IsDefault ()){
650                                         if (default_constructor != null) {
651                                                 Report.SymbolRelatedToPreviousError (default_constructor);
652                                                 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
653                                                 return;
654                                         }
655                                         default_constructor = c;
656                                 }
657                                 
658                                 if (instance_constructors == null)
659                                         instance_constructors = new MemberCoreArrayList ();
660                                 
661                                 instance_constructors.Add (c);
662                         }
663                 }
664
665                 internal static string Error111 {
666                         get {
667                                 return "`{0}' is already defined. Rename this member or use different parameter types";
668                         }
669                 }
670                 
671                 public bool AddInterface (TypeContainer iface)
672                 {
673                         if (!AddToTypeContainer (iface))
674                                 return false;
675
676                         if (interfaces == null) {
677                                 interfaces = new MemberCoreArrayList ();
678                         }
679
680                         RootContext.Tree.RecordDecl (iface.NamespaceEntry.NS, iface.MemberName, iface);
681                         interfaces.Add (iface);
682                         return true;
683                 }
684
685                 public void AddField (FieldMember field)
686                 {
687                         if (!AddToMemberContainer (field))
688                                 return;
689
690                         if (fields == null)
691                                 fields = new MemberCoreArrayList ();
692
693                         fields.Add (field);
694
695                         if ((field.ModFlags & Modifiers.STATIC) != 0)
696                                 return;
697
698                         if (first_nonstatic_field == null) {
699                                 first_nonstatic_field = field;
700                                 return;
701                         }
702
703                         if (Kind == Kind.Struct &&
704                             first_nonstatic_field.Parent != field.Parent &&
705                             RootContext.WarningLevel >= 3) {
706                                 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
707                                 Report.Warning (282, 3, field.Location,
708                                         "struct instance field `{0}' found in different declaration from instance field `{1}'",
709                                         field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
710                         }
711                 }
712
713                 public void AddProperty (Property prop)
714                 {
715                         if (!AddToMemberContainer (prop) || 
716                                 !AddToMemberContainer (prop.Get) || !AddToMemberContainer (prop.Set))
717                                 return;
718
719                         if (properties == null)
720                                 properties = new MemberCoreArrayList ();
721
722                         if (prop.MemberName.Left != null)
723                                 properties.Insert (0, prop);
724                         else
725                                 properties.Add (prop);
726                 }
727
728                 public void AddEvent (Event e)
729                 {
730                         if (!AddToMemberContainer (e))
731                                 return;
732
733                         if (e is EventProperty) {
734                                 if (!AddToMemberContainer (e.Add))
735                                         return;
736
737                                 if (!AddToMemberContainer (e.Remove))
738                                         return;
739                         }
740
741                         if (events == null)
742                                 events = new MemberCoreArrayList ();
743
744                         events.Add (e);
745                 }
746
747
748                 /// <summary>
749                 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
750                 /// </summary>
751                 public void AddIndexer (Indexer i)
752                 {
753                         if (indexers == null)
754                                 indexers = new IndexerArrayList (this);
755
756                         if (i.IsExplicitImpl)
757                                 indexers.Insert (0, i);
758                         else
759                                 indexers.Add (i);
760                 }
761
762                 public void AddOperator (Operator op)
763                 {
764                         if (!AddToMemberContainer (op))
765                                 return;
766
767                         if (operators == null)
768                                 operators = new OperatorArrayList (this);
769
770                         operators.Add (op);
771                 }
772
773                 public void AddIterator (Iterator i)
774                 {
775                         if (iterators == null)
776                                 iterators = new ArrayList ();
777
778                         iterators.Add (i);
779                 }
780
781                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
782                 {
783                         if (a.Type == TypeManager.default_member_type) {
784                                 if (Indexers != null) {
785                                         Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
786                                         return;
787                                 }
788                         }
789                         
790                         base.ApplyAttributeBuilder (a, cb);
791                 } 
792
793                 public override AttributeTargets AttributeTargets {
794                         get {
795                                 throw new NotSupportedException ();
796                         }
797                 }
798
799                 public ArrayList Types {
800                         get {
801                                 return types;
802                         }
803                 }
804
805                 public MethodArrayList Methods {
806                         get {
807                                 return methods;
808                         }
809                 }
810
811                 public ArrayList Constants {
812                         get {
813                                 return constants;
814                         }
815                 }
816
817                 public ArrayList Interfaces {
818                         get {
819                                 return interfaces;
820                         }
821                 }
822
823                 public ArrayList Iterators {
824                         get {
825                                 return iterators;
826                         }
827                 }
828
829                 protected Type BaseType {
830                         get {
831                                 return TypeBuilder.BaseType;
832                         }
833                 }
834                 
835                 public ArrayList Bases {
836                         get {
837                                 return type_bases;
838                         }
839
840                         set {
841                                 type_bases = value;
842                         }
843                 }
844
845                 public ArrayList Fields {
846                         get {
847                                 return fields;
848                         }
849                 }
850
851                 public ArrayList InstanceConstructors {
852                         get {
853                                 return instance_constructors;
854                         }
855                 }
856
857                 public ArrayList Properties {
858                         get {
859                                 return properties;
860                         }
861                 }
862
863                 public ArrayList Events {
864                         get {
865                                 return events;
866                         }
867                 }
868                 
869                 public ArrayList Enums {
870                         get {
871                                 return enums;
872                         }
873                 }
874
875                 public ArrayList Indexers {
876                         get {
877                                 return indexers;
878                         }
879                 }
880
881                 public ArrayList Operators {
882                         get {
883                                 return operators;
884                         }
885                 }
886
887                 public ArrayList Delegates {
888                         get {
889                                 return delegates;
890                         }
891                 }
892                 
893                 protected override TypeAttributes TypeAttr {
894                         get {
895                                 return Modifiers.TypeAttr (ModFlags, this) | base.TypeAttr;
896                         }
897                 }
898
899                 public string IndexerName {
900                         get {
901                                 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
902                         }
903                 }
904
905                 public bool IsComImport {
906                         get {
907                                 if (OptAttributes == null)
908                                         return false;
909
910                                 return OptAttributes.Contains (TypeManager.comimport_attr_type);
911                         }
912                 }
913
914                 public virtual void RegisterFieldForInitialization (FieldBase field)
915                 {
916                         if ((field.ModFlags & Modifiers.STATIC) != 0){
917                                 if (initialized_static_fields == null)
918                                         initialized_static_fields = new ArrayList (4);
919
920                                 initialized_static_fields.Add (field);
921                         } else {
922                                 if (initialized_fields == null)
923                                         initialized_fields = new ArrayList (4);
924
925                                 initialized_fields.Add (field);
926                         }
927                 }
928
929                 //
930                 // Emits the instance field initializers
931                 //
932                 public bool EmitFieldInitializers (EmitContext ec)
933                 {
934                         ArrayList fields;
935                         
936                         if (ec.IsStatic){
937                                 fields = initialized_static_fields;
938                         } else {
939                                 fields = initialized_fields;
940                         }
941
942                         if (fields == null)
943                                 return true;
944
945                         foreach (FieldBase f in fields) {
946                                 f.EmitInitializer (ec);
947                         }
948                         return true;
949                 }
950                 
951                 //
952                 // Defines the default constructors
953                 //
954                 protected void DefineDefaultConstructor (bool is_static)
955                 {
956                         // The default instance constructor is public
957                         // If the class is abstract, the default constructor is protected
958                         // The default static constructor is private
959
960                         int mods;
961                         if (is_static) {
962                                 if (initialized_static_fields == null || default_static_constructor != null)
963                                         return;
964                                 mods = Modifiers.STATIC | Modifiers.PRIVATE;
965                         } else {
966                                 if (instance_constructors != null)
967                                         return;
968
969                                 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
970                         }
971
972                         Constructor c = new Constructor (this, Basename, mods,
973                                              Parameters.EmptyReadOnlyParameters,
974                                              new GeneratedBaseInitializer (Location),
975                                              Location);
976                         
977                         AddConstructor (c);
978                         c.Block = new ToplevelBlock (null, Location);
979                 }
980
981                 public override string DocComment {
982                         get {
983                                 return comment;
984                         }
985                         set {
986                                 if (value == null)
987                                         return;
988
989                                 comment += value;
990                         }
991                 }
992
993                 public PendingImplementation PendingImplementations {
994                         get { return pending; }
995                 }
996
997                 public override bool GetClsCompliantAttributeValue ()
998                 {
999                         if (PartialContainer != this)
1000                                 return PartialContainer.GetClsCompliantAttributeValue ();
1001
1002                         return base.GetClsCompliantAttributeValue ();
1003                 }
1004
1005                 TypeExpr[] GetNormalBases (out TypeExpr base_class)
1006                 {
1007                         base_class = null;
1008                         if (Bases == null)
1009                                 return null;
1010
1011                         int count = Bases.Count;
1012                         int start = 0, i, j;
1013
1014                         if (Kind == Kind.Class){
1015                                 TypeExpr name = ((Expression) Bases [0]).ResolveAsBaseTerminal (this, false);
1016
1017                                 if (name == null){
1018                                         return null;
1019                                 }
1020
1021                                 if (!name.IsInterface) {
1022                                         // base_class could be a class, struct, enum, delegate.
1023                                         // This is validated in GetClassBases.
1024                                         base_class = name;
1025                                         start = 1;
1026                                 }
1027                         }
1028
1029                         TypeExpr [] ifaces = new TypeExpr [count-start];
1030                         
1031                         for (i = start, j = 0; i < count; i++, j++){
1032                                 TypeExpr resolved = ((Expression) Bases [i]).ResolveAsTypeTerminal (this, false);
1033                                 if (resolved == null) {
1034                                         return null;
1035                                 }
1036                                 
1037                                 ifaces [j] = resolved;
1038                         }
1039
1040                         return ifaces.Length == 0 ? null : ifaces;
1041                 }
1042
1043
1044                 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
1045                 {
1046                         ArrayList ifaces = new ArrayList (0);
1047                         if (iface_exprs != null)
1048                                 ifaces.AddRange (iface_exprs);
1049
1050                         foreach (TypeContainer part in partial_parts) {
1051                                 TypeExpr new_base_class;
1052                                 TypeExpr[] new_ifaces = part.GetClassBases (out new_base_class);
1053                                 if (new_base_class != TypeManager.system_object_expr) {
1054                                         if (base_class == TypeManager.system_object_expr)
1055                                                 base_class = new_base_class;
1056                                         else {
1057                                                 if (new_base_class != null && !new_base_class.Equals (base_class)) {
1058                                                         Report.SymbolRelatedToPreviousError (base_class.Location, "");
1059                                                         Report.Error (263, part.Location,
1060                                                                 "Partial declarations of `{0}' must not specify different base classes",
1061                                                                 part.GetSignatureForError ());
1062
1063                                                         return null;
1064                                                 }
1065                                         }
1066                                 }
1067
1068                                 if (new_ifaces == null)
1069                                         continue;
1070
1071                                 foreach (TypeExpr iface in new_ifaces) {
1072                                         if (ifaces.Contains (iface))
1073                                                 continue;
1074
1075                                         ifaces.Add (iface);
1076                                 }
1077                         }
1078
1079                         if (ifaces.Count == 0)
1080                                 return null;
1081
1082                         return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
1083                 }
1084
1085                 /// <summary>
1086                 ///   This function computes the Base class and also the
1087                 ///   list of interfaces that the class or struct @c implements.
1088                 ///   
1089                 ///   The return value is an array (might be null) of
1090                 ///   interfaces implemented (as Types).
1091                 ///   
1092                 ///   The @base_class argument is set to the base object or null
1093                 ///   if this is `System.Object'. 
1094                 /// </summary>
1095                 public virtual TypeExpr [] GetClassBases (out TypeExpr base_class)
1096                 {
1097                         TypeExpr[] ifaces = GetNormalBases (out base_class);
1098
1099                         if (ifaces == null)
1100                                 return null;
1101
1102                         int count = ifaces.Length;
1103
1104                         for (int i = 0; i < count; i++) {
1105                                 TypeExpr iface = (TypeExpr) ifaces [i];
1106
1107                                 if (!iface.IsInterface) {
1108                                         if (Kind != Kind.Class) {
1109                                                 // TODO: location of symbol related ....
1110                                                 Error_TypeInListIsNotInterface (Location, iface.FullName);
1111                                         }
1112                                         else if (base_class != null)
1113                                                 Report.Error (1721, Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1114                                                         GetSignatureForError (), base_class.GetSignatureForError (), iface.GetSignatureForError ());
1115                                         else {
1116                                                 Report.Error (1722, Location, "`{0}': Base class `{1}' must be specified as first",
1117                                                         GetSignatureForError (), iface.GetSignatureForError ());
1118                                         }
1119                                         return null;
1120                                 }
1121
1122                                 for (int x = 0; x < i; x++) {
1123                                         if (iface.Equals (ifaces [x])) {
1124                                                 Report.Error (528, Location,
1125                                                               "`{0}' is already listed in " +
1126                                                               "interface list", iface.GetSignatureForError ());
1127                                                 return null;
1128                                         }
1129                                 }
1130
1131                                 if ((Kind == Kind.Interface) &&
1132                                     !iface.AsAccessible (Parent, ModFlags)) {
1133                                         Report.Error (61, Location,
1134                                                       "Inconsistent accessibility: base " +
1135                                                       "interface `{0}' is less accessible " +
1136                                                       "than interface `{1}'", iface.Name,
1137                                                       Name);
1138                                         return null;
1139                                 }
1140                         }
1141                         return ifaces;
1142                 }
1143
1144                 bool error = false;
1145                 
1146                 protected void Error_TypeInListIsNotInterface (Location loc, string type)
1147                 {
1148                         Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
1149                 }
1150
1151                 bool DefineTypeBuilder ()
1152                 {
1153                         try {
1154                                 if (IsTopLevel){
1155                                         if (TypeManager.NamespaceClash (Name, Location)) {
1156                                                 return false;
1157                                         }
1158
1159                                         ModuleBuilder builder = CodeGen.Module.Builder;
1160                                         TypeBuilder = builder.DefineType (
1161                                                 Name, TypeAttr, null, null);
1162                                 } else {
1163                                         TypeBuilder builder = Parent.TypeBuilder;
1164
1165                                         TypeBuilder = builder.DefineNestedType (
1166                                                 Basename, TypeAttr, null, null);
1167                                 }
1168                         } catch (ArgumentException) {
1169                                 Report.RuntimeMissingSupport (Location, "static classes");
1170                                 return false;
1171                         }
1172
1173                         TypeManager.AddUserType (this);
1174
1175                         iface_exprs = GetClassBases (out base_type);
1176                         if (partial_parts != null) {
1177                                 iface_exprs = GetNormalPartialBases (ref base_type);
1178                         }
1179
1180                         //
1181                         // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1182                         // which in turn should have called DefineType()s on base types if necessary.
1183                         //
1184                         // None of the code below should trigger DefineType()s on classes that we depend on.
1185                         // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1186                         //
1187                         // Let's do it as soon as possible, since code below can call DefineType() on classes
1188                         // that depend on us to be populated before they are.
1189                         //
1190                         if (!(this is Iterator))
1191                                 RootContext.RegisterOrder (this); 
1192
1193
1194                         if (base_type != null) {
1195                                 TypeBuilder.SetParent (base_type.Type);
1196
1197                                 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1198                                 if (obsolete_attr != null && !IsInObsoleteScope) {
1199                                         AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1200                                 }
1201                         }
1202
1203                         if (!CheckRecursiveDefinition (this)) {
1204                                 return false;
1205                         }
1206
1207                         // add interfaces that were not added at type creation
1208                         if (iface_exprs != null) {
1209                                 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1210                                 if (ifaces == null) {
1211                                         return false;
1212                                 }
1213
1214                                 foreach (Type itype in ifaces)
1215                                         TypeBuilder.AddInterfaceImplementation (itype);
1216
1217                                 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1218                         }
1219
1220                         return true;
1221                 }
1222
1223                 //
1224                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1225                 //
1226                 public override TypeBuilder DefineType ()
1227                 {
1228                         if (TypeBuilder != null)
1229                                 return TypeBuilder;
1230
1231                         if (error)
1232                                 return null;
1233                         
1234                         if (!DefineTypeBuilder ()) {
1235                                 error = true;
1236                                 return null;
1237                         }
1238
1239                         if (partial_parts != null) {
1240                                 foreach (TypeContainer part in partial_parts)
1241                                         part.TypeBuilder = TypeBuilder;
1242                         }
1243
1244                         DefineNestedTypes ();
1245
1246                         return TypeBuilder;
1247                 }
1248
1249                 protected virtual bool DefineNestedTypes ()
1250                 {
1251                         if (Interfaces != null) {
1252                                 foreach (TypeContainer iface in Interfaces)
1253                                         if (iface.DefineType () == null)
1254                                                 return false;
1255                         }
1256                         
1257                         if (Types != null) {
1258                                 foreach (TypeContainer tc in Types)
1259                                         if (tc.DefineType () == null)
1260                                                 return false;
1261                         }
1262
1263                         if (Delegates != null) {
1264                                 foreach (Delegate d in Delegates)
1265                                         if (d.DefineType () == null)
1266                                                 return false;
1267                         }
1268
1269                         if (Enums != null) {
1270                                 foreach (Enum en in Enums)
1271                                         if (en.DefineType () == null)
1272                                                 return false;
1273                         }
1274
1275                         return true;
1276                 }
1277
1278                 TypeContainer InTransit;
1279
1280                 protected bool CheckRecursiveDefinition (TypeContainer tc)
1281                 {
1282                         if (InTransit != null) {
1283                                 Report.SymbolRelatedToPreviousError (this);
1284                                 if (this is Interface)
1285                                         Report.Error (
1286                                                 529, tc.Location, "Inherited interface `{0}' causes a " +
1287                                                 "cycle in the interface hierarchy of `{1}'",
1288                                                 GetSignatureForError (), tc.GetSignatureForError ());
1289                                 else
1290                                         Report.Error (
1291                                                 146, tc.Location, "Circular base class dependency " +
1292                                                 "involving `{0}' and `{1}'",
1293                                                 tc.GetSignatureForError (), GetSignatureForError ());
1294                                 return false;
1295                         }
1296
1297                         InTransit = tc;
1298
1299                         if (BaseType != null) {
1300                                 TypeContainer ptc = TypeManager.LookupTypeContainer (BaseType);
1301                                 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1302                                         return false;
1303                         }
1304
1305                         if (iface_exprs != null) {
1306                                 foreach (TypeExpr iface in iface_exprs) {
1307                                         Type itype = iface.Type;
1308
1309                                         TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1310                                         if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1311                                                 return false;
1312                                 }
1313                         }
1314
1315                         InTransit = null;
1316                         return true;
1317                 }
1318
1319                 public static void Error_KeywordNotAllowed (Location loc)
1320                 {
1321                         Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
1322                 }
1323
1324                 /// <summary>
1325                 ///   Populates our TypeBuilder with fields and methods
1326                 /// </summary>
1327                 public override bool DefineMembers ()
1328                 {
1329                         if (members_defined)
1330                                 return members_defined_ok;
1331
1332                         if (!base.DefineMembers ())
1333                                 return false;
1334
1335                         members_defined_ok = DoDefineMembers ();
1336                         members_defined = true;
1337
1338                         return members_defined_ok;
1339                 }
1340
1341                 public virtual void DefineDefaultConstructor ()
1342                 {
1343                 }
1344
1345                 protected virtual bool DoDefineMembers ()
1346                 {
1347                         if (!IsTopLevel) {
1348                                 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1349                                 if (conflict_symbol == null) {
1350                                         if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1351                                                 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1352                                 } else {
1353                                         if ((ModFlags & Modifiers.NEW) == 0) {
1354                                                 Report.SymbolRelatedToPreviousError (conflict_symbol);
1355                                                 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1356                                                         GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1357                                         }
1358                                 }
1359                         }
1360
1361                         DefineContainerMembers (constants);
1362                         DefineContainerMembers (fields);
1363
1364                         DefineDefaultConstructor ();
1365
1366                         if (Kind == Kind.Struct || Kind == Kind.Class) {
1367                                 pending = PendingImplementation.GetPendingImplementations (this);
1368                         }
1369                 
1370                         //
1371                         // Constructors are not in the defined_names array
1372                         //
1373                         DefineContainerMembers (instance_constructors);
1374                 
1375                         if (default_static_constructor != null)
1376                                 default_static_constructor.Define ();
1377                         
1378                         DefineContainerMembers (properties);
1379                         DefineContainerMembers (events);
1380                         DefineContainerMembers (indexers);
1381                         DefineContainerMembers (methods);
1382                         DefineContainerMembers (operators);
1383                         DefineContainerMembers (enums);
1384                         DefineContainerMembers (delegates);                     
1385
1386 #if CACHE
1387                         member_cache = new MemberCache (this);
1388                         if (partial_parts != null) {
1389                                 foreach (TypeContainer part in partial_parts)
1390                                         part.member_cache = member_cache;
1391                         }
1392 #endif
1393                         if (iterators != null) {
1394                                 foreach (Iterator iterator in iterators) {
1395                                         if (iterator.DefineType () == null)
1396                                                 return false;
1397                                 }
1398
1399                                 foreach (Iterator iterator in iterators) {
1400                                         if (!iterator.DefineMembers ())
1401                                                 return false;
1402                                 }
1403                         }
1404
1405                         return true;
1406                 }
1407
1408                 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1409                 {
1410                         if (mcal != null)
1411                                 mcal.DefineContainerMembers ();
1412                 }
1413
1414                 public override bool Define ()
1415                 {
1416                         if (iterators != null) {
1417                                 foreach (Iterator iterator in iterators) {
1418                                         if (!iterator.Define ())
1419                                                 return false;
1420                                 }
1421                         }
1422
1423                         return true;
1424                 }
1425
1426                 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1427                 {
1428                         return BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1429                 }
1430
1431                 /// <summary>
1432                 ///   This function is based by a delegate to the FindMembers routine
1433                 /// </summary>
1434                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1435                 {
1436                         return true;
1437                 }
1438
1439                 /// <summary>
1440                 ///   This filter is used by FindMembers, and we just keep
1441                 ///   a global for the filter to `AlwaysAccept'
1442                 /// </summary>
1443                 static MemberFilter accepting_filter;
1444
1445                 
1446                 static TypeContainer ()
1447                 {
1448                         accepting_filter = new MemberFilter (AlwaysAccept);
1449                 }
1450
1451                 public MethodInfo[] GetMethods ()
1452                 {
1453                         ArrayList members = new ArrayList ();
1454
1455                         DefineMembers ();
1456
1457                         if (methods != null) {
1458                                 int len = methods.Count;
1459                                 for (int i = 0; i < len; i++) {
1460                                         Method m = (Method) methods [i];
1461
1462                                         members.Add (m.MethodBuilder);
1463                                 }
1464                         }
1465
1466                         if (operators != null) {
1467                                 int len = operators.Count;
1468                                 for (int i = 0; i < len; i++) {
1469                                         Operator o = (Operator) operators [i];
1470
1471                                         members.Add (o.OperatorMethodBuilder);
1472                                 }
1473                         }
1474
1475                         if (properties != null) {
1476                                 int len = properties.Count;
1477                                 for (int i = 0; i < len; i++) {
1478                                         Property p = (Property) properties [i];
1479
1480                                         if (p.GetBuilder != null)
1481                                                 members.Add (p.GetBuilder);
1482                                         if (p.SetBuilder != null)
1483                                                 members.Add (p.SetBuilder);
1484                                 }
1485                         }
1486                                 
1487                         if (indexers != null) {
1488                                 int len = indexers.Count;
1489                                 for (int i = 0; i < len; i++) {
1490                                         Indexer ix = (Indexer) indexers [i];
1491
1492                                         if (ix.GetBuilder != null)
1493                                                 members.Add (ix.GetBuilder);
1494                                         if (ix.SetBuilder != null)
1495                                                 members.Add (ix.SetBuilder);
1496                                 }
1497                         }
1498
1499                         if (events != null) {
1500                                 int len = events.Count;
1501                                 for (int i = 0; i < len; i++) {
1502                                         Event e = (Event) events [i];
1503
1504                                         if (e.AddBuilder != null)
1505                                                 members.Add (e.AddBuilder);
1506                                         if (e.RemoveBuilder != null)
1507                                                 members.Add (e.RemoveBuilder);
1508                                 }
1509                         }
1510
1511                         MethodInfo[] retMethods = new MethodInfo [members.Count];
1512                         members.CopyTo (retMethods, 0);
1513                         return retMethods;
1514                 }
1515                 
1516                 // Indicated whether container has StructLayout attribute set Explicit
1517                 public bool HasExplicitLayout {
1518                         get {
1519                                 return (caching_flags & Flags.HasExplicitLayout) != 0;
1520                         }
1521                         set {
1522                                 caching_flags |= Flags.HasExplicitLayout;
1523                         }
1524                 }
1525
1526                 public override Type FindNestedType (string name)
1527                 {
1528                         if (PartialContainer != this)
1529                                 return PartialContainer.FindNestedType (name);
1530
1531                         ArrayList [] lists = { types, enums, delegates, interfaces };
1532
1533                         for (int j = 0; j < lists.Length; ++j) {
1534                                 ArrayList list = lists [j];
1535                                 if (list == null)
1536                                         continue;
1537                                 
1538                                 int len = list.Count;
1539                                 for (int i = 0; i < len; ++i) {
1540                                         DeclSpace ds = (DeclSpace) list [i];
1541                                         if (ds.Basename == name) {
1542                                                 return ds.DefineType ();
1543                                         }
1544                                 }
1545                         }
1546
1547                         return null;
1548                 }
1549
1550                 private void FindMembers_NestedTypes (int modflags,
1551                                                       BindingFlags bf, MemberFilter filter, object criteria,
1552                                                       ref ArrayList members)
1553                 {
1554                         ArrayList [] lists = { types, enums, delegates, interfaces };
1555
1556                         for (int j = 0; j < lists.Length; ++j) {
1557                                 ArrayList list = lists [j];
1558                                 if (list == null)
1559                                         continue;
1560                         
1561                                 int len = list.Count;
1562                                 for (int i = 0; i < len; i++) {
1563                                         DeclSpace ds = (DeclSpace) list [i];
1564                                         
1565                                         if ((ds.ModFlags & modflags) == 0)
1566                                                 continue;
1567                                         
1568                                         TypeBuilder tb = ds.TypeBuilder;
1569                                         if (tb == null) {
1570                                                 if (!(criteria is string) || ds.Basename.Equals (criteria))
1571                                                         tb = ds.DefineType ();
1572                                         }
1573                                         
1574                                         if (tb != null && (filter (tb, criteria) == true)) {
1575                                                 if (members == null)
1576                                                         members = new ArrayList ();
1577                                                 
1578                                                 members.Add (tb);
1579                                         }
1580                                 }
1581                         }
1582                 }
1583                 
1584                 /// <summary>
1585                 ///   This method returns the members of this type just like Type.FindMembers would
1586                 ///   Only, we need to use this for types which are _being_ defined because MS' 
1587                 ///   implementation can't take care of that.
1588                 /// </summary>
1589                 //
1590                 // FIXME: return an empty static array instead of null, that cleans up
1591                 // some code and is consistent with some coding conventions I just found
1592                 // out existed ;-)
1593                 //
1594                 //
1595                 // Notice that in various cases we check if our field is non-null,
1596                 // something that would normally mean that there was a bug elsewhere.
1597                 //
1598                 // The problem happens while we are defining p-invoke methods, as those
1599                 // will trigger a FindMembers, but this happens before things are defined
1600                 //
1601                 // Since the whole process is a no-op, it is fine to check for null here.
1602                 //
1603                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1604                                                         MemberFilter filter, object criteria)
1605                 {
1606                         ArrayList members = null;
1607
1608                         int modflags = 0;
1609                         if ((bf & BindingFlags.Public) != 0)
1610                                 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1611                                         Modifiers.INTERNAL;
1612                         if ((bf & BindingFlags.NonPublic) != 0)
1613                                 modflags |= Modifiers.PRIVATE;
1614
1615                         int static_mask = 0, static_flags = 0;
1616                         switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1617                         case BindingFlags.Static:
1618                                 static_mask = static_flags = Modifiers.STATIC;
1619                                 break;
1620
1621                         case BindingFlags.Instance:
1622                                 static_mask = Modifiers.STATIC;
1623                                 static_flags = 0;
1624                                 break;
1625
1626                         default:
1627                                 static_mask = static_flags = 0;
1628                                 break;
1629                         }
1630
1631                         Timer.StartTimer (TimerType.TcFindMembers);
1632
1633                         if (filter == null)
1634                                 filter = accepting_filter; 
1635
1636                         if ((mt & MemberTypes.Field) != 0) {
1637                                 if (fields != null) {
1638                                         int len = fields.Count;
1639                                         for (int i = 0; i < len; i++) {
1640                                                 FieldMember f = (FieldMember) fields [i];
1641                                                 
1642                                                 if ((f.ModFlags & modflags) == 0)
1643                                                         continue;
1644                                                 if ((f.ModFlags & static_mask) != static_flags)
1645                                                         continue;
1646
1647                                                 FieldBuilder fb = f.FieldBuilder;
1648                                                 if (fb != null && filter (fb, criteria) == true) {
1649                                                         if (members == null)
1650                                                                 members = new ArrayList ();
1651                                                         
1652                                                         members.Add (fb);
1653                                                 }
1654                                         }
1655                                 }
1656
1657                                 if (constants != null) {
1658                                         int len = constants.Count;
1659                                         for (int i = 0; i < len; i++) {
1660                                                 Const con = (Const) constants [i];
1661                                                 
1662                                                 if ((con.ModFlags & modflags) == 0)
1663                                                         continue;
1664                                                 if ((con.ModFlags & static_mask) != static_flags)
1665                                                         continue;
1666
1667                                                 FieldBuilder fb = con.FieldBuilder;
1668                                                 if (fb == null) {
1669                                                         if (con.Define ())
1670                                                                 fb = con.FieldBuilder;
1671                                                 }
1672                                                 if (fb != null && filter (fb, criteria) == true) {
1673                                                         if (members == null)
1674                                                                 members = new ArrayList ();
1675                                                         
1676                                                         members.Add (fb);
1677                                                 }
1678                                         }
1679                                 }
1680                         }
1681
1682                         if ((mt & MemberTypes.Method) != 0) {
1683                                 if (methods != null) {
1684                                         int len = methods.Count;
1685                                         for (int i = 0; i < len; i++) {
1686                                                 Method m = (Method) methods [i];
1687                                                 
1688                                                 if ((m.ModFlags & modflags) == 0)
1689                                                         continue;
1690                                                 if ((m.ModFlags & static_mask) != static_flags)
1691                                                         continue;
1692                                                 
1693                                                 MethodBuilder mb = m.MethodBuilder;
1694
1695                                                 if (mb != null && filter (mb, criteria) == true) {
1696                                                         if (members == null)
1697                                                                 members = new ArrayList ();
1698                                                         
1699                                                         members.Add (mb);
1700                                                 }
1701                                         }
1702                                 }
1703
1704                                 if (operators != null) {
1705                                         int len = operators.Count;
1706                                         for (int i = 0; i < len; i++) {
1707                                                 Operator o = (Operator) operators [i];
1708                                                 
1709                                                 if ((o.ModFlags & modflags) == 0)
1710                                                         continue;
1711                                                 if ((o.ModFlags & static_mask) != static_flags)
1712                                                         continue;
1713                                                 
1714                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1715                                                 if (ob != null && filter (ob, criteria) == true) {
1716                                                         if (members == null)
1717                                                                 members = new ArrayList ();
1718                                                         
1719                                                         members.Add (ob);
1720                                                 }
1721                                         }
1722                                 }
1723
1724                                 if (properties != null) {
1725                                         int len = properties.Count;
1726                                         for (int i = 0; i < len; i++) {
1727                                                 Property p = (Property) properties [i];
1728                                                 
1729                                                 if ((p.ModFlags & modflags) == 0)
1730                                                         continue;
1731                                                 if ((p.ModFlags & static_mask) != static_flags)
1732                                                         continue;
1733                                                 
1734                                                 MethodBuilder b;
1735
1736                                                 b = p.GetBuilder;
1737                                                 if (b != null && filter (b, criteria) == true) {
1738                                                         if (members == null)
1739                                                                 members = new ArrayList ();
1740                                                         
1741                                                         members.Add (b);
1742                                                 }
1743
1744                                                 b = p.SetBuilder;
1745                                                 if (b != null && filter (b, criteria) == true) {
1746                                                         if (members == null)
1747                                                                 members = new ArrayList ();
1748                                                         
1749                                                         members.Add (b);
1750                                                 }
1751                                         }
1752                                 }
1753                                 
1754                                 if (indexers != null) {
1755                                         int len = indexers.Count;
1756                                         for (int i = 0; i < len; i++) {
1757                                                 Indexer ix = (Indexer) indexers [i];
1758                                                 
1759                                                 if ((ix.ModFlags & modflags) == 0)
1760                                                         continue;
1761                                                 if ((ix.ModFlags & static_mask) != static_flags)
1762                                                         continue;
1763                                                 
1764                                                 MethodBuilder b;
1765
1766                                                 b = ix.GetBuilder;
1767                                                 if (b != null && filter (b, criteria) == true) {
1768                                                         if (members == null)
1769                                                                 members = new ArrayList ();
1770                                                         
1771                                                         members.Add (b);
1772                                                 }
1773
1774                                                 b = ix.SetBuilder;
1775                                                 if (b != null && filter (b, criteria) == true) {
1776                                                         if (members == null)
1777                                                                 members = new ArrayList ();
1778                                                         
1779                                                         members.Add (b);
1780                                                 }
1781                                         }
1782                                 }
1783                         }
1784
1785                         if ((mt & MemberTypes.Event) != 0) {
1786                                 if (events != null) {
1787                                         int len = events.Count;
1788                                         for (int i = 0; i < len; i++) {
1789                                                 Event e = (Event) events [i];
1790                                                 
1791                                                 if ((e.ModFlags & modflags) == 0)
1792                                                         continue;
1793                                                 if ((e.ModFlags & static_mask) != static_flags)
1794                                                         continue;
1795
1796                                                 MemberInfo eb = e.EventBuilder;
1797                                                 if (eb != null && filter (eb, criteria) == true) {
1798                                                         if (members == null)
1799                                                                 members = new ArrayList ();
1800                                                         
1801                                                         members.Add (e.EventBuilder);
1802                                                 }
1803                                         }
1804                                 }
1805                         }
1806                         
1807                         if ((mt & MemberTypes.Property) != 0){
1808                                 if (properties != null) {
1809                                         int len = properties.Count;
1810                                         for (int i = 0; i < len; i++) {
1811                                                 Property p = (Property) properties [i];
1812                                                 
1813                                                 if ((p.ModFlags & modflags) == 0)
1814                                                         continue;
1815                                                 if ((p.ModFlags & static_mask) != static_flags)
1816                                                         continue;
1817
1818                                                 MemberInfo pb = p.PropertyBuilder;
1819                                                 if (pb != null && filter (pb, criteria) == true) {
1820                                                         if (members == null)
1821                                                                 members = new ArrayList ();
1822                                                         
1823                                                         members.Add (p.PropertyBuilder);
1824                                                 }
1825                                         }
1826                                 }
1827
1828                                 if (indexers != null) {
1829                                         int len = indexers.Count;
1830                                         for (int i = 0; i < len; i++) {
1831                                                 Indexer ix = (Indexer) indexers [i];
1832                                                 
1833                                                 if ((ix.ModFlags & modflags) == 0)
1834                                                         continue;
1835                                                 if ((ix.ModFlags & static_mask) != static_flags)
1836                                                         continue;
1837
1838                                                 MemberInfo ib = ix.PropertyBuilder;
1839                                                 if (ib != null && filter (ib, criteria) == true) {
1840                                                         if (members == null)
1841                                                                 members = new ArrayList ();
1842                                                         
1843                                                         members.Add (ix.PropertyBuilder);
1844                                                 }
1845                                         }
1846                                 }
1847                         }
1848                         
1849                         if ((mt & MemberTypes.NestedType) != 0)
1850                                 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1851
1852                         if ((mt & MemberTypes.Constructor) != 0){
1853                                 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1854                                         int len = instance_constructors.Count;
1855                                         for (int i = 0; i < len; i++) {
1856                                                 Constructor c = (Constructor) instance_constructors [i];
1857                                                 
1858                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1859                                                 if (cb != null && filter (cb, criteria) == true) {
1860                                                         if (members == null)
1861                                                                 members = new ArrayList ();
1862                                                         
1863                                                         members.Add (cb);
1864                                                 }
1865                                         }
1866                                 }
1867
1868                                 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1869                                         ConstructorBuilder cb =
1870                                                 default_static_constructor.ConstructorBuilder;
1871                                         
1872                                         if (cb != null && filter (cb, criteria) == true) {
1873                                                 if (members == null)
1874                                                         members = new ArrayList ();
1875                                                 
1876                                                 members.Add (cb);
1877                                         }
1878                                 }
1879                         }
1880
1881                         //
1882                         // Lookup members in base if requested.
1883                         //
1884                         if ((bf & BindingFlags.DeclaredOnly) == 0) {
1885                                 if (TypeBuilder.BaseType != null) {
1886                                         MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1887                                         if (list.Count > 0) {
1888                                                 if (members == null)
1889                                                         members = new ArrayList ();
1890                                         
1891                                                 members.AddRange (list);
1892                                         }
1893                                 }
1894                                 if (ifaces != null) {
1895                                         foreach (Type base_type in ifaces) {
1896                                                 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1897
1898                                                 if (list.Count > 0) {
1899                                                         if (members == null)
1900                                                                 members = new ArrayList ();
1901                                                         members.AddRange (list);
1902                                                 }
1903                                         }
1904                                 }
1905                         }
1906
1907                         Timer.StopTimer (TimerType.TcFindMembers);
1908
1909                         if (members == null)
1910                                 return MemberList.Empty;
1911                         else
1912                                 return new MemberList (members);
1913                 }
1914
1915                 public override MemberCache MemberCache {
1916                         get {
1917                                 return member_cache;
1918                         }
1919                 }
1920
1921                 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1922                                                       MemberFilter filter, object criteria)
1923                 {
1924                         DeclSpace ds = TypeManager.LookupDeclSpace (t);
1925
1926                         if (ds != null)
1927                                 return ds.FindMembers (mt, bf, filter, criteria);
1928                         else
1929                                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1930                         
1931                 }
1932
1933                 /// <summary>
1934                 ///   Emits the values for the constants
1935                 /// </summary>
1936                 public void EmitConstants ()
1937                 {
1938                         if (constants != null)
1939                                 foreach (Const con in constants)
1940                                         con.Emit ();
1941                         return;
1942                 }
1943
1944                 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
1945                 {
1946                         if (al == null)
1947                                 return;
1948
1949                         foreach (MemberCore mc in al) {
1950                                 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1951                                         continue;
1952
1953                                 if (!mc.IsUsed) {
1954                                         Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
1955                                 }
1956                         }
1957                 }
1958
1959                 public virtual void VerifyMembers ()
1960                 {
1961                         //
1962                         // Check for internal or private fields that were never assigned
1963                         //
1964                         if (RootContext.WarningLevel >= 3) {
1965                                 CheckMemberUsage (properties, "property");
1966                                 CheckMemberUsage (methods, "method");
1967                                 CheckMemberUsage (constants, "constant");
1968
1969                                 if (fields != null){
1970                                         foreach (FieldMember f in fields) {
1971                                                 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1972                                                         continue;
1973                                                 
1974                                                 if (!f.IsUsed){
1975                                                         if ((f.caching_flags & Flags.IsAssigned) == 0)
1976                                                                 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
1977                                                         else {
1978 #if NET_2_0
1979                                                                 const int error_code = 414;
1980 #else
1981                                                                 const int error_code = 169;
1982 #endif
1983                                                                 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
1984                                                                         f.GetSignatureForError ());
1985                                                         }
1986                                                         continue;
1987                                                 }
1988                                                 
1989                                                 //
1990                                                 // Only report 649 on level 4
1991                                                 //
1992                                                 if (RootContext.WarningLevel < 4)
1993                                                         continue;
1994                                                 
1995                                                 if ((f.caching_flags & Flags.IsAssigned) != 0)
1996                                                         continue;
1997                                                 
1998                                                 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
1999                                                         f.GetSignatureForError (), f.Type.Type.IsValueType ? Activator.CreateInstance (f.Type.Type).ToString() : "null");
2000                                         }
2001                                 }
2002                         }
2003                 }
2004
2005                 // TODO: move to ClassOrStruct
2006                 void EmitConstructors ()
2007                 {
2008                         if (instance_constructors == null)
2009                                 return;
2010
2011                         if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2012                                 bool has_compliant_args = false;
2013
2014                                 foreach (Constructor c in instance_constructors) {
2015                                         c.Emit ();
2016
2017                                         if (has_compliant_args)
2018                                                 continue;
2019
2020                                         has_compliant_args = c.HasCompliantArgs;
2021                                 }
2022                                 if (!has_compliant_args)
2023                                         Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2024                         } else {
2025                                 foreach (Constructor c in instance_constructors)
2026                                         c.Emit ();
2027                         }
2028                 }
2029
2030                 /// <summary>
2031                 ///   Emits the code, this step is performed after all
2032                 ///   the types, enumerations, constructors
2033                 /// </summary>
2034                 public virtual void EmitType ()
2035                 {
2036                         if (OptAttributes != null)
2037                                 OptAttributes.Emit ();
2038                                 
2039                         //
2040                         // Structs with no fields need to have at least one byte.
2041                         // The right thing would be to set the PackingSize in a DefineType
2042                         // but there are no functions that allow interfaces *and* the size to
2043                         // be specified.
2044                         //
2045
2046                         if (Kind == Kind.Struct && first_nonstatic_field == null){
2047                                 FieldBuilder fb = TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
2048                                                                            FieldAttributes.Private);
2049
2050                                 if (HasExplicitLayout){
2051                                         object [] ctor_args = new object [1];
2052                                         ctor_args [0] = 0;
2053                                 
2054                                         CustomAttributeBuilder cba = new CustomAttributeBuilder (
2055                                                 TypeManager.field_offset_attribute_ctor, ctor_args);
2056                                         fb.SetCustomAttribute (cba);
2057                                 }
2058                         }
2059
2060                         Emit ();
2061
2062                         EmitConstructors ();
2063
2064                         // Can not continue if constants are broken
2065                         EmitConstants ();
2066                         if (Report.Errors > 0)
2067                                 return;
2068
2069                         if (default_static_constructor != null)
2070                                 default_static_constructor.Emit ();
2071                         
2072                         if (methods != null){
2073                                 foreach (Method m in methods)
2074                                         m.Emit ();
2075                         }
2076
2077                         if (operators != null)
2078                                 foreach (Operator o in operators)
2079                                         o.Emit ();
2080
2081                         if (properties != null)
2082                                 foreach (Property p in properties)
2083                                         p.Emit ();
2084
2085                         if (indexers != null){
2086                                 indexers.Emit ();
2087                         }
2088                         
2089                         if (fields != null)
2090                                 foreach (FieldMember f in fields)
2091                                         f.Emit ();
2092
2093                         if (events != null){
2094                                 foreach (Event e in Events)
2095                                         e.Emit ();
2096                         }
2097
2098                         if (delegates != null) {
2099                                 foreach (Delegate d in Delegates) {
2100                                         d.Emit ();
2101                                 }
2102                         }
2103
2104                         if (enums != null) {
2105                                 foreach (Enum e in enums) {
2106                                         e.Emit ();
2107                                 }
2108                         }
2109
2110                         if (pending != null)
2111                                 if (pending.VerifyPendingMethods ())
2112                                         return;
2113
2114                         if (iterators != null)
2115                                 foreach (Iterator iterator in iterators)
2116                                         iterator.EmitType ();
2117                 }
2118
2119                 public override void CloseType ()
2120                 {
2121                         if ((caching_flags & Flags.CloseTypeCreated) != 0)
2122                                 return;
2123
2124                         try {
2125                                 caching_flags |= Flags.CloseTypeCreated;
2126                                 TypeBuilder.CreateType ();
2127                         } catch (TypeLoadException){
2128                                 //
2129                                 // This is fine, the code still created the type
2130                                 //
2131 //                              Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2132 //                              Console.WriteLine (e.Message);
2133                         } catch {
2134                                 Console.WriteLine ("In type: " + Name);
2135                                 throw;
2136                         }
2137                         
2138                         if (Enums != null)
2139                                 foreach (Enum en in Enums)
2140                                         en.CloseType ();
2141
2142                         if (Types != null){
2143                                 foreach (TypeContainer tc in Types)
2144                                         if (tc.Kind == Kind.Struct)
2145                                                 tc.CloseType ();
2146
2147                                 foreach (TypeContainer tc in Types)
2148                                         if (tc.Kind != Kind.Struct)
2149                                                 tc.CloseType ();
2150                         }
2151
2152                         if (Delegates != null)
2153                                 foreach (Delegate d in Delegates)
2154                                         d.CloseType ();
2155
2156                         if (Iterators != null)
2157                                 foreach (Iterator i in Iterators)
2158                                         i.CloseType ();
2159
2160                         types = null;
2161                         properties = null;
2162                         enums = null;
2163                         delegates = null;
2164                         fields = null;
2165                         initialized_fields = null;
2166                         initialized_static_fields = null;
2167                         constants = null;
2168                         interfaces = null;
2169                         methods = null;
2170                         events = null;
2171                         indexers = null;
2172                         operators = null;
2173                         iterators = null;
2174                         default_constructor = null;
2175                         default_static_constructor = null;
2176                         type_bases = null;
2177                         OptAttributes = null;
2178                         ifaces = null;
2179                         base_cache = null;
2180                         member_cache = null;
2181                 }
2182
2183                 //
2184                 // Performs the validation on a Method's modifiers (properties have
2185                 // the same properties).
2186                 //
2187                 public bool MethodModifiersValid (MemberCore mc)
2188                 {
2189                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2190                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2191                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2192                         bool ok = true;
2193                         int flags = mc.ModFlags;
2194                         
2195                         //
2196                         // At most one of static, virtual or override
2197                         //
2198                         if ((flags & Modifiers.STATIC) != 0){
2199                                 if ((flags & vao) != 0){
2200                                         Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2201                                                 mc.GetSignatureForError ());
2202                                         ok = false;
2203                                 }
2204                         }
2205
2206                         if (Kind == Kind.Struct){
2207                                 if ((flags & va) != 0){
2208                                         Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2209                                         ok = false;
2210                                 }
2211                         }
2212
2213                         if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2214                                 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2215                                         mc.GetSignatureForError ());
2216                                 ok = false;
2217                         }
2218
2219                         //
2220                         // If the declaration includes the abstract modifier, then the
2221                         // declaration does not include static, virtual or extern
2222                         //
2223                         if ((flags & Modifiers.ABSTRACT) != 0){
2224                                 if ((flags & Modifiers.EXTERN) != 0){
2225                                         Report.Error (
2226                                                 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2227                                         ok = false;
2228                                 }
2229
2230                                 if ((flags & Modifiers.SEALED) != 0) {
2231                                         Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2232                                         ok = false;
2233                                 }
2234
2235                                 if ((flags & Modifiers.VIRTUAL) != 0){
2236                                         Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2237                                         ok = false;
2238                                 }
2239
2240                                 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2241                                         Report.Error (513, mc.Location, "`{0}' is abstract but it is contained in nonabstract class", mc.GetSignatureForError ());
2242                                         ok = false;
2243                                 }
2244                         }
2245
2246                         if ((flags & Modifiers.PRIVATE) != 0){
2247                                 if ((flags & vao) != 0){
2248                                         Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2249                                         ok = false;
2250                                 }
2251                         }
2252
2253                         if ((flags & Modifiers.SEALED) != 0){
2254                                 if ((flags & Modifiers.OVERRIDE) == 0){
2255                                         Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2256                                         ok = false;
2257                                 }
2258                         }
2259
2260                         return ok;
2261                 }
2262
2263                 public bool UserDefinedStaticConstructor {
2264                         get {
2265                                 return default_static_constructor != null;
2266                         }
2267                 }
2268
2269                 public Constructor DefaultStaticConstructor {
2270                         get { return default_static_constructor; }
2271                 }
2272
2273                 protected override bool VerifyClsCompliance ()
2274                 {
2275                         if (!base.VerifyClsCompliance ())
2276                                 return false;
2277
2278                         VerifyClsName ();
2279
2280                         Type base_type = TypeBuilder.BaseType;
2281                         if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2282                                 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2283                         }
2284
2285                         if (!Parent.IsClsComplianceRequired ()) {
2286                                 Report.Error (3018, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", 
2287                                         GetSignatureForError (), Parent.GetSignatureForError ());
2288                         }
2289                         return true;
2290                 }
2291
2292
2293                 /// <summary>
2294                 /// Checks whether container name is CLS Compliant
2295                 /// </summary>
2296                 void VerifyClsName ()
2297                 {
2298                         Hashtable base_members = base_cache == null ? 
2299                                 new Hashtable () :
2300                                 base_cache.GetPublicMembers ();
2301                         Hashtable this_members = new Hashtable ();
2302
2303                         foreach (DictionaryEntry entry in defined_names) {
2304                                 MemberCore mc = (MemberCore)entry.Value;
2305                                 if (!mc.IsClsComplianceRequired ())
2306                                         continue;
2307
2308                                 string name = (string) entry.Key;
2309                                 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2310
2311                                 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2312                                 object found = base_members [lcase];
2313                                 if (found == null) {
2314                                         found = this_members [lcase];
2315                                         if (found == null) {
2316                                                 this_members.Add (lcase, mc);
2317                                                 continue;
2318                                         }
2319                                 }
2320
2321                                 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2322                                         continue;                                       
2323
2324                                 if (found is MemberInfo) {
2325                                         if (basename == ((MemberInfo) found).Name)
2326                                                 continue;
2327                                         Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2328                                 } else {
2329                                         Report.SymbolRelatedToPreviousError ((MemberCore) found);
2330                                 }
2331                                 Report.Error (3005, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2332                         }
2333                 }
2334
2335
2336                 /// <summary>
2337                 ///   Performs checks for an explicit interface implementation.  First it
2338                 ///   checks whether the `interface_type' is a base inteface implementation.
2339                 ///   Then it checks whether `name' exists in the interface type.
2340                 /// </summary>
2341                 public virtual bool VerifyImplements (MemberBase mb)
2342                 {
2343                         if (ifaces != null) {
2344                                 foreach (Type t in ifaces){
2345                                         if (t == mb.InterfaceType)
2346                                                 return true;
2347                                 }
2348                         }
2349                         
2350                         Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2351                         Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2352                                 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2353                         return false;
2354                 }
2355
2356                 public void Mark_HasEquals ()
2357                 {
2358                         Methods.HasEquals = true;
2359                 }
2360
2361                 public void Mark_HasGetHashCode ()
2362                 {
2363                         Methods.HasGetHashCode = true;
2364                 }
2365
2366                 //
2367                 // IMemberContainer
2368                 //
2369
2370                 string IMemberContainer.Name {
2371                         get {
2372                                 return Name;
2373                         }
2374                 }
2375
2376                 Type IMemberContainer.Type {
2377                         get {
2378                                 return TypeBuilder;
2379                         }
2380                 }
2381
2382                 MemberCache IMemberContainer.MemberCache {
2383                         get {
2384                                 return member_cache;
2385                         }
2386                 }
2387
2388                 bool IMemberContainer.IsInterface {
2389                         get {
2390                                 return Kind == Kind.Interface;
2391                         }
2392                 }
2393
2394                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2395                 {
2396                         return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2397                 }
2398
2399                 //
2400                 // Generates xml doc comments (if any), and if required,
2401                 // handle warning report.
2402                 //
2403                 internal override void GenerateDocComment (DeclSpace ds)
2404                 {
2405                         DocUtil.GenerateTypeDocComment (this, ds);
2406                 }
2407
2408                 public override string DocCommentHeader {
2409                         get { return "T:"; }
2410                 }
2411
2412                 public virtual MemberCache BaseCache {
2413                         get {
2414                                 if (base_cache != null)
2415                                         return base_cache;
2416                                 if (TypeBuilder.BaseType != null)
2417                                         base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2418                                 if (TypeBuilder.IsInterface)
2419                                         base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2420                                 return base_cache;
2421                         }
2422                 }
2423         }
2424
2425         public abstract class ClassOrStruct : TypeContainer {
2426                 ListDictionary declarative_security;
2427
2428                 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2429                                       MemberName name, Attributes attrs, Kind kind)
2430                         : base (ns, parent, name, attrs, kind)
2431                 {
2432                 }
2433
2434                 protected override bool AddToContainer (MemberCore symbol, string name)
2435                 {
2436                         if (name == Basename) {
2437                                 Report.SymbolRelatedToPreviousError (this);
2438                                 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2439                                         symbol.GetSignatureForError ());
2440                                 return false;
2441                         }
2442
2443                         return base.AddToContainer (symbol, name);
2444                 }
2445
2446
2447                 public override void DefineDefaultConstructor ()
2448                 {
2449                         DefineDefaultConstructor (true);
2450                 }
2451
2452                 public override void VerifyMembers ()
2453                 {
2454                         base.VerifyMembers ();
2455
2456                         if ((events != null) && (RootContext.WarningLevel >= 3)) {
2457                                 foreach (Event e in events){
2458                                         if ((e.caching_flags & Flags.IsAssigned) == 0)
2459                                                 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2460                                 }
2461                         }
2462                 }
2463
2464                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2465                 {
2466                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2467                                 if (declarative_security == null)
2468                                         declarative_security = new ListDictionary ();
2469
2470                                 a.ExtractSecurityPermissionSet (declarative_security);
2471                                 return;
2472                         }
2473
2474                         if (a.Type == TypeManager.struct_layout_attribute_type && a.GetLayoutKindValue () == LayoutKind.Explicit) {
2475                                 HasExplicitLayout = true;
2476                         }
2477
2478                         base.ApplyAttributeBuilder (a, cb);
2479                 }
2480
2481                 public override void Emit()
2482                 {
2483                         base.Emit ();
2484
2485                         if (declarative_security != null) {
2486                                 foreach (DictionaryEntry de in declarative_security) {
2487                                         TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2488                                 }
2489                         }
2490                 }
2491         }
2492
2493
2494         // TODO: should be sealed
2495         public class Class : ClassOrStruct {
2496                 const int AllowedModifiers =
2497                         Modifiers.NEW |
2498                         Modifiers.PUBLIC |
2499                         Modifiers.PROTECTED |
2500                         Modifiers.INTERNAL |
2501                         Modifiers.PRIVATE |
2502                         Modifiers.ABSTRACT |
2503                         Modifiers.SEALED |
2504                         Modifiers.STATIC |
2505                         Modifiers.UNSAFE;
2506
2507                 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2508                               Attributes attrs)
2509                         : base (ns, parent, name, attrs, Kind.Class)
2510                 {
2511                         int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2512                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2513
2514                         if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2515                                 Report.FeatureIsNotStandardized (Location, "static classes");
2516                         }
2517                 }
2518
2519                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2520                 {
2521                         if (a.Type == TypeManager.attribute_usage_type) {
2522                                 if (BaseType != TypeManager.attribute_type && !BaseType.IsSubclassOf (TypeManager.attribute_type) &&
2523                                         TypeBuilder.FullName != "System.Attribute") {
2524                                         Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2525                                 }
2526                         }
2527
2528                         if (a.Type == TypeManager.conditional_attribute_type &&
2529                                 !(BaseType == TypeManager.attribute_type || BaseType.IsSubclassOf (TypeManager.attribute_type))) {
2530                                 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2531                                 return;
2532                         }
2533
2534                         if (AttributeTester.IsAttributeExcluded (a.Type))
2535                                 return;
2536
2537                         base.ApplyAttributeBuilder (a, cb);
2538                 }
2539
2540                 public override AttributeTargets AttributeTargets {
2541                         get {
2542                                 return AttributeTargets.Class;
2543                         }
2544                 }
2545
2546                 protected override void DefineContainerMembers (MemberCoreArrayList list)
2547                 {
2548                         if (list == null)
2549                                 return;
2550
2551                         if (!IsStatic) {
2552                                 base.DefineContainerMembers (list);
2553                                 return;
2554                         }
2555
2556                         foreach (MemberCore m in list) {
2557                                 if (m is Operator) {
2558                                         Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2559                                         continue;
2560                                 }
2561
2562                                 if (m is Destructor) {
2563                                         Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2564                                         continue;
2565                                 }
2566
2567                                 if ((m.ModFlags & Modifiers.PROTECTED) != 0) {
2568                                         Report.Error (1057, m.Location, "`{0}': Static classes cannot contain protected members", m.GetSignatureForError ());
2569                                         continue;
2570                                 }
2571
2572                                 if (m is Indexer) {
2573                                         Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2574                                         continue;
2575                                 }
2576
2577                                 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2578                                         continue;
2579
2580                                 if (m is Constructor) {
2581                                         Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2582                                         continue;
2583                                 }
2584
2585                                 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2586                         }
2587
2588                         base.DefineContainerMembers (list);
2589                 }
2590
2591                 public override void DefineDefaultConstructor ()
2592                 {
2593                         if (!IsStatic)
2594                                 DefineDefaultConstructor (false);
2595
2596                         base.DefineDefaultConstructor ();
2597                 }
2598
2599                 public override TypeBuilder DefineType ()
2600                 {
2601                         if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2602                                 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2603                                 return null;
2604                         }
2605
2606                         if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2607                                 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2608                                 return null;
2609                         }
2610
2611                         return base.DefineType ();
2612                 }
2613
2614                 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
2615                 {
2616                         TypeExpr[] ifaces = base.GetClassBases (out base_class);
2617
2618                         if (base_class == null) {
2619                                 if (RootContext.StdLib)
2620                                         base_class = TypeManager.system_object_expr;
2621                                 else if (Name != "System.Object")
2622                                         base_class = TypeManager.system_object_expr;
2623                         } else {
2624                                 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
2625                                         Report.Error (1521, base_class.Location, "Invalid base type");
2626                                         return ifaces;
2627                                 }
2628
2629                                 if (base_class.IsSealed){
2630                                         Report.SymbolRelatedToPreviousError (base_class.Type);
2631                                         if (base_class.Type.IsAbstract) {
2632                                                 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2633                                                         GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2634                                         } else {
2635                                                 Report.Error (509, Location, "`{0}': cannot derive from sealed class `{1}'",
2636                                                         GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2637                                         }
2638                                         return ifaces;
2639                                 }
2640
2641                                 if (!base_class.CanInheritFrom ()){
2642                                         Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2643                                                 GetSignatureForError (), base_class.GetSignatureForError ());
2644                                         return ifaces;
2645                                 }
2646
2647                                 if (!base_class.AsAccessible (this, ModFlags)) {
2648                                         Report.SymbolRelatedToPreviousError (base_class.Type);
2649                                         Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'", 
2650                                                 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2651                                 }
2652                         }
2653
2654                         if (IsStatic) {
2655                                 if (base_class != TypeManager.system_object_expr) {
2656                                         Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2657                                                 GetSignatureForError (), base_class.GetSignatureForError ());
2658                                         return ifaces;
2659                                 }
2660
2661                                 if (ifaces != null) {
2662                                         foreach (TypeExpr t in ifaces)
2663                                                 Report.SymbolRelatedToPreviousError (t.Type);
2664                                         Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
2665                                 }
2666                         }
2667
2668                         return ifaces;
2669                 }
2670
2671                 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2672                 /// Valid only for attribute classes.
2673                 public bool IsExcluded ()
2674                 {
2675                         if ((caching_flags & Flags.Excluded_Undetected) == 0)
2676                                 return (caching_flags & Flags.Excluded) != 0;
2677
2678                         caching_flags &= ~Flags.Excluded_Undetected;
2679
2680                         if (OptAttributes == null)
2681                                 return false;
2682
2683                         Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
2684
2685                         if (attrs == null)
2686                                 return false;
2687
2688                         foreach (Attribute a in attrs) {
2689                                 string condition = a.GetConditionalAttributeValue ();
2690                                 if (RootContext.AllDefines.Contains (condition))
2691                                         return false;
2692                         }
2693
2694                         caching_flags |= Flags.Excluded;
2695                         return true;
2696                 }
2697
2698                 bool IsStatic {
2699                         get {
2700                                 return (ModFlags & Modifiers.STATIC) != 0;
2701                         }
2702                 }
2703
2704                 //
2705                 // FIXME: How do we deal with the user specifying a different
2706                 // layout?
2707                 //
2708                 protected override TypeAttributes TypeAttr {
2709                         get {
2710                                 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2711                                 if (IsStatic)
2712                                         ta |= TypeAttributes.Abstract | TypeAttributes.Sealed;
2713                                 return ta;
2714                         }
2715                 }
2716         }
2717
2718         public sealed class Struct : ClassOrStruct {
2719                 // <summary>
2720                 //   Modifiers allowed in a struct declaration
2721                 // </summary>
2722                 const int AllowedModifiers =
2723                         Modifiers.NEW       |
2724                         Modifiers.PUBLIC    |
2725                         Modifiers.PROTECTED |
2726                         Modifiers.INTERNAL  |
2727                         Modifiers.UNSAFE    |
2728                         Modifiers.PRIVATE;
2729
2730                 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2731                                int mod, Attributes attrs)
2732                         : base (ns, parent, name, attrs, Kind.Struct)
2733                 {
2734                         int accmods;
2735                         
2736                         if (parent.Parent == null)
2737                                 accmods = Modifiers.INTERNAL;
2738                         else
2739                                 accmods = Modifiers.PRIVATE;
2740                         
2741                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2742
2743                         this.ModFlags |= Modifiers.SEALED;
2744                 }
2745
2746                 public override AttributeTargets AttributeTargets {
2747                         get {
2748                                 return AttributeTargets.Struct;
2749                         }
2750                 }
2751
2752                 const TypeAttributes DefaultTypeAttributes =
2753                         TypeAttributes.SequentialLayout |
2754                         TypeAttributes.Sealed |
2755                         TypeAttributes.BeforeFieldInit;
2756
2757
2758                 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
2759                 {
2760                         TypeExpr[] ifaces = base.GetClassBases (out base_class);
2761                         //
2762                         // If we are compiling our runtime,
2763                         // and we are defining ValueType, then our
2764                         // base is `System.Object'.
2765                         //
2766                         if (base_class == null) {
2767                                 if (!RootContext.StdLib && Name == "System.ValueType")
2768                                         base_class = TypeManager.system_object_expr;
2769                                 else
2770                                         base_class = TypeManager.system_valuetype_expr;
2771                         }
2772
2773                         return ifaces;
2774                 }
2775
2776                 //
2777                 // FIXME: Allow the user to specify a different set of attributes
2778                 // in some cases (Sealed for example is mandatory for a class,
2779                 // but what SequentialLayout can be changed
2780                 //
2781                 protected override TypeAttributes TypeAttr {
2782                         get {
2783                                 return base.TypeAttr | DefaultTypeAttributes;
2784                         }
2785                 }
2786
2787                 public override void RegisterFieldForInitialization (FieldBase field)
2788                 {
2789                         if ((field.ModFlags & Modifiers.STATIC) == 0) {
2790                                 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2791                                         field.GetSignatureForError ());
2792                                 return;
2793                         }
2794                         base.RegisterFieldForInitialization (field);
2795                 }
2796
2797         }
2798
2799         /// <summary>
2800         ///   Interfaces
2801         /// </summary>
2802         public sealed class Interface : TypeContainer, IMemberContainer {
2803
2804                 /// <summary>
2805                 ///   Modifiers allowed in a class declaration
2806                 /// </summary>
2807                 public const int AllowedModifiers =
2808                         Modifiers.NEW       |
2809                         Modifiers.PUBLIC    |
2810                         Modifiers.PROTECTED |
2811                         Modifiers.INTERNAL  |
2812                         Modifiers.UNSAFE    |
2813                         Modifiers.PRIVATE;
2814
2815                 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2816                                   Attributes attrs)
2817                         : base (ns, parent, name, attrs, Kind.Interface)
2818                 {
2819                         int accmods;
2820
2821                         if (parent.Parent == null)
2822                                 accmods = Modifiers.INTERNAL;
2823                         else
2824                                 accmods = Modifiers.PRIVATE;
2825
2826                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
2827                 }
2828
2829                 public override AttributeTargets AttributeTargets {
2830                         get {
2831                                 return AttributeTargets.Interface;
2832                         }
2833                 }
2834
2835                 const TypeAttributes DefaultTypeAttributes =
2836                         TypeAttributes.AutoLayout |
2837                         TypeAttributes.Abstract |
2838                         TypeAttributes.Interface;
2839
2840                 protected override TypeAttributes TypeAttr {
2841                         get {
2842                                 return base.TypeAttr | DefaultTypeAttributes;
2843                         }
2844                 }
2845
2846                 protected override bool VerifyClsCompliance ()
2847                 {
2848                         if (!base.VerifyClsCompliance ())
2849                                 return false;
2850
2851                         if (ifaces != null) {
2852                                 foreach (Type t in ifaces) {
2853                                         if (AttributeTester.IsClsCompliant (t))
2854                                                 continue;
2855
2856                                         Report.SymbolRelatedToPreviousError (t);
2857                                         Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2858                                                 GetSignatureForError (), TypeManager.CSharpName (t));
2859                                 }
2860                         }
2861
2862                         return true;
2863                 }
2864         }
2865
2866         public abstract class MethodCore : MemberBase {
2867                 public readonly Parameters Parameters;
2868                 protected ToplevelBlock block;
2869                 
2870                 // Whether this is an operator method.
2871                 public Operator IsOperator;
2872
2873                 //
2874                 // The method we're overriding if this is an override method.
2875                 //
2876                 protected MethodInfo base_method = null;
2877
2878                 static string[] attribute_targets = new string [] { "method", "return" };
2879
2880                 public MethodCore (DeclSpace parent, Expression type, int mod,
2881                                    int allowed_mod, bool is_interface, MemberName name,
2882                                    Attributes attrs, Parameters parameters)
2883                         : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
2884                                 attrs)
2885                 {
2886                         Parameters = parameters;
2887                         IsInterface = is_interface;
2888                 }
2889                 
2890                 //
2891                 //  Returns the System.Type array for the parameters of this method
2892                 //
2893                 public Type [] ParameterTypes {
2894                         get {
2895                                 return Parameters.Types;
2896                         }
2897                 }
2898
2899                 public Parameters ParameterInfo
2900                 {
2901                         get {
2902                                 return Parameters;
2903                         }
2904                 }
2905                 
2906                 public ToplevelBlock Block {
2907                         get {
2908                                 return block;
2909                         }
2910
2911                         set {
2912                                 block = value;
2913                         }
2914                 }
2915
2916                 public void SetYields ()
2917                 {
2918                         ModFlags |= Modifiers.METHOD_YIELDS;
2919                 }
2920
2921                 protected override bool CheckBase ()
2922                 {
2923                         if (!base.CheckBase ())
2924                                 return false;
2925                         
2926                         // Check whether arguments were correct.
2927                         if (!DoDefineParameters ())
2928                                 return false;
2929
2930                         if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
2931                                 return false;
2932
2933                         if (IsExplicitImpl)
2934                                 return true;
2935
2936                         // Is null for System.Object while compiling corlib and base interfaces
2937                         if (ParentContainer.BaseCache == null) {
2938                                 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
2939                                         Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
2940                                 }
2941                                 return true;
2942                         }
2943
2944                         Type base_ret_type = null;
2945                         if (IsOperator == null)
2946                                 base_method = FindOutBaseMethod (ref base_ret_type);
2947
2948                         // method is override
2949                         if (base_method != null) {
2950
2951                                 if (!CheckMethodAgainstBase ())
2952                                         return false;
2953
2954                                 if ((ModFlags & Modifiers.NEW) == 0) {
2955                                         if (MemberType != TypeManager.TypeToCoreType (base_ret_type)) {
2956                                                 Report.SymbolRelatedToPreviousError (base_method);
2957                                                 if (this is PropertyBase) {
2958                                                         Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'", 
2959                                                                 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
2960                                                 }
2961                                                 else {
2962                                                         Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
2963                                                                 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
2964                                                 }
2965                                                 return false;
2966                                         }
2967                                 } else {
2968                                         if (base_method.IsAbstract && !IsInterface) {
2969                                                 Report.SymbolRelatedToPreviousError (base_method);
2970                                                 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
2971                                                         GetSignatureForError (), TypeManager.CSharpSignature (base_method));
2972                                                 return false;
2973                                         }
2974                                 }
2975
2976                                 if (base_method.IsSpecialName && !(this is PropertyBase)) {
2977                                         Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
2978                                         return false;
2979                                 }
2980
2981                                 if (Name == "Equals" && Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type)
2982                                         ParentContainer.Mark_HasEquals ();
2983                                 else if (Name == "GetHashCode" && Parameters.Empty)
2984                                         ParentContainer.Mark_HasGetHashCode ();
2985
2986                                 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
2987                                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
2988                                         if (oa != null) {
2989                                                 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
2990                                                         Report.SymbolRelatedToPreviousError (base_method);
2991                                                         Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
2992                                                                 GetSignatureForError (), TypeManager.CSharpSignature (base_method) );
2993                                                 }
2994                                         }
2995                                 }
2996                                 return true;
2997                         }
2998
2999                         MemberInfo conflict_symbol = ParentContainer.FindBaseMemberWithSameName (Name, !(this is Property));
3000                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3001                                 if (conflict_symbol != null) {
3002                                         Report.SymbolRelatedToPreviousError (conflict_symbol);
3003                                         if (this is PropertyBase)
3004                                                 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3005                                         else
3006                                                 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3007                                 } else
3008                                         Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
3009                                 return false;
3010                         }
3011
3012                         if (conflict_symbol == null) {
3013                                 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3014                                         Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3015                                 }
3016                                 return true;
3017                         }
3018
3019                         if ((ModFlags & Modifiers.NEW) == 0) {
3020                                 if (this is Method && conflict_symbol is MethodBase)
3021                                         return true;
3022
3023                                 Report.SymbolRelatedToPreviousError (conflict_symbol);
3024                                 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3025                                         GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3026                         }
3027
3028                         return true;
3029                 }
3030
3031                 //
3032                 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3033                 // that have been defined.
3034                 //
3035                 // `name' is the user visible name for reporting errors (this is used to
3036                 // provide the right name regarding method names and properties)
3037                 //
3038                 bool CheckMethodAgainstBase ()
3039                 {
3040                         bool ok = true;
3041
3042                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
3043                                 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3044                                         Report.Error (506, Location,
3045                                                 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3046                                                  GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3047                                         ok = false;
3048                                 }
3049                                 
3050                                 // Now we check that the overriden method is not final
3051                                 
3052                                 if (base_method.IsFinal) {
3053                                         Report.SymbolRelatedToPreviousError (base_method);
3054                                         Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3055                                                               GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3056                                         ok = false;
3057                                 }
3058                                 //
3059                                 // Check that the permissions are not being changed
3060                                 //
3061                                 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3062                                 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3063
3064                                 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3065                                         Error_CannotChangeAccessModifiers (base_method, base_classp, null);
3066                                         ok = false;
3067                                 }
3068                         }
3069
3070                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3071                                 ModFlags |= Modifiers.NEW;
3072                                 Report.SymbolRelatedToPreviousError (base_method);
3073                                 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3074                                         Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3075                                                 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3076                                 } else {
3077                                         Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3078                                                 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3079                                 }
3080                         }
3081
3082                         return ok;
3083                 }
3084                 
3085                 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3086                 {
3087                         if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3088                                 //
3089                                 // when overriding protected internal, the method can be declared
3090                                 // protected internal only within the same assembly
3091                                 //
3092
3093                                 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3094                                         if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3095                                                 //
3096                                                 // assemblies differ - report an error
3097                                                 //
3098                                                 
3099                                                 return false;
3100                                         } else if (thisp != base_classp) {
3101                                                 //
3102                                                 // same assembly, but other attributes differ - report an error
3103                                                 //
3104                                                 
3105                                                 return false;
3106                                         };
3107                                 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3108                                         //
3109                                         // if it's not "protected internal", it must be "protected"
3110                                         //
3111
3112                                         return false;
3113                                 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3114                                         //
3115                                         // protected within the same assembly - an error
3116                                         //
3117                                         return false;
3118                                 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) != 
3119                                            (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3120                                         //
3121                                         // protected ok, but other attributes differ - report an error
3122                                         //
3123                                         return false;
3124                                 }
3125                                 return true;
3126                         } else {
3127                                 return (thisp == base_classp);
3128                         }
3129                 }
3130
3131                 public bool CheckAbstractAndExtern (bool has_block)
3132                 {
3133                         if (ParentContainer.Kind == Kind.Interface)
3134                                 return true;
3135
3136                         if (has_block) {
3137                                 if ((ModFlags & Modifiers.EXTERN) != 0) {
3138                                         Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
3139                                                 GetSignatureForError ());
3140                                         return false;
3141                                 }
3142
3143                                 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
3144                                         Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
3145                                                 GetSignatureForError ());
3146                                         return false;
3147                                 }
3148                         } else {
3149                                 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
3150                                         Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
3151                                                 GetSignatureForError ());
3152                                         return false;
3153                                 }
3154                         }
3155
3156                         return true;
3157                 }
3158
3159                 protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
3160                 {
3161                         Report.SymbolRelatedToPreviousError (base_method);
3162                         string base_name = TypeManager.GetFullNameSignature (base_method);
3163                         string this_name = GetSignatureForError ();
3164                         if (suffix != null) {
3165                                 base_name += suffix;
3166                                 this_name += suffix;
3167                         }
3168
3169                         Report.Error (507, Location, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3170                                 this_name, Modifiers.GetDescription (ma), base_name);
3171                 }
3172
3173                 protected static string Error722 {
3174                         get {
3175                                 return "`{0}': static types cannot be used as return types";
3176                         }
3177                 }
3178
3179                 /// <summary>
3180                 /// For custom member duplication search in a container
3181                 /// </summary>
3182                 protected abstract bool CheckForDuplications ();
3183
3184                 /// <summary>
3185                 /// Gets base method and its return type
3186                 /// </summary>
3187                 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3188
3189                 protected bool DoDefineParameters ()
3190                 {
3191                         // Check if arguments were correct
3192                         if (!Parameters.Resolve (this))
3193                                 return false;
3194
3195                         return CheckParameters (ParameterTypes);
3196                 }
3197
3198                 bool CheckParameters (Type [] parameters)
3199                 {
3200                         bool error = false;
3201                         DeclSpace ds = Parent;
3202
3203                         foreach (Type partype in parameters){
3204                                 if (partype == TypeManager.void_type) {
3205                                         Report.Error (
3206                                                 1547, Location, "Keyword 'void' cannot " +
3207                                                 "be used in this context");
3208                                         return false;
3209                                 }
3210
3211                                 if (partype.IsPointer){
3212                                         if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3213                                                 error = true;
3214                                 }
3215
3216                                 if (ds.AsAccessible (partype, ModFlags))
3217                                         continue;
3218
3219                                 if (this is Indexer)
3220                                         Report.Error (55, Location,
3221                                                 "Inconsistent accessibility: parameter type `" +
3222                                                 TypeManager.CSharpName (partype) + "' is less " +
3223                                                 "accessible than indexer `" + GetSignatureForError () + "'");
3224                                 else if ((this is Method) && ((Method) this).IsOperator != null)
3225                                         Report.Error (57, Location,
3226                                                 "Inconsistent accessibility: parameter type `" +
3227                                                 TypeManager.CSharpName (partype) + "' is less " +
3228                                                 "accessible than operator `" + GetSignatureForError () + "'");
3229                                 else
3230                                         Report.Error (51, Location,
3231                                                 "Inconsistent accessibility: parameter type `" +
3232                                                 TypeManager.CSharpName (partype) + "' is less " +
3233                                                 "accessible than method `" + GetSignatureForError () + "'");
3234                                 error = true;
3235                         }
3236
3237                         return !error;
3238                 }
3239
3240                 public override string[] ValidAttributeTargets {
3241                         get {
3242                                 return attribute_targets;
3243                         }
3244                 }
3245
3246                 protected override bool VerifyClsCompliance ()
3247                 {
3248                         if (!base.VerifyClsCompliance ()) {
3249                                 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3250                                         Report.Error (3011, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3251                                 }
3252                                 return false;
3253                         }
3254
3255                         if (Parameters.HasArglist) {
3256                                 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3257                         }
3258
3259                         if (!AttributeTester.IsClsCompliant (MemberType)) {
3260                                 if (this is PropertyBase)
3261                                         Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3262                                                       GetSignatureForError ());
3263                                 else
3264                                         Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant",
3265                                                       GetSignatureForError ());
3266                         }
3267
3268                         Parameters.VerifyClsCompliance ();
3269
3270                         return true;
3271                 }
3272
3273                 protected bool IsDuplicateImplementation (MethodCore method)
3274                 {
3275                         if (method == this || !(method.MemberName.Equals (MemberName)))
3276                                 return false;
3277
3278                         Type[] param_types = method.ParameterTypes;
3279                         // This never happen. Rewrite this as Equal
3280                         if (param_types == null && ParameterTypes == null)
3281                                 return true;
3282                         if (param_types == null || ParameterTypes == null)
3283                                 return false;
3284
3285                         if (param_types.Length != ParameterTypes.Length)
3286                                 return false;
3287
3288                         if (method.Parameters.HasArglist != Parameters.HasArglist)
3289                                 return false;
3290                         
3291                         for (int i = 0; i < param_types.Length; i++)
3292                                 if (param_types [i] != ParameterTypes [i])
3293                                         return false;
3294
3295                         // TODO: make operator compatible with MethodCore to avoid this
3296                         if (this is Operator && method is Operator) {
3297                                 if (MemberType != method.MemberType)
3298                                         return false;
3299                         }
3300
3301                         //
3302                         // Try to report 663: method only differs on out/ref
3303                         //
3304                         Parameters info = ParameterInfo;
3305                         Parameters other_info = method.ParameterInfo;
3306                         for (int i = 0; i < info.Count; i++){
3307                                 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3308                                         Report.SymbolRelatedToPreviousError (method);
3309                                         Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
3310                                                 GetSignatureForError ());
3311                                         return false;
3312                                 }
3313                         }
3314
3315                         Report.SymbolRelatedToPreviousError (method);
3316                         if (this is Operator && method is Operator)
3317                                 Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
3318                         else
3319                                 Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
3320                         return true;
3321                 }
3322
3323                 public override bool IsUsed {
3324                         get { return IsExplicitImpl || base.IsUsed; }
3325                 }
3326
3327                 //
3328                 // Returns a string that represents the signature for this 
3329                 // member which should be used in XML documentation.
3330                 //
3331                 public override string GetDocCommentName (DeclSpace ds)
3332                 {
3333                         return DocUtil.GetMethodDocCommentName (this, ds);
3334                 }
3335
3336                 //
3337                 // Raised (and passed an XmlElement that contains the comment)
3338                 // when GenerateDocComment is writing documentation expectedly.
3339                 //
3340                 // FIXME: with a few effort, it could be done with XmlReader,
3341                 // that means removal of DOM use.
3342                 //
3343                 internal override void OnGenerateDocComment (XmlElement el)
3344                 {
3345                         DocUtil.OnMethodGenerateDocComment (this, el);
3346                 }
3347
3348                 //
3349                 //   Represents header string for documentation comment.
3350                 //
3351                 public override string DocCommentHeader {
3352                         get { return "M:"; }
3353                 }
3354
3355         }
3356
3357         public class SourceMethod : ISourceMethod
3358         {
3359                 DeclSpace parent;
3360                 MethodBase builder;
3361
3362                 protected SourceMethod (DeclSpace parent, MethodBase builder,
3363                                         ISourceFile file, Location start, Location end)
3364                 {
3365                         this.parent = parent;
3366                         this.builder = builder;
3367                         
3368                         CodeGen.SymbolWriter.OpenMethod (file, this, start.Row, start.Column, end.Row, start.Column);
3369                 }
3370
3371                 public string Name {
3372                         get { return builder.Name; }
3373                 }
3374
3375                 public int NamespaceID {
3376                         get { return parent.NamespaceEntry.SymbolFileID; }
3377                 }
3378
3379                 public int Token {
3380                         get {
3381                                 if (builder is MethodBuilder)
3382                                         return ((MethodBuilder) builder).GetToken ().Token;
3383                                 else if (builder is ConstructorBuilder)
3384                                         return ((ConstructorBuilder) builder).GetToken ().Token;
3385                                 else
3386                                         throw new NotSupportedException ();
3387                         }
3388                 }
3389
3390                 public void CloseMethod ()
3391                 {
3392                         if (CodeGen.SymbolWriter != null)
3393                                 CodeGen.SymbolWriter.CloseMethod ();
3394                 }
3395
3396                 public static SourceMethod Create (DeclSpace parent, MethodBase builder, Block block)
3397                 {
3398                         if (CodeGen.SymbolWriter == null)
3399                                 return null;
3400                         if (block == null)
3401                                 return null;
3402
3403                         Location start_loc = block.StartLocation;
3404                         if (start_loc.IsNull)
3405                                 return null;
3406
3407                         Location end_loc = block.EndLocation;
3408                         if (end_loc.IsNull)
3409                                 return null;
3410
3411                         ISourceFile file = start_loc.SourceFile;
3412                         if (file == null)
3413                                 return null;
3414
3415                         return new SourceMethod (
3416                                 parent, builder, file, start_loc, end_loc);
3417                 }
3418         }
3419
3420         public class Method : MethodCore, IIteratorContainer, IMethodData {
3421                 public MethodBuilder MethodBuilder;
3422                 public MethodData MethodData;
3423                 ReturnParameter return_attributes;
3424                 ListDictionary declarative_security;
3425
3426                 /// <summary>
3427                 ///   Modifiers allowed in a class declaration
3428                 /// </summary>
3429                 const int AllowedModifiers =
3430                         Modifiers.NEW |
3431                         Modifiers.PUBLIC |
3432                         Modifiers.PROTECTED |
3433                         Modifiers.INTERNAL |
3434                         Modifiers.PRIVATE |
3435                         Modifiers.STATIC |
3436                         Modifiers.VIRTUAL |
3437                         Modifiers.SEALED |
3438                         Modifiers.OVERRIDE |
3439                         Modifiers.ABSTRACT |
3440                         Modifiers.UNSAFE |
3441                         Modifiers.METHOD_YIELDS | 
3442                         Modifiers.EXTERN;
3443
3444                 const int AllowedInterfaceModifiers =
3445                         Modifiers.NEW | Modifiers.UNSAFE;
3446
3447                 //
3448                 // return_type can be "null" for VOID values.
3449                 //
3450                 public Method (DeclSpace parent, Expression return_type, int mod, bool is_iface,
3451                                MemberName name, Parameters parameters, Attributes attrs)
3452                         : base (parent, return_type, mod,
3453                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3454                                 is_iface, name, attrs, parameters)
3455                 {
3456                 }
3457
3458                 public override AttributeTargets AttributeTargets {
3459                         get {
3460                                 return AttributeTargets.Method;
3461                         }
3462                 }
3463                 
3464                 public override string GetSignatureForError()
3465                 {
3466                         if (IsOperator != null)
3467                                 return IsOperator.GetSignatureForError ();
3468
3469                         return base.GetSignatureForError () + Parameters.GetSignatureForError ();
3470                 }
3471
3472                 void DuplicateEntryPoint (MethodInfo b, Location location)
3473                 {
3474                         Report.Error (
3475                                 17, location,
3476                                 "Program `" + CodeGen.FileName +
3477                                 "' has more than one entry point defined: `" +
3478                                 TypeManager.CSharpSignature(b) + "'");
3479                 }
3480
3481                 bool IsEntryPoint (MethodBuilder b, Parameters pinfo)
3482                 {
3483                         if (b.ReturnType != TypeManager.void_type &&
3484                             b.ReturnType != TypeManager.int32_type)
3485                                 return false;
3486
3487                         if (pinfo.Count == 0)
3488                                 return true;
3489
3490                         if (pinfo.Count > 1)
3491                                 return false;
3492
3493                         Type t = pinfo.ParameterType(0);
3494                         if (t.IsArray &&
3495                             (t.GetArrayRank() == 1) &&
3496                             (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3497                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3498                                 return true;
3499                         else
3500                                 return false;
3501                 }
3502
3503                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3504                 {
3505                         if (a.Target == AttributeTargets.ReturnValue) {
3506                                 if (return_attributes == null)
3507                                         return_attributes = new ReturnParameter (MethodBuilder, Location);
3508
3509                                 return_attributes.ApplyAttributeBuilder (a, cb);
3510                                 return;
3511                         }
3512
3513                         if (a.Type == TypeManager.methodimpl_attr_type &&
3514                                 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
3515                                 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3516                         }
3517
3518                         if (a.Type == TypeManager.dllimport_type) {
3519                                 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3520                                 if ((ModFlags & extern_static) != extern_static) {
3521                                         Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3522                                 }
3523
3524                                 return;
3525                         }
3526
3527                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3528                                 if (declarative_security == null)
3529                                         declarative_security = new ListDictionary ();
3530                                 a.ExtractSecurityPermissionSet (declarative_security);
3531                                 return;
3532                         }
3533
3534                         if (a.Type == TypeManager.conditional_attribute_type) {
3535                                 if (IsOperator != null || IsExplicitImpl) {
3536                                         Report.Error (577, Location, "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3537                                                 GetSignatureForError ());
3538                                         return;
3539                                 }
3540
3541                                 if (ReturnType != TypeManager.void_type) {
3542                                         Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
3543                                         return;
3544                                 }
3545
3546                                 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3547                                         Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
3548                                         return;
3549                                 }
3550
3551                                 if (IsInterface) {
3552                                         Report.Error (582, Location, "Conditional not valid on interface members");
3553                                         return;
3554                                 }
3555
3556                                 if (MethodData.implementing != null) {
3557                                         Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
3558                                                 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
3559                                         return;
3560                                 }
3561
3562                                 for (int i = 0; i < ParameterInfo.Count; ++i) {
3563                                         if ((ParameterInfo.ParameterModifier (i) & Parameter.Modifier.OUTMASK) != 0) {
3564                                                 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
3565                                                 return;
3566                                         }
3567                                 }
3568                         }
3569
3570                         MethodBuilder.SetCustomAttribute (cb);
3571                 }
3572
3573                 protected override bool CheckForDuplications ()
3574                 {
3575                         ArrayList ar = ParentContainer.Methods;
3576                         if (ar != null) {
3577                                 int arLen = ar.Count;
3578                                         
3579                                 for (int i = 0; i < arLen; i++) {
3580                                         Method m = (Method) ar [i];
3581                                         if (IsDuplicateImplementation (m))
3582                                                 return false;
3583                                 }
3584                         }
3585
3586                         ar = ParentContainer.Properties;
3587                         if (ar != null) {
3588                                 for (int i = 0; i < ar.Count; ++i) {
3589                                         PropertyBase pb = (PropertyBase) ar [i];
3590                                         if (pb.AreAccessorsDuplicateImplementation (this))
3591                                                 return false;
3592                                 }
3593                         }
3594
3595                         ar = ParentContainer.Indexers;
3596                         if (ar != null) {
3597                                 for (int i = 0; i < ar.Count; ++i) {
3598                                         PropertyBase pb = (PropertyBase) ar [i];
3599                                         if (pb.AreAccessorsDuplicateImplementation (this))
3600                                                 return false;
3601                                 }
3602                         }
3603
3604                         ar = ParentContainer.Events;
3605                         if (ar != null) {
3606                                 for (int i = 0; i < ar.Count; ++i) {
3607                                         Event ev = (Event) ar [i];
3608                                         if (ev.AreAccessorsDuplicateImplementation (this))
3609                                                 return false;
3610                                 }
3611                         }
3612
3613                         return true;
3614                 }
3615
3616                 //
3617                 // Creates the type
3618                 //
3619                 public override bool Define ()
3620                 {
3621                         if (!DoDefine ())
3622                                 return false;
3623
3624                         if (!CheckAbstractAndExtern (block != null))
3625                                 return false;
3626
3627                         if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
3628                                 Error1599 (Location, ReturnType);
3629                                 return false;
3630                         }
3631
3632                         if (!CheckBase ())
3633                                 return false;
3634
3635                         if (IsOperator != null)
3636                                 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3637
3638                         MethodData = new MethodData (this, ModFlags, flags, this);
3639
3640                         if (!MethodData.Define (ParentContainer))
3641                                 return false;
3642
3643                         if (ReturnType == TypeManager.void_type && ParameterTypes.Length == 0 && 
3644                                 Name == "Finalize" && !(this is Destructor)) {
3645                                 Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
3646                         }
3647
3648                         //
3649                         // Setup iterator if we are one
3650                         //
3651                         if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3652                                 Iterator iterator = new Iterator (this,
3653                                         Parent,
3654                                         ModFlags);
3655
3656                                 if (!iterator.DefineIterator ())
3657                                         return false;
3658                         }
3659
3660                         MethodBuilder = MethodData.MethodBuilder;
3661                         
3662                         //
3663                         // This is used to track the Entry Point,
3664                         //
3665                         if (Name == "Main" &&
3666                             ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint && 
3667                             (RootContext.MainClass == null ||
3668                              RootContext.MainClass == Parent.TypeBuilder.FullName)){
3669                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3670                                         IMethodData md = TypeManager.GetMethod (MethodBuilder);
3671                                         md.SetMemberIsUsed ();
3672
3673                                         if (RootContext.EntryPoint == null) {
3674                                                 RootContext.EntryPoint = MethodBuilder;
3675                                                 RootContext.EntryPointLocation = Location;
3676                                         } else {
3677                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3678                                                 DuplicateEntryPoint (MethodBuilder, Location);
3679                                         }
3680                                 } else {
3681                                         if (RootContext.WarningLevel >= 4)
3682                                                 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder));
3683                                 }
3684                         }
3685
3686                         if (MemberType.IsAbstract && MemberType.IsSealed) {
3687                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3688                                 return false;
3689                         }
3690
3691                         return true;
3692                 }
3693
3694                 //
3695                 // Emits the code
3696                 // 
3697                 public override void Emit ()
3698                 {
3699                         MethodData.Emit (Parent);
3700                         base.Emit ();
3701
3702                         if (declarative_security != null) {
3703                                 foreach (DictionaryEntry de in declarative_security) {
3704                                         MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3705                                 }
3706                         }
3707
3708                         Block = null;
3709                         MethodData = null;
3710                 }
3711
3712                 public static void Error1599 (Location loc, Type t)
3713                 {
3714                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
3715                 }
3716
3717                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
3718                 {
3719                         MethodInfo mi = (MethodInfo) ParentContainer.BaseCache.FindMemberToOverride (
3720                                 Parent.TypeBuilder, Name, ParameterTypes, false);
3721
3722                         if (mi == null)
3723                                 return null;
3724
3725                         base_ret_type = mi.ReturnType;
3726                         return mi;
3727                 }
3728
3729                 public override bool MarkForDuplicationCheck ()
3730                 {
3731                         caching_flags |= Flags.TestMethodDuplication;
3732                         return true;
3733                 }
3734
3735                 protected override bool VerifyClsCompliance ()
3736                 {
3737                         if (!base.VerifyClsCompliance ())
3738                                 return false;
3739
3740                         if (ParameterInfo.Count > 0) {
3741                                 ArrayList al = (ArrayList)ParentContainer.MemberCache.Members [Name];
3742                                 if (al.Count > 1)
3743                                         MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
3744                         }
3745
3746                         return true;
3747                 }
3748
3749                 #region IMethodData Members
3750
3751                 public CallingConventions CallingConventions {
3752                         get {
3753                                 CallingConventions cc = Parameters.CallingConvention;
3754                                 if (Parameters.HasArglist)
3755                                         block.HasVarargs = true;
3756
3757                                 if (!IsInterface)
3758                                         if ((ModFlags & Modifiers.STATIC) == 0)
3759                                                 cc |= CallingConventions.HasThis;
3760
3761                                 // FIXME: How is `ExplicitThis' used in C#?
3762                         
3763                                 return cc;
3764                         }
3765                 }
3766
3767                 public Type ReturnType {
3768                         get {
3769                                 return MemberType;
3770                         }
3771                 }
3772
3773                 public MemberName MethodName {
3774                         get {
3775                                 return MemberName;
3776                         }
3777                 }
3778
3779                 public new Location Location {
3780                         get {
3781                                 return base.Location;
3782                         }
3783                 }
3784
3785                 protected override bool CheckBase() {
3786                         if (!base.CheckBase ())
3787                                 return false;
3788
3789                         // TODO: Destructor should derive from MethodCore
3790                         if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
3791                                 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
3792                                 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
3793                                 return false;
3794                         }
3795
3796                         return true;
3797                 }
3798
3799                 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
3800                 {
3801                         EmitContext ec = new EmitContext (this, ds, Parent, Location, ig, ReturnType, ModFlags, false);
3802
3803                         ec.CurrentIterator = ds as Iterator;
3804                         if (ec.CurrentIterator != null)
3805                                 ec.CurrentAnonymousMethod = ec.CurrentIterator.Host;
3806
3807                         return ec;
3808                 }
3809
3810                 /// <summary>
3811                 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3812                 /// </summary>
3813                 public bool IsExcluded ()
3814                 {
3815                         if ((caching_flags & Flags.Excluded_Undetected) == 0)
3816                                 return (caching_flags & Flags.Excluded) != 0;
3817
3818                         caching_flags &= ~Flags.Excluded_Undetected;
3819
3820                         if (base_method == null) {
3821                                 if (OptAttributes == null)
3822                                         return false;
3823
3824                                 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
3825
3826                                 if (attrs == null)
3827                                         return false;
3828
3829                                 foreach (Attribute a in attrs) {
3830                                         string condition = a.GetConditionalAttributeValue ();
3831                                         if (RootContext.AllDefines.Contains (condition))
3832                                                 return false;
3833                                 }
3834
3835                                 caching_flags |= Flags.Excluded;
3836                                 return true;
3837                         }
3838
3839                         IMethodData md = TypeManager.GetMethod (base_method);
3840                         if (md == null) {
3841                                 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
3842                                         caching_flags |= Flags.Excluded;
3843                                         return true;
3844                                 }
3845                                 return false;
3846                         }
3847
3848                         if (md.IsExcluded ()) {
3849                                 caching_flags |= Flags.Excluded;
3850                                 return true;
3851                         }
3852                         return false;
3853                 }
3854
3855                 #endregion
3856         }
3857
3858         public abstract class ConstructorInitializer {
3859                 ArrayList argument_list;
3860                 protected ConstructorInfo base_constructor;
3861                 Location loc;
3862                 
3863                 public ConstructorInitializer (ArrayList argument_list, Location loc)
3864                 {
3865                         this.argument_list = argument_list;
3866                         this.loc = loc;
3867                 }
3868
3869                 public ArrayList Arguments {
3870                         get {
3871                                 return argument_list;
3872                         }
3873                 }
3874
3875                 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
3876                 {
3877                         Expression base_constructor_group;
3878                         Type t;
3879                         bool error = false;
3880
3881                         ec.CurrentBlock = block;
3882
3883                         if (argument_list != null){
3884                                 foreach (Argument a in argument_list){
3885                                         if (!a.Resolve (ec, loc))
3886                                                 return false;
3887                                 }
3888                         }
3889                         ec.CurrentBlock = null;
3890
3891                         if (this is ConstructorBaseInitializer) {
3892                                 if (ec.ContainerType.BaseType == null)
3893                                         return true;
3894
3895                                 t = ec.ContainerType.BaseType;
3896                                 if (ec.ContainerType.IsValueType) {
3897                                         Report.Error (522, loc,
3898                                                 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
3899                                         return false;
3900                                 }
3901                         } else
3902                                 t = ec.ContainerType;
3903
3904                         base_constructor_group = Expression.MemberLookup (
3905                                 ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
3906                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3907                                 loc);
3908                         
3909                         if (base_constructor_group == null){
3910                                 error = true;
3911                                 base_constructor_group = Expression.MemberLookup (
3912                                         t, null, t, ".ctor", MemberTypes.Constructor,
3913                                         BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3914                                         loc);
3915                         }
3916
3917                         int errors = Report.Errors;
3918                         if (base_constructor_group != null)
3919                                 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3920                                         ec, (MethodGroupExpr) base_constructor_group, argument_list,
3921                                         false, loc);
3922                         
3923                         if (base_constructor == null) {
3924                                 if (errors == Report.Errors)
3925                                         Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
3926                                                 argument_list == null ? 0 : argument_list.Count);
3927                                 return false;
3928                         }
3929
3930                         if (error) {
3931                                 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
3932                                 base_constructor = null;
3933                                 return false;
3934                         }
3935
3936                         if (base_constructor == caller_builder){
3937                                 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
3938                                 return false;
3939                         }
3940                         
3941                         return true;
3942                 }
3943
3944                 public virtual void Emit (EmitContext ec)
3945                 {
3946                         if (base_constructor != null){
3947                                 ec.Mark (loc, false);
3948                                 if (ec.IsStatic)
3949                                         Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
3950                                 else
3951                                         Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
3952                         }
3953                 }
3954         }
3955
3956         public class ConstructorBaseInitializer : ConstructorInitializer {
3957                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
3958                         base (argument_list, l)
3959                 {
3960                 }
3961         }
3962
3963         class GeneratedBaseInitializer: ConstructorBaseInitializer {
3964                 public GeneratedBaseInitializer (Location loc):
3965                         base (null, loc)
3966                 {
3967                 }
3968         }
3969
3970         public class ConstructorThisInitializer : ConstructorInitializer {
3971                 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
3972                         base (argument_list, l)
3973                 {
3974                 }
3975         }
3976         
3977         public class Constructor : MethodCore, IMethodData {
3978                 public ConstructorBuilder ConstructorBuilder;
3979                 public ConstructorInitializer Initializer;
3980                 ListDictionary declarative_security;
3981
3982                 // <summary>
3983                 //   Modifiers allowed for a constructor.
3984                 // </summary>
3985                 public const int AllowedModifiers =
3986                         Modifiers.PUBLIC |
3987                         Modifiers.PROTECTED |
3988                         Modifiers.INTERNAL |
3989                         Modifiers.STATIC |
3990                         Modifiers.UNSAFE |
3991                         Modifiers.EXTERN |              
3992                         Modifiers.PRIVATE;
3993
3994                 bool has_compliant_args = false;
3995                 //
3996                 // The spec claims that static is not permitted, but
3997                 // my very own code has static constructors.
3998                 //
3999                 public Constructor (DeclSpace parent, string name, int mod, Parameters args,
4000                                     ConstructorInitializer init, Location loc)
4001                         : base (parent, null, mod, AllowedModifiers, false, new MemberName (name, loc),
4002                                 null, args)
4003                 {
4004                         Initializer = init;
4005                 }
4006
4007                 public bool HasCompliantArgs {
4008                         get { return has_compliant_args; }
4009                 }
4010
4011                 public override AttributeTargets AttributeTargets {
4012                         get { return AttributeTargets.Constructor; }
4013                 }
4014
4015
4016                 //
4017                 // Returns true if this is a default constructor
4018                 //
4019                 public bool IsDefault ()
4020                 {
4021                         if ((ModFlags & Modifiers.STATIC) != 0)
4022                                 return Parameters.Empty;
4023                         
4024                         return Parameters.Empty &&
4025                                         (Initializer is ConstructorBaseInitializer) &&
4026                                         (Initializer.Arguments == null);
4027                 }
4028
4029                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4030                 {
4031                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4032                                 if (declarative_security == null) {
4033                                         declarative_security = new ListDictionary ();
4034                                 }
4035                                 a.ExtractSecurityPermissionSet (declarative_security);
4036                                 return;
4037                         }
4038
4039                         ConstructorBuilder.SetCustomAttribute (cb);
4040                 }
4041                 
4042                 protected override bool CheckForDuplications ()
4043                 {
4044                         ArrayList ar = ParentContainer.InstanceConstructors;
4045                         if (ar != null) {
4046                                 int arLen = ar.Count;
4047                                         
4048                                 for (int i = 0; i < arLen; i++) {
4049                                         Constructor m = (Constructor) ar [i];
4050                                         if (IsDuplicateImplementation (m))
4051                                                 return false;
4052                                 }
4053                         }
4054                         return true;
4055                 }
4056
4057                 protected override bool CheckBase ()
4058                 {
4059                         // Check whether arguments were correct.
4060                         if (!DoDefineParameters ())
4061                                 return false;
4062
4063                         // TODO: skip the rest for generated ctor
4064                         if ((ModFlags & Modifiers.STATIC) != 0)
4065                                 return true;
4066
4067                         if (!CheckForDuplications ())
4068                                 return false;
4069
4070                         if (ParentContainer.Kind == Kind.Struct) {
4071                                 if (ParameterTypes.Length == 0) {
4072                                         Report.Error (568, Location, 
4073                                                 "Structs cannot contain explicit parameterless constructors");
4074                                         return false;
4075                                 }
4076
4077                                 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4078                                         Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4079                                         return false;
4080                                 }
4081                         }
4082
4083                         if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4084                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4085                         }
4086                         
4087                         return true;
4088                 }
4089                 
4090                 //
4091                 // Creates the ConstructorBuilder
4092                 //
4093                 public override bool Define ()
4094                 {
4095                         if (ConstructorBuilder != null)
4096                                 return true;
4097
4098                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
4099                                                MethodAttributes.SpecialName);
4100                         
4101                         if ((ModFlags & Modifiers.STATIC) != 0) {
4102                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
4103                         } else {
4104                                 ca |= MethodAttributes.HideBySig;
4105
4106                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
4107                                         ca |= MethodAttributes.Public;
4108                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4109                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
4110                                                 ca |= MethodAttributes.FamORAssem;
4111                                         else 
4112                                                 ca |= MethodAttributes.Family;
4113                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4114                                         ca |= MethodAttributes.Assembly;
4115                                 else if (IsDefault ())
4116                                         ca |= MethodAttributes.Public;
4117                                 else
4118                                         ca |= MethodAttributes.Private;
4119                         }
4120
4121                         if (!CheckAbstractAndExtern (block != null))
4122                                 return false;
4123                         
4124                         // Check if arguments were correct.
4125                         if (!CheckBase ())
4126                                 return false;
4127
4128                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4129                                 ca, CallingConventions,
4130                                 ParameterTypes);
4131
4132                         if ((ModFlags & Modifiers.UNSAFE) != 0)
4133                                 ConstructorBuilder.InitLocals = false;
4134
4135                         if (ParentContainer.IsComImport) {
4136                                 if (!IsDefault ()) {
4137                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4138                                                 Parent.GetSignatureForError ());
4139                                         return false;
4140                                 }
4141                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4142                         }
4143                         
4144                         TypeManager.AddMethod (ConstructorBuilder, this);
4145
4146                         return true;
4147                 }
4148
4149                 //
4150                 // Emits the code
4151                 //
4152                 public override void Emit ()
4153                 {
4154                         EmitContext ec = CreateEmitContext (null, null);
4155
4156                         // If this is a non-static `struct' constructor and doesn't have any
4157                         // initializer, it must initialize all of the struct's fields.
4158                         if ((ParentContainer.Kind == Kind.Struct) &&
4159                             ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4160                                 Block.AddThisVariable (Parent, Location);
4161
4162                         if (block != null) {
4163                                 if (!block.ResolveMeta (ec, ParameterInfo))
4164                                         block = null;
4165                         }
4166
4167                         if ((ModFlags & Modifiers.STATIC) == 0){
4168                                 if (ParentContainer.Kind == Kind.Class && Initializer == null)
4169                                         Initializer = new GeneratedBaseInitializer (Location);
4170
4171
4172                                 //
4173                                 // Spec mandates that Initializers will not have
4174                                 // `this' access
4175                                 //
4176                                 ec.IsStatic = true;
4177                                 if ((Initializer != null) &&
4178                                     !Initializer.Resolve (ConstructorBuilder, block, ec))
4179                                         return;
4180                                 ec.IsStatic = false;
4181                         }
4182
4183                         Parameters.ApplyAttributes (ConstructorBuilder);
4184                         
4185                         SourceMethod source = SourceMethod.Create (
4186                                 Parent, ConstructorBuilder, block);
4187
4188                         //
4189                         // Classes can have base initializers and instance field initializers.
4190                         //
4191                         if (ParentContainer.Kind == Kind.Class){
4192                                 if ((ModFlags & Modifiers.STATIC) == 0){
4193
4194                                         //
4195                                         // If we use a "this (...)" constructor initializer, then
4196                                         // do not emit field initializers, they are initialized in the other constructor
4197                                         //
4198                                         if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4199                                                 ParentContainer.EmitFieldInitializers (ec);
4200                                 }
4201                         }
4202                         if (Initializer != null) {
4203                                 Initializer.Emit (ec);
4204                         }
4205                         
4206                         if ((ModFlags & Modifiers.STATIC) != 0)
4207                                 ParentContainer.EmitFieldInitializers (ec);
4208
4209                         if (OptAttributes != null) 
4210                                 OptAttributes.Emit ();
4211
4212                         ec.EmitTopBlock (this, block);
4213
4214                         if (source != null)
4215                                 source.CloseMethod ();
4216
4217                         base.Emit ();
4218
4219                         if (declarative_security != null) {
4220                                 foreach (DictionaryEntry de in declarative_security) {
4221                                         ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4222                                 }
4223                         }
4224
4225                         block = null;
4226                 }
4227
4228                 // Is never override
4229                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4230                 {
4231                         return null;
4232                 }
4233
4234                 public override string GetSignatureForError()
4235                 {
4236                         return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4237                 }
4238
4239                 protected override bool VerifyClsCompliance ()
4240                 {
4241                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4242                                 return false;
4243                         }
4244                         
4245                         if (ParameterInfo.Count > 0) {
4246                                 ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
4247                                 if (al.Count > 3)
4248                                         MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4249  
4250                                 if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4251                                         foreach (Type param in ParameterTypes) {
4252                                                 if (param.IsArray) {
4253                                                         return true;
4254                                                 }
4255                                         }
4256                                 }
4257                         }
4258                         has_compliant_args = true;
4259                         return true;
4260                 }
4261
4262                 #region IMethodData Members
4263
4264                 public System.Reflection.CallingConventions CallingConventions {
4265                         get {
4266                                 CallingConventions cc = Parameters.CallingConvention;
4267
4268                                 if (ParentContainer.Kind == Kind.Class)
4269                                         if ((ModFlags & Modifiers.STATIC) == 0)
4270                                                 cc |= CallingConventions.HasThis;
4271
4272                                 // FIXME: How is `ExplicitThis' used in C#?
4273                         
4274                                 return cc;
4275                         }
4276                 }
4277
4278                 public new Location Location {
4279                         get {
4280                                 return base.Location;
4281                         }
4282                 }
4283
4284                 public MemberName MethodName {
4285                         get {
4286                                 return MemberName;
4287                         }
4288                 }
4289
4290                 public Type ReturnType {
4291                         get {
4292                                 return MemberType;
4293                         }
4294                 }
4295
4296                 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
4297                 {
4298                         ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4299                         return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
4300                 }
4301
4302                 public bool IsExcluded()
4303                 {
4304                         return false;
4305                 }
4306
4307                 #endregion
4308         }
4309
4310         /// <summary>
4311         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4312         /// </summary>
4313         public interface IMethodData
4314         {
4315                 CallingConventions CallingConventions { get; }
4316                 Location Location { get; }
4317                 MemberName MethodName { get; }
4318                 Type ReturnType { get; }
4319                 Parameters ParameterInfo { get; }
4320
4321                 Attributes OptAttributes { get; }
4322                 ToplevelBlock Block { get; set; }
4323
4324                 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
4325                 ObsoleteAttribute GetObsoleteAttribute ();
4326                 string GetSignatureForError ();
4327                 bool IsExcluded ();
4328                 bool IsClsComplianceRequired ();
4329                 void SetMemberIsUsed ();
4330         }
4331
4332         //
4333         // Encapsulates most of the Method's state
4334         //
4335         public class MethodData {
4336
4337                 readonly IMethodData method;
4338
4339                 //
4340                 // Are we implementing an interface ?
4341                 //
4342                 public MethodInfo implementing;
4343
4344                 //
4345                 // Protected data.
4346                 //
4347                 protected MemberBase member;
4348                 protected int modifiers;
4349                 protected MethodAttributes flags;
4350
4351                 MethodBuilder builder = null;
4352                 public MethodBuilder MethodBuilder {
4353                         get {
4354                                 return builder;
4355                         }
4356                 }
4357
4358                 public MethodData (MemberBase member,
4359                                    int modifiers, MethodAttributes flags, IMethodData method)
4360                 {
4361                         this.member = member;
4362                         this.modifiers = modifiers;
4363                         this.flags = flags;
4364
4365                         this.method = method;
4366                 }
4367
4368                 public bool Define (DeclSpace parent)
4369                 {
4370                         string name = method.MethodName.Name;
4371                         string method_name = name;
4372
4373                         TypeContainer container = ((TypeContainer) parent).PartialContainer;
4374
4375                         PendingImplementation pending = container.PendingImplementations;
4376                         if (pending != null){
4377                                 if (member is Indexer) // TODO: test it, but it should work without this IF
4378                                         implementing = pending.IsInterfaceIndexer (
4379                                                 member.InterfaceType, method.ReturnType, method.ParameterInfo);
4380                                 else
4381                                         implementing = pending.IsInterfaceMethod (
4382                                                 member.InterfaceType, name, method.ReturnType, method.ParameterInfo);
4383
4384                                 if (member.InterfaceType != null){
4385                                         if (implementing == null){
4386                                                 if (member is PropertyBase) {
4387                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4388                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4389                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4390
4391                                                 } else {
4392                                                         Report.Error (539, method.Location,
4393                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
4394                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
4395                                                 }
4396                                                 return false;
4397                                         }
4398                                         if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
4399                                                 Report.SymbolRelatedToPreviousError (implementing);
4400                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
4401                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4402                                                 return false;
4403                                         }
4404                                         method_name = member.InterfaceType.FullName + "." + name;
4405                                 } else {
4406                                         if (implementing != null) {
4407                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
4408                                                 if (prop_method != null) {
4409                                                         if (!implementing.IsSpecialName) {
4410                                                                 Report.SymbolRelatedToPreviousError (implementing);
4411                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
4412                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4413                                                                 return false;
4414                                                         }
4415                                                         PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
4416                                                         if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
4417                                                                 Report.SymbolRelatedToPreviousError (implementing);
4418                                                                 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
4419                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
4420                                                                 return false;
4421                                                         }
4422                                                 }
4423                                         }
4424                                 }
4425                         }
4426
4427                         //
4428                         // For implicit implementations, make sure we are public, for
4429                         // explicit implementations, make sure we are private.
4430                         //
4431                         if (implementing != null){
4432                                 //
4433                                 // Setting null inside this block will trigger a more
4434                                 // verbose error reporting for missing interface implementations
4435                                 //
4436                                 // The "candidate" function has been flagged already
4437                                 // but it wont get cleared
4438                                 //
4439                                 if (member.IsExplicitImpl){
4440                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4441                                                 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4442                                                 implementing = null;
4443                                         }
4444                                 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4445                                         if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4446                                                 //
4447                                                 // If this is an interface method implementation,
4448                                                 // check for public accessibility
4449                                                 //
4450                                                 implementing = null;
4451                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4452                                                 // We may never be private.
4453                                                 implementing = null;
4454                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4455                                                 //
4456                                                 // We may be protected if we're overriding something.
4457                                                 //
4458                                                 implementing = null;
4459                                         }
4460                                 } 
4461                                         
4462                                 //
4463                                 // Static is not allowed
4464                                 //
4465                                 if ((modifiers & Modifiers.STATIC) != 0){
4466                                         implementing = null;
4467                                 }
4468                         }
4469                         
4470                         //
4471                         // If implementing is still valid, set flags
4472                         //
4473                         if (implementing != null){
4474                                 //
4475                                 // When implementing interface methods, set NewSlot
4476                                 // unless, we are overwriting a method.
4477                                 //
4478                                 if (implementing.DeclaringType.IsInterface){
4479                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
4480                                                 flags |= MethodAttributes.NewSlot;
4481                                 }
4482                                 flags |=
4483                                         MethodAttributes.Virtual |
4484                                         MethodAttributes.HideBySig;
4485
4486                                 // Set Final unless we're virtual, abstract or already overriding a method.
4487                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4488                                         flags |= MethodAttributes.Final;
4489                         }
4490
4491                         DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
4492
4493                         if (builder == null)
4494                                 return false;
4495
4496                         if ((modifiers & Modifiers.UNSAFE) != 0)
4497                                 builder.InitLocals = false;
4498
4499                         if (implementing != null){
4500                                 //
4501                                 // clear the pending implemntation flag
4502                                 //
4503                                 if (member is Indexer) {
4504                                         pending.ImplementIndexer (
4505                                                 member.InterfaceType, builder, method.ReturnType,
4506                                                 method.ParameterInfo, member.IsExplicitImpl);
4507                                 } else
4508                                         pending.ImplementMethod (
4509                                                 member.InterfaceType, name, method.ReturnType,
4510                                                 method.ParameterInfo, member.IsExplicitImpl);
4511
4512                                 if (member.IsExplicitImpl)
4513                                         container.TypeBuilder.DefineMethodOverride (
4514                                                 builder, implementing);
4515
4516                         }
4517
4518                         TypeManager.AddMethod (builder, method);
4519
4520                         return true;
4521                 }
4522
4523
4524                 /// <summary>
4525                 /// Create the MethodBuilder for the method 
4526                 /// </summary>
4527                 void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
4528                 {
4529                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4530
4531                         if ((modifiers & extern_static) == extern_static) {
4532
4533                                 if (method.OptAttributes != null) {
4534                                         Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type);
4535                                         if (dllimport_attribute != null) {
4536                                                 flags |= MethodAttributes.PinvokeImpl;
4537                                                 builder = dllimport_attribute.DefinePInvokeMethod (
4538                                                         container.TypeBuilder, method_name, flags,
4539                                                         method.ReturnType, ParameterTypes);
4540
4541                                                 return;
4542                                         }
4543                                 }
4544
4545                                 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4546                                 // We are more strict than Microsoft and report CS0626 like error
4547                                 if (method.OptAttributes == null ||
4548                                         !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type)) {
4549                                         Report.Error (626, method.Location, "Method, operator, or accessor `{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation",
4550                                                 method.GetSignatureForError ());
4551                                         return;
4552                                 }
4553                         }
4554
4555                         builder = container.TypeBuilder.DefineMethod (
4556                                 method_name, flags, method.CallingConventions,
4557                                 method.ReturnType, ParameterTypes);
4558                 }
4559
4560                 //
4561                 // Emits the code
4562                 // 
4563                 public void Emit (DeclSpace parent)
4564                 {
4565                         EmitContext ec;
4566                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
4567                                 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
4568                         else
4569                                 ec = method.CreateEmitContext (parent, null);
4570
4571                         method.ParameterInfo.ApplyAttributes (MethodBuilder);
4572
4573                         Attributes OptAttributes = method.OptAttributes;
4574
4575                         if (OptAttributes != null)
4576                                 OptAttributes.Emit ();
4577
4578                         ToplevelBlock block = method.Block;
4579                         
4580                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
4581
4582                         //
4583                         // Handle destructors specially
4584                         //
4585                         // FIXME: This code generates buggy code
4586                         //
4587                         if (member is Destructor)
4588                                 EmitDestructor (ec, block);
4589                         else
4590                                 ec.EmitTopBlock (method, block);
4591
4592                         if (source != null)
4593                                 source.CloseMethod ();
4594                 }
4595
4596                 void EmitDestructor (EmitContext ec, ToplevelBlock block)
4597                 {
4598                         ILGenerator ig = ec.ig;
4599                         
4600                         Label finish = ig.DefineLabel ();
4601
4602                         block.SetDestructor ();
4603                         
4604                         ig.BeginExceptionBlock ();
4605                         ec.ReturnLabel = finish;
4606                         ec.HasReturnLabel = true;
4607                         ec.EmitTopBlock (method, block);
4608                         
4609                         // ig.MarkLabel (finish);
4610                         ig.BeginFinallyBlock ();
4611                         
4612                         if (ec.ContainerType.BaseType != null) {
4613                                 Expression member_lookup = Expression.MemberLookup (
4614                                         ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4615                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4616
4617                                 if (member_lookup != null){
4618                                         MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
4619                                 
4620                                         ig.Emit (OpCodes.Ldarg_0);
4621                                         ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
4622                                 }
4623                         }
4624                         
4625                         ig.EndExceptionBlock ();
4626                         //ig.MarkLabel (ec.ReturnLabel);
4627                         ig.Emit (OpCodes.Ret);
4628                 }
4629         }
4630
4631         // TODO: Should derive from MethodCore
4632         public class Destructor : Method {
4633
4634                 public Destructor (DeclSpace parent, Expression return_type, int mod,
4635                                    string name, Parameters parameters, Attributes attrs,
4636                                    Location l)
4637                         : base (parent, return_type, mod, false, new MemberName (name, l),
4638                                 parameters, attrs)
4639                 { }
4640
4641                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4642                 {
4643                         if (a.Type == TypeManager.conditional_attribute_type) {
4644                                 Report.Error (577, Location, "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
4645                                         GetSignatureForError ());
4646                                 return;
4647                         }
4648
4649                         base.ApplyAttributeBuilder (a, cb);
4650                 }
4651
4652                 public override string GetSignatureForError ()
4653                 {
4654                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
4655                 }
4656
4657         }
4658         
4659         abstract public class MemberBase : MemberCore {
4660                 public Expression Type;
4661
4662                 public MethodAttributes flags;
4663                         
4664                 protected readonly int explicit_mod_flags;
4665
4666                 //
4667                 // The "short" name of this property / indexer / event.  This is the
4668                 // name without the explicit interface.
4669                 //
4670                 public string ShortName {
4671                         get { return MemberName.Name; }
4672                         set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
4673                 }
4674
4675                 public TypeContainer ParentContainer {
4676                         get { return ((TypeContainer) Parent).PartialContainer; }
4677                 }
4678
4679                 //
4680                 // The type of this property / indexer / event
4681                 //
4682                 Type member_type;
4683                 public Type MemberType {
4684                         get {
4685                                 if (member_type == null && Type != null) {
4686                                         Type = Type.ResolveAsTypeTerminal (ResolveContext, false);
4687                                         if (Type != null) {
4688                                                 member_type = Type.Type;
4689                                         }
4690                                 }
4691                                 return member_type;
4692                         }
4693                 }
4694
4695                 //
4696                 // Whether this is an interface member.
4697                 //
4698                 public bool IsInterface;
4699
4700                 //
4701                 // If true, this is an explicit interface implementation
4702                 //
4703                 public bool IsExplicitImpl;
4704
4705                 //
4706                 // The interface type we are explicitly implementing
4707                 //
4708                 public Type InterfaceType = null;
4709
4710                 //
4711                 // The constructor is only exposed to our children
4712                 //
4713                 protected MemberBase (DeclSpace parent, Expression type, int mod,
4714                                       int allowed_mod, int def_mod, MemberName name,
4715                                       Attributes attrs)
4716                         : base (parent, name, attrs)
4717                 {
4718                         explicit_mod_flags = mod;
4719                         Type = type;
4720                         ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
4721                         IsExplicitImpl = (MemberName.Left != null);
4722                 }
4723
4724                 protected virtual bool CheckBase ()
4725                 {
4726                         if ((ModFlags & Modifiers.PROTECTED) != 0 && ParentContainer.Kind == Kind.Struct) {
4727                                 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4728                                 return false;
4729                         }
4730    
4731                         if ((RootContext.WarningLevel >= 4) &&
4732                             ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
4733                             ((ModFlags & Modifiers.PROTECTED) != 0) &&
4734                             ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
4735                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4736                         }
4737                         return true;
4738         }
4739
4740                 protected virtual bool DoDefine ()
4741                 {
4742                         if (Name == null)
4743                                 throw new InternalErrorException ();
4744
4745                         if (IsInterface) {
4746                                 ModFlags = Modifiers.PUBLIC |
4747                                         Modifiers.ABSTRACT |
4748                                         Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
4749
4750                                 flags = MethodAttributes.Public |
4751                                         MethodAttributes.Abstract |
4752                                         MethodAttributes.HideBySig |
4753                                         MethodAttributes.NewSlot |
4754                                         MethodAttributes.Virtual;
4755                         } else {
4756                                 if (!ParentContainer.MethodModifiersValid (this))
4757                                         return false;
4758
4759                                 flags = Modifiers.MethodAttr (ModFlags);
4760                         }
4761
4762                         if (MemberType == null)
4763                                 return false;
4764
4765                         if ((Parent.ModFlags & Modifiers.SEALED) != 0 && 
4766                                 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
4767                                         Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
4768                                                 GetSignatureForError (), Parent.GetSignatureForError ());
4769                                         return false;
4770                         }
4771                         
4772                         // verify accessibility
4773                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
4774                                 Report.SymbolRelatedToPreviousError (MemberType);
4775                                 if (this is Property)
4776                                         Report.Error (53, Location,
4777                                                       "Inconsistent accessibility: property type `" +
4778                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4779                                                       "accessible than property `" + GetSignatureForError () + "'");
4780                                 else if (this is Indexer)
4781                                         Report.Error (54, Location,
4782                                                       "Inconsistent accessibility: indexer return type `" +
4783                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4784                                                       "accessible than indexer `" + GetSignatureForError () + "'");
4785                                 else if (this is MethodCore) {
4786                                         if (this is Operator)
4787                                                 Report.Error (56, Location,
4788                                                               "Inconsistent accessibility: return type `" +
4789                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4790                                                               "accessible than operator `" + GetSignatureForError () + "'");
4791                                         else
4792                                                 Report.Error (50, Location,
4793                                                               "Inconsistent accessibility: return type `" +
4794                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4795                                                               "accessible than method `" + GetSignatureForError () + "'");
4796                                 } else {
4797                                         Report.Error (52, Location,
4798                                                       "Inconsistent accessibility: field type `" +
4799                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4800                                                       "accessible than field `" + GetSignatureForError () + "'");
4801                                 }
4802                                 return false;
4803                         }
4804
4805                         if (IsExplicitImpl) {
4806                                 Expression expr = MemberName.Left.GetTypeExpression ();
4807                                 TypeExpr texpr = expr.ResolveAsTypeTerminal (ResolveContext, false);
4808                                 if (texpr == null)
4809                                         return false;
4810
4811                                 InterfaceType = texpr.Type;
4812
4813                                 if (!InterfaceType.IsInterface) {
4814                                         Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
4815                                         return false;
4816                                 }
4817                                 
4818                                 if (!ParentContainer.VerifyImplements (this))
4819                                         return false;
4820                                 
4821                                 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4822                                 
4823                         }
4824                         return true;
4825                 }
4826
4827                 protected bool IsTypePermitted ()
4828                 {
4829                         if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
4830                                 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
4831                                 return false;
4832                         }
4833                         return true;
4834                 }
4835
4836                 protected override bool VerifyClsCompliance()
4837                 {
4838                         if (base.VerifyClsCompliance ()) {
4839                                 return true;
4840                         }
4841
4842                         if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
4843                                 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
4844                         }
4845                         return false;
4846                 }
4847
4848         }
4849
4850         //
4851         // Fields and Events both generate FieldBuilders, we use this to share 
4852         // their common bits.  This is also used to flag usage of the field
4853         //
4854         abstract public class FieldBase : MemberBase {
4855                 public FieldBuilder  FieldBuilder;
4856                 public Status status;
4857                 protected Expression initializer;
4858
4859                 [Flags]
4860                 public enum Status : byte {
4861                         HAS_OFFSET = 4          // Used by FieldMember.
4862                 }
4863
4864                 static string[] attribute_targets = new string [] { "field" };
4865
4866                 /// <summary>
4867                 ///  Symbol with same name in base class/struct
4868                 /// </summary>
4869                 public MemberInfo conflict_symbol;
4870
4871                 protected FieldBase (DeclSpace parent, Expression type, int mod,
4872                                      int allowed_mod, MemberName name, Attributes attrs)
4873                         : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
4874                                 name, attrs)
4875                 {
4876                 }
4877
4878                 public override AttributeTargets AttributeTargets {
4879                         get {
4880                                 return AttributeTargets.Field;
4881                         }
4882                 }
4883
4884                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4885                 {
4886                         if (a.Type == TypeManager.marshal_as_attr_type) {
4887                                 UnmanagedMarshal marshal = a.GetMarshal (this);
4888                                 if (marshal != null) {
4889                                         FieldBuilder.SetMarshal (marshal);
4890                                 }
4891                                 return;
4892                         }
4893
4894                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
4895                                 a.Error_InvalidSecurityParent ();
4896                                 return;
4897                         }
4898
4899                         FieldBuilder.SetCustomAttribute (cb);
4900                 }
4901
4902                 public void EmitInitializer (EmitContext ec)
4903                 {
4904                         // Replace DeclSpace because of partial classes
4905                         ec.DeclContainer = DeclContainer;
4906
4907                         ec.IsFieldInitializer = true;
4908                         initializer = initializer.Resolve (ec);
4909                         ec.IsFieldInitializer = false;
4910                         if (initializer == null)
4911                                 return;
4912
4913                         FieldExpr fe = new FieldExpr (FieldBuilder, Location, true);
4914                         if ((ModFlags & Modifiers.STATIC) == 0)
4915                                 fe.InstanceExpression = new This (Location).Resolve (ec);
4916
4917                         ExpressionStatement a = new Assign (fe, initializer, Location);
4918
4919                         a = a.ResolveStatement (ec);
4920                         if (a == null)
4921                                 return;
4922
4923                         Constant c = initializer as Constant;
4924                         if (c != null && CanElideInitializer (c))
4925                                 return;
4926
4927                         a.EmitStatement (ec);
4928                 }
4929
4930                 bool CanElideInitializer (Constant c)
4931                 {
4932                         if (MemberType == c.Type)
4933                                 return c.IsDefaultValue;
4934
4935                         if (c.Type == TypeManager.null_type)
4936                                 return true;
4937
4938                         return false;
4939                 }
4940
4941                 protected override bool CheckBase ()
4942                 {
4943                         if (!base.CheckBase ())
4944                                 return false;
4945  
4946                         // TODO: Implement
4947                         if (IsInterface)
4948                                 return true;
4949  
4950                         conflict_symbol = ParentContainer.FindBaseMemberWithSameName (Name, false);
4951                         if (conflict_symbol == null) {
4952                                 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
4953                                         Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
4954                                 }
4955                                 return true;
4956                         }
4957  
4958                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
4959                                 Report.SymbolRelatedToPreviousError (conflict_symbol);
4960                                 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
4961                                         GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
4962                         }
4963  
4964                         return true;
4965                 }
4966
4967                 public Expression Initializer {
4968                         set {
4969                                 if (value != null) {
4970                                         this.initializer = value;
4971                                         ParentContainer.RegisterFieldForInitialization (this);
4972                                 }
4973                         }
4974                 }
4975
4976                 protected virtual bool IsFieldClsCompliant {
4977                         get {
4978                                 if (FieldBuilder == null)
4979                                         return true;
4980
4981                                 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
4982                         }
4983                 }
4984
4985                 public override string[] ValidAttributeTargets {
4986                         get {
4987                                 return attribute_targets;
4988                         }
4989                 }
4990
4991                 protected override bool VerifyClsCompliance ()
4992                 {
4993                         if (!base.VerifyClsCompliance ())
4994                                 return false;
4995
4996                         if (!IsFieldClsCompliant) {
4997                                 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
4998                         }
4999                         return true;
5000                 }
5001
5002
5003                 public void SetAssigned ()
5004                 {
5005                         caching_flags |= Flags.IsAssigned;
5006                 }
5007         }
5008
5009         public abstract class FieldMember : FieldBase
5010         {
5011                 protected FieldMember (DeclSpace parent, Expression type, int mod,
5012                         int allowed_mod, MemberName name, Attributes attrs)
5013                         : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, attrs)
5014                 {
5015                         if ((mod & Modifiers.ABSTRACT) != 0)
5016                                 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5017                 }
5018
5019                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5020                 {
5021                         if (a.Type == TypeManager.field_offset_attribute_type)
5022                         {
5023                                 status |= Status.HAS_OFFSET;
5024
5025                                 if (!ParentContainer.HasExplicitLayout) {
5026                                         Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5027                                         return;
5028                                 }
5029
5030                                 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5031                                         Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5032                                         return;
5033                                 }
5034                         }
5035
5036 #if NET_2_0
5037                         if (a.Type == TypeManager.fixed_buffer_attr_type) {
5038                                 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5039                                 return;
5040                         }
5041 #endif
5042
5043                         base.ApplyAttributeBuilder (a, cb);
5044                 }
5045
5046                 public override bool Define()
5047                 {
5048                         if (MemberType == null || Type == null)
5049                                 return false;
5050
5051                         if (MemberType == TypeManager.void_type) {
5052                                 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5053                                 return false;
5054                         }
5055
5056                         if (!CheckBase ())
5057                                 return false;
5058                         
5059                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
5060                                 Report.Error (52, Location,
5061                                         "Inconsistent accessibility: field type `" +
5062                                         TypeManager.CSharpName (MemberType) + "' is less " +
5063                                         "accessible than field `" + GetSignatureForError () + "'");
5064                                 return false;
5065                         }
5066
5067                         if (!IsTypePermitted ())
5068                                 return false;
5069
5070                         return true;
5071                 }
5072
5073                 public override void Emit ()
5074                 {
5075                         if (OptAttributes != null) {
5076                                 OptAttributes.Emit ();
5077                         }
5078
5079                         if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && ParentContainer.HasExplicitLayout) {
5080                                 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5081                         }
5082
5083                         base.Emit ();
5084                 }
5085
5086                 //
5087                 //   Represents header string for documentation comment.
5088                 //
5089                 public override string DocCommentHeader {
5090                         get { return "F:"; }
5091                 }
5092         }
5093
5094         interface IFixedBuffer
5095         {
5096                 FieldInfo Element { get; }
5097                 Type ElementType { get; }
5098         }
5099
5100         public class FixedFieldExternal: IFixedBuffer
5101         {
5102                 FieldInfo element_field;
5103
5104                 public FixedFieldExternal (FieldInfo fi)
5105                 {
5106                         element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5107                 }
5108
5109                 #region IFixedField Members
5110
5111                 public FieldInfo Element {
5112                         get {
5113                                 return element_field;
5114                         }
5115                 }
5116
5117                 public Type ElementType {
5118                         get {
5119                                 return element_field.FieldType;
5120                         }
5121                 }
5122
5123                 #endregion
5124         }
5125
5126         /// <summary>
5127         /// Fixed buffer implementation
5128         /// </summary>
5129         public class FixedField : FieldMember, IFixedBuffer
5130         {
5131                 public const string FixedElementName = "FixedElementField";
5132                 static int GlobalCounter = 0;
5133                 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5134                 static FieldInfo[] fi;
5135
5136                 TypeBuilder fixed_buffer_type;
5137                 FieldBuilder element;
5138                 Expression size_expr;
5139                 int buffer_size;
5140
5141                 const int AllowedModifiers =
5142                         Modifiers.NEW |
5143                         Modifiers.PUBLIC |
5144                         Modifiers.PROTECTED |
5145                         Modifiers.INTERNAL |
5146                         Modifiers.PRIVATE;
5147
5148                 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5149                         Expression size_expr, Attributes attrs, Location loc):
5150                         base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5151                 {
5152                         if (RootContext.Version == LanguageVersion.ISO_1)
5153                                 Report.FeatureIsNotStandardized (loc, "fixed size buffers");
5154
5155                         this.size_expr = size_expr;
5156                 }
5157
5158                 public override bool Define()
5159                 {
5160 #if !NET_2_0
5161                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5162                                 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5163 #endif
5164
5165                         if (ParentContainer.Kind != Kind.Struct) {
5166                                 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5167                                         GetSignatureForError ());
5168                                 return false;
5169                         }
5170
5171                         if (!base.Define ())
5172                                 return false;
5173
5174                         if (!TypeManager.IsPrimitiveType (MemberType)) {
5175                                 Report.Error (1663, Location, "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double",
5176                                         GetSignatureForError ());
5177                                 return false;
5178                         }
5179
5180                         EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5181                         Constant c = size_expr.ResolveAsConstant (ec, this);
5182                         if (c == null)
5183                                 return false;
5184
5185                         IntConstant buffer_size_const = c.ToInt (Location);
5186                         if (buffer_size_const == null)
5187                                 return false;
5188
5189                         buffer_size = buffer_size_const.Value;
5190
5191                         if (buffer_size <= 0) {
5192                                 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5193                                 return false;
5194                         }
5195
5196                         int type_size = Expression.GetTypeSize (MemberType);
5197
5198                         if (buffer_size > int.MaxValue / type_size) {
5199                                 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5200                                         GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5201                                 return false;
5202                         }
5203
5204                         buffer_size *= type_size;
5205
5206                         // Define nested
5207                         string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5208
5209                         fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5210                                 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5211                         element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5212                         RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5213
5214                         FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5215                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5216
5217                         return true;
5218                 }
5219
5220                 public override void Emit()
5221                 {
5222                         if (fi == null)
5223                                 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5224
5225                         object[] fi_val = new object[1];
5226                         fi_val [0] = buffer_size;
5227
5228                         CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
5229                                 ctor_args, fi, fi_val);
5230                         fixed_buffer_type.SetCustomAttribute (cab);
5231
5232 #if NET_2_0
5233                         cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5234                         FieldBuilder.SetCustomAttribute (cab);
5235 #endif
5236                         base.Emit ();
5237                 }
5238
5239                 protected override bool IsFieldClsCompliant {
5240                         get {
5241                                 return false;
5242                         }
5243                 }
5244
5245                 #region IFixedField Members
5246
5247                 public FieldInfo Element {
5248                         get {
5249                                 return element;
5250                         }
5251                 }
5252
5253                 public Type ElementType {
5254                         get {
5255                                 return MemberType;
5256                         }
5257                 }
5258
5259                 #endregion
5260         }
5261
5262         //
5263         // The Field class is used to represents class/struct fields during parsing.
5264         //
5265         public class Field : FieldMember {
5266                 // <summary>
5267                 //   Modifiers allowed in a class declaration
5268                 // </summary>
5269                 const int AllowedModifiers =
5270                         Modifiers.NEW |
5271                         Modifiers.PUBLIC |
5272                         Modifiers.PROTECTED |
5273                         Modifiers.INTERNAL |
5274                         Modifiers.PRIVATE |
5275                         Modifiers.STATIC |
5276                         Modifiers.VOLATILE |
5277                         Modifiers.UNSAFE |
5278                         Modifiers.READONLY;
5279
5280                 public Field (DeclSpace parent, Expression type, int mod, string name,
5281                               Attributes attrs, Location loc)
5282                         : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
5283                                 attrs)
5284                 {
5285                 }
5286
5287                 public override bool Define ()
5288                 {
5289                         if (!base.Define ())
5290                                 return false;
5291
5292                         if (RootContext.WarningLevel > 1){
5293                                 Type ptype = Parent.TypeBuilder.BaseType;
5294
5295                                 // ptype is only null for System.Object while compiling corlib.
5296                                 if (ptype != null){
5297                                         TypeContainer.FindMembers (
5298                                                 ptype, MemberTypes.Method,
5299                                                 BindingFlags.Public |
5300                                                 BindingFlags.Static | BindingFlags.Instance,
5301                                                 System.Type.FilterName, Name);
5302                                 }
5303                         }
5304
5305                         if ((ModFlags & Modifiers.VOLATILE) != 0){
5306                                 if (!MemberType.IsClass){
5307                                         Type vt = MemberType;
5308                                         
5309                                         if (TypeManager.IsEnumType (vt))
5310                                                 vt = TypeManager.EnumToUnderlying (MemberType);
5311
5312                                         if (!((vt == TypeManager.bool_type) ||
5313                                               (vt == TypeManager.sbyte_type) ||
5314                                               (vt == TypeManager.byte_type) ||
5315                                               (vt == TypeManager.short_type) ||
5316                                               (vt == TypeManager.ushort_type) ||
5317                                               (vt == TypeManager.int32_type) ||
5318                                               (vt == TypeManager.uint32_type) ||    
5319                                               (vt == TypeManager.char_type) ||
5320                                               (vt == TypeManager.float_type) ||
5321                                               (!vt.IsValueType))){
5322                                                 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5323                                                         GetSignatureForError (), TypeManager.CSharpName (vt));
5324                                                 return false;
5325                                         }
5326                                 }
5327
5328                                 if ((ModFlags & Modifiers.READONLY) != 0){
5329                                         Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5330                                                 GetSignatureForError ());
5331                                         return false;
5332                                 }
5333                         }
5334
5335                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5336
5337                         if (ParentContainer.Kind == Kind.Struct && 
5338                             ((fa & FieldAttributes.Static) == 0) &&
5339                             MemberType == Parent.TypeBuilder &&
5340                             !TypeManager.IsBuiltinType (MemberType)){
5341                                 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name + 
5342                                               "' causes a cycle in the structure layout");
5343                                 return false;
5344                         }
5345
5346                         try {
5347                                 FieldBuilder = Parent.TypeBuilder.DefineField (
5348                                         Name, MemberType, Modifiers.FieldAttr (ModFlags));
5349
5350                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
5351                         }
5352                         catch (ArgumentException) {
5353                                 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5354                                 return false;
5355                         }
5356
5357                         return true;
5358                 }
5359
5360                 protected override bool VerifyClsCompliance ()
5361                 {
5362                         if (!base.VerifyClsCompliance ())
5363                                 return false;
5364
5365                         if ((ModFlags & Modifiers.VOLATILE) != 0) {
5366                                 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5367                         }
5368
5369                         return true;
5370                 }
5371         }
5372
5373         //
5374         // `set' and `get' accessors are represented with an Accessor.
5375         // 
5376         public class Accessor : IIteratorContainer {
5377                 //
5378                 // Null if the accessor is empty, or a Block if not
5379                 //
5380                 public const int AllowedModifiers = 
5381                         Modifiers.PUBLIC |
5382                         Modifiers.PROTECTED |
5383                         Modifiers.INTERNAL |
5384                         Modifiers.PRIVATE;
5385                 
5386                 public ToplevelBlock Block;
5387                 public Attributes Attributes;
5388                 public Location Location;
5389                 public int ModFlags;
5390                 public bool Yields;
5391                 
5392                 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5393                 {
5394                         Block = b;
5395                         Attributes = attrs;
5396                         Location = loc;
5397                         ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5398                 }
5399
5400                 public void SetYields ()
5401                 {
5402                         Yields = true;
5403                 }
5404         }
5405
5406         // Ooouh Martin, templates are missing here.
5407         // When it will be possible move here a lot of child code and template method type.
5408         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5409                 protected MethodData method_data;
5410                 protected ToplevelBlock block;
5411                 protected ListDictionary declarative_security;
5412
5413                 // The accessor are created event if they are not wanted.
5414                 // But we need them because their names are reserved.
5415                 // Field says whether accessor will be emited or not
5416                 public readonly bool IsDummy;
5417
5418                 protected readonly string prefix;
5419
5420                 ReturnParameter return_attributes;
5421
5422                 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5423                         : base (member.Parent, SetupName (prefix, member, member.Location), null)
5424                 {
5425                         this.prefix = prefix;
5426                         IsDummy = true;
5427                 }
5428
5429                 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5430                                                     string prefix)
5431                         : base (member.Parent, SetupName (prefix, member, accessor.Location),
5432                                 accessor.Attributes)
5433                 {
5434                         this.prefix = prefix;
5435                         this.block = accessor.Block;
5436                 }
5437
5438                 static MemberName SetupName (string prefix, MemberBase member, Location loc)
5439                 {
5440                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5441                 }
5442
5443                 public void UpdateName (MemberBase member)
5444                 {
5445                         SetMemberName (SetupName (prefix, member, Location));
5446                 }
5447
5448                 #region IMethodData Members
5449
5450                 public ToplevelBlock Block {
5451                         get {
5452                                 return block;
5453                         }
5454
5455                         set {
5456                                 block = value;
5457                         }
5458                 }
5459
5460                 public CallingConventions CallingConventions {
5461                         get {
5462                                 return CallingConventions.Standard;
5463                         }
5464                 }
5465
5466                 public bool IsExcluded ()
5467                 {
5468                         return false;
5469                 }
5470
5471                 public MemberName MethodName {
5472                         get {
5473                                 return MemberName;
5474                         }
5475                 }
5476
5477                 public Type[] ParameterTypes { 
5478                         get {
5479                                 return ParameterInfo.Types;
5480                         }
5481                 }
5482
5483                 public abstract Parameters ParameterInfo { get ; }
5484                 public abstract Type ReturnType { get; }
5485                 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5486
5487                 #endregion
5488
5489                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5490                 {
5491                         if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5492                                         a.Type == TypeManager.conditional_attribute_type) {
5493                                 Report.Error (1667, a.Location,
5494                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
5495                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5496                                 return;
5497                         }
5498
5499                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5500                                 if (declarative_security == null)
5501                                         declarative_security = new ListDictionary ();
5502                                 a.ExtractSecurityPermissionSet (declarative_security);
5503                                 return;
5504                         }
5505
5506                         if (a.Target == AttributeTargets.Method) {
5507                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5508                                 return;
5509                         }
5510
5511                         if (a.Target == AttributeTargets.ReturnValue) {
5512                                 if (return_attributes == null)
5513                                         return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5514
5515                                 return_attributes.ApplyAttributeBuilder (a, cb);
5516                                 return;
5517                         }
5518
5519                         ApplyToExtraTarget (a, cb);
5520                 }
5521
5522                 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5523                 {
5524                         System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5525                 }
5526
5527                 public override bool Define()
5528                 {
5529                         throw new NotSupportedException ();
5530                 }
5531
5532                 public virtual void Emit (DeclSpace parent)
5533                 {
5534                         EmitMethod (parent);
5535
5536                         if (declarative_security != null) {
5537                                 foreach (DictionaryEntry de in declarative_security) {
5538                                         method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5539                                 }
5540                         }
5541
5542                         block = null;
5543                 }
5544
5545                 protected virtual void EmitMethod (DeclSpace parent)
5546                 {
5547                         method_data.Emit (parent);
5548                 }
5549
5550                 public override bool IsClsComplianceRequired()
5551                 {
5552                         return false;
5553                 }
5554
5555                 public bool IsDuplicateImplementation (MethodCore method)
5556                 {
5557                         if (!MemberName.Equals (method.MemberName))
5558                                 return false;
5559
5560                         Type[] param_types = method.ParameterTypes;
5561
5562                         if (param_types.Length != ParameterTypes.Length)
5563                                 return false;
5564
5565                         for (int i = 0; i < param_types.Length; i++)
5566                                 if (param_types [i] != ParameterTypes [i])
5567                                         return false;
5568
5569                         Report.SymbolRelatedToPreviousError (method);
5570                         Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
5571                         return true;
5572                 }
5573
5574                 public override bool IsUsed
5575                 {
5576                         get {
5577                                 if (IsDummy)
5578                                         return false;
5579
5580                                 return base.IsUsed;
5581                         }
5582                 }
5583
5584                 public new Location Location { 
5585                         get {
5586                                 return base.Location;
5587                         }
5588                 }
5589
5590                 //
5591                 //   Represents header string for documentation comment.
5592                 //
5593                 public override string DocCommentHeader {
5594                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
5595                 }
5596
5597         }
5598
5599         //
5600         // Properties and Indexers both generate PropertyBuilders, we use this to share 
5601         // their common bits.
5602         //
5603         abstract public class PropertyBase : MethodCore {
5604
5605                 public class GetMethod : PropertyMethod
5606                 {
5607                         static string[] attribute_targets = new string [] { "method", "return" };
5608
5609                         public GetMethod (MethodCore method):
5610                                 base (method, "get_")
5611                         {
5612                         }
5613
5614                         public GetMethod (MethodCore method, Accessor accessor):
5615                                 base (method, accessor, "get_")
5616                         {
5617                         }
5618
5619                         public override MethodBuilder Define (DeclSpace parent)
5620                         {
5621                                 base.Define (parent);
5622                                 
5623                                 method_data = new MethodData (method, ModFlags, flags, this);
5624
5625                                 if (!method_data.Define (parent))
5626                                         return null;
5627
5628                                 return method_data.MethodBuilder;
5629                         }
5630
5631                         public override Type ReturnType {
5632                                 get {
5633                                         return method.MemberType;
5634                                 }
5635                         }
5636
5637                         public override Parameters ParameterInfo {
5638                                 get {
5639                                         return Parameters.EmptyReadOnlyParameters;
5640                                 }
5641                         }
5642
5643                         public override string[] ValidAttributeTargets {
5644                                 get {
5645                                         return attribute_targets;
5646                                 }
5647                         }
5648                 }
5649
5650                 public class SetMethod : PropertyMethod {
5651
5652                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5653                         ImplicitParameter param_attr;
5654                         protected Parameters parameters;
5655
5656                         public SetMethod (MethodCore method):
5657                                 base (method, "set_")
5658                         {
5659                         }
5660
5661                         public SetMethod (MethodCore method, Accessor accessor):
5662                                 base (method, accessor, "set_")
5663                         {
5664                         }
5665
5666                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5667                         {
5668                                 if (a.Target == AttributeTargets.Parameter) {
5669                                         if (param_attr == null)
5670                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5671
5672                                         param_attr.ApplyAttributeBuilder (a, cb);
5673                                         return;
5674                                 }
5675
5676                                 base.ApplyAttributeBuilder (a, cb);
5677                         }
5678
5679                         public override Parameters ParameterInfo {
5680                                 get {
5681                                         return parameters;
5682                                 }
5683                         }
5684
5685                         protected virtual void DefineParameters ()
5686                         {
5687                                 parameters = new Parameters (
5688                                         new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
5689                                         new Type[] { method.MemberType });
5690                         }
5691
5692                         public override MethodBuilder Define (DeclSpace parent)
5693                         {
5694                                 DefineParameters ();
5695                                 if (IsDummy)
5696                                         return null;
5697
5698                                 base.Define (parent);
5699
5700                                 method_data = new MethodData (method, ModFlags, flags, this);
5701
5702                                 if (!method_data.Define (parent))
5703                                         return null;
5704
5705                                 return method_data.MethodBuilder;
5706                         }
5707
5708                         public override Type ReturnType {
5709                                 get {
5710                                         return TypeManager.void_type;
5711                                 }
5712                         }
5713
5714                         public override string[] ValidAttributeTargets {
5715                                 get {
5716                                         return attribute_targets;
5717                                 }
5718                         }
5719                 }
5720
5721                 static string[] attribute_targets = new string [] { "property" };
5722
5723                 public abstract class PropertyMethod : AbstractPropertyEventMethod
5724                 {
5725                         protected readonly MethodCore method;
5726                         protected MethodAttributes flags;
5727                         bool yields;
5728
5729                         public PropertyMethod (MethodCore method, string prefix)
5730                                 : base (method, prefix)
5731                         {
5732                                 this.method = method;
5733                         }
5734
5735                         public PropertyMethod (MethodCore method, Accessor accessor,
5736                                                string prefix)
5737                                 : base (method, accessor, prefix)
5738                         {
5739                                 this.method = method;
5740                                 this.ModFlags = accessor.ModFlags;
5741                                 yields = accessor.Yields;
5742
5743                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
5744                                         Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
5745                                 }
5746                         }
5747
5748                         public override AttributeTargets AttributeTargets {
5749                                 get {
5750                                         return AttributeTargets.Method;
5751                                 }
5752                         }
5753
5754                         public override bool IsClsComplianceRequired()
5755                         {
5756                                 return method.IsClsComplianceRequired ();
5757                         }
5758
5759                         public virtual MethodBuilder Define (DeclSpace parent)
5760                         {
5761                                 if (!method.CheckAbstractAndExtern (block != null))
5762                                         return null;
5763
5764                                 TypeContainer container = ((TypeContainer) parent).PartialContainer;
5765
5766                                 //
5767                                 // Check for custom access modifier
5768                                 //
5769                                 if (ModFlags == 0) {
5770                                         ModFlags = method.ModFlags;
5771                                         flags = method.flags;
5772                                 } else {
5773                                         if (container.Kind == Kind.Interface)
5774                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
5775                                                         GetSignatureForError ());
5776
5777                                         if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
5778                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
5779                                         }
5780
5781                                         CheckModifiers (ModFlags);
5782                                         ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
5783                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
5784                                         flags = Modifiers.MethodAttr (ModFlags);
5785                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
5786                                 }
5787
5788                                 //
5789                                 // Setup iterator if we are one
5790                                 //
5791                                 if (yields) {
5792                                         Iterator iterator = new Iterator (this, Parent as TypeContainer, ModFlags);
5793                                         
5794                                         if (!iterator.DefineIterator ())
5795                                                 return null;
5796                                 }
5797
5798                                 return null;
5799                         }
5800
5801                         public bool HasCustomAccessModifier
5802                         {
5803                                 get {
5804                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
5805                                 }
5806                         }
5807
5808                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
5809                         {
5810                                 return new EmitContext (method,
5811                                         ds, method.Parent, method.Location, ig, ReturnType,
5812                                         method.ModFlags, false);
5813                         }
5814
5815                         public override ObsoleteAttribute GetObsoleteAttribute ()
5816                         {
5817                                 return method.GetObsoleteAttribute ();
5818                         }
5819
5820                         public override string GetSignatureForError()
5821                         {
5822                                 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
5823                         }
5824                         
5825                         void CheckModifiers (int modflags)
5826                         {
5827                                 int flags = 0;
5828                                 int mflags = method.ModFlags & Modifiers.Accessibility;
5829
5830                                 if ((mflags & Modifiers.PUBLIC) != 0) {
5831                                         flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
5832                                 }
5833                                 else if ((mflags & Modifiers.PROTECTED) != 0) {
5834                                         if ((mflags & Modifiers.INTERNAL) != 0)
5835                                                 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
5836
5837                                         flags |= Modifiers.PRIVATE;
5838                                 }
5839                                 else if ((mflags & Modifiers.INTERNAL) != 0)
5840                                         flags |= Modifiers.PRIVATE;
5841
5842                                 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
5843                                         Report.Error (273, Location,
5844                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
5845                                                 GetSignatureForError (), method.GetSignatureForError ());
5846                                 }
5847                         }
5848
5849                         public override bool MarkForDuplicationCheck ()
5850                         {
5851                                 caching_flags |= Flags.TestMethodDuplication;
5852                                 return true;
5853                         }
5854                 }
5855
5856
5857                 public PropertyMethod Get, Set;
5858                 public PropertyBuilder PropertyBuilder;
5859                 public MethodBuilder GetBuilder, SetBuilder;
5860
5861                 protected EmitContext ec;
5862
5863                 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
5864                                      int allowed_mod, bool is_iface, MemberName name,
5865                                      Parameters parameters, Attributes attrs)
5866                         : base (parent, type, mod_flags, allowed_mod, is_iface, name,
5867                                 attrs, parameters)
5868                 {
5869                 }
5870
5871                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5872                 {
5873                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5874                                 a.Error_InvalidSecurityParent ();
5875                                 return;
5876                         }
5877
5878                         PropertyBuilder.SetCustomAttribute (cb);
5879                 }
5880
5881                 public override AttributeTargets AttributeTargets {
5882                         get {
5883                                 return AttributeTargets.Property;
5884                         }
5885                 }
5886
5887                 public override bool Define ()
5888                 {
5889                         if (!DoDefine ())
5890                                 return false;
5891
5892                         if (!IsTypePermitted ())
5893                                 return false;
5894
5895                         return true;
5896                 }
5897
5898                 protected override bool DoDefine ()
5899                 {
5900                         if (!base.DoDefine ())
5901                                 return false;
5902
5903                         //
5904                         // Accessors modifiers check
5905                         //
5906                         if (Get.ModFlags != 0 && Set.ModFlags != 0) {
5907                                 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
5908                                                 GetSignatureForError ());
5909                                 return false;
5910                         }
5911
5912                         if ((Get.IsDummy || Set.IsDummy)
5913                                         && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
5914                                 Report.Error (276, Location, 
5915                                         "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
5916                                         GetSignatureForError ());
5917                                 return false;
5918                         }
5919
5920                         if (MemberType.IsAbstract && MemberType.IsSealed) {
5921                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
5922                                 return false;
5923                         }
5924
5925                         return true;
5926                 }
5927
5928                 protected override bool CheckForDuplications ()
5929                 {
5930                         ArrayList ar = ParentContainer.Indexers;
5931                         if (ar != null) {
5932                                 int arLen = ar.Count;
5933                                         
5934                                 for (int i = 0; i < arLen; i++) {
5935                                         Indexer m = (Indexer) ar [i];
5936                                         if (IsDuplicateImplementation (m))
5937                                                 return false;
5938                                 }
5939                         }
5940
5941                         ar = ParentContainer.Properties;
5942                         if (ar != null) {
5943                                 int arLen = ar.Count;
5944                                         
5945                                 for (int i = 0; i < arLen; i++) {
5946                                         Property m = (Property) ar [i];
5947                                         if (IsDuplicateImplementation (m))
5948                                                 return false;
5949                                 }
5950                         }
5951
5952                         return true;
5953                 }
5954
5955                 // TODO: rename to Resolve......
5956                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5957                 {
5958                         PropertyInfo base_property = ParentContainer.BaseCache.FindMemberToOverride (
5959                                 Parent.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
5960   
5961                         if (base_property == null)
5962                                 return null;
5963   
5964                         base_ret_type = base_property.PropertyType;
5965                         MethodInfo get_accessor = base_property.GetGetMethod (true);
5966                         MethodInfo set_accessor = base_property.GetSetMethod (true);
5967                         MethodAttributes get_accessor_access, set_accessor_access;
5968
5969                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
5970                                 if (Get != null && !Get.IsDummy && get_accessor == null) {
5971                                         Report.SymbolRelatedToPreviousError (base_property);
5972                                         Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
5973                                 }
5974
5975                                 if (Set != null && !Set.IsDummy && set_accessor == null) {
5976                                         Report.SymbolRelatedToPreviousError (base_property);
5977                                         Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
5978                                 }
5979                         }
5980                         
5981                         //
5982                         // Check base class accessors access
5983                         //
5984
5985                         // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
5986                         get_accessor_access = set_accessor_access = 0;
5987                         if ((ModFlags & Modifiers.NEW) == 0) {
5988                                 if (get_accessor != null) {
5989                                         MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
5990                                         get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
5991
5992                                         if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
5993                                                 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access,  ".get");
5994                                 }
5995
5996                                 if (set_accessor != null)  {
5997                                         MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
5998                                         set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
5999
6000                                         if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6001                                                 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6002                                 }
6003                         }
6004
6005                         //
6006                         // Get the less restrictive access
6007                         //
6008                         return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6009                 }
6010
6011                 public override void Emit ()
6012                 {
6013                         //
6014                         // The PropertyBuilder can be null for explicit implementations, in that
6015                         // case, we do not actually emit the ".property", so there is nowhere to
6016                         // put the attribute
6017                         //
6018                         if (PropertyBuilder != null && OptAttributes != null)
6019                                 OptAttributes.Emit ();
6020
6021                         if (!Get.IsDummy)
6022                                 Get.Emit (Parent);
6023
6024                         if (!Set.IsDummy)
6025                                 Set.Emit (Parent);
6026
6027                         base.Emit ();
6028                 }
6029
6030                 /// <summary>
6031                 /// Tests whether accessors are not in collision with some method (CS0111)
6032                 /// </summary>
6033                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6034                 {
6035                         return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6036                 }
6037
6038                 public override bool IsUsed
6039                 {
6040                         get {
6041                                 if (IsExplicitImpl)
6042                                         return true;
6043
6044                                 return Get.IsUsed | Set.IsUsed;
6045                         }
6046                 }
6047
6048                 protected override void SetMemberName (MemberName new_name)
6049                 {
6050                         base.SetMemberName (new_name);
6051
6052                         Get.UpdateName (this);
6053                         Set.UpdateName (this);
6054                 }
6055
6056                 public override string[] ValidAttributeTargets {
6057                         get {
6058                                 return attribute_targets;
6059                         }
6060                 }
6061
6062                 //
6063                 //   Represents header string for documentation comment.
6064                 //
6065                 public override string DocCommentHeader {
6066                         get { return "P:"; }
6067                 }
6068         }
6069                         
6070         public class Property : PropertyBase {
6071                 const int AllowedModifiers =
6072                         Modifiers.NEW |
6073                         Modifiers.PUBLIC |
6074                         Modifiers.PROTECTED |
6075                         Modifiers.INTERNAL |
6076                         Modifiers.PRIVATE |
6077                         Modifiers.STATIC |
6078                         Modifiers.SEALED |
6079                         Modifiers.OVERRIDE |
6080                         Modifiers.ABSTRACT |
6081                         Modifiers.UNSAFE |
6082                         Modifiers.EXTERN |
6083                         Modifiers.METHOD_YIELDS |
6084                         Modifiers.VIRTUAL;
6085
6086                 const int AllowedInterfaceModifiers =
6087                         Modifiers.NEW;
6088
6089                 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6090                                  MemberName name, Attributes attrs, Accessor get_block,
6091                                  Accessor set_block)
6092                         : base (parent, type, mod,
6093                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6094                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs)
6095                 {
6096                         if (get_block == null)
6097                                 Get = new GetMethod (this);
6098                         else
6099                                 Get = new GetMethod (this, get_block);
6100
6101                         if (set_block == null)
6102                                 Set = new SetMethod (this);
6103                         else
6104                                 Set = new SetMethod (this, set_block);
6105                 }
6106
6107                 public override bool Define ()
6108                 {
6109                         if (!base.Define ())
6110                                 return false;
6111
6112                         if (!CheckBase ())
6113                                 return false;
6114
6115                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6116
6117                         if (!Get.IsDummy) {
6118                                 GetBuilder = Get.Define (Parent);
6119                                 if (GetBuilder == null)
6120                                         return false;
6121                         }
6122
6123                         SetBuilder = Set.Define (Parent);
6124                         if (!Set.IsDummy) {
6125                                 if (SetBuilder == null)
6126                                         return false;
6127                         }
6128
6129                         // FIXME - PropertyAttributes.HasDefault ?
6130
6131                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6132                              Name, PropertyAttributes.None, MemberType, null);
6133                         
6134                         if (!Get.IsDummy)
6135                                 PropertyBuilder.SetGetMethod (GetBuilder);
6136                                 
6137                         if (!Set.IsDummy)
6138                                 PropertyBuilder.SetSetMethod (SetBuilder);
6139                         
6140                         TypeManager.RegisterProperty (PropertyBuilder, this);
6141                         return true;
6142                 }
6143         }
6144
6145         /// </summary>
6146         ///  Gigantic workaround  for lameness in SRE follows :
6147         ///  This class derives from EventInfo and attempts to basically
6148         ///  wrap around the EventBuilder so that FindMembers can quickly
6149         ///  return this in it search for members
6150         /// </summary>
6151         public class MyEventBuilder : EventInfo {
6152                 
6153                 //
6154                 // We use this to "point" to our Builder which is
6155                 // not really a MemberInfo
6156                 //
6157                 EventBuilder MyBuilder;
6158                 
6159                 //
6160                 // We "catch" and wrap these methods
6161                 //
6162                 MethodInfo raise, remove, add;
6163
6164                 EventAttributes attributes;
6165                 Type declaring_type, reflected_type, event_type;
6166                 string name;
6167
6168                 Event my_event;
6169
6170                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6171                 {
6172                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6173
6174                         // And now store the values in our own fields.
6175                         
6176                         declaring_type = type_builder;
6177
6178                         reflected_type = type_builder;
6179                         
6180                         attributes = event_attr;
6181                         this.name = name;
6182                         my_event = ev;
6183                         this.event_type = event_type;
6184                 }
6185                 
6186                 //
6187                 // Methods that you have to override.  Note that you only need 
6188                 // to "implement" the variants that take the argument (those are
6189                 // the "abstract" methods, the others (GetAddMethod()) are 
6190                 // regular.
6191                 //
6192                 public override MethodInfo GetAddMethod (bool nonPublic)
6193                 {
6194                         return add;
6195                 }
6196                 
6197                 public override MethodInfo GetRemoveMethod (bool nonPublic)
6198                 {
6199                         return remove;
6200                 }
6201                 
6202                 public override MethodInfo GetRaiseMethod (bool nonPublic)
6203                 {
6204                         return raise;
6205                 }
6206                 
6207                 //
6208                 // These methods make "MyEventInfo" look like a Builder
6209                 //
6210                 public void SetRaiseMethod (MethodBuilder raiseMethod)
6211                 {
6212                         raise = raiseMethod;
6213                         MyBuilder.SetRaiseMethod (raiseMethod);
6214                 }
6215
6216                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6217                 {
6218                         remove = removeMethod;
6219                         MyBuilder.SetRemoveOnMethod (removeMethod);
6220                 }
6221
6222                 public void SetAddOnMethod (MethodBuilder addMethod)
6223                 {
6224                         add = addMethod;
6225                         MyBuilder.SetAddOnMethod (addMethod);
6226                 }
6227
6228                 public void SetCustomAttribute (CustomAttributeBuilder cb)
6229                 {
6230                         MyBuilder.SetCustomAttribute (cb);
6231                 }
6232                 
6233                 public override object [] GetCustomAttributes (bool inherit)
6234                 {
6235                         // FIXME : There's nothing which can be seemingly done here because
6236                         // we have no way of getting at the custom attribute objects of the
6237                         // EventBuilder !
6238                         return null;
6239                 }
6240
6241                 public override object [] GetCustomAttributes (Type t, bool inherit)
6242                 {
6243                         // FIXME : Same here !
6244                         return null;
6245                 }
6246
6247                 public override bool IsDefined (Type t, bool b)
6248                 {
6249                         return true;
6250                 }
6251
6252                 public override EventAttributes Attributes {
6253                         get {
6254                                 return attributes;
6255                         }
6256                 }
6257
6258                 public override string Name {
6259                         get {
6260                                 return name;
6261                         }
6262                 }
6263
6264                 public override Type DeclaringType {
6265                         get {
6266                                 return declaring_type;
6267                         }
6268                 }
6269
6270                 public override Type ReflectedType {
6271                         get {
6272                                 return reflected_type;
6273                         }
6274                 }
6275
6276                 public Type EventType {
6277                         get {
6278                                 return event_type;
6279                         }
6280                 }
6281                 
6282                 public void SetUsed ()
6283                 {
6284                         if (my_event != null) {
6285                                 my_event.SetAssigned ();
6286                                 my_event.SetMemberIsUsed ();
6287                         }
6288                 }
6289         }
6290         
6291         /// <summary>
6292         /// For case when event is declared like property (with add and remove accessors).
6293         /// </summary>
6294         public class EventProperty: Event {
6295
6296                 static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6297
6298                 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
6299                                       bool is_iface, MemberName name,
6300                                       Attributes attrs, Accessor add, Accessor remove)
6301                         : base (parent, type, mod_flags, is_iface, name, attrs)
6302                 {
6303                         Add = new AddDelegateMethod (this, add);
6304                         Remove = new RemoveDelegateMethod (this, remove);
6305
6306                         // For this event syntax we don't report error CS0067
6307                         // because it is hard to do it.
6308                         SetAssigned ();
6309                 }
6310
6311                 public override string[] ValidAttributeTargets {
6312                         get {
6313                                 return attribute_targets;
6314                         }
6315                 }
6316         }
6317
6318         /// <summary>
6319         /// Event is declared like field.
6320         /// </summary>
6321         public class EventField : Event {
6322
6323                 static string[] attribute_targets = new string [] { "event", "field", "method" };
6324                 static string[] attribute_targets_interface = new string[] { "event", "method" };
6325
6326                 public EventField (DeclSpace parent, Expression type, int mod_flags,
6327                                    bool is_iface, MemberName name,
6328                                    Attributes attrs)
6329                         : base (parent, type, mod_flags, is_iface, name, attrs)
6330                 {
6331                         Add = new AddDelegateMethod (this);
6332                         Remove = new RemoveDelegateMethod (this);
6333                 }
6334
6335                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6336                 {
6337                         if (a.Target == AttributeTargets.Field) {
6338                                 FieldBuilder.SetCustomAttribute (cb);
6339                                 return;
6340                         }
6341
6342                         if (a.Target == AttributeTargets.Method) {
6343                                 Add.ApplyAttributeBuilder (a, cb);
6344                                 Remove.ApplyAttributeBuilder (a, cb);
6345                                 return;
6346                         }
6347
6348                         base.ApplyAttributeBuilder (a, cb);
6349                 }
6350
6351                 public override bool Define()
6352                 {
6353                         if (!base.Define ())
6354                                 return false;
6355
6356                         if (initializer != null) {
6357                                 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
6358                                         Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
6359                                                 GetSignatureForError ());
6360                                         return false;
6361                                 }
6362                         }
6363
6364                         return true;
6365                 }
6366
6367                 public override string[] ValidAttributeTargets {
6368                         get {
6369                                 return IsInterface ? attribute_targets_interface : attribute_targets;
6370                         }
6371                 }
6372         }
6373
6374         public abstract class Event : FieldBase {
6375
6376                 protected sealed class AddDelegateMethod: DelegateMethod
6377                 {
6378
6379                         public AddDelegateMethod (Event method):
6380                                 base (method, "add_")
6381                         {
6382                         }
6383
6384                         public AddDelegateMethod (Event method, Accessor accessor):
6385                                 base (method, accessor, "add_")
6386                         {
6387                         }
6388
6389                         protected override MethodInfo DelegateMethodInfo {
6390                                 get {
6391                                         return TypeManager.delegate_combine_delegate_delegate;
6392                                 }
6393                         }
6394
6395                 }
6396
6397                 protected sealed class RemoveDelegateMethod: DelegateMethod
6398                 {
6399                         public RemoveDelegateMethod (Event method):
6400                                 base (method, "remove_")
6401                         {
6402                         }
6403
6404                         public RemoveDelegateMethod (Event method, Accessor accessor):
6405                                 base (method, accessor, "remove_")
6406                         {
6407                         }
6408
6409                         protected override MethodInfo DelegateMethodInfo {
6410                                 get {
6411                                         return TypeManager.delegate_remove_delegate_delegate;
6412                                 }
6413                         }
6414
6415                 }
6416
6417                 public abstract class DelegateMethod : AbstractPropertyEventMethod
6418                 {
6419                         protected readonly Event method;
6420                         ImplicitParameter param_attr;
6421
6422                         static string[] attribute_targets = new string [] { "method", "param", "return" };
6423
6424                         public DelegateMethod (Event method, string prefix)
6425                                 : base (method, prefix)
6426                         {
6427                                 this.method = method;
6428                         }
6429
6430                         public DelegateMethod (Event method, Accessor accessor, string prefix)
6431                                 : base (method, accessor, prefix)
6432                         {
6433                                 this.method = method;
6434                         }
6435
6436                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6437                         {
6438                                 if (a.Target == AttributeTargets.Parameter) {
6439                                         if (param_attr == null)
6440                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6441
6442                                         param_attr.ApplyAttributeBuilder (a, cb);
6443                                         return;
6444                                 }
6445
6446                                 base.ApplyAttributeBuilder (a, cb);
6447                         }
6448
6449                         public override AttributeTargets AttributeTargets {
6450                                 get {
6451                                         return AttributeTargets.Method;
6452                                 }
6453                         }
6454
6455                         public override bool IsClsComplianceRequired ()
6456                         {
6457                                 return method.IsClsComplianceRequired ();
6458                         }
6459
6460                         public MethodBuilder Define (DeclSpace parent)
6461                         {
6462                                 method_data = new MethodData (method, method.ModFlags,
6463                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6464
6465                                 if (!method_data.Define (parent))
6466                                         return null;
6467
6468                                 MethodBuilder mb = method_data.MethodBuilder;
6469                                 ParameterInfo.ApplyAttributes (mb);
6470                                 return mb;
6471                         }
6472
6473
6474                         protected override void EmitMethod (DeclSpace parent)
6475                         {
6476                                 if (block != null) {
6477                                         base.EmitMethod (parent);
6478                                         return;
6479                                 }
6480
6481                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6482                                         return;
6483
6484                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6485                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6486
6487                                 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6488                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6489                                         ig.Emit (OpCodes.Ldsfld, field_info);
6490                                         ig.Emit (OpCodes.Ldarg_0);
6491                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6492                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6493                                         ig.Emit (OpCodes.Stsfld, field_info);
6494                                 } else {
6495                                         ig.Emit (OpCodes.Ldarg_0);
6496                                         ig.Emit (OpCodes.Ldarg_0);
6497                                         ig.Emit (OpCodes.Ldfld, field_info);
6498                                         ig.Emit (OpCodes.Ldarg_1);
6499                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6500                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6501                                         ig.Emit (OpCodes.Stfld, field_info);
6502                                 }
6503                                 ig.Emit (OpCodes.Ret);
6504                         }
6505
6506                         protected abstract MethodInfo DelegateMethodInfo { get; }
6507
6508                         public override Type ReturnType {
6509                                 get {
6510                                         return TypeManager.void_type;
6511                                 }
6512                         }
6513
6514                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6515                         {
6516                                 return new EmitContext (method,
6517                                         ds, method.Parent, Location, ig, ReturnType,
6518                                         method.ModFlags, false);
6519                         }
6520
6521                         public override ObsoleteAttribute GetObsoleteAttribute ()
6522                         {
6523                                 return method.GetObsoleteAttribute ();
6524                         }
6525
6526                         public override string[] ValidAttributeTargets {
6527                                 get {
6528                                         return attribute_targets;
6529                                 }
6530                         }
6531
6532                         public override Parameters ParameterInfo {
6533                                 get {
6534                                         return method.parameters;
6535                                 }
6536                         }
6537
6538                 }
6539
6540
6541                 const int AllowedModifiers =
6542                         Modifiers.NEW |
6543                         Modifiers.PUBLIC |
6544                         Modifiers.PROTECTED |
6545                         Modifiers.INTERNAL |
6546                         Modifiers.PRIVATE |
6547                         Modifiers.STATIC |
6548                         Modifiers.VIRTUAL |
6549                         Modifiers.SEALED |
6550                         Modifiers.OVERRIDE |
6551                         Modifiers.UNSAFE |
6552                         Modifiers.ABSTRACT;
6553
6554                 const int AllowedInterfaceModifiers =
6555                         Modifiers.NEW;
6556
6557                 public DelegateMethod Add, Remove;
6558                 public MyEventBuilder     EventBuilder;
6559                 public MethodBuilder AddBuilder, RemoveBuilder;
6560                 Parameters parameters;
6561
6562                 protected Event (DeclSpace parent, Expression type, int mod_flags,
6563                               bool is_iface, MemberName name, Attributes attrs)
6564                         : base (parent, type, mod_flags,
6565                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6566                                 name, attrs)
6567                 {
6568                         IsInterface = is_iface;
6569                 }
6570
6571                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6572                 {
6573                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6574                                 a.Error_InvalidSecurityParent ();
6575                                 return;
6576                         }
6577                         
6578                         EventBuilder.SetCustomAttribute (cb);
6579                 }
6580
6581                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6582                 {
6583                         return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6584                 }
6585
6586                 public override AttributeTargets AttributeTargets {
6587                         get {
6588                                 return AttributeTargets.Event;
6589                         }
6590                 }
6591
6592                 public override bool Define ()
6593                 {
6594                         EventAttributes e_attr;
6595                         e_attr = EventAttributes.None;
6596
6597                         if (!DoDefine ())
6598                                 return false;
6599
6600                         if (!TypeManager.IsDelegateType (MemberType)) {
6601                                 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
6602                                 return false;
6603                         }
6604
6605                         parameters = new Parameters (
6606                                 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6607                                 new Type[] { MemberType } );
6608
6609                         if (!CheckBase ())
6610                                 return false;
6611
6612                         //
6613                         // Now define the accessors
6614                         //
6615
6616                         AddBuilder = Add.Define (Parent);
6617                         if (AddBuilder == null)
6618                                 return false;
6619
6620                         RemoveBuilder = Remove.Define (Parent);
6621                         if (RemoveBuilder == null)
6622                                 return false;
6623
6624                         EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
6625                         
6626                         if (Add.Block == null && Remove.Block == null && !IsInterface) {
6627                                 FieldBuilder = Parent.TypeBuilder.DefineField (
6628                                         Name, MemberType,
6629                                         FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6630                                 TypeManager.RegisterPrivateFieldOfEvent (
6631                                         (EventInfo) EventBuilder, FieldBuilder);
6632                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
6633                         }
6634                         
6635                         EventBuilder.SetAddOnMethod (AddBuilder);
6636                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6637
6638                         TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
6639                         return true;
6640                 }
6641
6642                 protected override bool CheckBase ()
6643                 {
6644                         if (!base.CheckBase ())
6645                                 return false;
6646  
6647                         if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
6648                                 if (!(conflict_symbol is EventInfo)) {
6649                                         Report.SymbolRelatedToPreviousError (conflict_symbol);
6650                                         Report.Error (72, Location, "Event `{0}' can override only event", GetSignatureForError ());
6651                                         return false;
6652                                 }
6653                         }
6654  
6655                         return true;
6656                 }
6657
6658                 public override void Emit ()
6659                 {
6660                         if (OptAttributes != null) {
6661                                 OptAttributes.Emit ();
6662                         }
6663
6664                         Add.Emit (Parent);
6665                         Remove.Emit (Parent);
6666
6667                         base.Emit ();
6668                 }
6669
6670                 public override string GetSignatureForError ()
6671                 {
6672                         return base.GetSignatureForError ();
6673                 }
6674
6675                 //
6676                 //   Represents header string for documentation comment.
6677                 //
6678                 public override string DocCommentHeader {
6679                         get { return "E:"; }
6680                 }
6681         }
6682
6683
6684         public class Indexer : PropertyBase {
6685
6686                 class GetIndexerMethod : GetMethod
6687                 {
6688                         public GetIndexerMethod (MethodCore method):
6689                                 base (method)
6690                         {
6691                         }
6692
6693                         public GetIndexerMethod (MethodCore method, Accessor accessor):
6694                                 base (method, accessor)
6695                         {
6696                         }
6697
6698                         public override Parameters ParameterInfo {
6699                                 get {
6700                                         return method.ParameterInfo;
6701                                 }
6702                         }
6703                 }
6704
6705                 class SetIndexerMethod: SetMethod
6706                 {
6707                         public SetIndexerMethod (MethodCore method):
6708                                 base (method)
6709                         {
6710                         }
6711
6712                         public SetIndexerMethod (MethodCore method, Accessor accessor):
6713                                 base (method, accessor)
6714                         {
6715                         }
6716
6717                         protected override void DefineParameters ()
6718                         {
6719                                 parameters = Parameters.MergeGenerated (method.Parameters,
6720                                         new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
6721                         }
6722                 }
6723
6724                 const int AllowedModifiers =
6725                         Modifiers.NEW |
6726                         Modifiers.PUBLIC |
6727                         Modifiers.PROTECTED |
6728                         Modifiers.INTERNAL |
6729                         Modifiers.PRIVATE |
6730                         Modifiers.VIRTUAL |
6731                         Modifiers.SEALED |
6732                         Modifiers.OVERRIDE |
6733                         Modifiers.UNSAFE |
6734                         Modifiers.EXTERN |
6735                         Modifiers.ABSTRACT;
6736
6737                 const int AllowedInterfaceModifiers =
6738                         Modifiers.NEW;
6739
6740
6741                 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
6742                                 bool is_iface, Parameters parameters, Attributes attrs,
6743                                 Accessor get_block, Accessor set_block)
6744                         : base (parent, type, mod,
6745                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6746                                 is_iface, name, parameters, attrs)
6747                 {
6748                         if (get_block == null)
6749                                 Get = new GetIndexerMethod (this);
6750                         else
6751                                 Get = new GetIndexerMethod (this, get_block);
6752
6753                         if (set_block == null)
6754                                 Set = new SetIndexerMethod (this);
6755                         else
6756                                 Set = new SetIndexerMethod (this, set_block);
6757                 }
6758                        
6759                 public override bool Define ()
6760                 {
6761                         if (!base.Define ())
6762                                 return false;
6763
6764                         if (MemberType == TypeManager.void_type) {
6765                                 Report.Error (620, Location, "Indexers cannot have void type");
6766                                 return false;
6767                         }
6768
6769                         if (OptAttributes != null) {
6770                                 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
6771                                 if (indexer_attr != null) {
6772                                         // Remove the attribute from the list because it is not emitted
6773                                         OptAttributes.Attrs.Remove (indexer_attr);
6774
6775                                         ShortName = indexer_attr.GetIndexerAttributeValue ();
6776
6777                                         if (IsExplicitImpl) {
6778                                                 Report.Error (415, indexer_attr.Location,
6779                                                               "The `IndexerName' attribute is valid only on an " +
6780                                                               "indexer that is not an explicit interface member declaration");
6781                                                 return false;
6782                                         }
6783
6784                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6785                                                 Report.Error (609, indexer_attr.Location,
6786                                                               "Cannot set the `IndexerName' attribute on an indexer marked override");
6787                                                 return false;
6788                                         }
6789
6790                                         if (!Tokenizer.IsValidIdentifier (ShortName)) {
6791                                                 Report.Error (633, indexer_attr.Location,
6792                                                               "The argument to the `IndexerName' attribute must be a valid identifier");
6793                                                 return false;
6794                                         }
6795                                 }
6796                         }
6797
6798                         if (InterfaceType != null) {
6799                                 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6800                                 if (base_IndexerName != Name)
6801                                         ShortName = base_IndexerName;
6802                         }
6803
6804                         if (!ParentContainer.AddToMemberContainer (this) ||
6805                                 !ParentContainer.AddToMemberContainer (Get) || !ParentContainer.AddToMemberContainer (Set))
6806                                 return false;
6807
6808                         if (!CheckBase ())
6809                                 return false;
6810
6811                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6812                         if (!Get.IsDummy){
6813                                 GetBuilder = Get.Define (Parent);
6814                                 if (GetBuilder == null)
6815                                         return false;
6816                         }
6817                         
6818                         SetBuilder = Set.Define (Parent);
6819                         if (!Set.IsDummy){
6820                                 if (SetBuilder == null)
6821                                         return false;
6822                         }
6823
6824                         //
6825                         // Now name the parameters
6826                         //
6827                         Parameter [] p = Parameters.FixedParameters;
6828                         if (p != null) {
6829                                 // TODO: should be done in parser and it needs to do cycle
6830                                 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
6831                                         Report.Error (631, Location, "ref and out are not valid in this context");
6832                                         return false;
6833                                 }
6834                         }
6835
6836                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6837                                 Name, PropertyAttributes.None, MemberType, ParameterTypes);
6838                         
6839                         if (!Get.IsDummy)
6840                                 PropertyBuilder.SetGetMethod (GetBuilder);
6841
6842                         if (!Set.IsDummy)
6843                                 PropertyBuilder.SetSetMethod (SetBuilder);
6844                                 
6845                         TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
6846
6847                         return true;
6848                 }
6849
6850                 public override string GetSignatureForError ()
6851                 {
6852                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
6853                         if (MemberName.Left != null) {
6854                                 sb.Append ('.');
6855                                 sb.Append (MemberName.Left);
6856                         }
6857
6858                         sb.Append (".this");
6859                         sb.Append (Parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
6860                         return sb.ToString ();
6861                 }
6862
6863                 public override bool MarkForDuplicationCheck ()
6864                 {
6865                         caching_flags |= Flags.TestMethodDuplication;
6866                         return true;
6867                 }
6868         }
6869
6870         public class Operator : MethodCore, IIteratorContainer {
6871
6872                 const int AllowedModifiers =
6873                         Modifiers.PUBLIC |
6874                         Modifiers.UNSAFE |
6875                         Modifiers.EXTERN |
6876                         Modifiers.STATIC;
6877
6878                 public enum OpType : byte {
6879
6880                         // Unary operators
6881                         LogicalNot,
6882                         OnesComplement,
6883                         Increment,
6884                         Decrement,
6885                         True,
6886                         False,
6887
6888                         // Unary and Binary operators
6889                         Addition,
6890                         Subtraction,
6891
6892                         UnaryPlus,
6893                         UnaryNegation,
6894                         
6895                         // Binary operators
6896                         Multiply,
6897                         Division,
6898                         Modulus,
6899                         BitwiseAnd,
6900                         BitwiseOr,
6901                         ExclusiveOr,
6902                         LeftShift,
6903                         RightShift,
6904                         Equality,
6905                         Inequality,
6906                         GreaterThan,
6907                         LessThan,
6908                         GreaterThanOrEqual,
6909                         LessThanOrEqual,
6910
6911                         // Implicit and Explicit
6912                         Implicit,
6913                         Explicit,
6914
6915                         // Just because of enum
6916                         TOP
6917                 };
6918
6919                 public readonly OpType OperatorType;
6920                 public MethodBuilder   OperatorMethodBuilder;
6921                 
6922                 public Method OperatorMethod;
6923
6924                 static string[] attribute_targets = new string [] { "method", "return" };
6925
6926                 public Operator (DeclSpace parent, OpType type, Expression ret_type,
6927                                  int mod_flags, Parameters parameters,
6928                                  ToplevelBlock block, Attributes attrs, Location loc)
6929                         : base (parent, ret_type, mod_flags, AllowedModifiers, false,
6930                                 new MemberName ("op_" + type, loc), attrs, parameters)
6931                 {
6932                         OperatorType = type;
6933                         Block = block;
6934                 }
6935
6936                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
6937                 {
6938                         OperatorMethod.ApplyAttributeBuilder (a, cb);
6939                 }
6940
6941                 public override AttributeTargets AttributeTargets {
6942                         get {
6943                                 return AttributeTargets.Method; 
6944                         }
6945                 }
6946                 
6947                 protected override bool CheckForDuplications ()
6948                 {
6949                         ArrayList ar = ParentContainer.Operators;
6950                         if (ar != null) {
6951                                 int arLen = ar.Count;
6952                                         
6953                                 for (int i = 0; i < arLen; i++) {
6954                                         Operator o = (Operator) ar [i];
6955                                         if (IsDuplicateImplementation (o))
6956                                                 return false;
6957                                 }
6958                         }
6959
6960                         ar = ParentContainer.Methods;
6961                         if (ar != null) {
6962                                 int arLen = ar.Count;
6963                                         
6964                                 for (int i = 0; i < arLen; i++) {
6965                                         Method m = (Method) ar [i];
6966                                         if (IsDuplicateImplementation (m))
6967                                                 return false;
6968                                 }
6969                         }
6970
6971                         return true;
6972                 }
6973
6974                 public override bool Define ()
6975                 {
6976                         const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
6977                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6978                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
6979                                 return false;
6980                         }
6981
6982                         if (!DoDefine ())
6983                                 return false;
6984
6985                         if (MemberType == TypeManager.void_type) {
6986                                 Report.Error (590, Location, "User-defined operators cannot return void");
6987                                 return false;
6988                         }
6989
6990                         OperatorMethod = new Method (
6991                                 Parent, Type, ModFlags, false, MemberName,
6992                                 Parameters, OptAttributes);
6993
6994                         OperatorMethod.Block = Block;
6995                         OperatorMethod.IsOperator = this;                       
6996                         OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
6997                         OperatorMethod.Define ();
6998
6999                         if (OperatorMethod.MethodBuilder == null)
7000                                 return false;
7001
7002                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7003
7004                         Type[] parameter_types = OperatorMethod.ParameterTypes;
7005                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
7006                         Type return_type = OperatorMethod.ReturnType;
7007                         Type first_arg_type = parameter_types [0];
7008
7009                         if (!CheckBase ())
7010                                 return false;
7011
7012                         // Rules for conversion operators
7013                         
7014                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7015                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
7016                                         Report.Error (555, Location,
7017                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7018                                         return false;
7019                                 }
7020                                 
7021                                 if (first_arg_type != declaring_type && return_type != declaring_type){
7022                                         Report.Error (
7023                                                 556, Location, 
7024                                                 "User-defined conversion must convert to or from the " +
7025                                                 "enclosing type");
7026                                         return false;
7027                                 }
7028
7029                                 if (first_arg_type.IsInterface || return_type.IsInterface){
7030                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7031                                                 GetSignatureForError ());
7032                                         return false;
7033                                 }
7034                                 
7035                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
7036                                         if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
7037                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7038                                                         GetSignatureForError ());
7039                                                 return false;
7040                                         }
7041                                         Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7042                                                 GetSignatureForError ());
7043                                         return false;
7044                                 }
7045                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7046                                 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7047                                         Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
7048                                         return false;
7049                                 }
7050                         } else if (Parameters.Count == 1) {
7051                                 // Checks for Unary operators
7052
7053                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7054                                         if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7055                                                 Report.Error (448, Location,
7056                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7057                                                 return false;
7058                                         }
7059                                         if (first_arg_type != declaring_type) {
7060                                                 Report.Error (
7061                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
7062                                                 return false;
7063                                         }
7064                                 }
7065                                 
7066                                 if (first_arg_type != declaring_type){
7067                                         Report.Error (
7068                                                 562, Location,
7069                                                 "The parameter of a unary operator must be the " +
7070                                                 "containing type");
7071                                         return false;
7072                                 }
7073                                 
7074                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7075                                         if (return_type != TypeManager.bool_type){
7076                                                 Report.Error (
7077                                                         215, Location,
7078                                                         "The return type of operator True or False " +
7079                                                         "must be bool");
7080                                                 return false;
7081                                         }
7082                                 }
7083                                 
7084                         } else {
7085                                 // Checks for Binary operators
7086                                 
7087                                 if (first_arg_type != declaring_type &&
7088                                     parameter_types [1] != declaring_type){
7089                                         Report.Error (
7090                                                 563, Location,
7091                                                 "One of the parameters of a binary operator must " +
7092                                                 "be the containing type");
7093                                         return false;
7094                                 }
7095                         }
7096
7097                         return true;
7098                 }
7099                 
7100                 public override void Emit ()
7101                 {
7102                         //
7103                         // abstract or extern methods have no bodies
7104                         //
7105                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7106                                 return;
7107                         
7108                         OperatorMethod.Emit ();
7109                         Block = null;
7110                 }
7111
7112                 // Operator cannot be override
7113                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7114                 {
7115                         return null;
7116                 }
7117
7118                 public static string GetName (OpType ot)
7119                 {
7120                         switch (ot){
7121                         case OpType.LogicalNot:
7122                                 return "!";
7123                         case OpType.OnesComplement:
7124                                 return "~";
7125                         case OpType.Increment:
7126                                 return "++";
7127                         case OpType.Decrement:
7128                                 return "--";
7129                         case OpType.True:
7130                                 return "true";
7131                         case OpType.False:
7132                                 return "false";
7133                         case OpType.Addition:
7134                                 return "+";
7135                         case OpType.Subtraction:
7136                                 return "-";
7137                         case OpType.UnaryPlus:
7138                                 return "+";
7139                         case OpType.UnaryNegation:
7140                                 return "-";
7141                         case OpType.Multiply:
7142                                 return "*";
7143                         case OpType.Division:
7144                                 return "/";
7145                         case OpType.Modulus:
7146                                 return "%";
7147                         case OpType.BitwiseAnd:
7148                                 return "&";
7149                         case OpType.BitwiseOr:
7150                                 return "|";
7151                         case OpType.ExclusiveOr:
7152                                 return "^";
7153                         case OpType.LeftShift:
7154                                 return "<<";
7155                         case OpType.RightShift:
7156                                 return ">>";
7157                         case OpType.Equality:
7158                                 return "==";
7159                         case OpType.Inequality:
7160                                 return "!=";
7161                         case OpType.GreaterThan:
7162                                 return ">";
7163                         case OpType.LessThan:
7164                                 return "<";
7165                         case OpType.GreaterThanOrEqual:
7166                                 return ">=";
7167                         case OpType.LessThanOrEqual:
7168                                 return "<=";
7169                         case OpType.Implicit:
7170                                 return "implicit";
7171                         case OpType.Explicit:
7172                                 return "explicit";
7173                         default: return "";
7174                         }
7175                 }
7176
7177                 public static OpType GetOperatorType (string name)
7178                 {
7179                         if (name.StartsWith ("op_")){
7180                                 for (int i = 0; i < Unary.oper_names.Length; ++i) {
7181                                         if (Unary.oper_names [i] == name)
7182                                                 return (OpType)i;
7183                                 }
7184
7185                                 for (int i = 0; i < Binary.oper_names.Length; ++i) {
7186                                         if (Binary.oper_names [i] == name)
7187                                                 return (OpType)i;
7188                                 }
7189                         }
7190                         return OpType.TOP;
7191                 }
7192
7193                 public override string GetSignatureForError ()
7194                 {
7195                         StringBuilder sb = new StringBuilder ();
7196                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7197                                 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
7198                         }
7199                         else {
7200                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7201                         }
7202
7203                         sb.Append (Parameters.GetSignatureForError ());
7204                         return sb.ToString ();
7205                 }
7206
7207                 public override bool MarkForDuplicationCheck ()
7208                 {
7209                         caching_flags |= Flags.TestMethodDuplication;
7210                         return true;
7211                 }
7212
7213                 public override string[] ValidAttributeTargets {
7214                         get {
7215                                 return attribute_targets;
7216                         }
7217                 }
7218         }
7219
7220         //
7221         // This is used to compare method signatures
7222         //
7223         struct MethodSignature {
7224                 public string Name;
7225                 public Type RetType;
7226                 public Type [] Parameters;
7227                 
7228                 /// <summary>
7229                 ///    This delegate is used to extract methods which have the
7230                 ///    same signature as the argument
7231                 /// </summary>
7232                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7233                 
7234                 public MethodSignature (string name, Type ret_type, Type [] parameters)
7235                 {
7236                         Name = name;
7237                         RetType = ret_type;
7238
7239                         if (parameters == null)
7240                                 Parameters = Type.EmptyTypes;
7241                         else
7242                                 Parameters = parameters;
7243                 }
7244
7245                 public override string ToString ()
7246                 {
7247                         string pars = "";
7248                         if (Parameters.Length != 0){
7249                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7250                                 for (int i = 0; i < Parameters.Length; i++){
7251                                         sb.Append (Parameters [i]);
7252                                         if (i+1 < Parameters.Length)
7253                                                 sb.Append (", ");
7254                                 }
7255                                 pars = sb.ToString ();
7256                         }
7257
7258                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7259                 }
7260                 
7261                 public override int GetHashCode ()
7262                 {
7263                         return Name.GetHashCode ();
7264                 }
7265
7266                 public override bool Equals (Object o)
7267                 {
7268                         MethodSignature other = (MethodSignature) o;
7269
7270                         if (other.Name != Name)
7271                                 return false;
7272
7273                         if (other.RetType != RetType)
7274                                 return false;
7275                         
7276                         if (Parameters == null){
7277                                 if (other.Parameters == null)
7278                                         return true;
7279                                 return false;
7280                         }
7281
7282                         if (other.Parameters == null)
7283                                 return false;
7284                         
7285                         int c = Parameters.Length;
7286                         if (other.Parameters.Length != c)
7287                                 return false;
7288
7289                         for (int i = 0; i < c; i++)
7290                                 if (other.Parameters [i] != Parameters [i])
7291                                         return false;
7292
7293                         return true;
7294                 }
7295
7296                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7297                 {
7298                         MethodSignature sig = (MethodSignature) filter_criteria;
7299
7300                         if (m.Name != sig.Name)
7301                                 return false;
7302
7303                         Type ReturnType;
7304                         MethodInfo mi = m as MethodInfo;
7305                         PropertyInfo pi = m as PropertyInfo;
7306
7307                         if (mi != null)
7308                                 ReturnType = mi.ReturnType;
7309                         else if (pi != null)
7310                                 ReturnType = pi.PropertyType;
7311                         else
7312                                 return false;
7313                         
7314                         //
7315                         // we use sig.RetType == null to mean `do not check the
7316                         // method return value.  
7317                         //
7318                         if (sig.RetType != null)
7319                                 if (ReturnType != sig.RetType)
7320                                         return false;
7321
7322                         Type [] args;
7323                         if (mi != null)
7324                                 args = TypeManager.GetParameterData (mi).Types;
7325                         else
7326                                 args = TypeManager.GetArgumentTypes (pi);
7327                         Type [] sigp = sig.Parameters;
7328
7329                         if (args.Length != sigp.Length)
7330                                 return false;
7331
7332                         for (int i = args.Length; i > 0; ){
7333                                 i--;
7334                                 if (args [i] != sigp [i])
7335                                         return false;
7336                         }
7337                         return true;
7338                 }
7339         }
7340 }