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