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