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