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