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