Fix bug #57151.
[mono.git] / mcs / mcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12
13 //
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change 
15 // the behavior of the compilation.  This can be removed if we rework
16 // the code to get a list of namespaces available.
17 //
18 #define SIMPLE_SPEEDUP
19
20 using System;
21 using System.IO;
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Text;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
30
31 namespace Mono.CSharp {
32
33 public class TypeManager {
34         //
35         // A list of core types that the compiler requires or uses
36         //
37         static public Type object_type;
38         static public Type value_type;
39         static public Type string_type;
40         static public Type int32_type;
41         static public Type uint32_type;
42         static public Type int64_type;
43         static public Type uint64_type;
44         static public Type float_type;
45         static public Type double_type;
46         static public Type char_type;
47         static public Type char_ptr_type;
48         static public Type short_type;
49         static public Type decimal_type;
50         static public Type bool_type;
51         static public Type sbyte_type;
52         static public Type byte_type;
53         static public Type ushort_type;
54         static public Type enum_type;
55         static public Type delegate_type;
56         static public Type multicast_delegate_type;
57         static public Type void_type;
58         static public Type enumeration_type;
59         static public Type array_type;
60         static public Type runtime_handle_type;
61         static public Type icloneable_type;
62         static public Type type_type;
63         static public Type ienumerator_type;
64         static public Type ienumerable_type;
65         static public Type idisposable_type;
66         static public Type default_member_type;
67         static public Type iasyncresult_type;
68         static public Type asynccallback_type;
69         static public Type intptr_type;
70         static public Type monitor_type;
71         static public Type runtime_field_handle_type;
72         static public Type attribute_type;
73         static public Type attribute_usage_type;
74         static public Type dllimport_type;
75         static public Type unverifiable_code_type;
76         static public Type methodimpl_attr_type;
77         static public Type marshal_as_attr_type;
78         static public Type param_array_type;
79         static public Type guid_attr_type;
80         static public Type void_ptr_type;
81         static public Type indexer_name_type;
82         static public Type exception_type;
83         static public Type invalid_operation_exception_type;
84         static public object obsolete_attribute_type;
85         static public object conditional_attribute_type;
86         static public Type in_attribute_type;
87         static public Type cls_compliant_attribute_type;
88         static public Type typed_reference_type;
89         static public Type arg_iterator_type;
90         static public Type mbr_type;
91         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 attribute types
238         // </remarks>
239
240         static Hashtable builder_to_attr;
241
242         // <remarks>
243         //  Keeps track of methods
244         // </remarks>
245
246         static Hashtable builder_to_method;
247
248         // <remarks>
249         //  Contains all public types from referenced assemblies.
250         //  This member is used only if CLS Compliance verification is required.
251         // </remarks>
252         public static Hashtable all_imported_types;
253
254         struct Signature {
255                 public string name;
256                 public Type [] args;
257         }
258         
259         public static void CleanUp ()
260         {
261                 // Lets get everything clean so that we can collect before generating code
262                 assemblies = null;
263                 modules = null;
264                 types = null;
265                 typecontainers = null;
266                 user_types = null;
267                 builder_to_declspace = null;
268                 builder_to_ifaces = null;
269                 method_arguments = null;
270                 indexer_arguments = null;
271                 method_internal_params = null;
272                 builder_to_attr = null;
273                 builder_to_method = null;
274                 
275                 fields = null;
276                 references = null;
277                 negative_hits = null;
278                 attr_to_allowmult = null;
279                 builder_to_constant = null;
280                 fieldbuilders_to_fields = null;
281                 events = null;
282                 priv_fields_events = null;
283                 properties = null;
284                 
285                 TypeHandle.CleanUp ();
286         }
287
288         /// <summary>
289         ///   A filter for Findmembers that uses the Signature object to
290         ///   extract objects
291         /// </summary>
292         static bool SignatureFilter (MemberInfo mi, object criteria)
293         {
294                 Signature sig = (Signature) criteria;
295
296                 if (!(mi is MethodBase))
297                         return false;
298                 
299                 if (mi.Name != sig.name)
300                         return false;
301
302                 int count = sig.args.Length;
303                 
304                 if (mi is MethodBuilder || mi is ConstructorBuilder){
305                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
306
307                         if (candidate_args.Length != count)
308                                 return false;
309                         
310                         for (int i = 0; i < count; i++)
311                                 if (candidate_args [i] != sig.args [i])
312                                         return false;
313                         
314                         return true;
315                 } else {
316                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
317
318                         if (pars.Length != count)
319                                 return false;
320
321                         for (int i = 0; i < count; i++)
322                                 if (pars [i].ParameterType != sig.args [i])
323                                         return false;
324                         return true;
325                 }
326         }
327
328         // A delegate that points to the filter above.
329         static MemberFilter signature_filter;
330
331         //
332         // These are expressions that represent some of the internal data types, used
333         // elsewhere
334         //
335         static void InitExpressionTypes ()
336         {
337                 system_object_expr  = new TypeLookupExpression ("System.Object");
338                 system_string_expr  = new TypeLookupExpression ("System.String");
339                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
340                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
341                 system_single_expr  = new TypeLookupExpression ("System.Single");
342                 system_double_expr  = new TypeLookupExpression ("System.Double");
343                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
344                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
345                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
346                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
347                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
348                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
349                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
350                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
351                 system_char_expr    = new TypeLookupExpression ("System.Char");
352                 system_void_expr    = new TypeLookupExpression ("System.Void");
353                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
354                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
355                 system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
356         }
357
358         static TypeManager ()
359         {
360                 assemblies = new Assembly [0];
361                 modules = null;
362                 user_types = new ArrayList ();
363                 
364                 types = new Hashtable ();
365                 typecontainers = new Hashtable ();
366                 
367                 builder_to_declspace = new PtrHashtable ();
368                 builder_to_attr = new PtrHashtable ();
369                 builder_to_method = new PtrHashtable ();
370                 method_arguments = new PtrHashtable ();
371                 method_internal_params = new PtrHashtable ();
372                 indexer_arguments = new PtrHashtable ();
373                 builder_to_ifaces = new PtrHashtable ();
374                 
375                 NoTypes = new Type [0];
376                 NoTypeExprs = new TypeExpr [0];
377
378                 signature_filter = new MemberFilter (SignatureFilter);
379                 InitExpressionTypes ();
380         }
381
382         public static void HandleDuplicate (string name, Type t)
383         {
384                 Type prev = (Type) types [name];
385                 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
386                 
387                 if (tc != null){
388                         //
389                         // This probably never happens, as we catch this before
390                         //
391                         Report.Error (-17, "The type `" + name + "' has already been defined.");
392                         return;
393                 }
394                 
395                 tc = builder_to_declspace [t] as TypeContainer;
396                 if (tc != null){
397                         Report.Warning (
398                                         1595, "The type `" + name + "' is defined in an existing assembly;"+
399                                         " Using the new definition from: " + tc.Location);
400                 } else {
401                         Report.Warning (
402                                         1595, "The type `" + name + "' is defined in an existing assembly;");
403                 }
404                 
405                 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
406                 
407                 types.Remove (name);
408                 types.Add (name, t);
409         }
410         
411         public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
412         {
413                 try {
414                         types.Add (name, t);
415                 } catch {
416                         HandleDuplicate (name, t); 
417                 }
418                 user_types.Add (t);
419                         
420                 if (ifaces != null)
421                         builder_to_ifaces [t] = ifaces;
422         }
423
424         //
425         // This entry point is used by types that we define under the covers
426         // 
427         public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
428         {
429                 if (ifaces != null)
430                         builder_to_ifaces [tb] = ifaces;
431         }
432         
433         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
434         {
435                 builder_to_declspace.Add (t, tc);
436                 typecontainers.Add (name, tc);
437                 AddUserType (name, t, ifaces);
438         }
439
440         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
441         {
442                 try {
443                         types.Add (name, t);
444                 } catch {
445                         HandleDuplicate (name, t);
446                 }
447                 
448                 builder_to_declspace.Add (t, del);
449         }
450         
451         public static void AddEnumType (string name, TypeBuilder t, Enum en)
452         {
453                 try {
454                         types.Add (name, t);
455                 } catch {
456                         HandleDuplicate (name, t);
457                 }
458                 builder_to_declspace.Add (t, en);
459         }
460
461         public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
462         {
463                 AddUserType (name, t, ifaces);
464                 builder_to_declspace.Add (t, i);
465         }
466
467         public static void AddMethod (MethodBuilder builder, MethodData method)
468         {
469                 builder_to_method.Add (builder, method);
470         }
471
472         public static void RegisterAttrType (Type t, TypeContainer tc)
473         {
474                 builder_to_attr.Add (t, tc);
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 TypeContainer LookupAttr (Type t)
522         {
523                 return (TypeContainer) builder_to_attr [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 attr_to_allowmult;
1610
1611         public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1612         {
1613                 if (attr_to_allowmult == null)
1614                         attr_to_allowmult = new PtrHashtable ();
1615
1616                 if (attr_to_allowmult.Contains (attr_type))
1617                         return;
1618
1619                 attr_to_allowmult.Add (attr_type, allow);
1620                                
1621         }
1622
1623         public static bool AreMultipleAllowed (Type attr_type)
1624         {
1625                 if (!(attr_type is TypeBuilder)) {
1626                         System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1627
1628                         foreach (System.Attribute tmp in attrs)
1629                                 if (tmp is AttributeUsageAttribute) {
1630                                         return ((AttributeUsageAttribute) tmp).AllowMultiple;
1631                                 }
1632
1633                         return false;
1634                 }
1635                 
1636                 if (attr_to_allowmult == null)
1637                         return false;
1638
1639                 return (bool) attr_to_allowmult [attr_type];
1640         }
1641
1642         static Hashtable builder_to_constant;
1643
1644         public static void RegisterConstant (FieldBuilder fb, Const c)
1645         {
1646                 if (builder_to_constant == null)
1647                         builder_to_constant = new PtrHashtable ();
1648
1649                 if (builder_to_constant.Contains (fb))
1650                         return;
1651
1652                 builder_to_constant.Add (fb, c);
1653         }
1654
1655         public static Const LookupConstant (FieldBuilder fb)
1656         {
1657                 if (builder_to_constant == null)
1658                         return null;
1659                 
1660                 return (Const) builder_to_constant [fb];
1661         }
1662         
1663         /// <summary>
1664         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1665         /// </summary>
1666         ///
1667         /// <remarks>
1668         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1669         ///   for anything which is dynamic, and we need this in a number of places,
1670         ///   we register this information here, and use it afterwards.
1671         /// </remarks>
1672         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1673         {
1674                 if (args == null)
1675                         args = NoTypes;
1676                                 
1677                 method_arguments.Add (mb, args);
1678                 method_internal_params.Add (mb, ip);
1679                 
1680                 return true;
1681         }
1682         
1683         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1684         {
1685                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1686                         return null;
1687                 
1688                 if (method_internal_params.Contains (mb))
1689                         return (InternalParameters) method_internal_params [mb];
1690                 else
1691                         throw new Exception ("Argument for Method not registered" + mb);
1692         }
1693
1694         /// <summary>
1695         ///    Returns the argument types for a method based on its methodbase
1696         ///
1697         ///    For dynamic methods, we use the compiler provided types, for
1698         ///    methods from existing assemblies we load them from GetParameters,
1699         ///    and insert them into the cache
1700         /// </summary>
1701         static public Type [] GetArgumentTypes (MethodBase mb)
1702         {
1703                 if (method_arguments.Contains (mb))
1704                         return (Type []) method_arguments [mb];
1705                 else {
1706                         ParameterInfo [] pi = mb.GetParameters ();
1707                         int c = pi.Length;
1708                         Type [] types = new Type [c];
1709                         
1710                         for (int i = 0; i < c; i++)
1711                                 types [i] = pi [i].ParameterType;
1712
1713                         method_arguments.Add (mb, types);
1714                         return types;
1715                 }
1716         }
1717
1718         /// <summary>
1719         ///    Returns the argument types for an indexer based on its PropertyInfo
1720         ///
1721         ///    For dynamic indexers, we use the compiler provided types, for
1722         ///    indexers from existing assemblies we load them from GetParameters,
1723         ///    and insert them into the cache
1724         /// </summary>
1725         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1726         {
1727                 if (indexer_arguments.Contains (indexer))
1728                         return (Type []) indexer_arguments [indexer];
1729                 else if (indexer is PropertyBuilder)
1730                         // If we're a PropertyBuilder and not in the
1731                         // `indexer_arguments' hash, then we're a property and
1732                         // not an indexer.
1733                         return NoTypes;
1734                 else {
1735                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1736                         // Property, not an indexer.
1737                         if (pi == null)
1738                                 return NoTypes;
1739                         int c = pi.Length;
1740                         Type [] types = new Type [c];
1741                         
1742                         for (int i = 0; i < c; i++)
1743                                 types [i] = pi [i].ParameterType;
1744
1745                         indexer_arguments.Add (indexer, types);
1746                         return types;
1747                 }
1748         }
1749         
1750         // <remarks>
1751         //  This is a workaround the fact that GetValue is not
1752         //  supported for dynamic types
1753         // </remarks>
1754         static Hashtable fields = new Hashtable ();
1755         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1756         {
1757                 if (fields.Contains (fb))
1758                         return false;
1759
1760                 fields.Add (fb, value);
1761
1762                 return true;
1763         }
1764
1765         static public object GetValue (FieldBuilder fb)
1766         {
1767                 return fields [fb];
1768         }
1769
1770         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1771         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1772         {
1773                 if (fieldbuilders_to_fields.Contains (fb))
1774                         return false;
1775
1776                 fieldbuilders_to_fields.Add (fb, f);
1777                 return true;
1778         }
1779
1780         //
1781         // The return value can be null;  This will be the case for
1782         // auxiliary FieldBuilders created by the compiler that have no
1783         // real field being declared on the source code
1784         //
1785         static public FieldBase GetField (FieldInfo fb)
1786         {
1787                 return (FieldBase) fieldbuilders_to_fields [fb];
1788         }
1789         
1790         static Hashtable events;
1791
1792         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1793         {
1794                 if (events == null)
1795                         events = new Hashtable ();
1796
1797                 if (events.Contains (eb))
1798                         return false;
1799
1800                 events.Add (eb, new Pair (add, remove));
1801
1802                 return true;
1803         }
1804
1805         static public MethodInfo GetAddMethod (EventInfo ei)
1806         {
1807                 if (ei is MyEventBuilder) {
1808                         Pair pair = (Pair) events [ei];
1809
1810                         return (MethodInfo) pair.First;
1811                 } else
1812                         return ei.GetAddMethod ();
1813         }
1814
1815         static public MethodInfo GetRemoveMethod (EventInfo ei)
1816         {
1817                 if (ei is MyEventBuilder) {
1818                         Pair pair = (Pair) events [ei];
1819
1820                         return (MethodInfo) pair.Second;
1821                 } else
1822                         return ei.GetRemoveMethod ();
1823         }
1824
1825         static Hashtable priv_fields_events;
1826
1827         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1828         {
1829                 if (priv_fields_events == null)
1830                         priv_fields_events = new Hashtable ();
1831
1832                 if (priv_fields_events.Contains (einfo))
1833                         return false;
1834
1835                 priv_fields_events.Add (einfo, builder);
1836
1837                 return true;
1838         }
1839
1840         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1841         {
1842                 if (priv_fields_events == null)
1843                         return null;
1844                 else
1845                         return (MemberInfo) priv_fields_events [ei];
1846         }
1847                 
1848         static Hashtable properties;
1849         
1850         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1851         {
1852                 if (properties == null)
1853                         properties = new Hashtable ();
1854
1855                 if (properties.Contains (pb))
1856                         return false;
1857
1858                 properties.Add (pb, new Pair (get, set));
1859
1860                 return true;
1861         }
1862
1863         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1864                                             MethodBase set, Type[] args)
1865         {
1866                 if (!RegisterProperty (pb, get,set))
1867                         return false;
1868
1869                 indexer_arguments.Add (pb, args);
1870
1871                 return true;
1872         }
1873
1874         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1875         {
1876                 Hashtable hash = new Hashtable ();
1877                 return CheckStructCycles (tc, seen, hash);
1878         }
1879
1880         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1881                                               Hashtable hash)
1882         {
1883                 if (!(tc is Struct) || IsBuiltinType (tc))
1884                         return true;
1885
1886                 //
1887                 // `seen' contains all types we've already visited.
1888                 //
1889                 if (seen.Contains (tc))
1890                         return true;
1891                 seen.Add (tc, null);
1892
1893                 if (tc.Fields == null)
1894                         return true;
1895
1896                 foreach (Field field in tc.Fields) {
1897                         if (field.FieldBuilder.IsStatic)
1898                                 continue;
1899
1900                         Type ftype = field.FieldBuilder.FieldType;
1901                         TypeContainer ftc = LookupTypeContainer (ftype);
1902                         if (ftc == null)
1903                                 continue;
1904
1905                         if (hash.Contains (ftc)) {
1906                                 Report.Error (523, tc.Location,
1907                                               "Struct member `{0}.{1}' of type `{2}' " +
1908                                               "causes a cycle in the struct layout",
1909                                               tc.Name, field.Name, ftc.Name);
1910                                 return false;
1911                         }
1912
1913                         //
1914                         // `hash' contains all types in the current path.
1915                         //
1916                         hash.Add (tc, null);
1917
1918                         bool ok = CheckStructCycles (ftc, seen, hash);
1919
1920                         hash.Remove (tc);
1921
1922                         if (!ok)
1923                                 return false;
1924
1925                         if (!seen.Contains (ftc))
1926                                 seen.Add (ftc, null);
1927                 }
1928
1929                 return true;
1930         }
1931
1932         /// <summary>
1933         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1934         ///   of an interface.  
1935         /// </summary>
1936         ///
1937         /// <remarks>
1938         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1939         ///   be IA, IB, IC.
1940         /// </remarks>
1941         public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
1942         {
1943                 ArrayList new_ifaces = new ArrayList ();
1944                 
1945                 foreach (TypeExpr iface in base_interfaces){
1946                         if (!new_ifaces.Contains (iface))
1947                                 new_ifaces.Add (iface);
1948                         
1949                         TypeExpr [] implementing = iface.GetInterfaces ();
1950                         
1951                         foreach (TypeExpr imp in implementing){
1952                                 if (!new_ifaces.Contains (imp))
1953                                         new_ifaces.Add (imp);
1954                         }
1955                 }
1956                 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
1957                 new_ifaces.CopyTo (ret, 0);
1958                 return ret;
1959         }
1960         
1961         static PtrHashtable iface_cache = new PtrHashtable ();
1962                 
1963         /// <summary>
1964         ///   This function returns the interfaces in the type `t'.  Works with
1965         ///   both types and TypeBuilders.
1966         /// </summary>
1967         public static TypeExpr [] GetInterfaces (Type t)
1968         {
1969                 
1970                 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
1971                 if (cached != null)
1972                         return cached;
1973                 
1974                 //
1975                 // The reason for catching the Array case is that Reflection.Emit
1976                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1977                 // but will still throw an exception if we try to call GetInterfaces
1978                 // on the type.
1979                 //
1980                 // Since the array interfaces are always constant, we return those for
1981                 // the System.Array
1982                 //
1983                 
1984                 if (t.IsArray)
1985                         t = TypeManager.array_type;
1986                 
1987                 if (t is TypeBuilder){
1988                         TypeExpr [] parent_ifaces;
1989                         
1990                         if (t.BaseType == null)
1991                                 parent_ifaces = NoTypeExprs;
1992                         else
1993                                 parent_ifaces = GetInterfaces (t.BaseType);
1994                         TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
1995                         if (type_ifaces == null)
1996                                 type_ifaces = NoTypeExprs;
1997
1998                         int parent_count = parent_ifaces.Length;
1999                         TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2000                         parent_ifaces.CopyTo (result, 0);
2001                         type_ifaces.CopyTo (result, parent_count);
2002
2003                         iface_cache [t] = result;
2004                         return result;
2005                 } else {
2006                         Type [] ifaces = t.GetInterfaces ();
2007                         if (ifaces.Length == 0)
2008                                 return NoTypeExprs;
2009
2010                         TypeExpr [] result = new TypeExpr [ifaces.Length];
2011                         for (int i = 0; i < ifaces.Length; i++)
2012                                 result [i] = new TypeExpression (ifaces [i], Location.Null);
2013                         
2014                         iface_cache [t] = result;
2015                         return result;
2016                 }
2017         }
2018         
2019         //
2020         // gets the interfaces that are declared explicitly on t
2021         //
2022         public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2023         {
2024                 return (TypeExpr []) builder_to_ifaces [t];
2025         }
2026         
2027         /// <remarks>
2028         ///  The following is used to check if a given type implements an interface.
2029         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2030         /// </remarks>
2031         public static bool ImplementsInterface (Type t, Type iface)
2032         {
2033                 TypeExpr [] interfaces;
2034
2035                 //
2036                 // FIXME OPTIMIZATION:
2037                 // as soon as we hit a non-TypeBuiler in the interface
2038                 // chain, we could return, as the `Type.GetInterfaces'
2039                 // will return all the interfaces implement by the type
2040                 // or its parents.
2041                 //
2042                 do {
2043                         interfaces = GetInterfaces (t);
2044
2045                         if (interfaces != null){
2046                                 foreach (TypeExpr i in interfaces){
2047                                         if (i.Type == iface)
2048                                                 return true;
2049                                 }
2050                         }
2051                         
2052                         t = t.BaseType;
2053                 } while (t != null);
2054                 
2055                 return false;
2056         }
2057
2058         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2059
2060         // This is a custom version of Convert.ChangeType() which works
2061         // with the TypeBuilder defined types when compiling corlib.
2062         public static object ChangeType (object value, Type conversionType, out bool error)
2063         {
2064                 IConvertible convert_value = value as IConvertible;
2065                 
2066                 if (convert_value == null){
2067                         error = true;
2068                         return null;
2069                 }
2070                 
2071                 //
2072                 // We must use Type.Equals() here since `conversionType' is
2073                 // the TypeBuilder created version of a system type and not
2074                 // the system type itself.  You cannot use Type.GetTypeCode()
2075                 // on such a type - it'd always return TypeCode.Object.
2076                 //
2077                 error = false;
2078                 try {
2079                         if (conversionType.Equals (typeof (Boolean)))
2080                                 return (object)(convert_value.ToBoolean (nf_provider));
2081                         else if (conversionType.Equals (typeof (Byte)))
2082                                 return (object)(convert_value.ToByte (nf_provider));
2083                         else if (conversionType.Equals (typeof (Char)))
2084                                 return (object)(convert_value.ToChar (nf_provider));
2085                         else if (conversionType.Equals (typeof (DateTime)))
2086                                 return (object)(convert_value.ToDateTime (nf_provider));
2087                         else if (conversionType.Equals (typeof (Decimal)))
2088                                 return (object)(convert_value.ToDecimal (nf_provider));
2089                         else if (conversionType.Equals (typeof (Double)))
2090                                 return (object)(convert_value.ToDouble (nf_provider));
2091                         else if (conversionType.Equals (typeof (Int16)))
2092                                 return (object)(convert_value.ToInt16 (nf_provider));
2093                         else if (conversionType.Equals (typeof (Int32)))
2094                                 return (object)(convert_value.ToInt32 (nf_provider));
2095                         else if (conversionType.Equals (typeof (Int64)))
2096                                 return (object)(convert_value.ToInt64 (nf_provider));
2097                         else if (conversionType.Equals (typeof (SByte)))
2098                                 return (object)(convert_value.ToSByte (nf_provider));
2099                         else if (conversionType.Equals (typeof (Single)))
2100                                 return (object)(convert_value.ToSingle (nf_provider));
2101                         else if (conversionType.Equals (typeof (String)))
2102                                 return (object)(convert_value.ToString (nf_provider));
2103                         else if (conversionType.Equals (typeof (UInt16)))
2104                                 return (object)(convert_value.ToUInt16 (nf_provider));
2105                         else if (conversionType.Equals (typeof (UInt32)))
2106                                 return (object)(convert_value.ToUInt32 (nf_provider));
2107                         else if (conversionType.Equals (typeof (UInt64)))
2108                                 return (object)(convert_value.ToUInt64 (nf_provider));
2109                         else if (conversionType.Equals (typeof (Object)))
2110                                 return (object)(value);
2111                         else 
2112                                 error = true;
2113                 } catch {
2114                         error = true;
2115                 }
2116                 return null;
2117         }
2118
2119         //
2120         // This is needed, because enumerations from assemblies
2121         // do not report their underlyingtype, but they report
2122         // themselves
2123         //
2124         public static Type EnumToUnderlying (Type t)
2125         {
2126                 if (t == TypeManager.enum_type)
2127                         return t;
2128
2129                 t = t.UnderlyingSystemType;
2130                 if (!TypeManager.IsEnumType (t))
2131                         return t;
2132         
2133                 if (t is TypeBuilder) {
2134                         // slow path needed to compile corlib
2135                         if (t == TypeManager.bool_type ||
2136                             t == TypeManager.byte_type ||
2137                             t == TypeManager.sbyte_type ||
2138                             t == TypeManager.char_type ||
2139                             t == TypeManager.short_type ||
2140                             t == TypeManager.ushort_type ||
2141                             t == TypeManager.int32_type ||
2142                             t == TypeManager.uint32_type ||
2143                             t == TypeManager.int64_type ||
2144                             t == TypeManager.uint64_type)
2145                                 return t;
2146                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2147                 }
2148                 TypeCode tc = Type.GetTypeCode (t);
2149
2150                 switch (tc){
2151                 case TypeCode.Boolean:
2152                         return TypeManager.bool_type;
2153                 case TypeCode.Byte:
2154                         return TypeManager.byte_type;
2155                 case TypeCode.SByte:
2156                         return TypeManager.sbyte_type;
2157                 case TypeCode.Char:
2158                         return TypeManager.char_type;
2159                 case TypeCode.Int16:
2160                         return TypeManager.short_type;
2161                 case TypeCode.UInt16:
2162                         return TypeManager.ushort_type;
2163                 case TypeCode.Int32:
2164                         return TypeManager.int32_type;
2165                 case TypeCode.UInt32:
2166                         return TypeManager.uint32_type;
2167                 case TypeCode.Int64:
2168                         return TypeManager.int64_type;
2169                 case TypeCode.UInt64:
2170                         return TypeManager.uint64_type;
2171                 }
2172                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2173         }
2174
2175         //
2176         // When compiling corlib and called with one of the core types, return
2177         // the corresponding typebuilder for that type.
2178         //
2179         public static Type TypeToCoreType (Type t)
2180         {
2181                 if (RootContext.StdLib || (t is TypeBuilder))
2182                         return t;
2183
2184                 TypeCode tc = Type.GetTypeCode (t);
2185
2186                 switch (tc){
2187                 case TypeCode.Boolean:
2188                         return TypeManager.bool_type;
2189                 case TypeCode.Byte:
2190                         return TypeManager.byte_type;
2191                 case TypeCode.SByte:
2192                         return TypeManager.sbyte_type;
2193                 case TypeCode.Char:
2194                         return TypeManager.char_type;
2195                 case TypeCode.Int16:
2196                         return TypeManager.short_type;
2197                 case TypeCode.UInt16:
2198                         return TypeManager.ushort_type;
2199                 case TypeCode.Int32:
2200                         return TypeManager.int32_type;
2201                 case TypeCode.UInt32:
2202                         return TypeManager.uint32_type;
2203                 case TypeCode.Int64:
2204                         return TypeManager.int64_type;
2205                 case TypeCode.UInt64:
2206                         return TypeManager.uint64_type;
2207                 case TypeCode.Single:
2208                         return TypeManager.float_type;
2209                 case TypeCode.Double:
2210                         return TypeManager.double_type;
2211                 case TypeCode.String:
2212                         return TypeManager.string_type;
2213                 default:
2214                         if (t == typeof (void))
2215                                 return TypeManager.void_type;
2216                         if (t == typeof (object))
2217                                 return TypeManager.object_type;
2218                         if (t == typeof (System.Type))
2219                                 return TypeManager.type_type;
2220                         if (t == typeof (System.IntPtr))
2221                                 return TypeManager.intptr_type;
2222                         return t;
2223                 }
2224         }
2225
2226         /// <summary>
2227         ///   Utility function that can be used to probe whether a type
2228         ///   is managed or not.  
2229         /// </summary>
2230         public static bool VerifyUnManaged (Type t, Location loc)
2231         {
2232                 if (t.IsValueType || t.IsPointer){
2233                         //
2234                         // FIXME: this is more complex, we actually need to
2235                         // make sure that the type does not contain any
2236                         // classes itself
2237                         //
2238                         return true;
2239                 }
2240
2241                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2242                         // We need this explicit check here to make it work when
2243                         // compiling corlib.
2244                         return true;
2245
2246                 Report.Error (
2247                         208, loc,
2248                         "Cannot take the address or size of a variable of a managed type ('" +
2249                         CSharpName (t) + "')");
2250                 return false;   
2251         }
2252         
2253         /// <summary>
2254         ///   Returns the name of the indexer in a given type.
2255         /// </summary>
2256         /// <remarks>
2257         ///   The default is not always `Item'.  The user can change this behaviour by
2258         ///   using the DefaultMemberAttribute in the class.
2259         ///
2260         ///   For example, the String class indexer is named `Chars' not `Item' 
2261         /// </remarks>
2262         public static string IndexerPropertyName (Type t)
2263         {
2264                 if (t is TypeBuilder) {
2265                         if (t.IsInterface) {
2266                                 Interface i = LookupInterface (t);
2267
2268                                 if ((i == null) || (i.IndexerName == null))
2269                                         return "Item";
2270
2271                                 return i.IndexerName;
2272                         } else {
2273                                 TypeContainer tc = LookupTypeContainer (t);
2274
2275                                 if ((tc == null) || (tc.IndexerName == null))
2276                                         return "Item";
2277
2278                                 return tc.IndexerName;
2279                         }
2280                 }
2281                 
2282                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2283                         t, TypeManager.default_member_type);
2284                 if (attr != null){
2285                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2286                         return dma.MemberName;
2287                 }
2288
2289                 return "Item";
2290         }
2291
2292         static MethodInfo pinned_method = null;
2293         public static void MakePinned (LocalBuilder builder)
2294         {
2295                 if (pinned_method == null) {
2296                         pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
2297                         if (pinned_method == null) {
2298                                 Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
2299                                         "This code may cause errors on a runtime with a moving GC");
2300                                 
2301                                 return;
2302                         }
2303                 }
2304                 
2305                 pinned_method.Invoke (builder, null);
2306         }
2307
2308
2309         //
2310         // Returns whether the array of memberinfos contains the given method
2311         //
2312         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2313         {
2314                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2315                 
2316                 foreach (MethodBase method in array) {
2317                         if (method.Name != new_method.Name)
2318                                 continue;
2319
2320                         if (method is MethodInfo && new_method is MethodInfo)
2321                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2322                                         continue;
2323
2324                         
2325                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2326                         int old_count = old_args.Length;
2327                         int i;
2328                         
2329                         if (new_args.Length != old_count)
2330                                 continue;
2331                         
2332                         for (i = 0; i < old_count; i++){
2333                                 if (old_args [i] != new_args [i])
2334                                         break;
2335                         }
2336                         if (i != old_count)
2337                                 continue;
2338
2339                         return true;
2340                 }
2341                 
2342                 return false;
2343         }
2344         
2345         //
2346         // We copy methods from `new_members' into `target_list' if the signature
2347         // for the method from in the new list does not exist in the target_list
2348         //
2349         // The name is assumed to be the same.
2350         //
2351         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2352         {
2353                 if (target_list == null){
2354                         target_list = new ArrayList ();
2355
2356                         foreach (MemberInfo mi in new_members){
2357                                 if (mi is MethodBase)
2358                                         target_list.Add (mi);
2359                         }
2360                         return target_list;
2361                 }
2362                 
2363                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2364                 target_list.CopyTo (target_array, 0);
2365                 
2366                 foreach (MemberInfo mi in new_members){
2367                         MethodBase new_method = (MethodBase) mi;
2368                         
2369                         if (!ArrayContainsMethod (target_array, new_method))
2370                                 target_list.Add (new_method);
2371                 }
2372                 return target_list;
2373         }
2374
2375         [Flags]
2376         public enum MethodFlags {
2377                 IsObsolete = 1,
2378                 IsObsoleteError = 1 << 1,
2379                 ShouldIgnore = 1 << 2
2380         }
2381         
2382         //
2383         // Returns the TypeManager.MethodFlags for this method.
2384         // This emits an error 619 / warning 618 if the method is obsolete.
2385         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2386         //
2387         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2388         {
2389                 MethodFlags flags = 0;
2390                 
2391                 if (mb.DeclaringType is TypeBuilder){
2392                         MethodData method = (MethodData) builder_to_method [mb];
2393                         if (method == null) {
2394                                 // FIXME: implement Obsolete attribute on Property,
2395                                 //        Indexer and Event.
2396                                 return 0;
2397                         }
2398
2399                         return method.GetMethodFlags (loc);
2400                 }
2401
2402                 object [] attrs = mb.GetCustomAttributes (true);
2403                 foreach (object ta in attrs){
2404                         if (!(ta is System.Attribute)){
2405                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2406                                 continue;
2407                         }
2408                         System.Attribute a = (System.Attribute) ta;
2409                         if (a.TypeId == TypeManager.obsolete_attribute_type){
2410                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2411
2412                                 string method_desc = TypeManager.CSharpSignature (mb);
2413
2414                                 if (oa.IsError) {
2415                                         Report.Error (619, loc, "Method `" + method_desc +
2416                                                       "' is obsolete: `" + oa.Message + "'");
2417                                         return MethodFlags.IsObsoleteError;
2418                                 } else
2419                                         Report.Warning (618, loc, "Method `" + method_desc +
2420                                                         "' is obsolete: `" + oa.Message + "'");
2421
2422                                 flags |= MethodFlags.IsObsolete;
2423
2424                                 continue;
2425                         }
2426                         
2427                         //
2428                         // Skip over conditional code.
2429                         //
2430                         if (a.TypeId == TypeManager.conditional_attribute_type){
2431                                 ConditionalAttribute ca = (ConditionalAttribute) a;
2432
2433                                 if (RootContext.AllDefines [ca.ConditionString] == null)
2434                                         flags |= MethodFlags.ShouldIgnore;
2435                         }
2436                 }
2437
2438                 return flags;
2439         }
2440         
2441 #region MemberLookup implementation
2442         
2443         //
2444         // Whether we allow private members in the result (since FindMembers
2445         // uses NonPublic for both protected and private), we need to distinguish.
2446         //
2447         static bool     closure_private_ok;
2448
2449         //
2450         // Who is invoking us and which type is being queried currently.
2451         //
2452         static Type     closure_invocation_type;
2453         static Type     closure_qualifier_type;
2454
2455         //
2456         // The assembly that defines the type is that is calling us
2457         //
2458         static Assembly closure_invocation_assembly;
2459
2460         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2461         {
2462                 return true;
2463         }
2464         
2465         //
2466         // This filter filters by name + whether it is ok to include private
2467         // members in the search
2468         //
2469         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2470         {
2471                 //
2472                 // Hack: we know that the filter criteria will always be in the `closure'
2473                 // fields. 
2474                 //
2475
2476                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2477                         return false;
2478
2479                 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2480                     (m.DeclaringType == closure_invocation_type))
2481                         return true;
2482
2483                 //
2484                 // Ugly: we need to find out the type of `m', and depending
2485                 // on this, tell whether we accept or not
2486                 //
2487                 if (m is MethodBase){
2488                         MethodBase mb = (MethodBase) m;
2489                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2490
2491                         if (ma == MethodAttributes.Private)
2492                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2493                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2494
2495                         //
2496                         // FamAndAssem requires that we not only derivate, but we are on the
2497                         // same assembly.  
2498                         //
2499                         if (ma == MethodAttributes.FamANDAssem){
2500                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2501                                         return false;
2502                         }
2503
2504                         // Assembly and FamORAssem succeed if we're in the same assembly.
2505                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2506                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2507                                         return true;
2508                         }
2509
2510                         // We already know that we aren't in the same assembly.
2511                         if (ma == MethodAttributes.Assembly)
2512                                 return false;
2513
2514                         // Family and FamANDAssem require that we derive.
2515                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2516                                 if (closure_invocation_type == null)
2517                                         return false;
2518
2519                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2520                                         return false;
2521
2522                                 // Although a derived class can access protected members of its base class
2523                                 // it cannot do so through an instance of the base class (CS1540).
2524                                 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2525                                     (closure_qualifier_type != null) &&
2526                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2527                                     !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2528                                         return false;
2529
2530                                 return true;
2531                         }
2532
2533                         // Public.
2534                         return true;
2535                 }
2536
2537                 if (m is FieldInfo){
2538                         FieldInfo fi = (FieldInfo) m;
2539                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2540
2541                         if (fa == FieldAttributes.Private)
2542                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2543                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2544
2545                         //
2546                         // FamAndAssem requires that we not only derivate, but we are on the
2547                         // same assembly.  
2548                         //
2549                         if (fa == FieldAttributes.FamANDAssem){
2550                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2551                                         return false;
2552                         }
2553
2554                         // Assembly and FamORAssem succeed if we're in the same assembly.
2555                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2556                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2557                                         return true;
2558                         }
2559
2560                         // We already know that we aren't in the same assembly.
2561                         if (fa == FieldAttributes.Assembly)
2562                                 return false;
2563
2564                         // Family and FamANDAssem require that we derive.
2565                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2566                                 if (closure_invocation_type == null)
2567                                         return false;
2568
2569                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2570                                         return false;
2571
2572                                 // Although a derived class can access protected members of its base class
2573                                 // it cannot do so through an instance of the base class (CS1540).
2574                                 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2575                                     (closure_qualifier_type != null) &&
2576                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2577                                     !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2578                                         return false;
2579
2580                                 return true;
2581                         }
2582
2583                         // Public.
2584                         return true;
2585                 }
2586
2587                 //
2588                 // EventInfos and PropertyInfos, return true because they lack permission
2589                 // informaiton, so we need to check later on the methods.
2590                 //
2591                 return true;
2592         }
2593
2594         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2595         static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2596
2597         //
2598         // Looks up a member called `name' in the `queried_type'.  This lookup
2599         // is done by code that is contained in the definition for `invocation_type'
2600         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2601         //
2602         // `invocation_type' is used to check whether we're allowed to access the requested
2603         // member wrt its protection level.
2604         //
2605         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2606         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2607         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2608         //
2609         // When resolving a SimpleName, `qualifier_type' is null.
2610         //
2611         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2612         // the same than `queried_type' - except when we're being called from BaseAccess;
2613         // in this case, `invocation_type' is the current type and `queried_type' the base
2614         // type, so this'd normally trigger a CS1540.
2615         //
2616         // The binding flags are `bf' and the kind of members being looked up are `mt'
2617         //
2618         // The return value always includes private members which code in `invocation_type'
2619         // is allowed to access (using the specified `qualifier_type' if given); only use
2620         // BindingFlags.NonPublic to bypass the permission check.
2621         //
2622         // Returns an array of a single element for everything but Methods/Constructors
2623         // that might return multiple matches.
2624         //
2625         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2626                                                   Type queried_type,  MemberTypes mt,
2627                                                   BindingFlags original_bf, string name)
2628         {
2629                 Timer.StartTimer (TimerType.MemberLookup);
2630
2631                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2632                                                         queried_type, mt, original_bf, name);
2633
2634                 Timer.StopTimer (TimerType.MemberLookup);
2635
2636                 return retval;
2637         }
2638
2639         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2640                                                Type queried_type, MemberTypes mt,
2641                                                BindingFlags original_bf, string name)
2642         {
2643                 BindingFlags bf = original_bf;
2644                 
2645                 ArrayList method_list = null;
2646                 Type current_type = queried_type;
2647                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2648                 bool skip_iface_check = true, used_cache = false;
2649                 bool always_ok_flag = false;
2650
2651                 closure_invocation_type = invocation_type;
2652                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2653                 closure_qualifier_type = qualifier_type;
2654
2655                 //
2656                 // If we are a nested class, we always have access to our container
2657                 // type names
2658                 //
2659                 if (invocation_type != null){
2660                         string invocation_name = invocation_type.FullName;
2661                         if (invocation_name.IndexOf ('+') != -1){
2662                                 string container = queried_type.FullName + "+";
2663                                 int container_length = container.Length;
2664
2665                                 if (invocation_name.Length > container_length){
2666                                         string shared = invocation_name.Substring (0, container_length);
2667                                 
2668                                         if (shared == container)
2669                                                 always_ok_flag = true;
2670                                 }
2671                         }
2672                 }
2673                 
2674                 // This is from the first time we find a method
2675                 // in most cases, we do not actually find a method in the base class
2676                 // so we can just ignore it, and save the arraylist allocation
2677                 MemberInfo [] first_members_list = null;
2678                 bool use_first_members_list = false;
2679                 
2680                 do {
2681                         MemberInfo [] list;
2682
2683                         //
2684                         // `NonPublic' is lame, because it includes both protected and
2685                         // private methods, so we need to control this behavior by
2686                         // explicitly tracking if a private method is ok or not.
2687                         //
2688                         // The possible cases are:
2689                         //    public, private and protected (internal does not come into the
2690                         //    equation)
2691                         //
2692                         if ((invocation_type != null) &&
2693                             ((invocation_type == current_type) ||
2694                              IsNestedChildOf (invocation_type, current_type)) ||
2695                             always_ok_flag)
2696                                 bf = original_bf | BindingFlags.NonPublic;
2697                         else
2698                                 bf = original_bf;
2699
2700                         closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2701
2702                         Timer.StopTimer (TimerType.MemberLookup);
2703
2704                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2705
2706                         Timer.StartTimer (TimerType.MemberLookup);
2707
2708                         //
2709                         // When queried for an interface type, the cache will automatically check all
2710                         // inherited members, so we don't need to do this here.  However, this only
2711                         // works if we already used the cache in the first iteration of this loop.
2712                         //
2713                         // If we used the cache in any further iteration, we can still terminate the
2714                         // loop since the cache always looks in all parent classes.
2715                         //
2716
2717                         if (used_cache)
2718                                 searching = false;
2719                         else
2720                                 skip_iface_check = false;
2721
2722                         if (current_type == TypeManager.object_type)
2723                                 searching = false;
2724                         else {
2725                                 current_type = current_type.BaseType;
2726                                 
2727                                 //
2728                                 // This happens with interfaces, they have a null
2729                                 // basetype.  Look members up in the Object class.
2730                                 //
2731                                 if (current_type == null)
2732                                         current_type = TypeManager.object_type;
2733                         }
2734                         
2735                         if (list.Length == 0)
2736                                 continue;
2737
2738                         //
2739                         // Events and types are returned by both `static' and `instance'
2740                         // searches, which means that our above FindMembers will
2741                         // return two copies of the same.
2742                         //
2743                         if (list.Length == 1 && !(list [0] is MethodBase)){
2744                                 return list;
2745                         }
2746
2747                         //
2748                         // Multiple properties: we query those just to find out the indexer
2749                         // name
2750                         //
2751                         if (list [0] is PropertyInfo)
2752                                 return list;
2753
2754                         //
2755                         // We found an event: the cache lookup returns both the event and
2756                         // its private field.
2757                         //
2758                         if (list [0] is EventInfo) {
2759                                 if ((list.Length == 2) && (list [1] is FieldInfo))
2760                                         return new MemberInfo [] { list [0] };
2761
2762                                 // Oooops
2763                                 return null;
2764                         }
2765
2766                         //
2767                         // We found methods, turn the search into "method scan"
2768                         // mode.
2769                         //
2770
2771                         if (first_members_list != null) {
2772                                 if (use_first_members_list) {
2773                                         method_list = CopyNewMethods (method_list, first_members_list);
2774                                         use_first_members_list = false;
2775                                 }
2776                                 
2777                                 method_list = CopyNewMethods (method_list, list);
2778                         } else {
2779                                 first_members_list = list;
2780                                 use_first_members_list = true;
2781                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2782                         }
2783                 } while (searching);
2784                 
2785                 if (use_first_members_list) {
2786                         foreach (MemberInfo mi in first_members_list) {
2787                                 if (! (mi is MethodBase)) {
2788                                         method_list = CopyNewMethods (method_list, first_members_list);
2789                                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2790                                 }
2791                         }
2792                         return (MemberInfo []) first_members_list;
2793                 }
2794
2795                 if (method_list != null && method_list.Count > 0)
2796                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2797                 
2798                 //
2799                 // This happens if we already used the cache in the first iteration, in this case
2800                 // the cache already looked in all interfaces.
2801                 //
2802                 if (skip_iface_check)
2803                         return null;
2804
2805                 //
2806                 // Interfaces do not list members they inherit, so we have to
2807                 // scan those.
2808                 // 
2809                 if (!queried_type.IsInterface)
2810                         return null;
2811
2812                 if (queried_type.IsArray)
2813                         queried_type = TypeManager.array_type;
2814                 
2815                 TypeExpr [] ifaces = GetInterfaces (queried_type);
2816                 if (ifaces == null)
2817                         return null;
2818                 
2819                 foreach (TypeExpr itype in ifaces){
2820                         MemberInfo [] x;
2821
2822                         x = MemberLookup (null, null, itype.Type, mt, bf, name);
2823                         if (x != null)
2824                                 return x;
2825                 }
2826                                         
2827                 return null;
2828         }
2829
2830         //
2831         // This is used to extract properties and event declarations from a type
2832         //
2833         static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2834         {
2835                 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2836
2837                 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2838                 
2839                 if (t is TypeBuilder) {
2840                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2841
2842                         return (MemberInfo []) decl.FindMembers (
2843                                 MemberTypes.Property | MemberTypes.Event,
2844                                 bf, FilterNone_delegate, null);
2845                 } else {
2846                         return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2847                                               bf, FilterNone_delegate, null);
2848
2849                 }
2850         }
2851         
2852         public static bool IsSpecialMethod (MethodBase mb)
2853         {
2854                 Type t = mb.DeclaringType;
2855                 
2856                 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2857                 if (matches == null)
2858                         return false;
2859                 
2860                 foreach (MemberInfo mi in matches){
2861                         if (mi is PropertyBuilder){
2862                                 Pair p = (Pair) properties [mi];
2863
2864                                 if (p.First == mb || p.Second == mb)
2865                                         return true;
2866                         } else if (mi is PropertyInfo){
2867                                 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2868                                 
2869                                 foreach (MethodInfo m in methods){
2870                                         if (m == mb)
2871                                                 return true;
2872                                 }
2873                         } else if (mi is MyEventBuilder){
2874                                 Pair p = (Pair) events [mi];
2875
2876                                 if (p.First == mb || p.Second == mb)
2877                                         return true;
2878                         } else if (mi is EventInfo){
2879                                 EventInfo ei = ((EventInfo) mi);
2880                                 
2881                                 if (ei.GetAddMethod (true) == mb)
2882                                         return true;
2883                                 
2884                                 if (ei.GetRemoveMethod (true) == mb)
2885                                         return true;
2886                                 
2887                                 if (ei.GetRaiseMethod (true) == mb)
2888                                         return true;
2889                         }
2890                 }
2891
2892                 //
2893                 // Now check if it is an operator method
2894                 //
2895                 string s = mb.Name;
2896
2897                 if (s.StartsWith ("op_")){
2898                         foreach (string name in Unary.oper_names){
2899                                 if (s == name)
2900                                         return true;
2901                         }
2902
2903                         foreach (string name in Binary.oper_names){
2904                                 if (s == name)
2905                                         return true;
2906                         }
2907                 }
2908                 
2909                 return false;
2910         }
2911                 
2912 #endregion
2913         
2914 }
2915
2916 /// <summary>
2917 ///   There is exactly one instance of this class per type.
2918 /// </summary>
2919 public sealed class TypeHandle : IMemberContainer {
2920         public readonly TypeHandle BaseType;
2921
2922         readonly int id = ++next_id;
2923         static int next_id = 0;
2924
2925         /// <summary>
2926         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2927         ///   a TypeHandle yet, a new instance of it is created.  This static method
2928         ///   ensures that we'll only have one TypeHandle instance per type.
2929         /// </summary>
2930         public static TypeHandle GetTypeHandle (Type t)
2931         {
2932                 TypeHandle handle = (TypeHandle) type_hash [t];
2933                 if (handle != null)
2934                         return handle;
2935
2936                 handle = new TypeHandle (t);
2937                 type_hash.Add (t, handle);
2938                 return handle;
2939         }
2940         
2941         public static void CleanUp ()
2942         {
2943                 type_hash = null;
2944         }
2945
2946         /// <summary>
2947         ///   Returns the TypeHandle for TypeManager.object_type.
2948         /// </summary>
2949         public static IMemberContainer ObjectType {
2950                 get {
2951                         if (object_type != null)
2952                                 return object_type;
2953
2954                         object_type = GetTypeHandle (TypeManager.object_type);
2955
2956                         return object_type;
2957                 }
2958         }
2959
2960         /// <summary>
2961         ///   Returns the TypeHandle for TypeManager.array_type.
2962         /// </summary>
2963         public static IMemberContainer ArrayType {
2964                 get {
2965                         if (array_type != null)
2966                                 return array_type;
2967
2968                         array_type = GetTypeHandle (TypeManager.array_type);
2969
2970                         return array_type;
2971                 }
2972         }
2973
2974         private static PtrHashtable type_hash = new PtrHashtable ();
2975
2976         private static TypeHandle object_type = null;
2977         private static TypeHandle array_type = null;
2978
2979         private Type type;
2980         private bool is_interface;
2981         private MemberCache member_cache;
2982
2983         private TypeHandle (Type type)
2984         {
2985                 this.type = type;
2986                 if (type.BaseType != null)
2987                         BaseType = GetTypeHandle (type.BaseType);
2988                 this.is_interface = type.IsInterface;
2989                 this.member_cache = new MemberCache (this);
2990         }
2991
2992         // IMemberContainer methods
2993
2994         public string Name {
2995                 get {
2996                         return type.FullName;
2997                 }
2998         }
2999
3000         public Type Type {
3001                 get {
3002                         return type;
3003                 }
3004         }
3005
3006         public IMemberContainer Parent {
3007                 get {
3008                         return BaseType;
3009                 }
3010         }
3011
3012         public bool IsInterface {
3013                 get {
3014                         return is_interface;
3015                 }
3016         }
3017
3018         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3019         {
3020                 MemberInfo [] members;
3021                 if (mt == MemberTypes.Event)
3022                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3023                 else
3024                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3025                                                     null, null);
3026                 Array.Reverse (members);
3027
3028                 return new MemberList (members);
3029         }
3030
3031         // IMemberFinder methods
3032
3033         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3034                                        MemberFilter filter, object criteria)
3035         {
3036                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3037         }
3038
3039         public MemberCache MemberCache {
3040                 get {
3041                         return member_cache;
3042                 }
3043         }
3044
3045         public override string ToString ()
3046         {
3047                 if (BaseType != null)
3048                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3049                 else
3050                         return "TypeHandle (" + id + "," + Name + ")";
3051         }
3052 }
3053
3054 }