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