2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[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                 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
877                 return (mi is MethodBase)
878                         ? GetFullNameSignature (mi as MethodBase) 
879                         : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
880         }
881
882         static public string GetFullNameSignature (MethodBase mb)
883         {
884                 string name = mb.Name;
885                 if (name == ".ctor")
886                         name = mb.DeclaringType.Name;
887
888                 if (mb.IsSpecialName) {
889                         if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
890                                 name = name.Remove (0, 4);
891                         }
892
893                         if (name == "Item")
894                                 name = "this";
895                 }
896
897                 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
898         }
899
900         /// <summary>
901         ///   Returns the signature of the property and indexer
902         /// </summary>
903         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
904         {
905                 if (!is_indexer) {
906                         return GetFullNameSignature (pb);
907                 }
908
909                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
910                 string signature = GetFullNameSignature (mb);
911                 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
912                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
913         }
914
915         /// <summary>
916         ///   Returns the signature of the method
917         /// </summary>
918         static public string CSharpSignature (MethodBase mb)
919         {
920                 StringBuilder sig = new StringBuilder ("(");
921
922                 //
923                 // FIXME: We should really have a single function to do
924                 // everything instead of the following 5 line pattern
925                 //
926                 ParameterData iparams = LookupParametersByBuilder (mb);
927
928                 if (iparams == null)
929                         iparams = new ReflectionParameters (mb);
930
931                 // Is property
932                 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
933                         return GetFullNameSignature (mb);
934                 
935                 for (int i = 0; i < iparams.Count; i++) {
936                         if (i > 0) {
937                                 sig.Append (", ");
938                         }
939                         sig.Append (iparams.ParameterDesc (i));
940                 }
941                 sig.Append (")");
942
943                 // Is indexer
944                 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
945                         sig.Replace ('(', '[');
946                         sig.Replace (')', ']');
947                 }
948
949                 return GetFullNameSignature (mb) + sig.ToString ();
950         }
951
952         /// <summary>
953         ///   Looks up a type, and aborts if it is not found.  This is used
954         ///   by types required by the compiler
955         /// </summary>
956         static Type CoreLookupType (string name)
957         {
958                 Type t = LookupTypeDirect (name);
959
960                 if (t == null){
961                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
962                         Environment.Exit (1);
963                 }
964
965                 return t;
966         }
967
968         /// <summary>
969         ///   Returns the MethodInfo for a method named `name' defined
970         ///   in type `t' which takes arguments of types `args'
971         /// </summary>
972         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
973         {
974                 MemberList list;
975                 Signature sig;
976                 BindingFlags flags = instance_and_static | BindingFlags.Public;
977
978                 sig.name = name;
979                 sig.args = args;
980
981                 if (is_private)
982                         flags |= BindingFlags.NonPublic;
983
984                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
985                 if (list.Count == 0) {
986                         if (report_errors)
987                                 Report.Error (-19, "Can not find the core function `" + name + "'");
988                         return null;
989                 }
990
991                 MethodInfo mi = list [0] as MethodInfo;
992                 if (mi == null) {
993                         if (report_errors)
994                                 Report.Error (-19, "Can not find the core function `" + name + "'");
995                         return null;
996                 }
997
998                 return mi;
999         }
1000
1001         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1002         {
1003                 return GetMethod (t, name, args, false, report_errors);
1004         }
1005
1006         static MethodInfo GetMethod (Type t, string name, Type [] args)
1007         {
1008                 return GetMethod (t, name, args, true);
1009         }
1010
1011
1012         /// <summary>
1013         ///    Returns the ConstructorInfo for "args"
1014         /// </summary>
1015         static ConstructorInfo GetConstructor (Type t, Type [] args)
1016         {
1017                 MemberList list;
1018                 Signature sig;
1019
1020                 sig.name = ".ctor";
1021                 sig.args = args;
1022                 
1023                 list = FindMembers (t, MemberTypes.Constructor,
1024                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1025                                     signature_filter, sig);
1026                 if (list.Count == 0){
1027                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1028                         return null;
1029                 }
1030
1031                 ConstructorInfo ci = list [0] as ConstructorInfo;
1032                 if (ci == null){
1033                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1034                         return null;
1035                 }
1036
1037                 return ci;
1038         }
1039
1040         public static void InitEnumUnderlyingTypes ()
1041         {
1042
1043                 int32_type    = CoreLookupType ("System.Int32");
1044                 int64_type    = CoreLookupType ("System.Int64");
1045                 uint32_type   = CoreLookupType ("System.UInt32"); 
1046                 uint64_type   = CoreLookupType ("System.UInt64"); 
1047                 byte_type     = CoreLookupType ("System.Byte");
1048                 sbyte_type    = CoreLookupType ("System.SByte");
1049                 short_type    = CoreLookupType ("System.Int16");
1050                 ushort_type   = CoreLookupType ("System.UInt16");
1051         }
1052         
1053         /// <remarks>
1054         ///   The types have to be initialized after the initial
1055         ///   population of the type has happened (for example, to
1056         ///   bootstrap the corlib.dll
1057         /// </remarks>
1058         public static void InitCoreTypes ()
1059         {
1060                 object_type   = CoreLookupType ("System.Object");
1061                 value_type    = CoreLookupType ("System.ValueType");
1062
1063                 InitEnumUnderlyingTypes ();
1064
1065                 char_type     = CoreLookupType ("System.Char");
1066                 string_type   = CoreLookupType ("System.String");
1067                 float_type    = CoreLookupType ("System.Single");
1068                 double_type   = CoreLookupType ("System.Double");
1069                 char_ptr_type = CoreLookupType ("System.Char*");
1070                 decimal_type  = CoreLookupType ("System.Decimal");
1071                 bool_type     = CoreLookupType ("System.Boolean");
1072                 enum_type     = CoreLookupType ("System.Enum");
1073
1074                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1075                 delegate_type           = CoreLookupType ("System.Delegate");
1076
1077                 array_type    = CoreLookupType ("System.Array");
1078                 void_type     = CoreLookupType ("System.Void");
1079                 type_type     = CoreLookupType ("System.Type");
1080
1081                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1082                 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1083                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1084                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1085                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1086                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1087                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1088                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1089                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1090                 idisposable_type     = CoreLookupType ("System.IDisposable");
1091                 icloneable_type      = CoreLookupType ("System.ICloneable");
1092                 iconvertible_type    = CoreLookupType ("System.IConvertible");
1093                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1094                 intptr_type          = CoreLookupType ("System.IntPtr");
1095
1096                 attribute_type       = CoreLookupType ("System.Attribute");
1097                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1098                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1099                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1100                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1101                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1102                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1103                 out_attribute_type   = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1104                 typed_reference_type = CoreLookupType ("System.TypedReference");
1105                 arg_iterator_type    = CoreLookupType ("System.ArgIterator");
1106                 mbr_type             = CoreLookupType ("System.MarshalByRefObject");
1107                 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1108
1109                 //
1110                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1111                 // people are running.
1112                 //
1113                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1114
1115                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1116
1117                 void_ptr_type         = CoreLookupType ("System.Void*");
1118
1119                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1120
1121                 exception_type        = CoreLookupType ("System.Exception");
1122                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1123                 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1124
1125                 //
1126                 // Attribute types
1127                 //
1128                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1129                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1130                 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1131                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1132                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1133                 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1134
1135                 //
1136                 // When compiling corlib, store the "real" types here.
1137                 //
1138                 if (!RootContext.StdLib) {
1139                         system_int32_type = typeof (System.Int32);
1140                         system_array_type = typeof (System.Array);
1141                         system_type_type = typeof (System.Type);
1142                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1143
1144                         Type [] void_arg = {  };
1145                         system_int_array_get_length = GetMethod (
1146                                 system_array_type, "get_Length", void_arg);
1147                         system_int_array_get_rank = GetMethod (
1148                                 system_array_type, "get_Rank", void_arg);
1149                         system_object_array_clone = GetMethod (
1150                                 system_array_type, "Clone", void_arg);
1151
1152                         Type [] system_int_arg = { system_int32_type };
1153                         system_int_array_get_length_int = GetMethod (
1154                                 system_array_type, "GetLength", system_int_arg);
1155                         system_int_array_get_upper_bound_int = GetMethod (
1156                                 system_array_type, "GetUpperBound", system_int_arg);
1157                         system_int_array_get_lower_bound_int = GetMethod (
1158                                 system_array_type, "GetLowerBound", system_int_arg);
1159
1160                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1161                         system_void_array_copyto_array_int = GetMethod (
1162                                 system_array_type, "CopyTo", system_array_int_arg);
1163
1164                         Type [] system_3_type_arg = {
1165                                 system_type_type, system_type_type, system_type_type };
1166                         Type [] system_4_type_arg = {
1167                                 system_type_type, system_type_type, system_type_type, system_type_type };
1168
1169                         MethodInfo set_corlib_type_builders = GetMethod (
1170                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1171                                 system_4_type_arg, true, false);
1172
1173                         if (set_corlib_type_builders != null) {
1174                                 object[] args = new object [4];
1175                                 args [0] = object_type;
1176                                 args [1] = value_type;
1177                                 args [2] = enum_type;
1178                                 args [3] = void_type;
1179                                 
1180                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1181                         } else {
1182                                 // Compatibility for an older version of the class libs.
1183                                 set_corlib_type_builders = GetMethod (
1184                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1185                                         system_3_type_arg, true, true);
1186
1187                                 if (set_corlib_type_builders == null) {
1188                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1189                                         return;
1190                                 }
1191
1192                                 object[] args = new object [3];
1193                                 args [0] = object_type;
1194                                 args [1] = value_type;
1195                                 args [2] = enum_type;
1196                                 
1197                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1198                         }
1199                 }
1200
1201                 system_object_expr.Type = object_type;
1202                 system_string_expr.Type = string_type;
1203                 system_boolean_expr.Type = bool_type;
1204                 system_decimal_expr.Type = decimal_type;
1205                 system_single_expr.Type = float_type;
1206                 system_double_expr.Type = double_type;
1207                 system_sbyte_expr.Type = sbyte_type;
1208                 system_byte_expr.Type = byte_type;
1209                 system_int16_expr.Type = short_type;
1210                 system_uint16_expr.Type = ushort_type;
1211                 system_int32_expr.Type = int32_type;
1212                 system_uint32_expr.Type = uint32_type;
1213                 system_int64_expr.Type = int64_type;
1214                 system_uint64_expr.Type = uint64_type;
1215                 system_char_expr.Type = char_type;
1216                 system_void_expr.Type = void_type;
1217                 system_asynccallback_expr.Type = asynccallback_type;
1218                 system_iasyncresult_expr.Type = iasyncresult_type;
1219                 system_valuetype_expr.Type = value_type;
1220
1221                 //
1222                 // These are only used for compare purposes
1223                 //
1224                 anonymous_method_type = typeof (AnonymousMethod);
1225                 null_type = typeof (NullType);
1226         }
1227
1228         //
1229         // The helper methods that are used by the compiler
1230         //
1231         public static void InitCodeHelpers ()
1232         {
1233                 //
1234                 // Now load the default methods that we use.
1235                 //
1236                 Type [] string_string = { string_type, string_type };
1237                 string_concat_string_string = GetMethod (
1238                         string_type, "Concat", string_string);
1239                 Type [] string_string_string = { string_type, string_type, string_type };
1240                 string_concat_string_string_string = GetMethod (
1241                         string_type, "Concat", string_string_string);
1242                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1243                 string_concat_string_string_string_string = GetMethod (
1244                         string_type, "Concat", string_string_string_string);
1245                 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1246                 string_concat_string_dot_dot_dot = GetMethod (
1247                         string_type, "Concat", params_string);
1248
1249                 Type [] object_object = { object_type, object_type };
1250                 string_concat_object_object = GetMethod (
1251                         string_type, "Concat", object_object);
1252                 Type [] object_object_object = { object_type, object_type, object_type };
1253                 string_concat_object_object_object = GetMethod (
1254                         string_type, "Concat", object_object_object);
1255                 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1256                 string_concat_object_dot_dot_dot = GetMethod (
1257                         string_type, "Concat", params_object);
1258
1259                 Type [] string_ = { string_type };
1260                 string_isinterneted_string = GetMethod (
1261                         string_type, "IsInterned", string_);
1262                 
1263                 Type [] runtime_type_handle = { runtime_handle_type };
1264                 system_type_get_type_from_handle = GetMethod (
1265                         type_type, "GetTypeFromHandle", runtime_type_handle);
1266
1267                 Type [] delegate_delegate = { delegate_type, delegate_type };
1268                 delegate_combine_delegate_delegate = GetMethod (
1269                                 delegate_type, "Combine", delegate_delegate);
1270
1271                 delegate_remove_delegate_delegate = GetMethod (
1272                                 delegate_type, "Remove", delegate_delegate);
1273
1274                 //
1275                 // Void arguments
1276                 //
1277                 Type [] void_arg = {  };
1278                 object_getcurrent_void = GetMethod (
1279                         ienumerator_type, "get_Current", void_arg);
1280                 bool_movenext_void = GetMethod (
1281                         ienumerator_type, "MoveNext", void_arg);
1282                 void_reset_void = GetMethod (
1283                         ienumerator_type, "Reset", void_arg);
1284                 void_dispose_void = GetMethod (
1285                         idisposable_type, "Dispose", void_arg);
1286                 int_get_offset_to_string_data = GetMethod (
1287                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1288                 int_array_get_length = GetMethod (
1289                         array_type, "get_Length", void_arg);
1290                 int_array_get_rank = GetMethod (
1291                         array_type, "get_Rank", void_arg);
1292                 ienumerable_getenumerator_void = GetMethod (
1293                         ienumerable_type, "GetEnumerator", void_arg);
1294                 
1295                 //
1296                 // Int32 arguments
1297                 //
1298                 Type [] int_arg = { int32_type };
1299                 int_array_get_length_int = GetMethod (
1300                         array_type, "GetLength", int_arg);
1301                 int_array_get_upper_bound_int = GetMethod (
1302                         array_type, "GetUpperBound", int_arg);
1303                 int_array_get_lower_bound_int = GetMethod (
1304                         array_type, "GetLowerBound", int_arg);
1305
1306                 //
1307                 // System.Array methods
1308                 //
1309                 object_array_clone = GetMethod (
1310                         array_type, "Clone", void_arg);
1311                 Type [] array_int_arg = { array_type, int32_type };
1312                 void_array_copyto_array_int = GetMethod (
1313                         array_type, "CopyTo", array_int_arg);
1314                 
1315                 //
1316                 // object arguments
1317                 //
1318                 Type [] object_arg = { object_type };
1319                 void_monitor_enter_object = GetMethod (
1320                         monitor_type, "Enter", object_arg);
1321                 void_monitor_exit_object = GetMethod (
1322                         monitor_type, "Exit", object_arg);
1323
1324                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1325                 
1326                 void_initializearray_array_fieldhandle = GetMethod (
1327                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1328
1329                 //
1330                 // Array functions
1331                 //
1332                 int_getlength_int = GetMethod (
1333                         array_type, "GetLength", int_arg);
1334
1335                 //
1336                 // Decimal constructors
1337                 //
1338                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1339                 void_decimal_ctor_five_args = GetConstructor (
1340                         decimal_type, dec_arg);
1341                 
1342                 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1343
1344                 //
1345                 // Attributes
1346                 //
1347                 cons_param_array_attribute = GetConstructor (
1348                         param_array_type, void_arg);
1349
1350                 unverifiable_code_ctor = GetConstructor (
1351                         unverifiable_code_type, void_arg);
1352
1353                 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1354                         { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1355
1356                 default_member_ctor = GetConstructor (default_member_type, string_);
1357
1358                 //
1359                 // InvalidOperationException
1360                 //
1361                 invalid_operation_ctor = GetConstructor (
1362                         invalid_operation_exception_type, void_arg);
1363
1364
1365                 // Object
1366                 object_ctor = GetConstructor (object_type, void_arg);
1367
1368         }
1369
1370         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1371
1372         /// <remarks>
1373         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1374         ///   the cache here because there is no member name argument.
1375         /// </remarks>
1376         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1377                                               MemberFilter filter, object criteria)
1378         {
1379                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1380
1381                 //
1382                 // `builder_to_declspace' contains all dynamic types.
1383                 //
1384                 if (decl != null) {
1385                         MemberList list;
1386                         Timer.StartTimer (TimerType.FindMembers);
1387                         list = decl.FindMembers (mt, bf, filter, criteria);
1388                         Timer.StopTimer (TimerType.FindMembers);
1389                         return list;
1390                 }
1391
1392                 //
1393                 // We have to take care of arrays specially, because GetType on
1394                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1395                 // and we can not call FindMembers on this type.
1396                 //
1397                 if (t.IsSubclassOf (TypeManager.array_type))
1398                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1399
1400                 //
1401                 // Since FindMembers will not lookup both static and instance
1402                 // members, we emulate this behaviour here.
1403                 //
1404                 if ((bf & instance_and_static) == instance_and_static){
1405                         MemberInfo [] i_members = t.FindMembers (
1406                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1407
1408                         int i_len = i_members.Length;
1409                         if (i_len == 1){
1410                                 MemberInfo one = i_members [0];
1411
1412                                 //
1413                                 // If any of these are present, we are done!
1414                                 //
1415                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1416                                         return new MemberList (i_members);
1417                         }
1418                                 
1419                         MemberInfo [] s_members = t.FindMembers (
1420                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1421
1422                         int s_len = s_members.Length;
1423                         if (i_len > 0 || s_len > 0)
1424                                 return new MemberList (i_members, s_members);
1425                         else {
1426                                 if (i_len > 0)
1427                                         return new MemberList (i_members);
1428                                 else
1429                                         return new MemberList (s_members);
1430                         }
1431                 }
1432
1433                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1434         }
1435
1436
1437         /// <summary>
1438         ///   This method is only called from within MemberLookup.  It tries to use the member
1439         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1440         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1441         ///   our return value will already contain all inherited members and the caller don't need
1442         ///   to check base classes and interfaces anymore.
1443         /// </summary>
1444         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1445                                                             string name, out bool used_cache)
1446         {
1447                 MemberCache cache;
1448
1449                 //
1450                 // We have to take care of arrays specially, because GetType on
1451                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1452                 // and we can not call FindMembers on this type.
1453                 //
1454                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1455                         used_cache = true;
1456                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1457                                 mt, bf, name, FilterWithClosure_delegate, null);
1458                 }
1459
1460                 //
1461                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1462                 // and we can ask the DeclSpace for the MemberCache.
1463                 //
1464                 if (t is TypeBuilder) {
1465                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1466                         cache = decl.MemberCache;
1467
1468                         //
1469                         // If this DeclSpace has a MemberCache, use it.
1470                         //
1471
1472                         if (cache != null) {
1473                                 used_cache = true;
1474                                 return cache.FindMembers (
1475                                         mt, bf, name, FilterWithClosure_delegate, null);
1476                         }
1477
1478                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1479                         // Note, this is a VERY uncommon route!
1480                         
1481                         MemberList list;
1482                         Timer.StartTimer (TimerType.FindMembers);
1483                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1484                                                  FilterWithClosure_delegate, name);
1485                         Timer.StopTimer (TimerType.FindMembers);
1486                         used_cache = false;
1487                         
1488                         return (MemberInfo []) list;
1489                 }
1490
1491                 //
1492                 // This call will always succeed.  There is exactly one TypeHandle instance per
1493                 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1494                 // the corresponding MemberCache.
1495                 //
1496                 cache = TypeHandle.GetMemberCache (t);
1497
1498                 used_cache = true;
1499                 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1500         }
1501
1502         public static bool IsBuiltinType (Type t)
1503         {
1504                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1505                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1506                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1507                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1508                         return true;
1509                 else
1510                         return false;
1511         }
1512
1513         public static bool IsBuiltinType (TypeContainer tc)
1514         {
1515                 return IsBuiltinType (tc.TypeBuilder);
1516         }
1517
1518         //
1519         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1520         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1521         // 
1522         public static bool IsCLRType (Type t)
1523         {
1524                 if (t == object_type || t == int32_type || t == uint32_type ||
1525                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1526                     t == char_type || t == short_type || t == bool_type ||
1527                     t == sbyte_type || t == byte_type || t == ushort_type)
1528                         return true;
1529                 else
1530                         return false;
1531         }
1532
1533         public static bool IsDelegateType (Type t)
1534         {
1535                 if (t.IsSubclassOf (TypeManager.delegate_type))
1536                         return true;
1537                 else
1538                         return false;
1539         }
1540         
1541         public static bool IsEnumType (Type t)
1542         {
1543                 if (t.IsSubclassOf (TypeManager.enum_type))
1544                         return true;
1545                 else
1546                         return false;
1547         }
1548         public static bool IsBuiltinOrEnum (Type t)
1549         {
1550                 if (IsBuiltinType (t))
1551                         return true;
1552                 
1553                 if (IsEnumType (t))
1554                         return true;
1555
1556                 return false;
1557         }
1558
1559         //
1560         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1561         //
1562         public static bool IsUnmanagedType (Type t)
1563         {
1564                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1565                         return true;
1566
1567                 if (IsEnumType (t))
1568                         return true;
1569
1570                 if (t.IsPointer)
1571                         return true;
1572
1573                 if (IsValueType (t)){
1574                         if (t is TypeBuilder){
1575                                 TypeContainer tc = LookupTypeContainer (t);
1576
1577                                 if (tc.Fields != null){
1578                                         foreach (Field f in tc.Fields){
1579                                                 if (f.FieldBuilder.IsStatic)
1580                                                         continue;
1581                                                 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1582                                                         return false;
1583                                         }
1584                                 } else
1585                                         return true;
1586                         } else {
1587                                 FieldInfo [] fields = t.GetFields ();
1588
1589                                 foreach (FieldInfo f in fields){
1590                                         if (f.IsStatic)
1591                                                 continue;
1592                                         if (!IsUnmanagedType (f.FieldType))
1593                                                 return false;
1594                                 }
1595                         }
1596                         return true;
1597                 }
1598
1599                 return false;
1600         }
1601                 
1602         public static bool IsValueType (Type t)
1603         {
1604                 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1605                         return true;
1606                 else
1607                         return false;
1608         }
1609         
1610         public static bool IsInterfaceType (Type t)
1611         {
1612                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1613                 if (tc == null)
1614                         return false;
1615
1616                 return tc.Kind == Kind.Interface;
1617         }
1618
1619         public static bool IsSubclassOf (Type type, Type base_type)
1620         {
1621                 do {
1622                         if (type.Equals (base_type))
1623                                 return true;
1624
1625                         type = type.BaseType;
1626                 } while (type != null);
1627
1628                 return false;
1629         }
1630
1631         public static bool IsFamilyAccessible (Type type, Type base_type)
1632         {
1633                 return IsSubclassOf (type, base_type);
1634         }
1635
1636         //
1637         // Checks whether `type' is a subclass or nested child of `base_type'.
1638         //
1639         public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1640         {
1641                 do {
1642                         if ((type == base_type) || type.IsSubclassOf (base_type))
1643                                 return true;
1644
1645                         // Handle nested types.
1646                         type = type.DeclaringType;
1647                 } while (type != null);
1648
1649                 return false;
1650         }
1651
1652         //
1653         // Checks whether `type' is a nested child of `parent'.
1654         //
1655         public static bool IsNestedChildOf (Type type, Type parent)
1656         {
1657                 if (type == parent)
1658                         return false;
1659
1660                 type = type.DeclaringType;
1661                 while (type != null) {
1662                         if (type == parent)
1663                                 return true;
1664
1665                         type = type.DeclaringType;
1666                 }
1667
1668                 return false;
1669         }
1670
1671         //
1672         // Do the right thing when returning the element type of an
1673         // array type based on whether we are compiling corlib or not
1674         //
1675         public static Type GetElementType (Type t)
1676         {
1677                 if (RootContext.StdLib)
1678                         return t.GetElementType ();
1679                 else
1680                         return TypeToCoreType (t.GetElementType ());
1681         }
1682
1683         /// <summary>
1684         ///   Returns the User Defined Types
1685         /// </summary>
1686         public static ArrayList UserTypes {
1687                 get {
1688                         return user_types;
1689                 }
1690         }
1691
1692         public static Hashtable TypeContainers {
1693                 get {
1694                         return typecontainers;
1695                 }
1696         }
1697
1698         static Hashtable builder_to_constant;
1699
1700         public static void RegisterConstant (FieldBuilder fb, Const c)
1701         {
1702                 if (builder_to_constant == null)
1703                         builder_to_constant = new PtrHashtable ();
1704
1705                 if (builder_to_constant.Contains (fb))
1706                         return;
1707
1708                 builder_to_constant.Add (fb, c);
1709         }
1710
1711         public static Const LookupConstant (FieldBuilder fb)
1712         {
1713                 if (builder_to_constant == null)
1714                         return null;
1715                 
1716                 return (Const) builder_to_constant [fb];
1717         }
1718         
1719         /// <summary>
1720         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1721         /// </summary>
1722         ///
1723         /// <remarks>
1724         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1725         ///   for anything which is dynamic, and we need this in a number of places,
1726         ///   we register this information here, and use it afterwards.
1727         /// </remarks>
1728         static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1729         {
1730                 if (args == null)
1731                         args = NoTypes;
1732                                 
1733                 method_arguments.Add (mb, args);
1734                 method_internal_params.Add (mb, ip);
1735         }
1736         
1737         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1738         {
1739                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1740                         return null;
1741                 
1742                 if (method_internal_params.Contains (mb))
1743                         return (InternalParameters) method_internal_params [mb];
1744                 else
1745                         throw new Exception ("Argument for Method not registered" + mb);
1746         }
1747
1748         /// <summary>
1749         ///    Returns the argument types for a method based on its methodbase
1750         ///
1751         ///    For dynamic methods, we use the compiler provided types, for
1752         ///    methods from existing assemblies we load them from GetParameters,
1753         ///    and insert them into the cache
1754         /// </summary>
1755         static public Type [] GetArgumentTypes (MethodBase mb)
1756         {
1757                 object t = method_arguments [mb];
1758                 if (t != null)
1759                         return (Type []) t;
1760
1761                 ParameterInfo [] pi = mb.GetParameters ();
1762                 int c = pi.Length;
1763                 Type [] types;
1764
1765                 if (c == 0) {
1766                         types = NoTypes;
1767                 } else {
1768                         types = new Type [c];
1769                         for (int i = 0; i < c; i++)
1770                                 types [i] = pi [i].ParameterType;
1771                 }
1772                 method_arguments.Add (mb, types);
1773                 return types;
1774         }
1775
1776         /// <summary>
1777         ///    Returns the argument types for an indexer based on its PropertyInfo
1778         ///
1779         ///    For dynamic indexers, we use the compiler provided types, for
1780         ///    indexers from existing assemblies we load them from GetParameters,
1781         ///    and insert them into the cache
1782         /// </summary>
1783         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1784         {
1785                 if (indexer_arguments.Contains (indexer))
1786                         return (Type []) indexer_arguments [indexer];
1787                 else if (indexer is PropertyBuilder)
1788                         // If we're a PropertyBuilder and not in the
1789                         // `indexer_arguments' hash, then we're a property and
1790                         // not an indexer.
1791                         return NoTypes;
1792                 else {
1793                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1794                         // Property, not an indexer.
1795                         if (pi == null)
1796                                 return NoTypes;
1797                         int c = pi.Length;
1798                         Type [] types = new Type [c];
1799                         
1800                         for (int i = 0; i < c; i++)
1801                                 types [i] = pi [i].ParameterType;
1802
1803                         indexer_arguments.Add (indexer, types);
1804                         return types;
1805                 }
1806         }
1807         
1808         // <remarks>
1809         //  This is a workaround the fact that GetValue is not
1810         //  supported for dynamic types
1811         // </remarks>
1812         static Hashtable fields = new Hashtable ();
1813         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1814         {
1815                 if (fields.Contains (fb))
1816                         return false;
1817
1818                 fields.Add (fb, value);
1819
1820                 return true;
1821         }
1822
1823         static public object GetValue (FieldBuilder fb)
1824         {
1825                 return fields [fb];
1826         }
1827
1828         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1829         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1830         {
1831                 if (fieldbuilders_to_fields.Contains (fb))
1832                         return false;
1833
1834                 fieldbuilders_to_fields.Add (fb, f);
1835                 return true;
1836         }
1837
1838         //
1839         // The return value can be null;  This will be the case for
1840         // auxiliary FieldBuilders created by the compiler that have no
1841         // real field being declared on the source code
1842         //
1843         static public FieldBase GetField (FieldInfo fb)
1844         {
1845                 return (FieldBase) fieldbuilders_to_fields [fb];
1846         }
1847         
1848         static Hashtable events;
1849
1850         static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1851         {
1852                 if (events == null)
1853                         events = new Hashtable ();
1854
1855                 if (!events.Contains (eb)) {
1856                         events.Add (eb, new Pair (add, remove));
1857                 }
1858         }
1859
1860         static public MethodInfo GetAddMethod (EventInfo ei)
1861         {
1862                 if (ei is MyEventBuilder) {
1863                         Pair pair = (Pair) events [ei];
1864
1865                         return (MethodInfo) pair.First;
1866                 }
1867                 return ei.GetAddMethod (true);
1868         }
1869
1870         static public MethodInfo GetRemoveMethod (EventInfo ei)
1871         {
1872                 if (ei is MyEventBuilder) {
1873                         Pair pair = (Pair) events [ei];
1874
1875                         return (MethodInfo) pair.Second;
1876                 }
1877                 return ei.GetRemoveMethod (true);
1878         }
1879
1880         static Hashtable priv_fields_events;
1881
1882         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1883         {
1884                 if (priv_fields_events == null)
1885                         priv_fields_events = new Hashtable ();
1886
1887                 if (priv_fields_events.Contains (einfo))
1888                         return false;
1889
1890                 priv_fields_events.Add (einfo, builder);
1891
1892                 return true;
1893         }
1894
1895         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1896         {
1897                 if (priv_fields_events == null)
1898                         return null;
1899                 else
1900                         return (MemberInfo) priv_fields_events [ei];
1901         }
1902                 
1903         static Hashtable properties;
1904         
1905         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1906         {
1907                 if (properties == null)
1908                         properties = new Hashtable ();
1909
1910                 if (properties.Contains (pb))
1911                         return false;
1912
1913                 properties.Add (pb, new Pair (get, set));
1914
1915                 return true;
1916         }
1917
1918         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1919                                             MethodBase set, Type[] args)
1920         {
1921                 if (!RegisterProperty (pb, get,set))
1922                         return false;
1923
1924                 indexer_arguments.Add (pb, args);
1925
1926                 return true;
1927         }
1928
1929         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1930         {
1931                 Hashtable hash = new Hashtable ();
1932                 return CheckStructCycles (tc, seen, hash);
1933         }
1934
1935         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1936                                               Hashtable hash)
1937         {
1938                 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
1939                         return true;
1940
1941                 //
1942                 // `seen' contains all types we've already visited.
1943                 //
1944                 if (seen.Contains (tc))
1945                         return true;
1946                 seen.Add (tc, null);
1947
1948                 if (tc.Fields == null)
1949                         return true;
1950
1951                 foreach (Field field in tc.Fields) {
1952                         if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1953                                 continue;
1954
1955                         Type ftype = field.FieldBuilder.FieldType;
1956                         TypeContainer ftc = LookupTypeContainer (ftype);
1957                         if (ftc == null)
1958                                 continue;
1959
1960                         if (hash.Contains (ftc)) {
1961                                 Report.Error (523, tc.Location,
1962                                               "Struct member `{0}.{1}' of type `{2}' " +
1963                                               "causes a cycle in the struct layout",
1964                                               tc.Name, field.Name, ftc.Name);
1965                                 return false;
1966                         }
1967
1968                         //
1969                         // `hash' contains all types in the current path.
1970                         //
1971                         hash.Add (tc, null);
1972
1973                         bool ok = CheckStructCycles (ftc, seen, hash);
1974
1975                         hash.Remove (tc);
1976
1977                         if (!ok)
1978                                 return false;
1979
1980                         if (!seen.Contains (ftc))
1981                                 seen.Add (ftc, null);
1982                 }
1983
1984                 return true;
1985         }
1986
1987         /// <summary>
1988         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1989         ///   of an interface.  
1990         /// </summary>
1991         ///
1992         /// <remarks>
1993         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1994         ///   be IA, IB, IC.
1995         /// </remarks>
1996         public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
1997         {
1998                 ArrayList new_ifaces = new ArrayList ();
1999
2000                 foreach (TypeExpr iface in base_interfaces){
2001                         Type itype = iface.ResolveType (ec);
2002                         if (itype == null)
2003                                 return null;
2004
2005                         if (!new_ifaces.Contains (itype))
2006                                 new_ifaces.Add (itype);
2007                         
2008                         Type [] implementing = itype.GetInterfaces ();
2009                         
2010                         foreach (Type imp in implementing){
2011                                 if (!new_ifaces.Contains (imp))
2012                                         new_ifaces.Add (imp);
2013                         }
2014                 }
2015                 Type [] ret = new Type [new_ifaces.Count];
2016                 new_ifaces.CopyTo (ret, 0);
2017                 return ret;
2018         }
2019         
2020         static PtrHashtable iface_cache = new PtrHashtable ();
2021                 
2022         /// <summary>
2023         ///   This function returns the interfaces in the type `t'.  Works with
2024         ///   both types and TypeBuilders.
2025         /// </summary>
2026         public static Type [] GetInterfaces (Type t)
2027         {
2028                 
2029                 Type [] cached = iface_cache [t] as Type [];
2030                 if (cached != null)
2031                         return cached;
2032                 
2033                 //
2034                 // The reason for catching the Array case is that Reflection.Emit
2035                 // will not return a TypeBuilder for Array types of TypeBuilder types,
2036                 // but will still throw an exception if we try to call GetInterfaces
2037                 // on the type.
2038                 //
2039                 // Since the array interfaces are always constant, we return those for
2040                 // the System.Array
2041                 //
2042                 
2043                 if (t.IsArray)
2044                         t = TypeManager.array_type;
2045                 
2046                 if (t is TypeBuilder){
2047                         Type [] base_ifaces;
2048                         
2049                         if (t.BaseType == null)
2050                                 base_ifaces = NoTypes;
2051                         else
2052                                 base_ifaces = GetInterfaces (t.BaseType);
2053                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
2054                         if (type_ifaces == null)
2055                                 type_ifaces = NoTypes;
2056
2057                         int base_count = base_ifaces.Length;
2058                         Type [] result = new Type [base_count + type_ifaces.Length];
2059                         base_ifaces.CopyTo (result, 0);
2060                         type_ifaces.CopyTo (result, base_count);
2061
2062                         iface_cache [t] = result;
2063                         return result;
2064                 } else {
2065                         Type[] ifaces = t.GetInterfaces ();
2066                         iface_cache [t] = ifaces;
2067                         return ifaces;
2068                 }
2069         }
2070         
2071         //
2072         // gets the interfaces that are declared explicitly on t
2073         //
2074         public static Type [] GetExplicitInterfaces (TypeBuilder t)
2075         {
2076                 return (Type []) builder_to_ifaces [t];
2077         }
2078         
2079         /// <remarks>
2080         ///  The following is used to check if a given type implements an interface.
2081         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2082         /// </remarks>
2083         public static bool ImplementsInterface (Type t, Type iface)
2084         {
2085                 Type [] interfaces;
2086
2087                 //
2088                 // FIXME OPTIMIZATION:
2089                 // as soon as we hit a non-TypeBuiler in the interface
2090                 // chain, we could return, as the `Type.GetInterfaces'
2091                 // will return all the interfaces implement by the type
2092                 // or its bases.
2093                 //
2094                 do {
2095                         interfaces = GetInterfaces (t);
2096
2097                         if (interfaces != null){
2098                                 foreach (Type i in interfaces){
2099                                         if (i == iface)
2100                                                 return true;
2101                                 }
2102                         }
2103                         
2104                         t = t.BaseType;
2105                 } while (t != null);
2106                 
2107                 return false;
2108         }
2109
2110         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2111
2112         // This is a custom version of Convert.ChangeType() which works
2113         // with the TypeBuilder defined types when compiling corlib.
2114         public static object ChangeType (object value, Type conversionType, out bool error)
2115         {
2116                 IConvertible convert_value = value as IConvertible;
2117                 
2118                 if (convert_value == null){
2119                         error = true;
2120                         return null;
2121                 }
2122                 
2123                 //
2124                 // We must use Type.Equals() here since `conversionType' is
2125                 // the TypeBuilder created version of a system type and not
2126                 // the system type itself.  You cannot use Type.GetTypeCode()
2127                 // on such a type - it'd always return TypeCode.Object.
2128                 //
2129                 error = false;
2130                 try {
2131                         if (conversionType.Equals (typeof (Boolean)))
2132                                 return (object)(convert_value.ToBoolean (nf_provider));
2133                         else if (conversionType.Equals (typeof (Byte)))
2134                                 return (object)(convert_value.ToByte (nf_provider));
2135                         else if (conversionType.Equals (typeof (Char)))
2136                                 return (object)(convert_value.ToChar (nf_provider));
2137                         else if (conversionType.Equals (typeof (DateTime)))
2138                                 return (object)(convert_value.ToDateTime (nf_provider));
2139                         else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2140                                 return (object)(convert_value.ToDecimal (nf_provider));
2141                         else if (conversionType.Equals (typeof (Double)))
2142                                 return (object)(convert_value.ToDouble (nf_provider));
2143                         else if (conversionType.Equals (typeof (Int16)))
2144                                 return (object)(convert_value.ToInt16 (nf_provider));
2145                         else if (conversionType.Equals (typeof (Int32)))
2146                                 return (object)(convert_value.ToInt32 (nf_provider));
2147                         else if (conversionType.Equals (typeof (Int64)))
2148                                 return (object)(convert_value.ToInt64 (nf_provider));
2149                         else if (conversionType.Equals (typeof (SByte)))
2150                                 return (object)(convert_value.ToSByte (nf_provider));
2151                         else if (conversionType.Equals (typeof (Single)))
2152                                 return (object)(convert_value.ToSingle (nf_provider));
2153                         else if (conversionType.Equals (typeof (String)))
2154                                 return (object)(convert_value.ToString (nf_provider));
2155                         else if (conversionType.Equals (typeof (UInt16)))
2156                                 return (object)(convert_value.ToUInt16 (nf_provider));
2157                         else if (conversionType.Equals (typeof (UInt32)))
2158                                 return (object)(convert_value.ToUInt32 (nf_provider));
2159                         else if (conversionType.Equals (typeof (UInt64)))
2160                                 return (object)(convert_value.ToUInt64 (nf_provider));
2161                         else if (conversionType.Equals (typeof (Object)))
2162                                 return (object)(value);
2163                         else 
2164                                 error = true;
2165                 } catch {
2166                         error = true;
2167                 }
2168                 return null;
2169         }
2170
2171         //
2172         // This is needed, because enumerations from assemblies
2173         // do not report their underlyingtype, but they report
2174         // themselves
2175         //
2176         public static Type EnumToUnderlying (Type t)
2177         {
2178                 if (t == TypeManager.enum_type)
2179                         return t;
2180
2181                 t = t.UnderlyingSystemType;
2182                 if (!TypeManager.IsEnumType (t))
2183                         return t;
2184         
2185                 if (t is TypeBuilder) {
2186                         // slow path needed to compile corlib
2187                         if (t == TypeManager.bool_type ||
2188                             t == TypeManager.byte_type ||
2189                             t == TypeManager.sbyte_type ||
2190                             t == TypeManager.char_type ||
2191                             t == TypeManager.short_type ||
2192                             t == TypeManager.ushort_type ||
2193                             t == TypeManager.int32_type ||
2194                             t == TypeManager.uint32_type ||
2195                             t == TypeManager.int64_type ||
2196                             t == TypeManager.uint64_type)
2197                                 return t;
2198                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2199                 }
2200                 TypeCode tc = Type.GetTypeCode (t);
2201
2202                 switch (tc){
2203                 case TypeCode.Boolean:
2204                         return TypeManager.bool_type;
2205                 case TypeCode.Byte:
2206                         return TypeManager.byte_type;
2207                 case TypeCode.SByte:
2208                         return TypeManager.sbyte_type;
2209                 case TypeCode.Char:
2210                         return TypeManager.char_type;
2211                 case TypeCode.Int16:
2212                         return TypeManager.short_type;
2213                 case TypeCode.UInt16:
2214                         return TypeManager.ushort_type;
2215                 case TypeCode.Int32:
2216                         return TypeManager.int32_type;
2217                 case TypeCode.UInt32:
2218                         return TypeManager.uint32_type;
2219                 case TypeCode.Int64:
2220                         return TypeManager.int64_type;
2221                 case TypeCode.UInt64:
2222                         return TypeManager.uint64_type;
2223                 }
2224                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2225         }
2226
2227         //
2228         // When compiling corlib and called with one of the core types, return
2229         // the corresponding typebuilder for that type.
2230         //
2231         public static Type TypeToCoreType (Type t)
2232         {
2233                 if (RootContext.StdLib || (t is TypeBuilder))
2234                         return t;
2235
2236                 TypeCode tc = Type.GetTypeCode (t);
2237
2238                 switch (tc){
2239                 case TypeCode.Boolean:
2240                         return TypeManager.bool_type;
2241                 case TypeCode.Byte:
2242                         return TypeManager.byte_type;
2243                 case TypeCode.SByte:
2244                         return TypeManager.sbyte_type;
2245                 case TypeCode.Char:
2246                         return TypeManager.char_type;
2247                 case TypeCode.Int16:
2248                         return TypeManager.short_type;
2249                 case TypeCode.UInt16:
2250                         return TypeManager.ushort_type;
2251                 case TypeCode.Int32:
2252                         return TypeManager.int32_type;
2253                 case TypeCode.UInt32:
2254                         return TypeManager.uint32_type;
2255                 case TypeCode.Int64:
2256                         return TypeManager.int64_type;
2257                 case TypeCode.UInt64:
2258                         return TypeManager.uint64_type;
2259                 case TypeCode.Single:
2260                         return TypeManager.float_type;
2261                 case TypeCode.Double:
2262                         return TypeManager.double_type;
2263                 case TypeCode.String:
2264                         return TypeManager.string_type;
2265                 case TypeCode.Decimal:
2266                         return TypeManager.decimal_type;
2267                 default:
2268                         if (t == typeof (void))
2269                                 return TypeManager.void_type;
2270                         if (t == typeof (object))
2271                                 return TypeManager.object_type;
2272                         if (t == typeof (System.Type))
2273                                 return TypeManager.type_type;
2274                         if (t == typeof (System.IntPtr))
2275                                 return TypeManager.intptr_type;
2276                         return t;
2277                 }
2278         }
2279
2280         /// <summary>
2281         ///   Utility function that can be used to probe whether a type
2282         ///   is managed or not.  
2283         /// </summary>
2284         public static bool VerifyUnManaged (Type t, Location loc)
2285         {
2286                 if (t.IsValueType || t.IsPointer){
2287                         //
2288                         // FIXME: this is more complex, we actually need to
2289                         // make sure that the type does not contain any
2290                         // classes itself
2291                         //
2292                         return true;
2293                 }
2294
2295                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2296                         // We need this explicit check here to make it work when
2297                         // compiling corlib.
2298                         return true;
2299
2300                 Report.Error (
2301                         208, loc,
2302                         "Cannot take the address or size of a variable of a managed type ('" +
2303                         CSharpName (t) + "')");
2304                 return false;   
2305         }
2306         
2307         /// <summary>
2308         ///   Returns the name of the indexer in a given type.
2309         /// </summary>
2310         /// <remarks>
2311         ///   The default is not always `Item'.  The user can change this behaviour by
2312         ///   using the IndexerNameAttribute in the container.
2313         ///   For example, the String class indexer is named `Chars' not `Item' 
2314         /// </remarks>
2315         public static string IndexerPropertyName (Type t)
2316         {
2317                 if (t is TypeBuilder) {
2318                         TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2319                         return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2320                 }
2321                 
2322                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2323                         t, TypeManager.default_member_type);
2324                 if (attr != null){
2325                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2326                         return dma.MemberName;
2327                 }
2328
2329                 return TypeContainer.DefaultIndexerName;
2330         }
2331
2332         static MethodInfo declare_local_method = null;
2333         
2334         public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2335         {
2336                 if (declare_local_method == null){
2337                         declare_local_method = typeof (ILGenerator).GetMethod (
2338                                 "DeclareLocal",
2339                                 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2340                                 null, 
2341                                 new Type [] { typeof (Type), typeof (bool)},
2342                                 null);
2343                         if (declare_local_method == null){
2344                                 Report.Warning (-24, new Location (-1),
2345                                                 "This version of the runtime does not support making pinned local variables.  " +
2346                                                 "This code may cause errors on a runtime with a moving GC");
2347                                 return ig.DeclareLocal (t);
2348                         }
2349                 }
2350                 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2351         }
2352         
2353         //
2354         // Returns whether the array of memberinfos contains the given method
2355         //
2356         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2357         {
2358                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2359                 
2360                 foreach (MethodBase method in array) {
2361                         if (method.Name != new_method.Name)
2362                                 continue;
2363
2364                         if (method is MethodInfo && new_method is MethodInfo)
2365                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2366                                         continue;
2367
2368                         
2369                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2370                         int old_count = old_args.Length;
2371                         int i;
2372                         
2373                         if (new_args.Length != old_count)
2374                                 continue;
2375                         
2376                         for (i = 0; i < old_count; i++){
2377                                 if (old_args [i] != new_args [i])
2378                                         break;
2379                         }
2380                         if (i != old_count)
2381                                 continue;
2382
2383                         return true;
2384                 }
2385                 
2386                 return false;
2387         }
2388         
2389         //
2390         // We copy methods from `new_members' into `target_list' if the signature
2391         // for the method from in the new list does not exist in the target_list
2392         //
2393         // The name is assumed to be the same.
2394         //
2395         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2396         {
2397                 if (target_list == null){
2398                         target_list = new ArrayList ();
2399
2400                         foreach (MemberInfo mi in new_members){
2401                                 if (mi is MethodBase)
2402                                         target_list.Add (mi);
2403                         }
2404                         return target_list;
2405                 }
2406                 
2407                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2408                 target_list.CopyTo (target_array, 0);
2409                 
2410                 foreach (MemberInfo mi in new_members){
2411                         MethodBase new_method = (MethodBase) mi;
2412                         
2413                         if (!ArrayContainsMethod (target_array, new_method))
2414                                 target_list.Add (new_method);
2415                 }
2416                 return target_list;
2417         }
2418
2419
2420 #region MemberLookup implementation
2421         
2422         //
2423         // Whether we allow private members in the result (since FindMembers
2424         // uses NonPublic for both protected and private), we need to distinguish.
2425         //
2426
2427         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2428         {
2429                 return true;
2430         }
2431
2432         internal class Closure {
2433                 internal bool     private_ok;
2434
2435                 // Who is invoking us and which type is being queried currently.
2436                 internal Type     invocation_type;
2437                 internal Type     qualifier_type;
2438
2439                 // The assembly that defines the type is that is calling us
2440                 internal Assembly invocation_assembly;
2441                 internal IList almost_match;
2442
2443                 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2444                 {
2445                         if (invocation_type == null)
2446                                 return false;
2447
2448                         Debug.Assert (IsNestedFamilyAccessible (invocation_type, m.DeclaringType));
2449
2450                         if (is_static)
2451                                 return true;
2452                         
2453                         // A nested class has access to all the protected members visible to its parent.
2454                         if (qualifier_type != null
2455                             && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2456                                 return true;
2457
2458                         if (invocation_type == m.DeclaringType
2459                             || invocation_type.IsSubclassOf (m.DeclaringType)) {
2460                                 // Although a derived class can access protected members of its base class
2461                                 // it cannot do so through an instance of the base class (CS1540).
2462                                 // => Ancestry should be: declaring_type ->* invocation_type ->*  qualified_type
2463                                 if (qualifier_type == null
2464                                     || qualifier_type == invocation_type
2465                                     || qualifier_type.IsSubclassOf (invocation_type))
2466                                         return true;
2467                         }
2468
2469                         if (almost_match != null)
2470                                 almost_match.Add (m);
2471                         return false;
2472                 }
2473                 
2474                 //
2475                 // This filter filters by name + whether it is ok to include private
2476                 // members in the search
2477                 //
2478                 internal bool Filter (MemberInfo m, object filter_criteria)
2479                 {
2480                         //
2481                         // Hack: we know that the filter criteria will always be in the `closure'
2482                         // fields. 
2483                         //
2484
2485                         if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2486                                 return false;
2487                         
2488                         if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2489                             (m.DeclaringType == invocation_type))
2490                                 return true;
2491                         
2492                         //
2493                         // Ugly: we need to find out the type of `m', and depending
2494                         // on this, tell whether we accept or not
2495                         //
2496                         if (m is MethodBase){
2497                                 MethodBase mb = (MethodBase) m;
2498                                 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2499
2500                                 if (ma == MethodAttributes.Private)
2501                                         return private_ok || (invocation_type == m.DeclaringType) ||
2502                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2503                                 
2504                                 // Assembly succeeds if we're in the same assembly.
2505                                 if (ma == MethodAttributes.Assembly)
2506                                         return (invocation_assembly == mb.DeclaringType.Assembly);
2507                                 
2508                                 // FamAndAssem requires that we not only derive, but we are on the same assembly.  
2509                                 if (ma == MethodAttributes.FamANDAssem){
2510                                         if (invocation_assembly != mb.DeclaringType.Assembly)
2511                                                 return false;
2512                                 }
2513                                 
2514                                 // Family and FamANDAssem require that we derive.
2515                                 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem))
2516                                         return CheckValidFamilyAccess (mb.IsStatic, m);
2517                                 
2518                                 // Public.
2519                                 return true;
2520                         }
2521                         
2522                         if (m is FieldInfo){
2523                                 FieldInfo fi = (FieldInfo) m;
2524                                 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2525                                 
2526                                 if (fa == FieldAttributes.Private)
2527                                         return private_ok || (invocation_type == m.DeclaringType) ||
2528                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2529                                 
2530                                 // Assembly succeeds if we're in the same assembly.
2531                                 if (fa == FieldAttributes.Assembly)
2532                                         return (invocation_assembly == fi.DeclaringType.Assembly);
2533                                                 
2534                                 // FamAndAssem requires that we not only derive, but we are on the same assembly.  
2535                                 if (fa == FieldAttributes.FamANDAssem){
2536                                         if (invocation_assembly != fi.DeclaringType.Assembly)
2537                                                 return false;
2538                                 }
2539                                 
2540                                 // Family and FamANDAssem require that we derive.
2541                                 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem))
2542                                         return CheckValidFamilyAccess (fi.IsStatic, m);
2543                                 
2544                                 // Public.
2545                                 return true;
2546                         }
2547                         
2548                         //
2549                         // EventInfos and PropertyInfos, return true because they lack permission
2550                         // information, so we need to check later on the methods.
2551                         //
2552                         return true;
2553                 }
2554         }
2555
2556         static Closure closure = new Closure ();
2557         static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2558
2559         //
2560         // Looks up a member called `name' in the `queried_type'.  This lookup
2561         // is done by code that is contained in the definition for `invocation_type'
2562         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2563         //
2564         // `invocation_type' is used to check whether we're allowed to access the requested
2565         // member wrt its protection level.
2566         //
2567         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2568         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2569         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2570         //
2571         // When resolving a SimpleName, `qualifier_type' is null.
2572         //
2573         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2574         // the same than `queried_type' - except when we're being called from BaseAccess;
2575         // in this case, `invocation_type' is the current type and `queried_type' the base
2576         // type, so this'd normally trigger a CS1540.
2577         //
2578         // The binding flags are `bf' and the kind of members being looked up are `mt'
2579         //
2580         // The return value always includes private members which code in `invocation_type'
2581         // is allowed to access (using the specified `qualifier_type' if given); only use
2582         // BindingFlags.NonPublic to bypass the permission check.
2583         //
2584         // The 'almost_match' argument is used for reporting error CS1540.
2585         //
2586         // Returns an array of a single element for everything but Methods/Constructors
2587         // that might return multiple matches.
2588         //
2589         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2590                                                   Type queried_type,  MemberTypes mt,
2591                                                   BindingFlags original_bf, string name, IList almost_match)
2592         {
2593                 Timer.StartTimer (TimerType.MemberLookup);
2594
2595                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2596                                                         queried_type, mt, original_bf, name, almost_match);
2597
2598                 Timer.StopTimer (TimerType.MemberLookup);
2599
2600                 return retval;
2601         }
2602
2603         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2604                                                Type queried_type, MemberTypes mt,
2605                                                BindingFlags original_bf, string name, IList almost_match)
2606         {
2607                 BindingFlags bf = original_bf;
2608                 
2609                 ArrayList method_list = null;
2610                 Type current_type = queried_type;
2611                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2612                 bool skip_iface_check = true, used_cache = false;
2613                 bool always_ok_flag = false;
2614
2615                 closure.invocation_type = invocation_type;
2616                 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2617                 closure.qualifier_type = qualifier_type;
2618                 closure.almost_match = almost_match;
2619
2620                 //
2621                 // If we are a nested class, we always have access to our container
2622                 // type names
2623                 //
2624                 if (invocation_type != null){
2625                         string invocation_name = invocation_type.FullName;
2626                         if (invocation_name.IndexOf ('+') != -1){
2627                                 string container = queried_type.FullName + "+";
2628                                 int container_length = container.Length;
2629
2630                                 if (invocation_name.Length > container_length){
2631                                         string shared = invocation_name.Substring (0, container_length);
2632                                 
2633                                         if (shared == container)
2634                                                 always_ok_flag = true;
2635                                 }
2636                         }
2637                 }
2638                 
2639                 // This is from the first time we find a method
2640                 // in most cases, we do not actually find a method in the base class
2641                 // so we can just ignore it, and save the arraylist allocation
2642                 MemberInfo [] first_members_list = null;
2643                 bool use_first_members_list = false;
2644                 
2645                 do {
2646                         MemberInfo [] list;
2647
2648                         //
2649                         // `NonPublic' is lame, because it includes both protected and
2650                         // private methods, so we need to control this behavior by
2651                         // explicitly tracking if a private method is ok or not.
2652                         //
2653                         // The possible cases are:
2654                         //    public, private and protected (internal does not come into the
2655                         //    equation)
2656                         //
2657                         if ((invocation_type != null) &&
2658                             ((invocation_type == current_type) ||
2659                              IsNestedChildOf (invocation_type, current_type)) ||
2660                             always_ok_flag)
2661                                 bf = original_bf | BindingFlags.NonPublic;
2662                         else
2663                                 bf = original_bf;
2664
2665                         closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2666
2667                         Timer.StopTimer (TimerType.MemberLookup);
2668
2669                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2670
2671                         Timer.StartTimer (TimerType.MemberLookup);
2672
2673                         //
2674                         // When queried for an interface type, the cache will automatically check all
2675                         // inherited members, so we don't need to do this here.  However, this only
2676                         // works if we already used the cache in the first iteration of this loop.
2677                         //
2678                         // If we used the cache in any further iteration, we can still terminate the
2679                         // loop since the cache always looks in all base classes.
2680                         //
2681
2682                         if (used_cache)
2683                                 searching = false;
2684                         else
2685                                 skip_iface_check = false;
2686
2687                         if (current_type == TypeManager.object_type)
2688                                 searching = false;
2689                         else {
2690                                 current_type = current_type.BaseType;
2691                                 
2692                                 //
2693                                 // This happens with interfaces, they have a null
2694                                 // basetype.  Look members up in the Object class.
2695                                 //
2696                                 if (current_type == null) {
2697                                         current_type = TypeManager.object_type;
2698                                         searching = true;
2699                                 }
2700                         }
2701                         
2702                         if (list.Length == 0)
2703                                 continue;
2704
2705                         //
2706                         // Events and types are returned by both `static' and `instance'
2707                         // searches, which means that our above FindMembers will
2708                         // return two copies of the same.
2709                         //
2710                         if (list.Length == 1 && !(list [0] is MethodBase)){
2711                                 return list;
2712                         }
2713
2714                         //
2715                         // Multiple properties: we query those just to find out the indexer
2716                         // name
2717                         //
2718                         if (list [0] is PropertyInfo)
2719                                 return list;
2720
2721                         //
2722                         // We found an event: the cache lookup returns both the event and
2723                         // its private field.
2724                         //
2725                         if (list [0] is EventInfo) {
2726                                 if ((list.Length == 2) && (list [1] is FieldInfo))
2727                                         return new MemberInfo [] { list [0] };
2728
2729                                 // Oooops
2730                                 return null;
2731                         }
2732
2733                         //
2734                         // We found methods, turn the search into "method scan"
2735                         // mode.
2736                         //
2737
2738                         if (first_members_list != null) {
2739                                 if (use_first_members_list) {
2740                                         method_list = CopyNewMethods (method_list, first_members_list);
2741                                         use_first_members_list = false;
2742                                 }
2743                                 
2744                                 method_list = CopyNewMethods (method_list, list);
2745                         } else {
2746                                 first_members_list = list;
2747                                 use_first_members_list = true;
2748                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2749                         }
2750                 } while (searching);
2751                 
2752                 if (use_first_members_list) {
2753                         foreach (MemberInfo mi in first_members_list) {
2754                                 if (! (mi is MethodBase)) {
2755                                         method_list = CopyNewMethods (method_list, first_members_list);
2756                                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2757                                 }
2758                         }
2759                         return (MemberInfo []) first_members_list;
2760                 }
2761
2762                 if (method_list != null && method_list.Count > 0)
2763                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2764                 
2765                 //
2766                 // This happens if we already used the cache in the first iteration, in this case
2767                 // the cache already looked in all interfaces.
2768                 //
2769                 if (skip_iface_check)
2770                         return null;
2771
2772                 //
2773                 // Interfaces do not list members they inherit, so we have to
2774                 // scan those.
2775                 // 
2776                 if (!queried_type.IsInterface)
2777                         return null;
2778
2779                 if (queried_type.IsArray)
2780                         queried_type = TypeManager.array_type;
2781                 
2782                 Type [] ifaces = GetInterfaces (queried_type);
2783                 if (ifaces == null)
2784                         return null;
2785                 
2786                 foreach (Type itype in ifaces){
2787                         MemberInfo [] x;
2788
2789                         x = MemberLookup (null, null, itype, mt, bf, name, null);
2790                         if (x != null)
2791                                 return x;
2792                 }
2793                                         
2794                 return null;
2795         }
2796
2797         // Tests whether external method is really special
2798         public static bool IsSpecialMethod (MethodBase mb)
2799         {
2800                 string name = mb.Name;
2801                 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
2802                         return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
2803
2804                 if (name.StartsWith ("add_"))
2805                         return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
2806
2807                 if (name.StartsWith ("remove_"))
2808                         return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
2809
2810                 if (name.StartsWith ("op_")){
2811                         foreach (string oname in Unary.oper_names) {
2812                                 if (oname == name)
2813                                         return true;
2814                         }
2815                 
2816                         foreach (string oname in Binary.oper_names) {
2817                                 if (oname == name)
2818                                         return true;
2819                         }
2820                 }
2821                 return false;
2822         }
2823                 
2824 #endregion
2825         
2826 }
2827
2828 /// <summary>
2829 ///   There is exactly one instance of this class per type.
2830 /// </summary>
2831 public sealed class TypeHandle : IMemberContainer {
2832         public readonly TypeHandle BaseType;
2833
2834         readonly int id = ++next_id;
2835         static int next_id = 0;
2836
2837         /// <summary>
2838         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2839         ///   a TypeHandle yet, a new instance of it is created.  This static method
2840         ///   ensures that we'll only have one TypeHandle instance per type.
2841         /// </summary>
2842         private static TypeHandle GetTypeHandle (Type t)
2843         {
2844                 TypeHandle handle = (TypeHandle) type_hash [t];
2845                 if (handle != null)
2846                         return handle;
2847
2848                 handle = new TypeHandle (t);
2849                 type_hash.Add (t, handle);
2850                 return handle;
2851         }
2852
2853         public static MemberCache GetMemberCache (Type t)
2854         {
2855                 return GetTypeHandle (t).MemberCache;
2856         }
2857         
2858         public static void CleanUp ()
2859         {
2860                 type_hash = null;
2861         }
2862
2863         /// <summary>
2864         ///   Returns the TypeHandle for TypeManager.object_type.
2865         /// </summary>
2866         public static IMemberContainer ObjectType {
2867                 get {
2868                         if (object_type != null)
2869                                 return object_type;
2870
2871                         object_type = GetTypeHandle (TypeManager.object_type);
2872
2873                         return object_type;
2874                 }
2875         }
2876
2877         /// <summary>
2878         ///   Returns the TypeHandle for TypeManager.array_type.
2879         /// </summary>
2880         public static IMemberContainer ArrayType {
2881                 get {
2882                         if (array_type != null)
2883                                 return array_type;
2884
2885                         array_type = GetTypeHandle (TypeManager.array_type);
2886
2887                         return array_type;
2888                 }
2889         }
2890
2891         private static PtrHashtable type_hash = new PtrHashtable ();
2892
2893         private static TypeHandle object_type = null;
2894         private static TypeHandle array_type = null;
2895
2896         private Type type;
2897         private bool is_interface;
2898         private MemberCache member_cache;
2899         private MemberCache base_cache;
2900
2901         private TypeHandle (Type type)
2902         {
2903                 this.type = type;
2904                 if (type.BaseType != null) {
2905                         BaseType = GetTypeHandle (type.BaseType);
2906                         base_cache = BaseType.MemberCache;
2907                 } else if (type.IsInterface)
2908                         base_cache = TypeManager.LookupBaseInterfacesCache (type);
2909                 this.is_interface = type.IsInterface;
2910                 this.member_cache = new MemberCache (this);
2911         }
2912
2913         // IMemberContainer methods
2914
2915         public string Name {
2916                 get {
2917                         return type.FullName;
2918                 }
2919         }
2920
2921         public Type Type {
2922                 get {
2923                         return type;
2924                 }
2925         }
2926
2927         public MemberCache BaseCache {
2928                 get {
2929                         return base_cache;
2930                 }
2931         }
2932
2933         public bool IsInterface {
2934                 get {
2935                         return is_interface;
2936                 }
2937         }
2938
2939         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2940         {
2941                 MemberInfo [] members;
2942                 if (mt == MemberTypes.Event)
2943                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2944                 else
2945                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2946                                                     null, null);
2947                 Array.Reverse (members);
2948
2949                 return new MemberList (members);
2950         }
2951
2952         // IMemberFinder methods
2953
2954         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2955                                        MemberFilter filter, object criteria)
2956         {
2957                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
2958         }
2959
2960         public MemberCache MemberCache {
2961                 get {
2962                         return member_cache;
2963                 }
2964         }
2965
2966         public override string ToString ()
2967         {
2968                 if (BaseType != null)
2969                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2970                 else
2971                         return "TypeHandle (" + id + "," + Name + ")";
2972         }
2973 }
2974
2975 }