**** Merged r40464 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 #if NET_2_0
106         static internal Type compiler_generated_attr_type;
107         static internal Type fixed_buffer_attr_type;
108 #endif
109
110         //
111         // An empty array of types
112         //
113         static public Type [] NoTypes;
114         static public TypeExpr [] NoTypeExprs;
115
116
117         // 
118         // Expressions representing the internal types.  Used during declaration
119         // definition.
120         //
121         static public TypeExpr system_object_expr, system_string_expr; 
122         static public TypeExpr system_boolean_expr, system_decimal_expr;
123         static public TypeExpr system_single_expr, system_double_expr;
124         static public TypeExpr system_sbyte_expr, system_byte_expr;
125         static public TypeExpr system_int16_expr, system_uint16_expr;
126         static public TypeExpr system_int32_expr, system_uint32_expr;
127         static public TypeExpr system_int64_expr, system_uint64_expr;
128         static public TypeExpr system_char_expr, system_void_expr;
129         static public TypeExpr system_asynccallback_expr;
130         static public TypeExpr system_iasyncresult_expr;
131         static public TypeExpr system_valuetype_expr;
132         static public TypeExpr system_intptr_expr;
133
134         //
135         // This is only used when compiling corlib
136         //
137         static public Type system_int32_type;
138         static public Type system_array_type;
139         static public Type system_type_type;
140         static public Type system_assemblybuilder_type;
141         static public MethodInfo system_int_array_get_length;
142         static public MethodInfo system_int_array_get_rank;
143         static public MethodInfo system_object_array_clone;
144         static public MethodInfo system_int_array_get_length_int;
145         static public MethodInfo system_int_array_get_lower_bound_int;
146         static public MethodInfo system_int_array_get_upper_bound_int;
147         static public MethodInfo system_void_array_copyto_array_int;
148
149         
150         //
151         // Internal, not really used outside
152         //
153         static Type runtime_helpers_type;
154         
155         //
156         // These methods are called by code generated by the compiler
157         //
158         static public MethodInfo string_concat_string_string;
159         static public MethodInfo string_concat_string_string_string;
160         static public MethodInfo string_concat_string_string_string_string;
161         static public MethodInfo string_concat_string_dot_dot_dot;
162         static public MethodInfo string_concat_object_object;
163         static public MethodInfo string_concat_object_object_object;
164         static public MethodInfo string_concat_object_dot_dot_dot;
165         static public MethodInfo string_isinterneted_string;
166         static public MethodInfo system_type_get_type_from_handle;
167         static public MethodInfo object_getcurrent_void;
168         static public MethodInfo bool_movenext_void;
169         static public MethodInfo ienumerable_getenumerator_void;
170         static public MethodInfo void_reset_void;
171         static public MethodInfo void_dispose_void;
172         static public MethodInfo void_monitor_enter_object;
173         static public MethodInfo void_monitor_exit_object;
174         static public MethodInfo void_initializearray_array_fieldhandle;
175         static public MethodInfo int_getlength_int;
176         static public MethodInfo delegate_combine_delegate_delegate;
177         static public MethodInfo delegate_remove_delegate_delegate;
178         static public MethodInfo int_get_offset_to_string_data;
179         static public MethodInfo int_array_get_length;
180         static public MethodInfo int_array_get_rank;
181         static public MethodInfo object_array_clone;
182         static public MethodInfo int_array_get_length_int;
183         static public MethodInfo int_array_get_lower_bound_int;
184         static public MethodInfo int_array_get_upper_bound_int;
185         static public MethodInfo void_array_copyto_array_int;
186         
187         //
188         // The attribute constructors.
189         //
190         static public ConstructorInfo object_ctor;
191         static public ConstructorInfo cons_param_array_attribute;
192         static public ConstructorInfo void_decimal_ctor_five_args;
193         static public ConstructorInfo void_decimal_ctor_int_arg;
194         static public ConstructorInfo unverifiable_code_ctor;
195         static public ConstructorInfo default_member_ctor;
196         static public ConstructorInfo decimal_constant_attribute_ctor;
197         static internal ConstructorInfo struct_layout_attribute_ctor;
198
199         ///
200         /// A new in C# 2.0
201         /// 
202 #if NET_2_0
203         static internal CustomAttributeBuilder compiler_generated_attr;
204         static internal ConstructorInfo fixed_buffer_attr_ctor;
205 #endif
206
207         // <remarks>
208         //   Holds the Array of Assemblies that have been loaded
209         //   (either because it is the default or the user used the
210         //   -r command line option)
211         // </remarks>
212         static Assembly [] assemblies;
213
214         // <remarks>
215         //  Keeps a list of modules. We used this to do lookups
216         //  on the module using GetType -- needed for arrays
217         // </remarks>
218         static Module [] modules;
219
220         // <remarks>
221         //   This is the type_cache from the assemblies to avoid
222         //   hitting System.Reflection on every lookup.
223         // </summary>
224         static Hashtable types;
225
226         // <remarks>
227         //  This is used to hotld the corresponding TypeContainer objects
228         //  since we need this in FindMembers
229         // </remarks>
230         static Hashtable typecontainers;
231
232         // <remarks>
233         //   Keeps track of those types that are defined by the
234         //   user's program
235         // </remarks>
236         static ArrayList user_types;
237
238         static PtrHashtable builder_to_declspace;
239
240         static PtrHashtable builder_to_member_cache;
241
242         // <remarks>
243         //   Tracks the interfaces implemented by typebuilders.  We only
244         //   enter those who do implement or or more interfaces
245         // </remarks>
246         static PtrHashtable builder_to_ifaces;
247
248         // <remarks>
249         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
250         //   the arguments to the method
251         // </remarks>
252         static Hashtable method_arguments;
253
254         // <remarks>
255         //   Maps PropertyBuilder to a Type array that contains
256         //   the arguments to the indexer
257         // </remarks>
258         static Hashtable indexer_arguments;
259
260         // <remarks>
261         //   Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
262         // <remarks>
263         static Hashtable method_params;
264
265         // <remarks>
266         //  Keeps track of methods
267         // </remarks>
268
269         static Hashtable builder_to_method;
270
271         // <remarks>
272         //  Contains all public types from referenced assemblies.
273         //  This member is used only if CLS Compliance verification is required.
274         // </remarks>
275         public static Hashtable all_imported_types;
276
277         struct Signature {
278                 public string name;
279                 public Type [] args;
280         }
281
282         public static void CleanUp ()
283         {
284                 // Lets get everything clean so that we can collect before generating code
285                 assemblies = null;
286                 modules = null;
287                 types = null;
288                 typecontainers = null;
289                 user_types = null;
290                 builder_to_declspace = null;
291                 builder_to_member_cache = null;
292                 builder_to_ifaces = null;
293                 method_arguments = null;
294                 indexer_arguments = null;
295                 method_params = null;
296                 builder_to_method = null;
297                 
298                 fields = null;
299                 references = null;
300                 negative_hits = null;
301                 builder_to_constant = null;
302                 fieldbuilders_to_fields = null;
303                 events = null;
304                 priv_fields_events = null;
305                 properties = null;
306
307                 CleanUpGenerics ();             
308                 TypeHandle.CleanUp ();
309         }
310
311         /// <summary>
312         ///   A filter for Findmembers that uses the Signature object to
313         ///   extract objects
314         /// </summary>
315         static bool SignatureFilter (MemberInfo mi, object criteria)
316         {
317                 Signature sig = (Signature) criteria;
318
319                 if (!(mi is MethodBase))
320                         return false;
321                 
322                 if (mi.Name != sig.name)
323                         return false;
324
325                 int count = sig.args.Length;
326                 
327                 if (mi is MethodBuilder || mi is ConstructorBuilder){
328                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
329
330                         if (candidate_args.Length != count)
331                                 return false;
332                         
333                         for (int i = 0; i < count; i++)
334                                 if (candidate_args [i] != sig.args [i])
335                                         return false;
336                         
337                         return true;
338                 } else {
339                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
340
341                         if (pars.Length != count)
342                                 return false;
343
344                         for (int i = 0; i < count; i++)
345                                 if (pars [i].ParameterType != sig.args [i])
346                                         return false;
347                         return true;
348                 }
349         }
350
351         // A delegate that points to the filter above.
352         static MemberFilter signature_filter;
353
354         //
355         // These are expressions that represent some of the internal data types, used
356         // elsewhere
357         //
358         static void InitExpressionTypes ()
359         {
360                 system_object_expr  = new TypeLookupExpression ("System.Object");
361                 system_string_expr  = new TypeLookupExpression ("System.String");
362                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
363                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
364                 system_single_expr  = new TypeLookupExpression ("System.Single");
365                 system_double_expr  = new TypeLookupExpression ("System.Double");
366                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
367                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
368                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
369                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
370                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
371                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
372                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
373                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
374                 system_char_expr    = new TypeLookupExpression ("System.Char");
375                 system_void_expr    = new TypeLookupExpression ("System.Void");
376                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
377                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
378                 system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
379                 system_intptr_expr  = new TypeLookupExpression ("System.IntPtr");
380         }
381
382         static TypeManager ()
383         {
384                 assemblies = new Assembly [0];
385                 modules = null;
386                 user_types = new ArrayList ();
387                 
388                 types = new Hashtable ();
389                 typecontainers = new Hashtable ();
390                 
391                 builder_to_declspace = new PtrHashtable ();
392                 builder_to_member_cache = new PtrHashtable ();
393                 builder_to_method = new PtrHashtable ();
394                 method_arguments = new PtrHashtable ();
395                 method_params = new PtrHashtable ();
396                 indexer_arguments = new PtrHashtable ();
397                 builder_to_ifaces = new PtrHashtable ();
398                 
399                 NoTypes = new Type [0];
400                 NoTypeExprs = new TypeExpr [0];
401
402                 signature_filter = new MemberFilter (SignatureFilter);
403                 InitGenerics ();
404                 InitExpressionTypes ();
405         }
406
407         public static void HandleDuplicate (string name, Type t)
408         {
409                 Type prev = (Type) types [name];
410                 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
411                 
412                 if (tc != null){
413                         //
414                         // This probably never happens, as we catch this before
415                         //
416                         Report.Error (-17, "The type `" + name + "' has already been defined.");
417                         return;
418                 }
419                 
420                 tc = builder_to_declspace [t] as TypeContainer;
421                 if (tc != null){
422                         Report.Warning (
423                                         1595, "The type `" + name + "' is defined in an existing assembly;"+
424                                         " Using the new definition from: " + tc.Location);
425                 } else {
426                         Report.Warning (
427                                         1595, "The type `" + name + "' is defined in an existing assembly;");
428                 }
429                 
430                 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
431                 
432                 types.Remove (name);
433                 types.Add (name, t);
434         }
435         
436         public static void AddUserType (string name, TypeBuilder t)
437         {
438                 try {
439                         types.Add (name, t);
440                 } catch {
441                         HandleDuplicate (name, t); 
442                 }
443                 user_types.Add (t);
444         }
445
446         //
447         // This entry point is used by types that we define under the covers
448         // 
449         public static void RegisterBuilder (Type tb, Type [] ifaces)
450         {
451                 if (ifaces != null)
452                         builder_to_ifaces [tb] = ifaces;
453         }
454         
455         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
456         {
457                 builder_to_declspace.Add (t, tc);
458                 typecontainers.Add (name, tc);
459                 AddUserType (name, t);
460         }
461
462         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
463         {
464                 try {
465                         types.Add (name, t);
466                 } catch {
467                         HandleDuplicate (name, t);
468                 }
469                 
470                 builder_to_declspace.Add (t, del);
471         }
472         
473         public static void AddEnumType (string name, TypeBuilder t, Enum en)
474         {
475                 try {
476                         types.Add (name, t);
477                 } catch {
478                         HandleDuplicate (name, t);
479                 }
480                 builder_to_declspace.Add (t, en);
481         }
482
483         public static void AddMethod (MethodBase builder, IMethodData method)
484         {
485                 builder_to_method.Add (builder, method);
486         }
487
488         public static IMethodData GetMethod (MethodBase builder)
489         {
490                 return (IMethodData) builder_to_method [builder];
491         }
492
493         /// <summary>
494         ///   Returns the DeclSpace whose Type is `t' or null if there is no
495         ///   DeclSpace for `t' (ie, the Type comes from a library)
496         /// </summary>
497         public static DeclSpace LookupDeclSpace (Type t)
498         {
499                 return builder_to_declspace [t] as DeclSpace;
500         }
501
502         /// <summary>
503         ///   Returns the TypeContainer whose Type is `t' or null if there is no
504         ///   TypeContainer for `t' (ie, the Type comes from a library)
505         /// </summary>
506         public static TypeContainer LookupTypeContainer (Type t)
507         {
508                 return builder_to_declspace [t] as TypeContainer;
509         }
510
511         public static MemberCache LookupMemberCache (Type t)
512         {
513                 if (t is TypeBuilder) {
514                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
515                         if (container != null)
516                                 return container.MemberCache;
517                 }
518
519                 if (t is GenericTypeParameterBuilder) {
520                         IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
521
522                         if (container != null)
523                                 return container.MemberCache;
524                 }
525
526                 return TypeHandle.GetMemberCache (t);
527         }
528
529         public static MemberCache LookupBaseInterfacesCache (Type t)
530         {
531                 Type [] ifaces = t.GetInterfaces ();
532
533                 if (ifaces != null && ifaces.Length == 1)
534                         return LookupMemberCache (ifaces [0]);
535
536                 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
537                 MemberCache cache = builder_to_member_cache [t] as MemberCache;
538                 if (cache != null)
539                         return cache;
540
541                 cache = new MemberCache (ifaces);
542                 builder_to_member_cache.Add (t, cache);
543                 return cache;
544         }
545
546         public static TypeContainer LookupInterface (Type t)
547         {
548                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
549                 if ((tc == null) || (tc.Kind != Kind.Interface))
550                         return null;
551
552                 return tc;
553         }
554
555         public static Delegate LookupDelegate (Type t)
556         {
557                 return builder_to_declspace [t] as Delegate;
558         }
559
560         public static Enum LookupEnum (Type t)
561         {
562                 return builder_to_declspace [t] as Enum;
563         }
564         
565         public static Class LookupClass (Type t)
566         {
567                 return (Class) builder_to_declspace [t];
568         }
569         
570         /// <summary>
571         ///   Registers an assembly to load types from.
572         /// </summary>
573         public static void AddAssembly (Assembly a)
574         {
575                 foreach (Assembly assembly in assemblies) {
576                         if (a == assembly)
577                                 return;
578                 }
579
580                 int top = assemblies.Length;
581                 Assembly [] n = new Assembly [top + 1];
582
583                 assemblies.CopyTo (n, 0);
584                 
585                 n [top] = a;
586                 assemblies = n;
587         }
588
589         public static Assembly [] GetAssemblies ()
590         {
591                 return assemblies;
592         }
593
594         /// <summary>
595         ///  Registers a module builder to lookup types from
596         /// </summary>
597         public static void AddModule (Module mb)
598         {
599                 int top = modules != null ? modules.Length : 0;
600                 Module [] n = new Module [top + 1];
601
602                 if (modules != null)
603                         modules.CopyTo (n, 0);
604                 n [top] = mb;
605                 modules = n;
606         }
607
608         public static Module[] Modules {
609                 get {
610                         return modules;
611                 }
612         }
613
614         static Hashtable references = new Hashtable ();
615         
616         //
617         // Gets the reference to T version of the Type (T&)
618         //
619         public static Type GetReferenceType (Type t)
620         {
621                 return t.MakeByRefType ();
622         }
623
624         static Hashtable pointers = new Hashtable ();
625
626         //
627         // Gets the pointer to T version of the Type  (T*)
628         //
629         public static Type GetPointerType (Type t)
630         {
631                 string tname = t.FullName + "*";
632                 
633                 Type ret = t.Assembly.GetType (tname);
634                 
635                 //
636                 // If the type comes from the assembly we are building
637                 // We need the Hashtable, because .NET 1.1 will return different instance types
638                 // every time we call ModuleBuilder.GetType.
639                 //
640                 if (ret == null){
641                         if (pointers [t] == null)
642                                 pointers [t] = CodeGen.Module.Builder.GetType (tname);
643                         
644                         ret = (Type) pointers [t];
645                 }
646
647                 return ret;
648         }
649         
650         //
651         // Low-level lookup, cache-less
652         //
653         static Type LookupTypeReflection (string name)
654         {
655                 Type t;
656
657                 foreach (Assembly a in assemblies){
658                         t = a.GetType (name);
659                         if (t == null)
660                                 continue;
661
662                         do {
663                                 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
664                                 if (ta == TypeAttributes.NotPublic ||
665                                     ta == TypeAttributes.NestedPrivate ||
666                                     ta == TypeAttributes.NestedAssembly ||
667                                     ta == TypeAttributes.NestedFamANDAssem){
668                                         
669                                         //
670                                         // In .NET pointers turn out to be private, even if their
671                                         // element type is not
672                                         //
673                                         if (t.IsPointer){
674                                                 t = t.GetElementType ();
675                                                 continue;
676                                         } else
677                                                 t = null;
678                                 } else {
679                                         return t;
680                                 }
681                         } while (t != null);
682                 }
683
684                 foreach (Module mb in modules) {
685                         t = mb.GetType (name);
686                         if (t != null) 
687                                 return t;
688                 }
689                         
690                 return null;
691         }
692
693         static Hashtable negative_hits = new Hashtable ();
694         
695         //
696         // This function is used when you want to avoid the lookups, and want to go
697         // directly to the source.  This will use the cache.
698         //
699         // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
700         // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
701         // way to test things other than doing a fullname compare
702         //
703         public static Type LookupTypeDirect (string name)
704         {
705                 Type t = (Type) types [name];
706                 if (t != null)
707                         return t;
708
709                 t = LookupTypeReflection (name);
710                 if (t == null)
711                         return null;
712
713                 types [name] = t;
714                 return t;
715         }
716
717         static readonly char [] dot_array = { '.' };
718
719         /// <summary>
720         ///   Returns the Type associated with @name, takes care of the fact that
721         ///   reflection expects nested types to be separated from the main type
722         ///   with a "+" instead of a "."
723         /// </summary>
724         public static Type LookupType (string name)
725         {
726                 Type t;
727
728                 //
729                 // First lookup in user defined and cached values
730                 //
731
732                 t = (Type) types [name];
733                 if (t != null)
734                         return t;
735
736                 // Two thirds of the failures are caught here.
737                 if (negative_hits.Contains (name))
738                         return null;
739
740                 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
741                 string [] elements = name.Split (dot_array);
742                 int count = elements.Length;
743
744                 for (int n = 1; n <= count; n++){
745                         string top_level_type = String.Join (".", elements, 0, n);
746
747                         // One third of the failures are caught here.
748                         if (negative_hits.Contains (top_level_type))
749                                 continue;
750                         
751                         t = (Type) types [top_level_type];
752                         if (t == null){
753                                 t = LookupTypeReflection (top_level_type);
754                                 if (t == null){
755                                         negative_hits [top_level_type] = null;
756                                         continue;
757                                 }
758                         }
759                         
760                         if (count == n){
761                                 types [name] = t;
762                                 return t;
763                         } 
764
765                         //
766                         // We know that System.Object does not have children, and since its the base of 
767                         // all the objects, it always gets probbed for inner classes. 
768                         //
769                         if (top_level_type == "System.Object")
770                                 return null;
771                         
772                         string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
773                         //Console.WriteLine ("Looking up: " + newt + " " + name);
774                         t = LookupTypeReflection (newt);
775                         if (t == null)
776                                 negative_hits [name] = null;
777                         else
778                                 types [name] = t;
779                         return t;
780                 }
781                 negative_hits [name] = null;
782                 return null;
783         }
784
785         /// <summary>
786         ///   Computes the namespaces that we import from the assemblies we reference.
787         /// </summary>
788         public static void ComputeNamespaces ()
789         {
790                 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
791
792                 //
793                 // First add the assembly namespaces
794                 //
795                 if (assembly_get_namespaces != null){
796                         int count = assemblies.Length;
797
798                         for (int i = 0; i < count; i++){
799                                 Assembly a = assemblies [i];
800                                 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
801                                 foreach (string ns in namespaces){
802                                         if (ns == "")
803                                                 continue;
804                                         Namespace.LookupNamespace (ns, true);
805                                 }
806                         }
807                 } else {
808                         Hashtable cache = new Hashtable ();
809                         cache.Add ("", null);
810                         foreach (Assembly a in assemblies) {
811                                 foreach (Type t in a.GetExportedTypes ()) {
812                                         string ns = t.Namespace;
813                                         if (ns == null || cache.Contains (ns))
814                                                 continue;
815
816                                         Namespace.LookupNamespace (ns, true);
817                                         cache.Add (ns, null);
818                                 }
819                         }
820                 }
821         }
822
823         /// <summary>
824         /// Fills static table with exported types from all referenced assemblies.
825         /// This information is required for CLS Compliance tests.
826         /// </summary>
827         public static void LoadAllImportedTypes ()
828         {
829                 all_imported_types = new Hashtable ();
830                 foreach (Assembly a in assemblies) {
831                         foreach (Type t in a.GetExportedTypes ()) {
832                                 all_imported_types [t.FullName] = t;
833                         }
834                 }
835         }
836
837         public static bool NamespaceClash (string name, Location loc)
838         {
839                 if (Namespace.LookupNamespace (name, false) == null)
840                         return false;
841
842                 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
843                 return true;
844         }
845
846         /// <summary>
847         ///   Returns the C# name of a type if possible, or the full type name otherwise
848         /// </summary>
849         static public string CSharpName (Type t)
850         {
851                 if (t.FullName == null)
852                         return t.Name;
853
854                 return Regex.Replace (t.FullName, 
855                         @"^System\." +
856                         @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
857                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
858                         @"Boolean|String|Void|Null)" +
859                         @"(\W+|\b)", 
860                         new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
861         }       
862         
863         static String CSharpNameMatch (Match match) 
864         {
865                 string s = match.Groups [1].Captures [0].Value;
866                 return s.ToLower ().
867                 Replace ("int32", "int").
868                 Replace ("uint32", "uint").
869                 Replace ("int16", "short").
870                 Replace ("uint16", "ushort").
871                 Replace ("int64", "long").
872                 Replace ("uint64", "ulong").
873                 Replace ("single", "float").
874                 Replace ("boolean", "bool")
875                 + match.Groups [2].Captures [0].Value;
876         }
877
878         /// <summary>
879         ///  Returns the signature of the method with full namespace classification
880         /// </summary>
881         static public string GetFullNameSignature (MemberInfo mi)
882         {
883                 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
884                 return (mi is MethodBase)
885                         ? GetFullNameSignature (mi as MethodBase) 
886                         : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
887         }
888                 
889         static public string GetFullNameSignature (MethodBase mb)
890         {
891                 string name = mb.Name;
892                 if (name == ".ctor")
893                         name = mb.DeclaringType.Name;
894
895                 if (mb.IsSpecialName) {
896                         if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
897                                 name = name.Remove (0, 4);
898                         }
899
900                         if (name == "Item")
901                                 name = "this";
902                 }
903
904                 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
905         }
906
907         static public string GetFullName (Type t)
908         {
909                 if (t.FullName == null)
910                         return t.Name;
911
912                 string name = t.FullName.Replace ('+', '.');
913
914                 DeclSpace tc = LookupDeclSpace (t);
915                 if ((tc != null) && tc.IsGeneric) {
916                         TypeParameter[] tparam = tc.TypeParameters;
917
918                         StringBuilder sb = new StringBuilder (name);
919                         sb.Append ("<");
920                         for (int i = 0; i < tparam.Length; i++) {
921                                 if (i > 0)
922                                         sb.Append (",");
923                                 sb.Append (tparam [i].Name);
924                         }
925                         sb.Append (">");
926                         return sb.ToString ();
927                 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
928                         Type[] tparam = t.GetGenericArguments ();
929
930                         StringBuilder sb = new StringBuilder (name);
931                         sb.Append ("<");
932                         for (int i = 0; i < tparam.Length; i++) {
933                                 if (i > 0)
934                                         sb.Append (",");
935                                 sb.Append (tparam [i].Name);
936                         }
937                         sb.Append (">");
938                         return sb.ToString ();
939                 }
940
941                 return name;
942         }
943
944         /// <summary>
945         ///   Returns the signature of the property and indexer
946         /// </summary>
947         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
948         {
949                 if (!is_indexer) {
950                         return GetFullNameSignature (pb);
951                 }
952
953                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
954                 string signature = GetFullNameSignature (mb);
955                 string arg = GetParameterData (mb).ParameterDesc (0);
956                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
957         }
958
959         /// <summary>
960         ///   Returns the signature of the method
961         /// </summary>
962         static public string CSharpSignature (MethodBase mb)
963         {
964                 StringBuilder sig = new StringBuilder ("(");
965
966                 ParameterData iparams = GetParameterData (mb);
967
968                 // Is property
969                 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
970                         return GetFullNameSignature (mb);
971                 
972                 for (int i = 0; i < iparams.Count; i++) {
973                         if (i > 0) {
974                                 sig.Append (", ");
975                         }
976                         sig.Append (iparams.ParameterDesc (i));
977                 }
978                 sig.Append (")");
979
980                 // Is indexer
981                 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
982                         sig.Replace ('(', '[');
983                         sig.Replace (')', ']');
984                 }
985
986                 return GetFullNameSignature (mb) + sig.ToString ();
987         }
988
989         public static string GetMethodName (MethodInfo m)
990         {
991                 if (!IsGenericMethod (m))
992                         return m.Name;
993
994                 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
995         }
996
997         /// <summary>
998         ///   Looks up a type, and aborts if it is not found.  This is used
999         ///   by types required by the compiler
1000         /// </summary>
1001         static Type CoreLookupType (string name)
1002         {
1003                 Type t = LookupTypeDirect (name);
1004
1005                 if (t == null){
1006                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1007                         Environment.Exit (1);
1008                 }
1009
1010                 return t;
1011         }
1012
1013         /// <summary>
1014         ///   Returns the MethodInfo for a method named `name' defined
1015         ///   in type `t' which takes arguments of types `args'
1016         /// </summary>
1017         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1018         {
1019                 MemberList list;
1020                 Signature sig;
1021                 BindingFlags flags = instance_and_static | BindingFlags.Public;
1022
1023                 sig.name = name;
1024                 sig.args = args;
1025                 
1026                 if (is_private)
1027                         flags |= BindingFlags.NonPublic;
1028
1029                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1030                 if (list.Count == 0) {
1031                         if (report_errors)
1032                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1033                         return null;
1034                 }
1035
1036                 MethodInfo mi = list [0] as MethodInfo;
1037                 if (mi == null) {
1038                         if (report_errors)
1039                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1040                         return null;
1041                 }
1042
1043                 return mi;
1044         }
1045
1046         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1047         {
1048                 return GetMethod (t, name, args, false, report_errors);
1049         }
1050
1051         static MethodInfo GetMethod (Type t, string name, Type [] args)
1052         {
1053                 return GetMethod (t, name, args, true);
1054         }
1055
1056
1057         /// <summary>
1058         ///    Returns the ConstructorInfo for "args"
1059         /// </summary>
1060         static ConstructorInfo GetConstructor (Type t, Type [] args)
1061         {
1062                 MemberList list;
1063                 Signature sig;
1064
1065                 sig.name = ".ctor";
1066                 sig.args = args;
1067                 
1068                 list = FindMembers (t, MemberTypes.Constructor,
1069                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1070                                     signature_filter, sig);
1071                 if (list.Count == 0){
1072                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1073                         return null;
1074                 }
1075
1076                 ConstructorInfo ci = list [0] as ConstructorInfo;
1077                 if (ci == null){
1078                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1079                         return null;
1080                 }
1081
1082                 return ci;
1083         }
1084
1085         public static void InitEnumUnderlyingTypes ()
1086         {
1087
1088                 int32_type    = CoreLookupType ("System.Int32");
1089                 int64_type    = CoreLookupType ("System.Int64");
1090                 uint32_type   = CoreLookupType ("System.UInt32"); 
1091                 uint64_type   = CoreLookupType ("System.UInt64"); 
1092                 byte_type     = CoreLookupType ("System.Byte");
1093                 sbyte_type    = CoreLookupType ("System.SByte");
1094                 short_type    = CoreLookupType ("System.Int16");
1095                 ushort_type   = CoreLookupType ("System.UInt16");
1096         }
1097         
1098         /// <remarks>
1099         ///   The types have to be initialized after the initial
1100         ///   population of the type has happened (for example, to
1101         ///   bootstrap the corlib.dll
1102         /// </remarks>
1103         public static void InitCoreTypes ()
1104         {
1105                 object_type   = CoreLookupType ("System.Object");
1106                 value_type    = CoreLookupType ("System.ValueType");
1107
1108                 InitEnumUnderlyingTypes ();
1109
1110                 char_type     = CoreLookupType ("System.Char");
1111                 string_type   = CoreLookupType ("System.String");
1112                 float_type    = CoreLookupType ("System.Single");
1113                 double_type   = CoreLookupType ("System.Double");
1114                 char_ptr_type = CoreLookupType ("System.Char*");
1115                 decimal_type  = CoreLookupType ("System.Decimal");
1116                 bool_type     = CoreLookupType ("System.Boolean");
1117                 enum_type     = CoreLookupType ("System.Enum");
1118
1119                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1120                 delegate_type           = CoreLookupType ("System.Delegate");
1121
1122                 array_type    = CoreLookupType ("System.Array");
1123                 void_type     = CoreLookupType ("System.Void");
1124                 type_type     = CoreLookupType ("System.Type");
1125
1126                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1127                 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1128                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1129                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1130                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1131                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1132                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1133                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1134                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1135                 idisposable_type     = CoreLookupType ("System.IDisposable");
1136                 icloneable_type      = CoreLookupType ("System.ICloneable");
1137                 iconvertible_type    = CoreLookupType ("System.IConvertible");
1138                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1139                 intptr_type          = CoreLookupType ("System.IntPtr");
1140
1141                 attribute_type       = CoreLookupType ("System.Attribute");
1142                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1143                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1144                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1145                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1146                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1147                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1148                 out_attribute_type   = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1149                 typed_reference_type = CoreLookupType ("System.TypedReference");
1150                 arg_iterator_type    = CoreLookupType ("System.ArgIterator");
1151                 mbr_type             = CoreLookupType ("System.MarshalByRefObject");
1152                 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1153
1154                 //
1155                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1156                 // people are running.
1157                 //
1158                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1159
1160                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1161
1162                 void_ptr_type         = CoreLookupType ("System.Void*");
1163
1164                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1165
1166                 exception_type        = CoreLookupType ("System.Exception");
1167                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1168                 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1169
1170                 //
1171                 // Attribute types
1172                 //
1173                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1174                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1175                 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1176                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1177                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1178                 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1179
1180                 InitGenericCoreTypes ();
1181
1182                 //
1183                 // .NET 2.0
1184                 //
1185 #if NET_2_0
1186                 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
1187                 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices.FixedBufferAttribute");
1188 #endif
1189                 //
1190                 // When compiling corlib, store the "real" types here.
1191                 //
1192                 if (!RootContext.StdLib) {
1193                         system_int32_type = typeof (System.Int32);
1194                         system_array_type = typeof (System.Array);
1195                         system_type_type = typeof (System.Type);
1196                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1197
1198                         Type [] void_arg = {  };
1199                         system_int_array_get_length = GetMethod (
1200                                 system_array_type, "get_Length", void_arg);
1201                         system_int_array_get_rank = GetMethod (
1202                                 system_array_type, "get_Rank", void_arg);
1203                         system_object_array_clone = GetMethod (
1204                                 system_array_type, "Clone", void_arg);
1205
1206                         Type [] system_int_arg = { system_int32_type };
1207                         system_int_array_get_length_int = GetMethod (
1208                                 system_array_type, "GetLength", system_int_arg);
1209                         system_int_array_get_upper_bound_int = GetMethod (
1210                                 system_array_type, "GetUpperBound", system_int_arg);
1211                         system_int_array_get_lower_bound_int = GetMethod (
1212                                 system_array_type, "GetLowerBound", system_int_arg);
1213
1214                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1215                         system_void_array_copyto_array_int = GetMethod (
1216                                 system_array_type, "CopyTo", system_array_int_arg);
1217
1218                         Type [] system_3_type_arg = {
1219                                 system_type_type, system_type_type, system_type_type };
1220                         Type [] system_4_type_arg = {
1221                                 system_type_type, system_type_type, system_type_type, system_type_type };
1222
1223                         MethodInfo set_corlib_type_builders = GetMethod (
1224                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1225                                 system_4_type_arg, true, false);
1226
1227                         if (set_corlib_type_builders != null) {
1228                                 object[] args = new object [4];
1229                                 args [0] = object_type;
1230                                 args [1] = value_type;
1231                                 args [2] = enum_type;
1232                                 args [3] = void_type;
1233                                 
1234                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1235                         } else {
1236                                 // Compatibility for an older version of the class libs.
1237                                 set_corlib_type_builders = GetMethod (
1238                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1239                                         system_3_type_arg, true, true);
1240
1241                                 if (set_corlib_type_builders == null) {
1242                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1243                                         return;
1244                                 }
1245
1246                                 object[] args = new object [3];
1247                                 args [0] = object_type;
1248                                 args [1] = value_type;
1249                                 args [2] = enum_type;
1250                                 
1251                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1252                         }
1253                 }
1254
1255                 system_object_expr.Type = object_type;
1256                 system_string_expr.Type = string_type;
1257                 system_boolean_expr.Type = bool_type;
1258                 system_decimal_expr.Type = decimal_type;
1259                 system_single_expr.Type = float_type;
1260                 system_double_expr.Type = double_type;
1261                 system_sbyte_expr.Type = sbyte_type;
1262                 system_byte_expr.Type = byte_type;
1263                 system_int16_expr.Type = short_type;
1264                 system_uint16_expr.Type = ushort_type;
1265                 system_int32_expr.Type = int32_type;
1266                 system_uint32_expr.Type = uint32_type;
1267                 system_int64_expr.Type = int64_type;
1268                 system_uint64_expr.Type = uint64_type;
1269                 system_char_expr.Type = char_type;
1270                 system_void_expr.Type = void_type;
1271                 system_asynccallback_expr.Type = asynccallback_type;
1272                 system_iasyncresult_expr.Type = iasyncresult_type;
1273                 system_valuetype_expr.Type = value_type;
1274
1275                 //
1276                 // These are only used for compare purposes
1277                 //
1278                 anonymous_method_type = typeof (AnonymousMethod);
1279                 null_type = typeof (NullType);
1280         }
1281
1282         //
1283         // The helper methods that are used by the compiler
1284         //
1285         public static void InitCodeHelpers ()
1286         {
1287                 //
1288                 // Now load the default methods that we use.
1289                 //
1290                 Type [] string_string = { string_type, string_type };
1291                 string_concat_string_string = GetMethod (
1292                         string_type, "Concat", string_string);
1293                 Type [] string_string_string = { string_type, string_type, string_type };
1294                 string_concat_string_string_string = GetMethod (
1295                         string_type, "Concat", string_string_string);
1296                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1297                 string_concat_string_string_string_string = GetMethod (
1298                         string_type, "Concat", string_string_string_string);
1299                 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1300                 string_concat_string_dot_dot_dot = GetMethod (
1301                         string_type, "Concat", params_string);
1302
1303                 Type [] object_object = { object_type, object_type };
1304                 string_concat_object_object = GetMethod (
1305                         string_type, "Concat", object_object);
1306                 Type [] object_object_object = { object_type, object_type, object_type };
1307                 string_concat_object_object_object = GetMethod (
1308                         string_type, "Concat", object_object_object);
1309                 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1310                 string_concat_object_dot_dot_dot = GetMethod (
1311                         string_type, "Concat", params_object);
1312
1313                 Type [] string_ = { string_type };
1314                 string_isinterneted_string = GetMethod (
1315                         string_type, "IsInterned", string_);
1316                 
1317                 Type [] runtime_type_handle = { runtime_handle_type };
1318                 system_type_get_type_from_handle = GetMethod (
1319                         type_type, "GetTypeFromHandle", runtime_type_handle);
1320
1321                 Type [] delegate_delegate = { delegate_type, delegate_type };
1322                 delegate_combine_delegate_delegate = GetMethod (
1323                                 delegate_type, "Combine", delegate_delegate);
1324
1325                 delegate_remove_delegate_delegate = GetMethod (
1326                                 delegate_type, "Remove", delegate_delegate);
1327
1328                 //
1329                 // Void arguments
1330                 //
1331                 Type [] void_arg = {  };
1332                 object_getcurrent_void = GetMethod (
1333                         ienumerator_type, "get_Current", void_arg);
1334                 bool_movenext_void = GetMethod (
1335                         ienumerator_type, "MoveNext", void_arg);
1336                 void_reset_void = GetMethod (
1337                         ienumerator_type, "Reset", void_arg);
1338                 void_dispose_void = GetMethod (
1339                         idisposable_type, "Dispose", void_arg);
1340                 int_get_offset_to_string_data = GetMethod (
1341                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1342                 int_array_get_length = GetMethod (
1343                         array_type, "get_Length", void_arg);
1344                 int_array_get_rank = GetMethod (
1345                         array_type, "get_Rank", void_arg);
1346                 ienumerable_getenumerator_void = GetMethod (
1347                         ienumerable_type, "GetEnumerator", void_arg);
1348                 
1349                 //
1350                 // Int32 arguments
1351                 //
1352                 Type [] int_arg = { int32_type };
1353                 int_array_get_length_int = GetMethod (
1354                         array_type, "GetLength", int_arg);
1355                 int_array_get_upper_bound_int = GetMethod (
1356                         array_type, "GetUpperBound", int_arg);
1357                 int_array_get_lower_bound_int = GetMethod (
1358                         array_type, "GetLowerBound", int_arg);
1359
1360                 //
1361                 // System.Array methods
1362                 //
1363                 object_array_clone = GetMethod (
1364                         array_type, "Clone", void_arg);
1365                 Type [] array_int_arg = { array_type, int32_type };
1366                 void_array_copyto_array_int = GetMethod (
1367                         array_type, "CopyTo", array_int_arg);
1368                 
1369                 //
1370                 // object arguments
1371                 //
1372                 Type [] object_arg = { object_type };
1373                 void_monitor_enter_object = GetMethod (
1374                         monitor_type, "Enter", object_arg);
1375                 void_monitor_exit_object = GetMethod (
1376                         monitor_type, "Exit", object_arg);
1377
1378                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1379                 
1380                 void_initializearray_array_fieldhandle = GetMethod (
1381                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1382
1383                 //
1384                 // Array functions
1385                 //
1386                 int_getlength_int = GetMethod (
1387                         array_type, "GetLength", int_arg);
1388
1389                 //
1390                 // Decimal constructors
1391                 //
1392                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1393                 void_decimal_ctor_five_args = GetConstructor (
1394                         decimal_type, dec_arg);
1395                 
1396                 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1397
1398                 //
1399                 // Attributes
1400                 //
1401                 cons_param_array_attribute = GetConstructor (param_array_type, void_arg);
1402                 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg);
1403                 default_member_ctor = GetConstructor (default_member_type, string_);
1404
1405                 Type[] short_arg = { short_type };
1406                 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1407
1408                 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1409                         { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1410
1411
1412                 //
1413                 // .NET 2.0 types
1414                 //
1415 #if NET_2_0
1416                 compiler_generated_attr = new CustomAttributeBuilder (
1417                         GetConstructor (compiler_generated_attr_type, void_arg), new object[0]);
1418
1419                 Type[] type_int_arg = { type_type, int32_type };
1420                 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1421 #endif
1422
1423                 // Object
1424                 object_ctor = GetConstructor (object_type, void_arg);
1425
1426                 InitGenericCodeHelpers ();
1427         }
1428
1429         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1430
1431         /// <remarks>
1432         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1433         ///   the cache here because there is no member name argument.
1434         /// </remarks>
1435         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1436                                               MemberFilter filter, object criteria)
1437         {
1438                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1439
1440                 //
1441                 // `builder_to_declspace' contains all dynamic types.
1442                 //
1443                 if (decl != null) {
1444                         MemberList list;
1445                         Timer.StartTimer (TimerType.FindMembers);
1446                         list = decl.FindMembers (mt, bf, filter, criteria);
1447                         Timer.StopTimer (TimerType.FindMembers);
1448                         return list;
1449                 }
1450
1451                 //
1452                 // We have to take care of arrays specially, because GetType on
1453                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1454                 // and we can not call FindMembers on this type.
1455                 //
1456                 if (t.IsSubclassOf (TypeManager.array_type))
1457                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1458
1459                 if (t is GenericTypeParameterBuilder) {
1460                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1461
1462                         Timer.StartTimer (TimerType.FindMembers);
1463                         MemberList list = tparam.FindMembers (
1464                                 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1465                         Timer.StopTimer (TimerType.FindMembers);
1466                         return list;
1467                 }
1468
1469                 //
1470                 // Since FindMembers will not lookup both static and instance
1471                 // members, we emulate this behaviour here.
1472                 //
1473                 if ((bf & instance_and_static) == instance_and_static){
1474                         MemberInfo [] i_members = t.FindMembers (
1475                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1476
1477                         int i_len = i_members.Length;
1478                         if (i_len == 1){
1479                                 MemberInfo one = i_members [0];
1480
1481                                 //
1482                                 // If any of these are present, we are done!
1483                                 //
1484                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1485                                         return new MemberList (i_members);
1486                         }
1487                                 
1488                         MemberInfo [] s_members = t.FindMembers (
1489                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1490
1491                         int s_len = s_members.Length;
1492                         if (i_len > 0 || s_len > 0)
1493                                 return new MemberList (i_members, s_members);
1494                         else {
1495                                 if (i_len > 0)
1496                                         return new MemberList (i_members);
1497                                 else
1498                                         return new MemberList (s_members);
1499                         }
1500                 }
1501
1502                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1503         }
1504
1505
1506         /// <summary>
1507         ///   This method is only called from within MemberLookup.  It tries to use the member
1508         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1509         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1510         ///   our return value will already contain all inherited members and the caller don't need
1511         ///   to check base classes and interfaces anymore.
1512         /// </summary>
1513         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1514                                                             string name, out bool used_cache)
1515         {
1516                 MemberCache cache;
1517
1518                 //
1519                 // We have to take care of arrays specially, because GetType on
1520                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1521                 // and we can not call FindMembers on this type.
1522                 //
1523                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1524                         used_cache = true;
1525                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1526                                 mt, bf, name, FilterWithClosure_delegate, null);
1527                 }
1528
1529                 //
1530                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1531                 // and we can ask the DeclSpace for the MemberCache.
1532                 //
1533                 if (t is TypeBuilder) {
1534                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1535                         cache = decl.MemberCache;
1536
1537                         //
1538                         // If this DeclSpace has a MemberCache, use it.
1539                         //
1540
1541                         if (cache != null) {
1542                                 used_cache = true;
1543                                 return cache.FindMembers (
1544                                         mt, bf, name, FilterWithClosure_delegate, null);
1545                         }
1546
1547                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1548                         // Note, this is a VERY uncommon route!
1549
1550                         MemberList list;
1551                         Timer.StartTimer (TimerType.FindMembers);
1552                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1553                                                  FilterWithClosure_delegate, name);
1554                         Timer.StopTimer (TimerType.FindMembers);
1555                         used_cache = false;
1556                         return (MemberInfo []) list;
1557                 }
1558
1559                 if (t is GenericTypeParameterBuilder) {
1560                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1561
1562                         MemberList list;
1563                         Timer.StartTimer (TimerType.FindMembers);
1564                         list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1565                                                    FilterWithClosure_delegate, name);
1566                         Timer.StopTimer (TimerType.FindMembers);
1567                         used_cache = false;
1568                         return (MemberInfo []) list;
1569                 }
1570
1571                 //
1572                 // This call will always succeed.  There is exactly one TypeHandle instance per
1573                 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1574                 // the corresponding MemberCache.
1575                 //
1576                 cache = TypeHandle.GetMemberCache (t);
1577
1578                 used_cache = true;
1579                 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1580         }
1581
1582         public static bool IsBuiltinType (Type t)
1583         {
1584                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1585                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1586                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1587                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1588                         return true;
1589                 else
1590                         return false;
1591         }
1592
1593         public static bool IsBuiltinType (TypeContainer tc)
1594         {
1595                 return IsBuiltinType (tc.TypeBuilder);
1596         }
1597
1598         //
1599         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1600         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1601         // 
1602         public static bool IsCLRType (Type t)
1603         {
1604                 if (t == object_type || t == int32_type || t == uint32_type ||
1605                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1606                     t == char_type || t == short_type || t == bool_type ||
1607                     t == sbyte_type || t == byte_type || t == ushort_type)
1608                         return true;
1609                 else
1610                         return false;
1611         }
1612
1613         public static bool IsDelegateType (Type t)
1614         {
1615                 if (t.IsGenericInstance)
1616                         t = t.GetGenericTypeDefinition ();
1617
1618                 if (t.IsSubclassOf (TypeManager.delegate_type))
1619                         return true;
1620                 else
1621                         return false;
1622         }
1623         
1624         public static bool IsEnumType (Type t)
1625         {
1626                 if (t.IsSubclassOf (TypeManager.enum_type))
1627                         return true;
1628                 else
1629                         return false;
1630         }
1631         public static bool IsBuiltinOrEnum (Type t)
1632         {
1633                 if (IsBuiltinType (t))
1634                         return true;
1635                 
1636                 if (IsEnumType (t))
1637                         return true;
1638
1639                 return false;
1640         }
1641
1642         public static bool IsNullType (Type t)
1643         {
1644                 return t == null_type;
1645         }
1646         
1647         //
1648         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1649         //
1650         public static bool IsUnmanagedType (Type t)
1651         {
1652                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1653                         return true;
1654
1655                 if (IsEnumType (t))
1656                         return true;
1657
1658                 if (t.IsPointer)
1659                         return true;
1660
1661                 if (IsValueType (t)){
1662                         if (t is TypeBuilder){
1663                                 TypeContainer tc = LookupTypeContainer (t);
1664
1665                                 if (tc.Fields != null){
1666                                 foreach (Field f in tc.Fields){
1667                                         if (f.FieldBuilder.IsStatic)
1668                                                 continue;
1669                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1670                                                 return false;
1671                                 }
1672                                 } else
1673                                         return true;
1674                         } else {
1675                                 FieldInfo [] fields = t.GetFields ();
1676
1677                                 foreach (FieldInfo f in fields){
1678                                         if (f.IsStatic)
1679                                                 continue;
1680                                         if (!IsUnmanagedType (f.FieldType))
1681                                                 return false;
1682                                 }
1683                         }
1684                         return true;
1685                 }
1686
1687                 return false;
1688         }
1689                 
1690         public static bool IsValueType (Type t)
1691         {
1692                 return t.IsGenericParameter || t.IsValueType;
1693         }
1694         
1695         public static bool IsInterfaceType (Type t)
1696         {
1697                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1698                 if (tc == null)
1699                         return false;
1700
1701                 return tc.Kind == Kind.Interface;
1702         }
1703
1704         public static bool IsSubclassOf (Type type, Type base_type)
1705         {
1706                 TypeParameter tparam = LookupTypeParameter (type);
1707                 TypeParameter pparam = LookupTypeParameter (base_type);
1708
1709                 if ((tparam != null) && (pparam != null)) {
1710                         if (tparam == pparam)
1711                                 return true;
1712
1713                         return tparam.IsSubclassOf (base_type);
1714                 }
1715
1716                 do {
1717                         if (type.Equals (base_type))
1718                                 return true;
1719
1720                         type = type.BaseType;
1721                 } while (type != null);
1722
1723                 return false;
1724         }
1725
1726         public static bool IsPrivateAccessible (Type type, Type parent)
1727         {
1728                 if (type.Equals (parent))
1729                         return true;
1730
1731                 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
1732                         //
1733                         // `a' is a generic type definition's TypeBuilder and `b' is a
1734                         // generic instance of the same type.
1735                         //
1736                         // Example:
1737                         //
1738                         // class Stack<T>
1739                         // {
1740                         //     void Test (Stack<T> stack) { }
1741                         // }
1742                         //
1743                         // The first argument of `Test' will be the generic instance
1744                         // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1745                         //
1746                         //
1747                         // We hit this via Closure.Filter() for gen-82.cs.
1748                         //
1749                         if (type != parent.GetGenericTypeDefinition ())
1750                                 return false;
1751
1752                         return true;
1753                 }
1754
1755                 if (type.IsGenericInstance && parent.IsGenericInstance) {
1756                         if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
1757                                 return false;
1758
1759                         return true;
1760                 }
1761
1762                 return false;
1763         }
1764
1765         public static bool IsFamilyAccessible (Type type, Type parent)
1766         {
1767                 TypeParameter tparam = LookupTypeParameter (type);
1768                 TypeParameter pparam = LookupTypeParameter (parent);
1769
1770                 if ((tparam != null) && (pparam != null)) {
1771                         if (tparam == pparam)
1772                                 return true;
1773
1774                         return tparam.IsSubclassOf (parent);
1775                 }
1776
1777                 do {
1778                         if (IsEqualGenericInstance (type, parent))
1779                                 return true;
1780
1781                         type = type.BaseType;
1782                 } while (type != null);
1783
1784                 return false;
1785         }
1786
1787         //
1788         // Checks whether `type' is a subclass or nested child of `base_type'.
1789         //
1790         public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1791         {
1792                 do {
1793                         if (IsFamilyAccessible (type, base_type))
1794                                 return true;
1795
1796                         // Handle nested types.
1797                         type = type.DeclaringType;
1798                 } while (type != null);
1799
1800                 return false;
1801         }
1802
1803         //
1804         // Checks whether `type' is a nested child of `parent'.
1805         //
1806         public static bool IsNestedChildOf (Type type, Type parent)
1807         {
1808                 if (IsEqual (type, parent))
1809                         return false;
1810
1811                 type = type.DeclaringType;
1812                 while (type != null) {
1813                         if (IsEqual (type, parent))
1814                                 return true;
1815
1816                         type = type.DeclaringType;
1817                 }
1818
1819                 return false;
1820         }
1821
1822         //
1823         // Do the right thing when returning the element type of an
1824         // array type based on whether we are compiling corlib or not
1825         //
1826         public static Type GetElementType (Type t)
1827         {
1828                 if (RootContext.StdLib)
1829                         return t.GetElementType ();
1830                 else
1831                         return TypeToCoreType (t.GetElementType ());
1832         }
1833
1834         /// <summary>
1835         /// This method is not implemented by MS runtime for dynamic types
1836         /// </summary>
1837         public static bool HasElementType (Type t)
1838         {
1839                 return t.IsArray || t.IsPointer || t.IsByRef;
1840         }
1841
1842         /// <summary>
1843         ///   Returns the User Defined Types
1844         /// </summary>
1845         public static ArrayList UserTypes {
1846                 get {
1847                         return user_types;
1848                 }
1849         }
1850
1851         public static Hashtable TypeContainers {
1852                 get {
1853                         return typecontainers;
1854                 }
1855         }
1856
1857         static Hashtable builder_to_constant;
1858
1859         public static void RegisterConstant (FieldBuilder fb, Const c)
1860         {
1861                 if (builder_to_constant == null)
1862                         builder_to_constant = new PtrHashtable ();
1863
1864                 if (builder_to_constant.Contains (fb))
1865                         return;
1866
1867                 builder_to_constant.Add (fb, c);
1868         }
1869
1870         public static Const LookupConstant (FieldBuilder fb)
1871         {
1872                 if (builder_to_constant == null)
1873                         return null;
1874                 
1875                 return (Const) builder_to_constant [fb];
1876         }
1877         
1878         /// <summary>
1879         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1880         /// </summary>
1881         ///
1882         /// <remarks>
1883         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1884         ///   for anything which is dynamic, and we need this in a number of places,
1885         ///   we register this information here, and use it afterwards.
1886         /// </remarks>
1887         static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1888         {
1889                 if (args == null)
1890                         args = NoTypes;
1891                                 
1892                 method_arguments.Add (mb, args);
1893                 method_params.Add (mb, ip);
1894         }
1895         
1896         static public ParameterData GetParameterData (MethodBase mb)
1897         {
1898                 object pd = method_params [mb];
1899                 if (pd == null) {
1900                         if (mb is MethodBuilder || mb is ConstructorBuilder)
1901                                 throw new InternalErrorException ("Argument for Method not registered" + mb);
1902
1903                         method_params [mb] = pd = new ReflectionParameters (mb);
1904                 }
1905
1906                 return (ParameterData) pd;
1907         }
1908
1909         /// <summary>
1910         ///    Returns the argument types for a method based on its methodbase
1911         ///
1912         ///    For dynamic methods, we use the compiler provided types, for
1913         ///    methods from existing assemblies we load them from GetParameters,
1914         ///    and insert them into the cache
1915         /// </summary>
1916         static public Type [] GetArgumentTypes (MethodBase mb)
1917         {
1918                 object t = method_arguments [mb];
1919                 if (t != null)
1920                         return (Type []) t;
1921
1922                         ParameterInfo [] pi = mb.GetParameters ();
1923                         int c = pi.Length;
1924                 Type [] types;
1925                         
1926                 if (c == 0) {
1927                         types = NoTypes;
1928                 } else {
1929                         types = new Type [c];
1930                         for (int i = 0; i < c; i++)
1931                                 types [i] = pi [i].ParameterType;
1932                 }
1933                         method_arguments.Add (mb, types);
1934                         return types;
1935                 }
1936
1937         /// <summary>
1938         ///    Returns the argument types for an indexer based on its PropertyInfo
1939         ///
1940         ///    For dynamic indexers, we use the compiler provided types, for
1941         ///    indexers from existing assemblies we load them from GetParameters,
1942         ///    and insert them into the cache
1943         /// </summary>
1944         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1945         {
1946                 if (indexer_arguments.Contains (indexer))
1947                         return (Type []) indexer_arguments [indexer];
1948                 else if (indexer is PropertyBuilder)
1949                         // If we're a PropertyBuilder and not in the
1950                         // `indexer_arguments' hash, then we're a property and
1951                         // not an indexer.
1952                         return NoTypes;
1953                 else {
1954                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1955                         // Property, not an indexer.
1956                         if (pi == null)
1957                                 return NoTypes;
1958                         int c = pi.Length;
1959                         Type [] types = new Type [c];
1960                         
1961                         for (int i = 0; i < c; i++)
1962                                 types [i] = pi [i].ParameterType;
1963
1964                         indexer_arguments.Add (indexer, types);
1965                         return types;
1966                 }
1967         }
1968         
1969         // <remarks>
1970         //  This is a workaround the fact that GetValue is not
1971         //  supported for dynamic types
1972         // </remarks>
1973         static Hashtable fields = new Hashtable ();
1974         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1975         {
1976                 if (fields.Contains (fb))
1977                         return false;
1978
1979                 fields.Add (fb, value);
1980
1981                 return true;
1982         }
1983
1984         static public object GetValue (FieldBuilder fb)
1985         {
1986                 return fields [fb];
1987         }
1988
1989         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1990         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1991         {
1992                 if (fieldbuilders_to_fields.Contains (fb))
1993                         return false;
1994
1995                 fieldbuilders_to_fields.Add (fb, f);
1996                 return true;
1997         }
1998
1999         //
2000         // The return value can be null;  This will be the case for
2001         // auxiliary FieldBuilders created by the compiler that have no
2002         // real field being declared on the source code
2003         //
2004         static public FieldBase GetField (FieldInfo fb)
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 TypeHandle 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                         BaseType = GetTypeHandle (type.BaseType);
3141                         base_cache = BaseType.MemberCache;
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 }