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