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