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