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