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