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