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