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