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