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