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