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