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