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