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