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