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