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