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