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