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