326e22f66ea1dab420dea22c394e2b5badbe8f94
[mono.git] / mcs / gmcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12
13 //
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change 
15 // the behavior of the compilation.  This can be removed if we rework
16 // the code to get a list of namespaces available.
17 //
18 #define SIMPLE_SPEEDUP
19
20 using System;
21 using System.IO;
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Text;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
30
31 namespace Mono.CSharp {
32
33 public class TypeManager {
34         //
35         // A list of core types that the compiler requires or uses
36         //
37         static public Type object_type;
38         static public Type value_type;
39         static public Type string_type;
40         static public Type int32_type;
41         static public Type uint32_type;
42         static public Type int64_type;
43         static public Type uint64_type;
44         static public Type float_type;
45         static public Type double_type;
46         static public Type char_type;
47         static public Type char_ptr_type;
48         static public Type short_type;
49         static public Type decimal_type;
50         static public Type bool_type;
51         static public Type sbyte_type;
52         static public Type byte_type;
53         static public Type ushort_type;
54         static public Type enum_type;
55         static public Type delegate_type;
56         static public Type multicast_delegate_type;
57         static public Type void_type;
58         static public Type enumeration_type;
59         static public Type array_type;
60         static public Type runtime_handle_type;
61         static public Type icloneable_type;
62         static public Type type_type;
63         static public Type ienumerator_type;
64         static public Type ienumerable_type;
65         static public Type idisposable_type;
66         static public Type default_member_type;
67         static public Type iasyncresult_type;
68         static public Type asynccallback_type;
69         static public Type intptr_type;
70         static public Type monitor_type;
71         static public Type runtime_field_handle_type;
72         static public Type attribute_type;
73         static public Type attribute_usage_type;
74         static public Type dllimport_type;
75         static public Type unverifiable_code_type;
76         static public Type methodimpl_attr_type;
77         static public Type marshal_as_attr_type;
78         static public Type param_array_type;
79         static public Type guid_attr_type;
80         static public Type void_ptr_type;
81         static public Type indexer_name_type;
82         static public Type exception_type;
83         static public Type invalid_operation_exception_type;
84         static public object obsolete_attribute_type;
85         static public object conditional_attribute_type;
86         static public Type in_attribute_type;
87
88         //
89         // An empty array of types
90         //
91         static public Type [] NoTypes;
92
93
94         // 
95         // Expressions representing the internal types.  Used during declaration
96         // definition.
97         //
98         static public Expression system_object_expr, system_string_expr; 
99         static public Expression system_boolean_expr, system_decimal_expr;
100         static public Expression system_single_expr, system_double_expr;
101         static public Expression system_sbyte_expr, system_byte_expr;
102         static public Expression system_int16_expr, system_uint16_expr;
103         static public Expression system_int32_expr, system_uint32_expr;
104         static public Expression system_int64_expr, system_uint64_expr;
105         static public Expression system_char_expr, system_void_expr;
106         static public Expression system_asynccallback_expr;
107         static public Expression system_iasyncresult_expr;
108
109         //
110         // This is only used when compiling corlib
111         //
112         static public Type system_int32_type;
113         static public Type system_array_type;
114         static public Type system_type_type;
115         static public Type system_assemblybuilder_type;
116         static public MethodInfo system_int_array_get_length;
117         static public MethodInfo system_int_array_get_rank;
118         static public MethodInfo system_object_array_clone;
119         static public MethodInfo system_int_array_get_length_int;
120         static public MethodInfo system_int_array_get_lower_bound_int;
121         static public MethodInfo system_int_array_get_upper_bound_int;
122         static public MethodInfo system_void_array_copyto_array_int;
123
124         
125         //
126         // Internal, not really used outside
127         //
128         static Type runtime_helpers_type;
129         
130         //
131         // These methods are called by code generated by the compiler
132         //
133         static public MethodInfo string_concat_string_string;
134         static public MethodInfo string_concat_string_string_string;
135         static public MethodInfo string_concat_string_string_string_string;
136         static public MethodInfo string_concat_object_object;
137         static public MethodInfo string_isinterneted_string;
138         static public MethodInfo system_type_get_type_from_handle;
139         static public MethodInfo object_getcurrent_void;
140         static public MethodInfo bool_movenext_void;
141         static public MethodInfo ienumerable_getenumerator_void;
142         static public MethodInfo void_reset_void;
143         static public MethodInfo void_dispose_void;
144         static public MethodInfo void_monitor_enter_object;
145         static public MethodInfo void_monitor_exit_object;
146         static public MethodInfo void_initializearray_array_fieldhandle;
147         static public MethodInfo int_getlength_int;
148         static public MethodInfo delegate_combine_delegate_delegate;
149         static public MethodInfo delegate_remove_delegate_delegate;
150         static public MethodInfo int_get_offset_to_string_data;
151         static public MethodInfo int_array_get_length;
152         static public MethodInfo int_array_get_rank;
153         static public MethodInfo object_array_clone;
154         static public MethodInfo int_array_get_length_int;
155         static public MethodInfo int_array_get_lower_bound_int;
156         static public MethodInfo int_array_get_upper_bound_int;
157         static public MethodInfo void_array_copyto_array_int;
158         
159         //
160         // The attribute constructors.
161         //
162         static public ConstructorInfo object_ctor;
163         static public ConstructorInfo cons_param_array_attribute;
164         static public ConstructorInfo void_decimal_ctor_five_args;
165         static public ConstructorInfo unverifiable_code_ctor;
166         static public ConstructorInfo invalid_operation_ctor;
167         
168         // <remarks>
169         //   Holds the Array of Assemblies that have been loaded
170         //   (either because it is the default or the user used the
171         //   -r command line option)
172         // </remarks>
173         static Assembly [] assemblies;
174
175         // <remarks>
176         //  Keeps a list of module builders. We used this to do lookups
177         //  on the modulebuilder using GetType -- needed for arrays
178         // </remarks>
179         static ModuleBuilder [] modules;
180
181         // <remarks>
182         //   This is the type_cache from the assemblies to avoid
183         //   hitting System.Reflection on every lookup.
184         // </summary>
185         static Hashtable types;
186
187         // <remarks>
188         //  This is used to hotld the corresponding TypeContainer objects
189         //  since we need this in FindMembers
190         // </remarks>
191         static Hashtable typecontainers;
192
193         // <remarks>
194         //   Keeps track of those types that are defined by the
195         //   user's program
196         // </remarks>
197         static ArrayList user_types;
198
199         static PtrHashtable builder_to_declspace;
200
201         // <remarks>
202         //   Tracks the interfaces implemented by typebuilders.  We only
203         //   enter those who do implement or or more interfaces
204         // </remarks>
205         static PtrHashtable builder_to_ifaces;
206
207         // <remarks>
208         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
209         //   the arguments to the method
210         // </remarks>
211         static Hashtable method_arguments;
212
213         // <remarks>
214         //   Maps PropertyBuilder to a Type array that contains
215         //   the arguments to the indexer
216         // </remarks>
217         static Hashtable indexer_arguments;
218
219         // <remarks>
220         //   Maybe `method_arguments' should be replaced and only
221         //   method_internal_params should be kept?
222         // <remarks>
223         static Hashtable method_internal_params;
224
225         // <remarks>
226         //  Keeps track of attribute types
227         // </remarks>
228
229         static Hashtable builder_to_attr;
230
231         // <remarks>
232         //  Keeps track of methods
233         // </remarks>
234
235         static Hashtable builder_to_method;
236
237         struct Signature {
238                 public string name;
239                 public Type [] args;
240         }
241
242         /// <summary>
243         ///   A filter for Findmembers that uses the Signature object to
244         ///   extract objects
245         /// </summary>
246         static bool SignatureFilter (MemberInfo mi, object criteria)
247         {
248                 Signature sig = (Signature) criteria;
249
250                 if (!(mi is MethodBase))
251                         return false;
252                 
253                 if (mi.Name != sig.name)
254                         return false;
255
256                 int count = sig.args.Length;
257                 
258                 if (mi is MethodBuilder || mi is ConstructorBuilder){
259                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
260
261                         if (candidate_args.Length != count)
262                                 return false;
263                         
264                         for (int i = 0; i < count; i++)
265                                 if (candidate_args [i] != sig.args [i])
266                                         return false;
267                         
268                         return true;
269                 } else {
270                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
271
272                         if (pars.Length != count)
273                                 return false;
274
275                         for (int i = 0; i < count; i++)
276                                 if (pars [i].ParameterType != sig.args [i])
277                                         return false;
278                         return true;
279                 }
280         }
281
282         // A delegate that points to the filter above.
283         static MemberFilter signature_filter;
284
285         //
286         // These are expressions that represent some of the internal data types, used
287         // elsewhere
288         //
289         static void InitExpressionTypes ()
290         {
291                 system_object_expr  = new TypeLookupExpression ("System.Object");
292                 system_string_expr  = new TypeLookupExpression ("System.String");
293                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
294                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
295                 system_single_expr  = new TypeLookupExpression ("System.Single");
296                 system_double_expr  = new TypeLookupExpression ("System.Double");
297                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
298                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
299                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
300                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
301                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
302                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
303                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
304                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
305                 system_char_expr    = new TypeLookupExpression ("System.Char");
306                 system_void_expr    = new TypeLookupExpression ("System.Void");
307                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
308                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
309         }
310         
311         static TypeManager ()
312         {
313                 assemblies = new Assembly [0];
314                 modules = null;
315                 user_types = new ArrayList ();
316                 
317                 types = new Hashtable ();
318                 typecontainers = new Hashtable ();
319                 
320                 builder_to_declspace = new PtrHashtable ();
321                 builder_to_attr = new PtrHashtable ();
322                 builder_to_method = new PtrHashtable ();
323                 method_arguments = new PtrHashtable ();
324                 method_internal_params = new PtrHashtable ();
325                 indexer_arguments = new PtrHashtable ();
326                 builder_to_ifaces = new PtrHashtable ();
327                 
328                 NoTypes = new Type [0];
329
330                 signature_filter = new MemberFilter (SignatureFilter);
331                 InitExpressionTypes ();
332         }
333
334         public static void HandleDuplicate (string name, Type t)
335         {
336                 Type prev = (Type) types [name];
337                 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
338                 
339                 if (tc != null){
340                         //
341                         // This probably never happens, as we catch this before
342                         //
343                         Report.Error (-17, "The type `" + name + "' has already been defined.");
344                         return;
345                 }
346                 
347                 Location l;
348                 tc = builder_to_declspace [t] as TypeContainer;
349                 if (tc != null){
350                         Report.Warning (
351                                         1595, "The type `" + name + "' is defined in an existing assembly;"+
352                                         " Using the new definition from: " + tc.Location);
353                 } else {
354                         Report.Warning (
355                                         1595, "The type `" + name + "' is defined in an existing assembly;");
356                 }
357                 
358                 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
359                 
360                 types.Remove (name);
361                 types.Add (name, t);
362         }
363         
364         public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
365         {
366                 try {
367                         types.Add (name, t);
368                 } catch {
369                         HandleDuplicate (name, t); 
370                 }
371                 user_types.Add (t);
372                         
373                 if (ifaces != null)
374                         builder_to_ifaces [t] = ifaces;
375         }
376
377         //
378         // This entry point is used by types that we define under the covers
379         // 
380         public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
381         {
382                 if (ifaces != null)
383                         builder_to_ifaces [tb] = ifaces;
384         }
385         
386         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
387         {
388                 builder_to_declspace.Add (t, tc);
389                 typecontainers.Add (name, tc);
390                 AddUserType (name, t, ifaces);
391         }
392
393         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
394         {
395                 try {
396                         types.Add (name, t);
397                 } catch {
398                         HandleDuplicate (name, t);
399                 }
400                 
401                 builder_to_declspace.Add (t, del);
402         }
403         
404         public static void AddEnumType (string name, TypeBuilder t, Enum en)
405         {
406                 try {
407                         types.Add (name, t);
408                 } catch {
409                         HandleDuplicate (name, t);
410                 }
411                 builder_to_declspace.Add (t, en);
412         }
413
414         public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
415         {
416                 AddUserType (name, t, ifaces);
417                 builder_to_declspace.Add (t, i);
418         }
419
420         public static void AddMethod (MethodBuilder builder, MethodData method)
421         {
422                 builder_to_method.Add (builder, method);
423         }
424
425         public static void RegisterAttrType (Type t, TypeContainer tc)
426         {
427                 builder_to_attr.Add (t, tc);
428         }
429
430         /// <summary>
431         ///   Returns the DeclSpace whose Type is `t' or null if there is no
432         ///   DeclSpace for `t' (ie, the Type comes from a library)
433         /// </summary>
434         public static DeclSpace LookupDeclSpace (Type t)
435         {
436                 return builder_to_declspace [t] as DeclSpace;
437         }
438
439         /// <summary>
440         ///   Returns the TypeContainer whose Type is `t' or null if there is no
441         ///   TypeContainer for `t' (ie, the Type comes from a library)
442         /// </summary>
443         public static TypeContainer LookupTypeContainer (Type t)
444         {
445                 return builder_to_declspace [t] as TypeContainer;
446         }
447         
448         public static IMemberContainer LookupMemberContainer (Type t)
449         {
450                 if (t is TypeBuilder) {
451                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
452                         if (container != null)
453                                 return container;
454                 }
455
456                 return TypeHandle.GetTypeHandle (t);
457         }
458
459         public static Interface LookupInterface (Type t)
460         {
461                 return builder_to_declspace [t] as Interface;
462         }
463
464         public static Delegate LookupDelegate (Type t)
465         {
466                 return builder_to_declspace [t] as Delegate;
467         }
468
469         public static Enum LookupEnum (Type t)
470         {
471                 return builder_to_declspace [t] as Enum;
472         }
473         
474         public static TypeContainer LookupAttr (Type t)
475         {
476                 return (TypeContainer) builder_to_attr [t];
477         }
478         
479         /// <summary>
480         ///   Registers an assembly to load types from.
481         /// </summary>
482         public static void AddAssembly (Assembly a)
483         {
484                 int top = assemblies.Length;
485                 Assembly [] n = new Assembly [top + 1];
486
487                 assemblies.CopyTo (n, 0);
488                 
489                 n [top] = a;
490                 assemblies = n;
491         }
492
493         /// <summary>
494         ///  Registers a module builder to lookup types from
495         /// </summary>
496         public static void AddModule (ModuleBuilder mb)
497         {
498                 int top = modules != null ? modules.Length : 0;
499                 ModuleBuilder [] n = new ModuleBuilder [top + 1];
500
501                 if (modules != null)
502                         modules.CopyTo (n, 0);
503                 n [top] = mb;
504                 modules = n;
505         }
506
507         static Hashtable references = new Hashtable ();
508         
509         //
510         // Gets the reference to T version of the Type (T&)
511         //
512         public static Type GetReferenceType (Type t)
513         {
514                 string tname = t.FullName + "&";
515                 
516                 Type ret = t.Assembly.GetType (tname);
517
518                 //
519                 // If the type comes from the assembly we are building
520                 // We need the Hashtable, because .NET 1.1 will return different instance types
521                 // every time we call ModuleBuilder.GetType.
522                 //
523                 if (ret == null){
524                         if (references [t] == null)
525                                 references [t] = CodeGen.ModuleBuilder.GetType (tname);
526                         ret = (Type) references [t];
527                 }
528
529                 return ret;
530         }
531
532         static Hashtable pointers = new Hashtable ();
533
534         //
535         // Gets the pointer to T version of the Type  (T*)
536         //
537         public static Type GetPointerType (Type t)
538         {
539                 string tname = t.FullName + "*";
540                 
541                 Type ret = t.Assembly.GetType (tname);
542                 
543                 //
544                 // If the type comes from the assembly we are building
545                 // We need the Hashtable, because .NET 1.1 will return different instance types
546                 // every time we call ModuleBuilder.GetType.
547                 //
548                 if (ret == null){
549                         if (pointers [t] == null)
550                                 pointers [t] = CodeGen.ModuleBuilder.GetType (tname);
551                         
552                         ret = (Type) pointers [t];
553                 }
554
555                 return ret;
556         }
557         
558         //
559         // Low-level lookup, cache-less
560         //
561         static Type LookupTypeReflection (string name)
562         {
563                 Type t;
564
565                 foreach (Assembly a in assemblies){
566                         t = a.GetType (name);
567                         if (t == null)
568                                 continue;
569
570                         TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
571                         if (ta == TypeAttributes.NotPublic ||
572                             ta == TypeAttributes.NestedPrivate ||
573                             ta == TypeAttributes.NestedAssembly ||
574                             ta == TypeAttributes.NestedFamANDAssem)
575                                 continue;
576                         return t;
577                 }
578
579                 foreach (ModuleBuilder mb in modules) {
580                         t = mb.GetType (name);
581                         if (t != null) 
582                                 return t;
583                 }
584                         
585                 return null;
586         }
587
588         static Hashtable negative_hits = new Hashtable ();
589         
590         //
591         // This function is used when you want to avoid the lookups, and want to go
592         // directly to the source.  This will use the cache.
593         //
594         // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
595         // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
596         // way to test things other than doing a fullname compare
597         //
598         public static Type LookupTypeDirect (string name)
599         {
600                 Type t = (Type) types [name];
601                 if (t != null)
602                         return t;
603
604                 t = LookupTypeReflection (name);
605                 if (t == null)
606                         return null;
607
608                 types [name] = t;
609                 return t;
610         }
611
612         /// <summary>
613         ///   Returns the Type associated with @name, takes care of the fact that
614         ///   reflection expects nested types to be separated from the main type
615         ///   with a "+" instead of a "."
616         /// </summary>
617         public static Type LookupType (string name)
618         {
619                 Type t;
620
621                 //
622                 // First lookup in user defined and cached values
623                 //
624
625                 t = (Type) types [name];
626                 if (t != null)
627                         return t;
628
629                 // Two thirds of the failures are caught here.
630                 if (negative_hits.Contains (name))
631                         return null;
632
633                 string [] elements = name.Split ('.');
634                 int count = elements.Length;
635
636                 for (int n = 1; n <= count; n++){
637                         string top_level_type = String.Join (".", elements, 0, n);
638
639                         // One third of the failures are caught here.
640                         if (negative_hits.Contains (top_level_type))
641                                 continue;
642                         
643                         t = (Type) types [top_level_type];
644                         if (t == null){
645                                 t = LookupTypeReflection (top_level_type);
646                                 if (t == null){
647                                         negative_hits [top_level_type] = true;
648                                         continue;
649                                 }
650                         }
651                         
652                         if (count == n){
653                                 types [name] = t;
654                                 return t;
655                         } 
656
657                         //
658                         // We know that System.Object does not have children, and since its the parent of 
659                         // all the objects, it always gets probbed for inner classes. 
660                         //
661                         if (top_level_type == "System.Object")
662                                 return null;
663                         
664                         string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
665                         //Console.WriteLine ("Looking up: " + newt + " " + name);
666                         t = LookupTypeReflection (newt);
667                         if (t == null)
668                                 negative_hits [name] = true;
669                         else
670                                 types [name] = t;
671                         return t;
672                 }
673                 negative_hits [name] = true;
674                 return null;
675         }
676
677         /// <summary>
678         ///   Computes the namespaces that we import from the assemblies we reference.
679         /// </summary>
680         public static void ComputeNamespaces ()
681         {
682                 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces");
683
684                 //
685                 // First add the assembly namespaces
686                 //
687                 if (assembly_get_namespaces != null){
688                         int count = assemblies.Length;
689                         int total;
690
691                         for (int i = 0; i < count; i++){
692                                 Assembly a = assemblies [i];
693                                 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
694                                 foreach (string ns in namespaces){
695                                         if (ns == "")
696                                                 continue;
697                                         Namespace.LookupNamespace (ns, true);
698                                 }
699                         }
700                 } else {
701                         foreach (Assembly a in assemblies){
702                                 foreach (Type t in a.GetTypes ()){
703                                         string ns = t.Namespace;
704
705                                         // t.Namespace returns null for <PrivateImplDetails>
706                                         if (ns == ""|| ns == null)
707                                                 continue;
708                                         Namespace.LookupNamespace (ns, true);
709                                 }
710                         }
711                 }
712         }
713
714         public static bool NamespaceClash (string name, Location loc)
715         {
716                 if (Namespace.LookupNamespace (name, false) == null)
717                         return false;
718
719                 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
720                 return true;
721         }
722
723         /// <summary>
724         ///   Returns the C# name of a type if possible, or the full type name otherwise
725         /// </summary>
726         static public string CSharpName (Type t)
727         {
728                 return Regex.Replace (t.FullName, 
729                         @"^System\." +
730                         @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
731                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
732                         @"Boolean|String|Void)" +
733                         @"(\W+|\b)", 
734                         new MatchEvaluator (CSharpNameMatch));
735         }       
736         
737         static String CSharpNameMatch (Match match) 
738         {
739                 string s = match.Groups [1].Captures [0].Value;
740                 return s.ToLower ().
741                 Replace ("int32", "int").
742                 Replace ("uint32", "uint").
743                 Replace ("int16", "short").
744                 Replace ("uint16", "ushort").
745                 Replace ("int64", "long").
746                 Replace ("uint64", "ulong").
747                 Replace ("single", "float").
748                 Replace ("boolean", "bool")
749                 + match.Groups [2].Captures [0].Value;
750         }
751
752         /// <summary>
753         ///   Returns the signature of the method
754         /// </summary>
755         static public string CSharpSignature (MethodBase mb)
756         {
757                 string sig = "(";
758
759                 //
760                 // FIXME: We should really have a single function to do
761                 // everything instead of the following 5 line pattern
762                 //
763                 ParameterData iparams = LookupParametersByBuilder (mb);
764
765                 if (iparams == null){
766                         ParameterInfo [] pi = mb.GetParameters ();
767                         iparams = new ReflectionParameters (pi);
768                 }
769                 
770                 for (int i = 0; i < iparams.Count; i++) {
771                         if (i > 0) {
772                                 sig += ", ";
773                         }
774                         sig += iparams.ParameterDesc(i);
775                 }
776                 sig += ")";
777
778                 return mb.DeclaringType.Name + "." + mb.Name + sig;
779         }
780
781         /// <summary>
782         ///   Looks up a type, and aborts if it is not found.  This is used
783         ///   by types required by the compiler
784         /// </summary>
785         static Type CoreLookupType (string name)
786         {
787                 Type t = LookupTypeDirect (name);
788
789                 if (t == null){
790                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
791                         Environment.Exit (0);
792                 }
793
794                 return t;
795         }
796
797         /// <summary>
798         ///   Returns the MethodInfo for a method named `name' defined
799         ///   in type `t' which takes arguments of types `args'
800         /// </summary>
801         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
802         {
803                 MemberList list;
804                 Signature sig;
805
806                 sig.name = name;
807                 sig.args = args;
808                 
809                 list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
810                                     signature_filter, sig);
811                 if (list.Count == 0) {
812                         if (report_errors)
813                                 Report.Error (-19, "Can not find the core function `" + name + "'");
814                         return null;
815                 }
816
817                 MethodInfo mi = list [0] as MethodInfo;
818                 if (mi == null) {
819                         if (report_errors)
820                                 Report.Error (-19, "Can not find the core function `" + name + "'");
821                         return null;
822                 }
823
824                 return mi;
825         }
826
827         static MethodInfo GetMethod (Type t, string name, Type [] args)
828         {
829                 return GetMethod (t, name, args, true);
830         }
831
832
833         /// <summary>
834         ///    Returns the ConstructorInfo for "args"
835         /// </summary>
836         static ConstructorInfo GetConstructor (Type t, Type [] args)
837         {
838                 MemberList list;
839                 Signature sig;
840
841                 sig.name = ".ctor";
842                 sig.args = args;
843                 
844                 list = FindMembers (t, MemberTypes.Constructor,
845                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
846                                     signature_filter, sig);
847                 if (list.Count == 0){
848                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
849                         return null;
850                 }
851
852                 ConstructorInfo ci = list [0] as ConstructorInfo;
853                 if (ci == null){
854                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
855                         return null;
856                 }
857
858                 return ci;
859         }
860
861         public static void InitEnumUnderlyingTypes ()
862         {
863
864                 int32_type    = CoreLookupType ("System.Int32");
865                 int64_type    = CoreLookupType ("System.Int64");
866                 uint32_type   = CoreLookupType ("System.UInt32"); 
867                 uint64_type   = CoreLookupType ("System.UInt64"); 
868                 byte_type     = CoreLookupType ("System.Byte");
869                 sbyte_type    = CoreLookupType ("System.SByte");
870                 short_type    = CoreLookupType ("System.Int16");
871                 ushort_type   = CoreLookupType ("System.UInt16");
872         }
873         
874         /// <remarks>
875         ///   The types have to be initialized after the initial
876         ///   population of the type has happened (for example, to
877         ///   bootstrap the corlib.dll
878         /// </remarks>
879         public static void InitCoreTypes ()
880         {
881                 object_type   = CoreLookupType ("System.Object");
882                 value_type    = CoreLookupType ("System.ValueType");
883
884                 InitEnumUnderlyingTypes ();
885
886                 char_type     = CoreLookupType ("System.Char");
887                 string_type   = CoreLookupType ("System.String");
888                 float_type    = CoreLookupType ("System.Single");
889                 double_type   = CoreLookupType ("System.Double");
890                 char_ptr_type = CoreLookupType ("System.Char*");
891                 decimal_type  = CoreLookupType ("System.Decimal");
892                 bool_type     = CoreLookupType ("System.Boolean");
893                 enum_type     = CoreLookupType ("System.Enum");
894
895                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
896                 delegate_type           = CoreLookupType ("System.Delegate");
897
898                 array_type    = CoreLookupType ("System.Array");
899                 void_type     = CoreLookupType ("System.Void");
900                 type_type     = CoreLookupType ("System.Type");
901
902                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
903                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
904                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
905                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
906                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
907                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
908                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
909                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
910                 idisposable_type     = CoreLookupType ("System.IDisposable");
911                 icloneable_type      = CoreLookupType ("System.ICloneable");
912                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
913                 intptr_type          = CoreLookupType ("System.IntPtr");
914
915                 attribute_type       = CoreLookupType ("System.Attribute");
916                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
917                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
918                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
919                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
920                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
921                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
922
923                 //
924                 // Sigh. Remove this before the release.  Wonder what versions of Mono
925                 // people are running.
926                 //
927                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
928
929                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
930
931                 void_ptr_type         = CoreLookupType ("System.Void*");
932
933                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
934
935                 exception_type        = CoreLookupType ("System.Exception");
936                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
937
938                 //
939                 // Attribute types
940                 //
941                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
942                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
943
944                 //
945                 // When compiling corlib, store the "real" types here.
946                 //
947                 if (!RootContext.StdLib) {
948                         system_int32_type = typeof (System.Int32);
949                         system_array_type = typeof (System.Array);
950                         system_type_type = typeof (System.Type);
951                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
952
953                         Type [] void_arg = {  };
954                         system_int_array_get_length = GetMethod (
955                                 system_array_type, "get_Length", void_arg);
956                         system_int_array_get_rank = GetMethod (
957                                 system_array_type, "get_Rank", void_arg);
958                         system_object_array_clone = GetMethod (
959                                 system_array_type, "Clone", void_arg);
960
961                         Type [] system_int_arg = { system_int32_type };
962                         system_int_array_get_length_int = GetMethod (
963                                 system_array_type, "GetLength", system_int_arg);
964                         system_int_array_get_upper_bound_int = GetMethod (
965                                 system_array_type, "GetUpperBound", system_int_arg);
966                         system_int_array_get_lower_bound_int = GetMethod (
967                                 system_array_type, "GetLowerBound", system_int_arg);
968
969                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
970                         system_void_array_copyto_array_int = GetMethod (
971                                 system_array_type, "CopyTo", system_array_int_arg);
972
973                         Type [] system_3_type_arg = {
974                                 system_type_type, system_type_type, system_type_type };
975                         Type [] system_4_type_arg = {
976                                 system_type_type, system_type_type, system_type_type, system_type_type };
977
978                         MethodInfo set_corlib_type_builders = GetMethod (
979                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
980                                 system_4_type_arg, false);
981
982                         if (set_corlib_type_builders != null) {
983                                 object[] args = new object [4];
984                                 args [0] = object_type;
985                                 args [1] = value_type;
986                                 args [2] = enum_type;
987                                 args [3] = void_type;
988                                 
989                                 set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
990                         } else {
991                                 // Compatibility for an older version of the class libs.
992                                 set_corlib_type_builders = GetMethod (
993                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
994                                         system_3_type_arg, true);
995
996                                 if (set_corlib_type_builders == null) {
997                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
998                                         return;
999                                 }
1000
1001                                 object[] args = new object [3];
1002                                 args [0] = object_type;
1003                                 args [1] = value_type;
1004                                 args [2] = enum_type;
1005                                 
1006                                 set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
1007                         }
1008                 }
1009         }
1010
1011         //
1012         // The helper methods that are used by the compiler
1013         //
1014         public static void InitCodeHelpers ()
1015         {
1016                 //
1017                 // Now load the default methods that we use.
1018                 //
1019                 Type [] string_string = { string_type, string_type };
1020                 string_concat_string_string = GetMethod (
1021                         string_type, "Concat", string_string);
1022                 Type [] string_string_string = { string_type, string_type, string_type };
1023                 string_concat_string_string_string = GetMethod (
1024                         string_type, "Concat", string_string_string);
1025                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1026                 string_concat_string_string_string_string = GetMethod (
1027                         string_type, "Concat", string_string_string_string);
1028
1029                 Type [] object_object = { object_type, object_type };
1030                 string_concat_object_object = GetMethod (
1031                         string_type, "Concat", object_object);
1032
1033                 Type [] string_ = { string_type };
1034                 string_isinterneted_string = GetMethod (
1035                         string_type, "IsInterned", string_);
1036                 
1037                 Type [] runtime_type_handle = { runtime_handle_type };
1038                 system_type_get_type_from_handle = GetMethod (
1039                         type_type, "GetTypeFromHandle", runtime_type_handle);
1040
1041                 Type [] delegate_delegate = { delegate_type, delegate_type };
1042                 delegate_combine_delegate_delegate = GetMethod (
1043                                 delegate_type, "Combine", delegate_delegate);
1044
1045                 delegate_remove_delegate_delegate = GetMethod (
1046                                 delegate_type, "Remove", delegate_delegate);
1047
1048                 //
1049                 // Void arguments
1050                 //
1051                 Type [] void_arg = {  };
1052                 object_getcurrent_void = GetMethod (
1053                         ienumerator_type, "get_Current", void_arg);
1054                 bool_movenext_void = GetMethod (
1055                         ienumerator_type, "MoveNext", void_arg);
1056                 void_reset_void = GetMethod (
1057                         ienumerator_type, "Reset", void_arg);
1058                 void_dispose_void = GetMethod (
1059                         idisposable_type, "Dispose", void_arg);
1060                 int_get_offset_to_string_data = GetMethod (
1061                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1062                 int_array_get_length = GetMethod (
1063                         array_type, "get_Length", void_arg);
1064                 int_array_get_rank = GetMethod (
1065                         array_type, "get_Rank", void_arg);
1066                 ienumerable_getenumerator_void = GetMethod (
1067                         ienumerable_type, "GetEnumerator", void_arg);
1068                 
1069                 //
1070                 // Int32 arguments
1071                 //
1072                 Type [] int_arg = { int32_type };
1073                 int_array_get_length_int = GetMethod (
1074                         array_type, "GetLength", int_arg);
1075                 int_array_get_upper_bound_int = GetMethod (
1076                         array_type, "GetUpperBound", int_arg);
1077                 int_array_get_lower_bound_int = GetMethod (
1078                         array_type, "GetLowerBound", int_arg);
1079
1080                 //
1081                 // System.Array methods
1082                 //
1083                 object_array_clone = GetMethod (
1084                         array_type, "Clone", void_arg);
1085                 Type [] array_int_arg = { array_type, int32_type };
1086                 void_array_copyto_array_int = GetMethod (
1087                         array_type, "CopyTo", array_int_arg);
1088                 
1089                 //
1090                 // object arguments
1091                 //
1092                 Type [] object_arg = { object_type };
1093                 void_monitor_enter_object = GetMethod (
1094                         monitor_type, "Enter", object_arg);
1095                 void_monitor_exit_object = GetMethod (
1096                         monitor_type, "Exit", object_arg);
1097
1098                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1099                 
1100                 void_initializearray_array_fieldhandle = GetMethod (
1101                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1102
1103                 //
1104                 // Array functions
1105                 //
1106                 int_getlength_int = GetMethod (
1107                         array_type, "GetLength", int_arg);
1108
1109                 //
1110                 // Decimal constructors
1111                 //
1112                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1113                 void_decimal_ctor_five_args = GetConstructor (
1114                         decimal_type, dec_arg);
1115                 
1116                 //
1117                 // Attributes
1118                 //
1119                 cons_param_array_attribute = GetConstructor (
1120                         param_array_type, void_arg);
1121
1122                 unverifiable_code_ctor = GetConstructor (
1123                         unverifiable_code_type, void_arg);
1124
1125                 //
1126                 // InvalidOperationException
1127                 //
1128                 invalid_operation_ctor = GetConstructor (
1129                         invalid_operation_exception_type, void_arg);
1130
1131
1132                 // Object
1133                 object_ctor = GetConstructor (object_type, void_arg);
1134
1135         }
1136
1137         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1138
1139         static Hashtable type_hash = new Hashtable ();
1140
1141         /// <remarks>
1142         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1143         ///   the cache here because there is no member name argument.
1144         /// </remarks>
1145         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1146                                               MemberFilter filter, object criteria)
1147         {
1148                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1149
1150                 //
1151                 // `builder_to_declspace' contains all dynamic types.
1152                 //
1153                 if (decl != null) {
1154                         MemberList list;
1155                         Timer.StartTimer (TimerType.FindMembers);
1156                         list = decl.FindMembers (mt, bf, filter, criteria);
1157                         Timer.StopTimer (TimerType.FindMembers);
1158                         return list;
1159                 }
1160
1161                 //
1162                 // We have to take care of arrays specially, because GetType on
1163                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1164                 // and we can not call FindMembers on this type.
1165                 //
1166                 if (t.IsSubclassOf (TypeManager.array_type))
1167                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1168
1169                 //
1170                 // Since FindMembers will not lookup both static and instance
1171                 // members, we emulate this behaviour here.
1172                 //
1173                 if ((bf & instance_and_static) == instance_and_static){
1174                         MemberInfo [] i_members = t.FindMembers (
1175                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1176
1177                         int i_len = i_members.Length;
1178                         if (i_len == 1){
1179                                 MemberInfo one = i_members [0];
1180
1181                                 //
1182                                 // If any of these are present, we are done!
1183                                 //
1184                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1185                                         return new MemberList (i_members);
1186                         }
1187                                 
1188                         MemberInfo [] s_members = t.FindMembers (
1189                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1190
1191                         int s_len = s_members.Length;
1192                         if (i_len > 0 || s_len > 0)
1193                                 return new MemberList (i_members, s_members);
1194                         else {
1195                                 if (i_len > 0)
1196                                         return new MemberList (i_members);
1197                                 else
1198                                         return new MemberList (s_members);
1199                         }
1200                 }
1201
1202                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1203         }
1204
1205
1206         /// <summary>
1207         ///   This method is only called from within MemberLookup.  It tries to use the member
1208         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1209         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1210         ///   our return value will already contain all inherited members and the caller don't need
1211         ///   to check base classes and interfaces anymore.
1212         /// </summary>
1213         private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1214                                                             string name, out bool used_cache)
1215         {
1216                 bool not_loaded_corlib = (t.Assembly == CodeGen.AssemblyBuilder);
1217                 
1218                 //
1219                 // We have to take care of arrays specially, because GetType on
1220                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1221                 // and we can not call FindMembers on this type.
1222                 //
1223                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1224                         used_cache = true;
1225                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1226                                 mt, bf, name, FilterWithClosure_delegate, null);
1227                 }
1228
1229                 //
1230                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1231                 // and we can ask the DeclSpace for the MemberCache.
1232                 //
1233                 if (t is TypeBuilder) {
1234                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1235                         MemberCache cache = decl.MemberCache;
1236
1237                         //
1238                         // If this DeclSpace has a MemberCache, use it.
1239                         //
1240
1241                         if (cache != null) {
1242                                 used_cache = true;
1243                                 return cache.FindMembers (
1244                                         mt, bf, name, FilterWithClosure_delegate, null);
1245                         }
1246
1247                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1248
1249                         MemberList list;
1250                         Timer.StartTimer (TimerType.FindMembers);
1251                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1252                                                  FilterWithClosure_delegate, name);
1253                         Timer.StopTimer (TimerType.FindMembers);
1254                         used_cache = false;
1255                         return list;
1256                 }
1257
1258                 //
1259                 // This call will always succeed.  There is exactly one TypeHandle instance per
1260                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1261                 // if it didn't already exist.
1262                 //
1263                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1264
1265                 used_cache = true;
1266                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1267         }
1268
1269         public static bool IsBuiltinType (Type t)
1270         {
1271                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1272                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1273                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1274                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1275                         return true;
1276                 else
1277                         return false;
1278         }
1279
1280         //
1281         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1282         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1283         // 
1284         public static bool IsCLRType (Type t)
1285         {
1286                 if (t == object_type || t == int32_type || t == uint32_type ||
1287                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1288                     t == char_type || t == short_type || t == bool_type ||
1289                     t == sbyte_type || t == byte_type || t == ushort_type)
1290                         return true;
1291                 else
1292                         return false;
1293         }
1294
1295         public static bool IsDelegateType (Type t)
1296         {
1297                 if (t.IsSubclassOf (TypeManager.delegate_type))
1298                         return true;
1299                 else
1300                         return false;
1301         }
1302         
1303         public static bool IsEnumType (Type t)
1304         {
1305                 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1306                         return true;
1307                 else
1308                         return false;
1309         }
1310
1311         //
1312         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1313         //
1314         public static bool IsUnmanagedType (Type t)
1315         {
1316                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1317                         return true;
1318
1319                 if (IsEnumType (t))
1320                         return true;
1321
1322                 if (t.IsPointer)
1323                         return true;
1324
1325                 if (IsValueType (t)){
1326                         if (t is TypeBuilder){
1327                                 TypeContainer tc = LookupTypeContainer (t);
1328
1329                                 foreach (Field f in tc.Fields){
1330                                         if (f.FieldBuilder.IsStatic)
1331                                                 continue;
1332                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1333                                                 return false;
1334                                 }
1335                         } else {
1336                                 FieldInfo [] fields = t.GetFields ();
1337
1338                                 foreach (FieldInfo f in fields){
1339                                         if (f.IsStatic)
1340                                                 continue;
1341                                         if (!IsUnmanagedType (f.FieldType))
1342                                                 return false;
1343                                 }
1344                         }
1345                         return true;
1346                 }
1347
1348                 return false;
1349         }
1350                 
1351         public static bool IsValueType (Type t)
1352         {
1353                 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1354                         return true;
1355                 else
1356                         return false;
1357         }
1358         
1359         public static bool IsInterfaceType (Type t)
1360         {
1361                 Interface iface = builder_to_declspace [t] as Interface;
1362
1363                 if (iface != null)
1364                         return true;
1365                 else
1366                         return false;
1367         }
1368
1369         //
1370         // Checks whether `type' is a subclass or nested child of `parent'.
1371         //
1372         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1373         {
1374                 do {
1375                         if ((type == parent) || type.IsSubclassOf (parent))
1376                                 return true;
1377
1378                         // Handle nested types.
1379                         type = type.DeclaringType;
1380                 } while (type != null);
1381
1382                 return false;
1383         }
1384
1385         //
1386         // Checks whether `type' is a nested child of `parent'.
1387         //
1388         public static bool IsNestedChildOf (Type type, Type parent)
1389         {
1390                 if (type == parent)
1391                         return false;
1392
1393                 type = type.DeclaringType;
1394                 while (type != null) {
1395                         if (type == parent)
1396                                 return true;
1397
1398                         type = type.DeclaringType;
1399                 }
1400
1401                 return false;
1402         }
1403
1404         //
1405         // Do the right thing when returning the element type of
1406         // an array type based on whether we 
1407         //
1408         public static Type GetElementType (Type t)
1409         {
1410                 if (RootContext.StdLib)
1411                         return t.GetElementType ();
1412                 else
1413                         return TypeToCoreType (t.GetElementType ());
1414         }
1415
1416         /// <summary>
1417         ///   Returns the User Defined Types
1418         /// </summary>
1419         public static ArrayList UserTypes {
1420                 get {
1421                         return user_types;
1422                 }
1423         }
1424
1425         public static Hashtable TypeContainers {
1426                 get {
1427                         return typecontainers;
1428                 }
1429         }
1430
1431         static Hashtable attr_to_allowmult;
1432
1433         public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1434         {
1435                 if (attr_to_allowmult == null)
1436                         attr_to_allowmult = new PtrHashtable ();
1437
1438                 if (attr_to_allowmult.Contains (attr_type))
1439                         return;
1440
1441                 attr_to_allowmult.Add (attr_type, allow);
1442                                
1443         }
1444
1445         public static bool AreMultipleAllowed (Type attr_type)
1446         {
1447                 if (!(attr_type is TypeBuilder)) {
1448                         System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1449
1450                         foreach (System.Attribute tmp in attrs)
1451                                 if (tmp is AttributeUsageAttribute) {
1452                                         return ((AttributeUsageAttribute) tmp).AllowMultiple;
1453                                 }
1454
1455                         return false;
1456                 }
1457                 
1458                 if (attr_to_allowmult == null)
1459                         return false;
1460
1461                 return (bool) attr_to_allowmult [attr_type];
1462         }
1463
1464         static Hashtable builder_to_constant;
1465
1466         public static void RegisterConstant (FieldBuilder fb, Const c)
1467         {
1468                 if (builder_to_constant == null)
1469                         builder_to_constant = new PtrHashtable ();
1470
1471                 if (builder_to_constant.Contains (fb))
1472                         return;
1473
1474                 builder_to_constant.Add (fb, c);
1475         }
1476
1477         public static Const LookupConstant (FieldBuilder fb)
1478         {
1479                 if (builder_to_constant == null)
1480                         return null;
1481                 
1482                 return (Const) builder_to_constant [fb];
1483         }
1484         
1485         /// <summary>
1486         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1487         /// </summary>
1488         ///
1489         /// <remarks>
1490         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1491         ///   for anything which is dynamic, and we need this in a number of places,
1492         ///   we register this information here, and use it afterwards.
1493         /// </remarks>
1494         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1495         {
1496                 if (args == null)
1497                         args = NoTypes;
1498                                 
1499                 method_arguments.Add (mb, args);
1500                 method_internal_params.Add (mb, ip);
1501                 
1502                 return true;
1503         }
1504         
1505         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1506         {
1507                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1508                         return null;
1509                 
1510                 if (method_internal_params.Contains (mb))
1511                         return (InternalParameters) method_internal_params [mb];
1512                 else
1513                         throw new Exception ("Argument for Method not registered" + mb);
1514         }
1515
1516         /// <summary>
1517         ///    Returns the argument types for a method based on its methodbase
1518         ///
1519         ///    For dynamic methods, we use the compiler provided types, for
1520         ///    methods from existing assemblies we load them from GetParameters,
1521         ///    and insert them into the cache
1522         /// </summary>
1523         static public Type [] GetArgumentTypes (MethodBase mb)
1524         {
1525                 if (method_arguments.Contains (mb))
1526                         return (Type []) method_arguments [mb];
1527                 else {
1528                         ParameterInfo [] pi = mb.GetParameters ();
1529                         int c = pi.Length;
1530                         Type [] types = new Type [c];
1531                         
1532                         for (int i = 0; i < c; i++)
1533                                 types [i] = pi [i].ParameterType;
1534
1535                         method_arguments.Add (mb, types);
1536                         return types;
1537                 }
1538         }
1539
1540         /// <summary>
1541         ///    Returns the argument types for an indexer based on its PropertyInfo
1542         ///
1543         ///    For dynamic indexers, we use the compiler provided types, for
1544         ///    indexers from existing assemblies we load them from GetParameters,
1545         ///    and insert them into the cache
1546         /// </summary>
1547         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1548         {
1549                 if (indexer_arguments.Contains (indexer))
1550                         return (Type []) indexer_arguments [indexer];
1551                 else if (indexer is PropertyBuilder)
1552                         // If we're a PropertyBuilder and not in the
1553                         // `indexer_arguments' hash, then we're a property and
1554                         // not an indexer.
1555                         return NoTypes;
1556                 else {
1557                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1558                         // Property, not an indexer.
1559                         if (pi == null)
1560                                 return NoTypes;
1561                         int c = pi.Length;
1562                         Type [] types = new Type [c];
1563                         
1564                         for (int i = 0; i < c; i++)
1565                                 types [i] = pi [i].ParameterType;
1566
1567                         indexer_arguments.Add (indexer, types);
1568                         return types;
1569                 }
1570         }
1571         
1572         // <remarks>
1573         //  This is a workaround the fact that GetValue is not
1574         //  supported for dynamic types
1575         // </remarks>
1576         static Hashtable fields = new Hashtable ();
1577         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1578         {
1579                 if (fields.Contains (fb))
1580                         return false;
1581
1582                 fields.Add (fb, value);
1583
1584                 return true;
1585         }
1586
1587         static public object GetValue (FieldBuilder fb)
1588         {
1589                 return fields [fb];
1590         }
1591
1592         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1593         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1594         {
1595                 if (fieldbuilders_to_fields.Contains (fb))
1596                         return false;
1597
1598                 fieldbuilders_to_fields.Add (fb, f);
1599                 return true;
1600         }
1601
1602         static public FieldBase GetField (FieldInfo fb)
1603         {
1604                 return (FieldBase) fieldbuilders_to_fields [fb];
1605         }
1606         
1607         static Hashtable events;
1608
1609         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1610         {
1611                 if (events == null)
1612                         events = new Hashtable ();
1613
1614                 if (events.Contains (eb))
1615                         return false;
1616
1617                 events.Add (eb, new Pair (add, remove));
1618
1619                 return true;
1620         }
1621
1622         static public MethodInfo GetAddMethod (EventInfo ei)
1623         {
1624                 if (ei is MyEventBuilder) {
1625                         Pair pair = (Pair) events [ei];
1626
1627                         return (MethodInfo) pair.First;
1628                 } else
1629                         return ei.GetAddMethod ();
1630         }
1631
1632         static public MethodInfo GetRemoveMethod (EventInfo ei)
1633         {
1634                 if (ei is MyEventBuilder) {
1635                         Pair pair = (Pair) events [ei];
1636
1637                         return (MethodInfo) pair.Second;
1638                 } else
1639                         return ei.GetRemoveMethod ();
1640         }
1641
1642         static Hashtable priv_fields_events;
1643
1644         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1645         {
1646                 if (priv_fields_events == null)
1647                         priv_fields_events = new Hashtable ();
1648
1649                 if (priv_fields_events.Contains (einfo))
1650                         return false;
1651
1652                 priv_fields_events.Add (einfo, builder);
1653
1654                 return true;
1655         }
1656
1657         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1658         {
1659                 if (priv_fields_events == null)
1660                         return null;
1661                 else
1662                         return (MemberInfo) priv_fields_events [ei];
1663         }
1664                 
1665         static Hashtable properties;
1666         
1667         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1668         {
1669                 if (properties == null)
1670                         properties = new Hashtable ();
1671
1672                 if (properties.Contains (pb))
1673                         return false;
1674
1675                 properties.Add (pb, new Pair (get, set));
1676
1677                 return true;
1678         }
1679
1680         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1681                                             MethodBase set, Type[] args)
1682         {
1683                 if (!RegisterProperty (pb, get,set))
1684                         return false;
1685
1686                 indexer_arguments.Add (pb, args);
1687
1688                 return true;
1689         }
1690
1691         /// <summary>
1692         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1693         ///   of an interface.  
1694         /// </summary>
1695         ///
1696         /// <remarks>
1697         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1698         ///   be IA, IB, IC.
1699         /// </remarks>
1700         public static Type [] ExpandInterfaces (Type [] base_interfaces)
1701         {
1702                 ArrayList new_ifaces = new ArrayList ();
1703                 
1704                 foreach (Type iface in base_interfaces){
1705                         if (!new_ifaces.Contains (iface))
1706                                 new_ifaces.Add (iface);
1707                         
1708                         Type [] implementing = TypeManager.GetInterfaces (iface);
1709                         
1710                         foreach (Type imp in implementing){
1711                                 if (!new_ifaces.Contains (imp))
1712                                         new_ifaces.Add (imp);
1713                         }
1714                 }
1715                 Type [] ret = new Type [new_ifaces.Count];
1716                 new_ifaces.CopyTo (ret, 0);
1717                 return ret;
1718         }
1719                 
1720         /// <summary>
1721         ///   This function returns the interfaces in the type `t'.  Works with
1722         ///   both types and TypeBuilders.
1723         /// </summary>
1724         public static Type [] GetInterfaces (Type t)
1725         {
1726                 //
1727                 // The reason for catching the Array case is that Reflection.Emit
1728                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1729                 // but will still throw an exception if we try to call GetInterfaces
1730                 // on the type.
1731                 //
1732                 // Since the array interfaces are always constant, we return those for
1733                 // the System.Array
1734                 //
1735                 
1736                 if (t.IsArray)
1737                         t = TypeManager.array_type;
1738                 
1739                 if (t is TypeBuilder){
1740                         Type [] parent_ifaces;
1741                         
1742                         if (t.BaseType == null)
1743                                 parent_ifaces = NoTypes;
1744                         else
1745                                 parent_ifaces = GetInterfaces (t.BaseType);
1746                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1747                         if (type_ifaces == null)
1748                                 type_ifaces = NoTypes;
1749
1750                         int parent_count = parent_ifaces.Length;
1751                         Type [] result = new Type [parent_count + type_ifaces.Length];
1752                         parent_ifaces.CopyTo (result, 0);
1753                         type_ifaces.CopyTo (result, parent_count);
1754
1755                         return result;
1756                 } else
1757                         return t.GetInterfaces ();
1758         }
1759         
1760         /// <remarks>
1761         ///  The following is used to check if a given type implements an interface.
1762         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1763         /// </remarks>
1764         public static bool ImplementsInterface (Type t, Type iface)
1765         {
1766                 Type [] interfaces;
1767
1768                 //
1769                 // FIXME OPTIMIZATION:
1770                 // as soon as we hit a non-TypeBuiler in the interface
1771                 // chain, we could return, as the `Type.GetInterfaces'
1772                 // will return all the interfaces implement by the type
1773                 // or its parents.
1774                 //
1775                 do {
1776                         interfaces = GetInterfaces (t);
1777
1778                         if (interfaces != null){
1779                                 foreach (Type i in interfaces){
1780                                         if (i == iface)
1781                                                 return true;
1782                                 }
1783                         }
1784                         
1785                         t = t.BaseType;
1786                 } while (t != null);
1787                 
1788                 return false;
1789         }
1790
1791         // This is a custom version of Convert.ChangeType() which works
1792         // with the TypeBuilder defined types when compiling corlib.
1793         public static object ChangeType (object value, Type conversionType, out bool error)
1794         {
1795                 if (!(value is IConvertible)){
1796                         error = true;
1797                         return null;
1798                 }
1799                 
1800                 IConvertible convertValue = (IConvertible) value;
1801                 CultureInfo ci = CultureInfo.CurrentCulture;
1802                 NumberFormatInfo provider = ci.NumberFormat;
1803
1804                 //
1805                 // We must use Type.Equals() here since `conversionType' is
1806                 // the TypeBuilder created version of a system type and not
1807                 // the system type itself.  You cannot use Type.GetTypeCode()
1808                 // on such a type - it'd always return TypeCode.Object.
1809                 //
1810                 error = false;
1811                 try {
1812                         if (conversionType.Equals (typeof (Boolean)))
1813                                 return (object)(convertValue.ToBoolean (provider));
1814                         else if (conversionType.Equals (typeof (Byte)))
1815                                 return (object)(convertValue.ToByte (provider));
1816                         else if (conversionType.Equals (typeof (Char)))
1817                                 return (object)(convertValue.ToChar (provider));
1818                         else if (conversionType.Equals (typeof (DateTime)))
1819                                 return (object)(convertValue.ToDateTime (provider));
1820                         else if (conversionType.Equals (typeof (Decimal)))
1821                                 return (object)(convertValue.ToDecimal (provider));
1822                         else if (conversionType.Equals (typeof (Double)))
1823                                 return (object)(convertValue.ToDouble (provider));
1824                         else if (conversionType.Equals (typeof (Int16)))
1825                                 return (object)(convertValue.ToInt16 (provider));
1826                         else if (conversionType.Equals (typeof (Int32)))
1827                                 return (object)(convertValue.ToInt32 (provider));
1828                         else if (conversionType.Equals (typeof (Int64)))
1829                                 return (object)(convertValue.ToInt64 (provider));
1830                         else if (conversionType.Equals (typeof (SByte)))
1831                                 return (object)(convertValue.ToSByte (provider));
1832                         else if (conversionType.Equals (typeof (Single)))
1833                                 return (object)(convertValue.ToSingle (provider));
1834                         else if (conversionType.Equals (typeof (String)))
1835                                 return (object)(convertValue.ToString (provider));
1836                         else if (conversionType.Equals (typeof (UInt16)))
1837                                 return (object)(convertValue.ToUInt16 (provider));
1838                         else if (conversionType.Equals (typeof (UInt32)))
1839                                 return (object)(convertValue.ToUInt32 (provider));
1840                         else if (conversionType.Equals (typeof (UInt64)))
1841                                 return (object)(convertValue.ToUInt64 (provider));
1842                         else if (conversionType.Equals (typeof (Object)))
1843                                 return (object)(value);
1844                         else 
1845                                 error = true;
1846                 } catch {
1847                         error = true;
1848                 }
1849                 return null;
1850         }
1851
1852         //
1853         // This is needed, because enumerations from assemblies
1854         // do not report their underlyingtype, but they report
1855         // themselves
1856         //
1857         public static Type EnumToUnderlying (Type t)
1858         {
1859                 if (t == TypeManager.enum_type)
1860                         return t;
1861
1862                 t = t.UnderlyingSystemType;
1863                 if (!TypeManager.IsEnumType (t))
1864                         return t;
1865         
1866                 if (t is TypeBuilder) {
1867                         // slow path needed to compile corlib
1868                         if (t == TypeManager.bool_type ||
1869                                         t == TypeManager.byte_type ||
1870                                         t == TypeManager.sbyte_type ||
1871                                         t == TypeManager.char_type ||
1872                                         t == TypeManager.short_type ||
1873                                         t == TypeManager.ushort_type ||
1874                                         t == TypeManager.int32_type ||
1875                                         t == TypeManager.uint32_type ||
1876                                         t == TypeManager.int64_type ||
1877                                         t == TypeManager.uint64_type)
1878                                 return t;
1879                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1880                 }
1881                 TypeCode tc = Type.GetTypeCode (t);
1882
1883                 switch (tc){
1884                 case TypeCode.Boolean:
1885                         return TypeManager.bool_type;
1886                 case TypeCode.Byte:
1887                         return TypeManager.byte_type;
1888                 case TypeCode.SByte:
1889                         return TypeManager.sbyte_type;
1890                 case TypeCode.Char:
1891                         return TypeManager.char_type;
1892                 case TypeCode.Int16:
1893                         return TypeManager.short_type;
1894                 case TypeCode.UInt16:
1895                         return TypeManager.ushort_type;
1896                 case TypeCode.Int32:
1897                         return TypeManager.int32_type;
1898                 case TypeCode.UInt32:
1899                         return TypeManager.uint32_type;
1900                 case TypeCode.Int64:
1901                         return TypeManager.int64_type;
1902                 case TypeCode.UInt64:
1903                         return TypeManager.uint64_type;
1904                 }
1905                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1906         }
1907
1908         //
1909         // When compiling corlib and called with one of the core types, return
1910         // the corresponding typebuilder for that type.
1911         //
1912         public static Type TypeToCoreType (Type t)
1913         {
1914                 if (RootContext.StdLib || (t is TypeBuilder))
1915                         return t;
1916
1917                 TypeCode tc = Type.GetTypeCode (t);
1918
1919                 switch (tc){
1920                 case TypeCode.Boolean:
1921                         return TypeManager.bool_type;
1922                 case TypeCode.Byte:
1923                         return TypeManager.byte_type;
1924                 case TypeCode.SByte:
1925                         return TypeManager.sbyte_type;
1926                 case TypeCode.Char:
1927                         return TypeManager.char_type;
1928                 case TypeCode.Int16:
1929                         return TypeManager.short_type;
1930                 case TypeCode.UInt16:
1931                         return TypeManager.ushort_type;
1932                 case TypeCode.Int32:
1933                         return TypeManager.int32_type;
1934                 case TypeCode.UInt32:
1935                         return TypeManager.uint32_type;
1936                 case TypeCode.Int64:
1937                         return TypeManager.int64_type;
1938                 case TypeCode.UInt64:
1939                         return TypeManager.uint64_type;
1940                 case TypeCode.String:
1941                         return TypeManager.string_type;
1942                 default:
1943                         if (t == typeof (void))
1944                                 return TypeManager.void_type;
1945                         if (t == typeof (object))
1946                                 return TypeManager.object_type;
1947                         if (t == typeof (System.Type))
1948                                 return TypeManager.type_type;
1949                         return t;
1950                 }
1951         }
1952
1953         /// <summary>
1954         ///   Utility function that can be used to probe whether a type
1955         ///   is managed or not.  
1956         /// </summary>
1957         public static bool VerifyUnManaged (Type t, Location loc)
1958         {
1959                 if (t.IsValueType || t.IsPointer){
1960                         //
1961                         // FIXME: this is more complex, we actually need to
1962                         // make sure that the type does not contain any
1963                         // classes itself
1964                         //
1965                         return true;
1966                 }
1967
1968                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1969                         // We need this explicit check here to make it work when
1970                         // compiling corlib.
1971                         return true;
1972
1973                 Report.Error (
1974                         208, loc,
1975                         "Cannot take the address or size of a variable of a managed type ('" +
1976                         CSharpName (t) + "')");
1977                 return false;   
1978         }
1979         
1980         /// <summary>
1981         ///   Returns the name of the indexer in a given type.
1982         /// </summary>
1983         /// <remarks>
1984         ///   The default is not always `Item'.  The user can change this behaviour by
1985         ///   using the DefaultMemberAttribute in the class.
1986         ///
1987         ///   For example, the String class indexer is named `Chars' not `Item' 
1988         /// </remarks>
1989         public static string IndexerPropertyName (Type t)
1990         {
1991                 if (t is TypeBuilder) {
1992                         if (t.IsInterface) {
1993                                 Interface i = LookupInterface (t);
1994
1995                                 if ((i == null) || (i.IndexerName == null))
1996                                         return "Item";
1997
1998                                 return i.IndexerName;
1999                         } else {
2000                                 TypeContainer tc = LookupTypeContainer (t);
2001
2002                                 if ((tc == null) || (tc.IndexerName == null))
2003                                         return "Item";
2004
2005                                 return tc.IndexerName;
2006                         }
2007                 }
2008                 
2009                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2010                         t, TypeManager.default_member_type);
2011                 if (attr != null){
2012                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2013                         return dma.MemberName;
2014                 }
2015
2016                 return "Item";
2017         }
2018
2019         public static void MakePinned (LocalBuilder builder)
2020         {
2021                 //
2022                 // FIXME: Flag the "LocalBuilder" type as being
2023                 // pinned.  Figure out API.
2024                 //
2025         }
2026
2027
2028         //
2029         // Returns whether the array of memberinfos contains the given method
2030         //
2031         static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2032         {
2033                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2034                 
2035                 foreach (MethodBase method in array){
2036                         if (method.Name != new_method.Name)
2037                                 continue;
2038                         
2039                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2040                         int old_count = old_args.Length;
2041                         int i;
2042                         
2043                         if (new_args.Length != old_count)
2044                                 continue;
2045                         
2046                         for (i = 0; i < old_count; i++){
2047                                 if (old_args [i] != new_args [i])
2048                                         break;
2049                         }
2050                         if (i != old_count)
2051                                 continue;
2052
2053                         return true;
2054                 }
2055                 return false;
2056         }
2057         
2058         //
2059         // We copy methods from `new_members' into `target_list' if the signature
2060         // for the method from in the new list does not exist in the target_list
2061         //
2062         // The name is assumed to be the same.
2063         //
2064         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
2065         {
2066                 if (target_list == null){
2067                         target_list = new ArrayList ();
2068
2069                         foreach (MemberInfo mi in new_members){
2070                                 if (mi is MethodBase)
2071                                         target_list.Add (mi);
2072                         }
2073                         return target_list;
2074                 }
2075                 
2076                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2077                 target_list.CopyTo (target_array, 0);
2078                 
2079                 foreach (MemberInfo mi in new_members){
2080                         MethodBase new_method = (MethodBase) mi;
2081                         
2082                         if (!ArrayContainsMethod (target_array, new_method))
2083                                 target_list.Add (new_method);
2084                 }
2085                 return target_list;
2086         }
2087
2088         [Flags]
2089         public enum MethodFlags {
2090                 IsObsolete = 1,
2091                 IsObsoleteError = 2,
2092                 ShouldIgnore = 3
2093         }
2094         
2095         //
2096         // Returns the TypeManager.MethodFlags for this method.
2097         // This emits an error 619 / warning 618 if the method is obsolete.
2098         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2099         //
2100         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2101         {
2102                 MethodFlags flags = 0;
2103                 
2104                 if (mb.DeclaringType is TypeBuilder){
2105                         MethodData method = (MethodData) builder_to_method [mb];
2106                         if (method == null) {
2107                                 // FIXME: implement Obsolete attribute on Property,
2108                                 //        Indexer and Event.
2109                                 return 0;
2110                         }
2111
2112                         return method.GetMethodFlags (loc);
2113                 }
2114
2115                 object [] attrs = mb.GetCustomAttributes (true);
2116                 foreach (object ta in attrs){
2117                         if (!(ta is System.Attribute)){
2118                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2119                                 continue;
2120                         }
2121                         System.Attribute a = (System.Attribute) ta;
2122                         if (a.TypeId == TypeManager.obsolete_attribute_type){
2123                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2124
2125                                 string method_desc = TypeManager.CSharpSignature (mb);
2126
2127                                 if (oa.IsError) {
2128                                         Report.Error (619, loc, "Method `" + method_desc +
2129                                                       "' is obsolete: `" + oa.Message + "'");
2130                                         return MethodFlags.IsObsoleteError;
2131                                 } else
2132                                         Report.Warning (618, loc, "Method `" + method_desc +
2133                                                         "' is obsolete: `" + oa.Message + "'");
2134
2135                                 flags |= MethodFlags.IsObsolete;
2136
2137                                 continue;
2138                         }
2139                         
2140                         //
2141                         // Skip over conditional code.
2142                         //
2143                         if (a.TypeId == TypeManager.conditional_attribute_type){
2144                                 ConditionalAttribute ca = (ConditionalAttribute) a;
2145
2146                                 if (RootContext.AllDefines [ca.ConditionString] == null)
2147                                         flags |= MethodFlags.ShouldIgnore;
2148                         }
2149                 }
2150
2151                 return flags;
2152         }
2153         
2154 #region MemberLookup implementation
2155         
2156         //
2157         // Name of the member
2158         //
2159         static string   closure_name;
2160
2161         //
2162         // Whether we allow private members in the result (since FindMembers
2163         // uses NonPublic for both protected and private), we need to distinguish.
2164         //
2165         static bool     closure_private_ok;
2166
2167         //
2168         // Who is invoking us and which type is being queried currently.
2169         //
2170         static Type     closure_invocation_type;
2171         static Type     closure_queried_type;
2172         static Type     closure_qualifier_type;
2173
2174         //
2175         // The assembly that defines the type is that is calling us
2176         //
2177         static Assembly closure_invocation_assembly;
2178
2179         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2180         {
2181                 return true;
2182         }
2183         
2184         //
2185         // This filter filters by name + whether it is ok to include private
2186         // members in the search
2187         //
2188         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2189         {
2190                 //
2191                 // Hack: we know that the filter criteria will always be in the `closure'
2192                 // fields. 
2193                 //
2194
2195                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2196                         return false;
2197
2198                 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2199                     (m.DeclaringType == closure_invocation_type))
2200                         return true;
2201
2202                 //
2203                 // Ugly: we need to find out the type of `m', and depending
2204                 // on this, tell whether we accept or not
2205                 //
2206                 if (m is MethodBase){
2207                         MethodBase mb = (MethodBase) m;
2208                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2209
2210                         if (ma == MethodAttributes.Private)
2211                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2212                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2213
2214                         //
2215                         // FamAndAssem requires that we not only derivate, but we are on the
2216                         // same assembly.  
2217                         //
2218                         if (ma == MethodAttributes.FamANDAssem){
2219                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2220                                         return false;
2221                         }
2222
2223                         // Assembly and FamORAssem succeed if we're in the same assembly.
2224                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2225                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2226                                         return true;
2227                         }
2228
2229                         // We already know that we aren't in the same assembly.
2230                         if (ma == MethodAttributes.Assembly)
2231                                 return false;
2232
2233                         // Family and FamANDAssem require that we derive.
2234                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2235                                 if (closure_invocation_type == null)
2236                                         return false;
2237
2238                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2239                                         return false;
2240
2241                                 // Although a derived class can access protected members of its base class
2242                                 // it cannot do so through an instance of the base class (CS1540).
2243                                 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2244                                     (closure_qualifier_type != null) &&
2245                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2246                                         return false;
2247
2248                                 return true;
2249                         }
2250
2251                         // Public.
2252                         return true;
2253                 }
2254
2255                 if (m is FieldInfo){
2256                         FieldInfo fi = (FieldInfo) m;
2257                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2258
2259                         if (fa == FieldAttributes.Private)
2260                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2261                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2262
2263                         //
2264                         // FamAndAssem requires that we not only derivate, but we are on the
2265                         // same assembly.  
2266                         //
2267                         if (fa == FieldAttributes.FamANDAssem){
2268                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2269                                         return false;
2270                         }
2271
2272                         // Assembly and FamORAssem succeed if we're in the same assembly.
2273                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2274                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2275                                         return true;
2276                         }
2277
2278                         // We already know that we aren't in the same assembly.
2279                         if (fa == FieldAttributes.Assembly)
2280                                 return false;
2281
2282                         // Family and FamANDAssem require that we derive.
2283                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2284                                 if (closure_invocation_type == null)
2285                                         return false;
2286
2287                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2288                                         return false;
2289
2290                                 // Although a derived class can access protected members of its base class
2291                                 // it cannot do so through an instance of the base class (CS1540).
2292                                 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2293                                     (closure_qualifier_type != null) &&
2294                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2295                                         return false;
2296
2297                                 return true;
2298                         }
2299
2300                         // Public.
2301                         return true;
2302                 }
2303
2304                 //
2305                 // EventInfos and PropertyInfos, return true because they lack permission
2306                 // informaiton, so we need to check later on the methods.
2307                 //
2308                 return true;
2309         }
2310
2311         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2312         static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2313
2314         //
2315         // Looks up a member called `name' in the `queried_type'.  This lookup
2316         // is done by code that is contained in the definition for `invocation_type'
2317         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2318         //
2319         // `invocation_type' is used to check whether we're allowed to access the requested
2320         // member wrt its protection level.
2321         //
2322         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2323         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2324         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2325         //
2326         // When resolving a SimpleName, `qualifier_type' is null.
2327         //
2328         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2329         // the same than `queried_type' - except when we're being called from BaseAccess;
2330         // in this case, `invocation_type' is the current type and `queried_type' the base
2331         // type, so this'd normally trigger a CS1540.
2332         //
2333         // The binding flags are `bf' and the kind of members being looked up are `mt'
2334         //
2335         // The return value always includes private members which code in `invocation_type'
2336         // is allowed to access (using the specified `qualifier_type' if given); only use
2337         // BindingFlags.NonPublic to bypass the permission check.
2338         //
2339         // Returns an array of a single element for everything but Methods/Constructors
2340         // that might return multiple matches.
2341         //
2342         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2343                                                   Type queried_type,  MemberTypes mt,
2344                                                   BindingFlags original_bf, string name)
2345         {
2346                 Timer.StartTimer (TimerType.MemberLookup);
2347
2348                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2349                                                         queried_type, mt, original_bf, name);
2350
2351                 Timer.StopTimer (TimerType.MemberLookup);
2352
2353                 return retval;
2354         }
2355
2356         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2357                                                Type queried_type, MemberTypes mt,
2358                                                BindingFlags original_bf, string name)
2359         {
2360                 BindingFlags bf = original_bf;
2361                 
2362                 ArrayList method_list = null;
2363                 Type current_type = queried_type;
2364                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2365                 bool skip_iface_check = true, used_cache = false;
2366                 bool always_ok_flag = false;
2367
2368                 closure_name = name;
2369                 closure_invocation_type = invocation_type;
2370                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2371                 closure_qualifier_type = qualifier_type;
2372
2373                 //
2374                 // If we are a nested class, we always have access to our container
2375                 // type names
2376                 //
2377                 if (invocation_type != null){
2378                         string invocation_name = invocation_type.FullName;
2379                         if (invocation_name.IndexOf ('+') != -1){
2380                                 string container = queried_type.FullName + "+";
2381                                 int container_length = container.Length;
2382
2383                                 if (invocation_name.Length > container_length){
2384                                         string shared = invocation_name.Substring (0, container_length);
2385                                 
2386                                         if (shared == container)
2387                                                 always_ok_flag = true;
2388                                 }
2389                         }
2390                 }
2391                 
2392                 do {
2393                         MemberList list;
2394
2395                         //
2396                         // `NonPublic' is lame, because it includes both protected and
2397                         // private methods, so we need to control this behavior by
2398                         // explicitly tracking if a private method is ok or not.
2399                         //
2400                         // The possible cases are:
2401                         //    public, private and protected (internal does not come into the
2402                         //    equation)
2403                         //
2404                         if ((invocation_type != null) &&
2405                             ((invocation_type == current_type) ||
2406                              IsNestedChildOf (invocation_type, current_type)) ||
2407                             always_ok_flag)
2408                                 bf = original_bf | BindingFlags.NonPublic;
2409                         else
2410                                 bf = original_bf;
2411
2412                         closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2413                         closure_queried_type = current_type;
2414
2415                         Timer.StopTimer (TimerType.MemberLookup);
2416
2417                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2418
2419                         Timer.StartTimer (TimerType.MemberLookup);
2420
2421                         //
2422                         // When queried for an interface type, the cache will automatically check all
2423                         // inherited members, so we don't need to do this here.  However, this only
2424                         // works if we already used the cache in the first iteration of this loop.
2425                         //
2426                         // If we used the cache in any further iteration, we can still terminate the
2427                         // loop since the cache always looks in all parent classes.
2428                         //
2429
2430                         if (used_cache)
2431                                 searching = false;
2432                         else
2433                                 skip_iface_check = false;
2434
2435                         if (current_type == TypeManager.object_type)
2436                                 searching = false;
2437                         else {
2438                                 current_type = current_type.BaseType;
2439                                 
2440                                 //
2441                                 // This happens with interfaces, they have a null
2442                                 // basetype.  Look members up in the Object class.
2443                                 //
2444                                 if (current_type == null)
2445                                         current_type = TypeManager.object_type;
2446                         }
2447                         
2448                         if (list.Count == 0)
2449                                 continue;
2450
2451                         //
2452                         // Events and types are returned by both `static' and `instance'
2453                         // searches, which means that our above FindMembers will
2454                         // return two copies of the same.
2455                         //
2456                         if (list.Count == 1 && !(list [0] is MethodBase)){
2457                                 return (MemberInfo []) list;
2458                         }
2459
2460                         //
2461                         // Multiple properties: we query those just to find out the indexer
2462                         // name
2463                         //
2464                         if (list [0] is PropertyInfo)
2465                                 return (MemberInfo []) list;
2466
2467                         //
2468                         // We found an event: the cache lookup returns both the event and
2469                         // its private field.
2470                         //
2471                         if (list [0] is EventInfo) {
2472                                 if ((list.Count == 2) && (list [1] is FieldInfo))
2473                                         return new MemberInfo [] { list [0] };
2474
2475                                 // Oooops
2476                                 return null;
2477                         }
2478
2479                         //
2480                         // We found methods, turn the search into "method scan"
2481                         // mode.
2482                         //
2483
2484                         method_list = CopyNewMethods (method_list, list);
2485                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2486                 } while (searching);
2487
2488                 if (method_list != null && method_list.Count > 0) {
2489                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2490                 }
2491                 //
2492                 // This happens if we already used the cache in the first iteration, in this case
2493                 // the cache already looked in all interfaces.
2494                 //
2495                 if (skip_iface_check)
2496                         return null;
2497
2498                 //
2499                 // Interfaces do not list members they inherit, so we have to
2500                 // scan those.
2501                 // 
2502                 if (!queried_type.IsInterface)
2503                         return null;
2504
2505                 if (queried_type.IsArray)
2506                         queried_type = TypeManager.array_type;
2507                 
2508                 Type [] ifaces = GetInterfaces (queried_type);
2509                 if (ifaces == null)
2510                         return null;
2511                 
2512                 foreach (Type itype in ifaces){
2513                         MemberInfo [] x;
2514
2515                         x = MemberLookup (null, null, itype, mt, bf, name);
2516                         if (x != null)
2517                                 return x;
2518                 }
2519                                         
2520                 return null;
2521         }
2522
2523         //
2524         // This is used to extract properties and event declarations from a type
2525         //
2526         static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2527         {
2528                 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2529
2530                 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2531                 
2532                 if (t is TypeBuilder) {
2533                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2534
2535                         return (MemberInfo []) decl.FindMembers (
2536                                 MemberTypes.Property | MemberTypes.Event,
2537                                 bf, FilterNone_delegate, null);
2538                 } else {
2539                         return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2540                                               bf, FilterNone_delegate, null);
2541
2542                 }
2543         }
2544         
2545         public static bool IsSpecialMethod (MethodBase mb)
2546         {
2547                 Type t = mb.DeclaringType;
2548                 
2549                 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2550                 if (matches == null)
2551                         return false;
2552                 
2553                 foreach (MemberInfo mi in matches){
2554                         if (mi is PropertyBuilder){
2555                                 Pair p = (Pair) properties [mi];
2556
2557                                 if (p.First == mb || p.Second == mb)
2558                                         return true;
2559                         } else if (mi is PropertyInfo){
2560                                 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2561                                 
2562                                 foreach (MethodInfo m in methods){
2563                                         if (m == mb)
2564                                                 return true;
2565                                 }
2566                         } else if (mi is MyEventBuilder){
2567                                 Pair p = (Pair) events [mi];
2568
2569                                 if (p.First == mb || p.Second == mb)
2570                                         return true;
2571                         } else if (mi is EventInfo){
2572                                 EventInfo ei = ((EventInfo) mi);
2573                                 
2574                                 if (ei.GetAddMethod (true) == mb)
2575                                         return true;
2576                                 
2577                                 if (ei.GetRemoveMethod (true) == mb)
2578                                         return true;
2579                                 
2580                                 if (ei.GetRaiseMethod (true) == mb)
2581                                         return true;
2582                         }
2583                 }
2584
2585                 //
2586                 // Now check if it is an operator method
2587                 //
2588                 string s = mb.Name;
2589
2590                 if (s.StartsWith ("op_")){
2591                         foreach (string name in Unary.oper_names){
2592                                 if (s == name)
2593                                         return true;
2594                         }
2595
2596                         foreach (string name in Binary.oper_names){
2597                                 if (s == name)
2598                                         return true;
2599                         }
2600                 }
2601                 
2602                 return false;
2603         }
2604                 
2605 #endregion
2606         
2607 }
2608
2609 /// <summary>
2610 ///   There is exactly one instance of this class per type.
2611 /// </summary>
2612 public sealed class TypeHandle : IMemberContainer {
2613         public readonly TypeHandle BaseType;
2614
2615         readonly int id = ++next_id;
2616         static int next_id = 0;
2617
2618         /// <summary>
2619         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2620         ///   a TypeHandle yet, a new instance of it is created.  This static method
2621         ///   ensures that we'll only have one TypeHandle instance per type.
2622         /// </summary>
2623         public static TypeHandle GetTypeHandle (Type t)
2624         {
2625                 TypeHandle handle = (TypeHandle) type_hash [t];
2626                 if (handle != null)
2627                         return handle;
2628
2629                 handle = new TypeHandle (t);
2630                 type_hash.Add (t, handle);
2631                 return handle;
2632         }
2633
2634         /// <summary>
2635         ///   Returns the TypeHandle for TypeManager.object_type.
2636         /// </summary>
2637         public static IMemberContainer ObjectType {
2638                 get {
2639                         if (object_type != null)
2640                                 return object_type;
2641
2642                         object_type = GetTypeHandle (TypeManager.object_type);
2643
2644                         return object_type;
2645                 }
2646         }
2647
2648         /// <summary>
2649         ///   Returns the TypeHandle for TypeManager.array_type.
2650         /// </summary>
2651         public static IMemberContainer ArrayType {
2652                 get {
2653                         if (array_type != null)
2654                                 return array_type;
2655
2656                         array_type = GetTypeHandle (TypeManager.array_type);
2657
2658                         return array_type;
2659                 }
2660         }
2661
2662         private static PtrHashtable type_hash = new PtrHashtable ();
2663
2664         private static TypeHandle object_type = null;
2665         private static TypeHandle array_type = null;
2666
2667         private Type type;
2668         private bool is_interface;
2669         private MemberCache member_cache;
2670
2671         private TypeHandle (Type type)
2672         {
2673                 this.type = type;
2674                 if (type.BaseType != null)
2675                         BaseType = GetTypeHandle (type.BaseType);
2676                 else if ((type != TypeManager.object_type) && (type != typeof (object)))
2677                         is_interface = true;
2678                 this.member_cache = new MemberCache (this);
2679         }
2680
2681         // IMemberContainer methods
2682
2683         public string Name {
2684                 get {
2685                         return type.FullName;
2686                 }
2687         }
2688
2689         public Type Type {
2690                 get {
2691                         return type;
2692                 }
2693         }
2694
2695         public IMemberContainer Parent {
2696                 get {
2697                         return BaseType;
2698                 }
2699         }
2700
2701         public bool IsInterface {
2702                 get {
2703                         return is_interface;
2704                 }
2705         }
2706
2707         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2708         {
2709                 if (mt == MemberTypes.Event)
2710                         return new MemberList (type.GetEvents (bf | BindingFlags.DeclaredOnly));
2711                 else
2712                         return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2713                                                                  null, null));
2714         }
2715
2716         // IMemberFinder methods
2717
2718         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2719                                        MemberFilter filter, object criteria)
2720         {
2721                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2722         }
2723
2724         public MemberCache MemberCache {
2725                 get {
2726                         return member_cache;
2727                 }
2728         }
2729
2730         public override string ToString ()
2731         {
2732                 if (BaseType != null)
2733                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2734                 else
2735                         return "TypeHandle (" + id + "," + Name + ")";
2736         }
2737 }
2738
2739 }