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