Import changes from mainline
[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
1324         //
1325         // Only a quick hack to get things moving, while real runtime support appears
1326         //
1327         public static bool IsGeneric (Type t)
1328         {
1329                 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1330
1331                 return ds.IsGeneric;
1332         }
1333         
1334         //
1335         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1336         //
1337         public static bool IsUnmanagedType (Type t)
1338         {
1339                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1340                         return true;
1341
1342                 if (IsEnumType (t))
1343                         return true;
1344
1345                 if (t.IsPointer)
1346                         return true;
1347
1348                 if (IsValueType (t)){
1349                         if (t is TypeBuilder){
1350                                 TypeContainer tc = LookupTypeContainer (t);
1351
1352                                 foreach (Field f in tc.Fields){
1353                                         if (f.FieldBuilder.IsStatic)
1354                                                 continue;
1355                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1356                                                 return false;
1357                                 }
1358                         } else {
1359                                 FieldInfo [] fields = t.GetFields ();
1360
1361                                 foreach (FieldInfo f in fields){
1362                                         if (f.IsStatic)
1363                                                 continue;
1364                                         if (!IsUnmanagedType (f.FieldType))
1365                                                 return false;
1366                                 }
1367                         }
1368                         return true;
1369                 }
1370
1371                 return false;
1372         }
1373                 
1374         public static bool IsValueType (Type t)
1375         {
1376                 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1377                         return true;
1378                 else
1379                         return false;
1380         }
1381         
1382         public static bool IsInterfaceType (Type t)
1383         {
1384                 Interface iface = builder_to_declspace [t] as Interface;
1385
1386                 if (iface != null)
1387                         return true;
1388                 else
1389                         return false;
1390         }
1391
1392         //
1393         // Checks whether `type' is a subclass or nested child of `parent'.
1394         //
1395         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1396         {
1397                 do {
1398                         if ((type == parent) || type.IsSubclassOf (parent))
1399                                 return true;
1400
1401                         // Handle nested types.
1402                         type = type.DeclaringType;
1403                 } while (type != null);
1404
1405                 return false;
1406         }
1407
1408         //
1409         // Checks whether `type' is a nested child of `parent'.
1410         //
1411         public static bool IsNestedChildOf (Type type, Type parent)
1412         {
1413                 if (type == parent)
1414                         return false;
1415
1416                 type = type.DeclaringType;
1417                 while (type != null) {
1418                         if (type == parent)
1419                                 return true;
1420
1421                         type = type.DeclaringType;
1422                 }
1423
1424                 return false;
1425         }
1426
1427         //
1428         // Do the right thing when returning the element type of an
1429         // array type based on whether we are compiling corlib or not
1430         //
1431         public static Type GetElementType (Type t)
1432         {
1433                 if (RootContext.StdLib)
1434                         return t.GetElementType ();
1435                 else
1436                         return TypeToCoreType (t.GetElementType ());
1437         }
1438
1439         /// <summary>
1440         ///   Returns the User Defined Types
1441         /// </summary>
1442         public static ArrayList UserTypes {
1443                 get {
1444                         return user_types;
1445                 }
1446         }
1447
1448         public static Hashtable TypeContainers {
1449                 get {
1450                         return typecontainers;
1451                 }
1452         }
1453
1454         static Hashtable attr_to_allowmult;
1455
1456         public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1457         {
1458                 if (attr_to_allowmult == null)
1459                         attr_to_allowmult = new PtrHashtable ();
1460
1461                 if (attr_to_allowmult.Contains (attr_type))
1462                         return;
1463
1464                 attr_to_allowmult.Add (attr_type, allow);
1465                                
1466         }
1467
1468         public static bool AreMultipleAllowed (Type attr_type)
1469         {
1470                 if (!(attr_type is TypeBuilder)) {
1471                         System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1472
1473                         foreach (System.Attribute tmp in attrs)
1474                                 if (tmp is AttributeUsageAttribute) {
1475                                         return ((AttributeUsageAttribute) tmp).AllowMultiple;
1476                                 }
1477
1478                         return false;
1479                 }
1480                 
1481                 if (attr_to_allowmult == null)
1482                         return false;
1483
1484                 return (bool) attr_to_allowmult [attr_type];
1485         }
1486
1487         static Hashtable builder_to_constant;
1488
1489         public static void RegisterConstant (FieldBuilder fb, Const c)
1490         {
1491                 if (builder_to_constant == null)
1492                         builder_to_constant = new PtrHashtable ();
1493
1494                 if (builder_to_constant.Contains (fb))
1495                         return;
1496
1497                 builder_to_constant.Add (fb, c);
1498         }
1499
1500         public static Const LookupConstant (FieldBuilder fb)
1501         {
1502                 if (builder_to_constant == null)
1503                         return null;
1504                 
1505                 return (Const) builder_to_constant [fb];
1506         }
1507         
1508         /// <summary>
1509         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1510         /// </summary>
1511         ///
1512         /// <remarks>
1513         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1514         ///   for anything which is dynamic, and we need this in a number of places,
1515         ///   we register this information here, and use it afterwards.
1516         /// </remarks>
1517         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1518         {
1519                 if (args == null)
1520                         args = NoTypes;
1521                                 
1522                 method_arguments.Add (mb, args);
1523                 method_internal_params.Add (mb, ip);
1524                 
1525                 return true;
1526         }
1527         
1528         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1529         {
1530                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1531                         return null;
1532                 
1533                 if (method_internal_params.Contains (mb))
1534                         return (InternalParameters) method_internal_params [mb];
1535                 else
1536                         throw new Exception ("Argument for Method not registered" + mb);
1537         }
1538
1539         /// <summary>
1540         ///    Returns the argument types for a method based on its methodbase
1541         ///
1542         ///    For dynamic methods, we use the compiler provided types, for
1543         ///    methods from existing assemblies we load them from GetParameters,
1544         ///    and insert them into the cache
1545         /// </summary>
1546         static public Type [] GetArgumentTypes (MethodBase mb)
1547         {
1548                 if (method_arguments.Contains (mb))
1549                         return (Type []) method_arguments [mb];
1550                 else {
1551                         ParameterInfo [] pi = mb.GetParameters ();
1552                         int c = pi.Length;
1553                         Type [] types = new Type [c];
1554                         
1555                         for (int i = 0; i < c; i++)
1556                                 types [i] = pi [i].ParameterType;
1557
1558                         method_arguments.Add (mb, types);
1559                         return types;
1560                 }
1561         }
1562
1563         /// <summary>
1564         ///    Returns the argument types for an indexer based on its PropertyInfo
1565         ///
1566         ///    For dynamic indexers, we use the compiler provided types, for
1567         ///    indexers from existing assemblies we load them from GetParameters,
1568         ///    and insert them into the cache
1569         /// </summary>
1570         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1571         {
1572                 if (indexer_arguments.Contains (indexer))
1573                         return (Type []) indexer_arguments [indexer];
1574                 else if (indexer is PropertyBuilder)
1575                         // If we're a PropertyBuilder and not in the
1576                         // `indexer_arguments' hash, then we're a property and
1577                         // not an indexer.
1578                         return NoTypes;
1579                 else {
1580                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1581                         // Property, not an indexer.
1582                         if (pi == null)
1583                                 return NoTypes;
1584                         int c = pi.Length;
1585                         Type [] types = new Type [c];
1586                         
1587                         for (int i = 0; i < c; i++)
1588                                 types [i] = pi [i].ParameterType;
1589
1590                         indexer_arguments.Add (indexer, types);
1591                         return types;
1592                 }
1593         }
1594         
1595         // <remarks>
1596         //  This is a workaround the fact that GetValue is not
1597         //  supported for dynamic types
1598         // </remarks>
1599         static Hashtable fields = new Hashtable ();
1600         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1601         {
1602                 if (fields.Contains (fb))
1603                         return false;
1604
1605                 fields.Add (fb, value);
1606
1607                 return true;
1608         }
1609
1610         static public object GetValue (FieldBuilder fb)
1611         {
1612                 return fields [fb];
1613         }
1614
1615         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1616         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1617         {
1618                 if (fieldbuilders_to_fields.Contains (fb))
1619                         return false;
1620
1621                 fieldbuilders_to_fields.Add (fb, f);
1622                 return true;
1623         }
1624
1625         //
1626         // The return value can be null;  This will be the case for
1627         // auxiliary FieldBuilders created by the compiler that have no
1628         // real field being declared on the source code
1629         //
1630         static public FieldBase GetField (FieldInfo fb)
1631         {
1632                 return (FieldBase) fieldbuilders_to_fields [fb];
1633         }
1634         
1635         static Hashtable events;
1636
1637         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1638         {
1639                 if (events == null)
1640                         events = new Hashtable ();
1641
1642                 if (events.Contains (eb))
1643                         return false;
1644
1645                 events.Add (eb, new Pair (add, remove));
1646
1647                 return true;
1648         }
1649
1650         static public MethodInfo GetAddMethod (EventInfo ei)
1651         {
1652                 if (ei is MyEventBuilder) {
1653                         Pair pair = (Pair) events [ei];
1654
1655                         return (MethodInfo) pair.First;
1656                 } else
1657                         return ei.GetAddMethod ();
1658         }
1659
1660         static public MethodInfo GetRemoveMethod (EventInfo ei)
1661         {
1662                 if (ei is MyEventBuilder) {
1663                         Pair pair = (Pair) events [ei];
1664
1665                         return (MethodInfo) pair.Second;
1666                 } else
1667                         return ei.GetRemoveMethod ();
1668         }
1669
1670         static Hashtable priv_fields_events;
1671
1672         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1673         {
1674                 if (priv_fields_events == null)
1675                         priv_fields_events = new Hashtable ();
1676
1677                 if (priv_fields_events.Contains (einfo))
1678                         return false;
1679
1680                 priv_fields_events.Add (einfo, builder);
1681
1682                 return true;
1683         }
1684
1685         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1686         {
1687                 if (priv_fields_events == null)
1688                         return null;
1689                 else
1690                         return (MemberInfo) priv_fields_events [ei];
1691         }
1692                 
1693         static Hashtable properties;
1694         
1695         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1696         {
1697                 if (properties == null)
1698                         properties = new Hashtable ();
1699
1700                 if (properties.Contains (pb))
1701                         return false;
1702
1703                 properties.Add (pb, new Pair (get, set));
1704
1705                 return true;
1706         }
1707
1708         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1709                                             MethodBase set, Type[] args)
1710         {
1711                 if (!RegisterProperty (pb, get,set))
1712                         return false;
1713
1714                 indexer_arguments.Add (pb, args);
1715
1716                 return true;
1717         }
1718
1719         /// <summary>
1720         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1721         ///   of an interface.  
1722         /// </summary>
1723         ///
1724         /// <remarks>
1725         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1726         ///   be IA, IB, IC.
1727         /// </remarks>
1728         public static Type [] ExpandInterfaces (Type [] base_interfaces)
1729         {
1730                 ArrayList new_ifaces = new ArrayList ();
1731                 
1732                 foreach (Type iface in base_interfaces){
1733                         if (!new_ifaces.Contains (iface))
1734                                 new_ifaces.Add (iface);
1735                         
1736                         Type [] implementing = TypeManager.GetInterfaces (iface);
1737                         
1738                         foreach (Type imp in implementing){
1739                                 if (!new_ifaces.Contains (imp))
1740                                         new_ifaces.Add (imp);
1741                         }
1742                 }
1743                 Type [] ret = new Type [new_ifaces.Count];
1744                 new_ifaces.CopyTo (ret, 0);
1745                 return ret;
1746         }
1747                 
1748         /// <summary>
1749         ///   This function returns the interfaces in the type `t'.  Works with
1750         ///   both types and TypeBuilders.
1751         /// </summary>
1752         public static Type [] GetInterfaces (Type t)
1753         {
1754                 //
1755                 // The reason for catching the Array case is that Reflection.Emit
1756                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1757                 // but will still throw an exception if we try to call GetInterfaces
1758                 // on the type.
1759                 //
1760                 // Since the array interfaces are always constant, we return those for
1761                 // the System.Array
1762                 //
1763                 
1764                 if (t.IsArray)
1765                         t = TypeManager.array_type;
1766                 
1767                 if (t is TypeBuilder){
1768                         Type [] parent_ifaces;
1769                         
1770                         if (t.BaseType == null)
1771                                 parent_ifaces = NoTypes;
1772                         else
1773                                 parent_ifaces = GetInterfaces (t.BaseType);
1774                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1775                         if (type_ifaces == null)
1776                                 type_ifaces = NoTypes;
1777
1778                         int parent_count = parent_ifaces.Length;
1779                         Type [] result = new Type [parent_count + type_ifaces.Length];
1780                         parent_ifaces.CopyTo (result, 0);
1781                         type_ifaces.CopyTo (result, parent_count);
1782
1783                         return result;
1784                 } else
1785                         return t.GetInterfaces ();
1786         }
1787         
1788         /// <remarks>
1789         ///  The following is used to check if a given type implements an interface.
1790         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1791         /// </remarks>
1792         public static bool ImplementsInterface (Type t, Type iface)
1793         {
1794                 Type [] interfaces;
1795
1796                 //
1797                 // FIXME OPTIMIZATION:
1798                 // as soon as we hit a non-TypeBuiler in the interface
1799                 // chain, we could return, as the `Type.GetInterfaces'
1800                 // will return all the interfaces implement by the type
1801                 // or its parents.
1802                 //
1803                 do {
1804                         interfaces = GetInterfaces (t);
1805
1806                         if (interfaces != null){
1807                                 foreach (Type i in interfaces){
1808                                         if (i == iface)
1809                                                 return true;
1810                                 }
1811                         }
1812                         
1813                         t = t.BaseType;
1814                 } while (t != null);
1815                 
1816                 return false;
1817         }
1818
1819         // This is a custom version of Convert.ChangeType() which works
1820         // with the TypeBuilder defined types when compiling corlib.
1821         public static object ChangeType (object value, Type conversionType, out bool error)
1822         {
1823                 if (!(value is IConvertible)){
1824                         error = true;
1825                         return null;
1826                 }
1827                 
1828                 IConvertible convertValue = (IConvertible) value;
1829                 CultureInfo ci = CultureInfo.CurrentCulture;
1830                 NumberFormatInfo provider = ci.NumberFormat;
1831
1832                 //
1833                 // We must use Type.Equals() here since `conversionType' is
1834                 // the TypeBuilder created version of a system type and not
1835                 // the system type itself.  You cannot use Type.GetTypeCode()
1836                 // on such a type - it'd always return TypeCode.Object.
1837                 //
1838                 error = false;
1839                 try {
1840                         if (conversionType.Equals (typeof (Boolean)))
1841                                 return (object)(convertValue.ToBoolean (provider));
1842                         else if (conversionType.Equals (typeof (Byte)))
1843                                 return (object)(convertValue.ToByte (provider));
1844                         else if (conversionType.Equals (typeof (Char)))
1845                                 return (object)(convertValue.ToChar (provider));
1846                         else if (conversionType.Equals (typeof (DateTime)))
1847                                 return (object)(convertValue.ToDateTime (provider));
1848                         else if (conversionType.Equals (typeof (Decimal)))
1849                                 return (object)(convertValue.ToDecimal (provider));
1850                         else if (conversionType.Equals (typeof (Double)))
1851                                 return (object)(convertValue.ToDouble (provider));
1852                         else if (conversionType.Equals (typeof (Int16)))
1853                                 return (object)(convertValue.ToInt16 (provider));
1854                         else if (conversionType.Equals (typeof (Int32)))
1855                                 return (object)(convertValue.ToInt32 (provider));
1856                         else if (conversionType.Equals (typeof (Int64)))
1857                                 return (object)(convertValue.ToInt64 (provider));
1858                         else if (conversionType.Equals (typeof (SByte)))
1859                                 return (object)(convertValue.ToSByte (provider));
1860                         else if (conversionType.Equals (typeof (Single)))
1861                                 return (object)(convertValue.ToSingle (provider));
1862                         else if (conversionType.Equals (typeof (String)))
1863                                 return (object)(convertValue.ToString (provider));
1864                         else if (conversionType.Equals (typeof (UInt16)))
1865                                 return (object)(convertValue.ToUInt16 (provider));
1866                         else if (conversionType.Equals (typeof (UInt32)))
1867                                 return (object)(convertValue.ToUInt32 (provider));
1868                         else if (conversionType.Equals (typeof (UInt64)))
1869                                 return (object)(convertValue.ToUInt64 (provider));
1870                         else if (conversionType.Equals (typeof (Object)))
1871                                 return (object)(value);
1872                         else 
1873                                 error = true;
1874                 } catch {
1875                         error = true;
1876                 }
1877                 return null;
1878         }
1879
1880         //
1881         // This is needed, because enumerations from assemblies
1882         // do not report their underlyingtype, but they report
1883         // themselves
1884         //
1885         public static Type EnumToUnderlying (Type t)
1886         {
1887                 if (t == TypeManager.enum_type)
1888                         return t;
1889
1890                 t = t.UnderlyingSystemType;
1891                 if (!TypeManager.IsEnumType (t))
1892                         return t;
1893         
1894                 if (t is TypeBuilder) {
1895                         // slow path needed to compile corlib
1896                         if (t == TypeManager.bool_type ||
1897                                         t == TypeManager.byte_type ||
1898                                         t == TypeManager.sbyte_type ||
1899                                         t == TypeManager.char_type ||
1900                                         t == TypeManager.short_type ||
1901                                         t == TypeManager.ushort_type ||
1902                                         t == TypeManager.int32_type ||
1903                                         t == TypeManager.uint32_type ||
1904                                         t == TypeManager.int64_type ||
1905                                         t == TypeManager.uint64_type)
1906                                 return t;
1907                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1908                 }
1909                 TypeCode tc = Type.GetTypeCode (t);
1910
1911                 switch (tc){
1912                 case TypeCode.Boolean:
1913                         return TypeManager.bool_type;
1914                 case TypeCode.Byte:
1915                         return TypeManager.byte_type;
1916                 case TypeCode.SByte:
1917                         return TypeManager.sbyte_type;
1918                 case TypeCode.Char:
1919                         return TypeManager.char_type;
1920                 case TypeCode.Int16:
1921                         return TypeManager.short_type;
1922                 case TypeCode.UInt16:
1923                         return TypeManager.ushort_type;
1924                 case TypeCode.Int32:
1925                         return TypeManager.int32_type;
1926                 case TypeCode.UInt32:
1927                         return TypeManager.uint32_type;
1928                 case TypeCode.Int64:
1929                         return TypeManager.int64_type;
1930                 case TypeCode.UInt64:
1931                         return TypeManager.uint64_type;
1932                 }
1933                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1934         }
1935
1936         //
1937         // When compiling corlib and called with one of the core types, return
1938         // the corresponding typebuilder for that type.
1939         //
1940         public static Type TypeToCoreType (Type t)
1941         {
1942                 if (RootContext.StdLib || (t is TypeBuilder))
1943                         return t;
1944
1945                 TypeCode tc = Type.GetTypeCode (t);
1946
1947                 switch (tc){
1948                 case TypeCode.Boolean:
1949                         return TypeManager.bool_type;
1950                 case TypeCode.Byte:
1951                         return TypeManager.byte_type;
1952                 case TypeCode.SByte:
1953                         return TypeManager.sbyte_type;
1954                 case TypeCode.Char:
1955                         return TypeManager.char_type;
1956                 case TypeCode.Int16:
1957                         return TypeManager.short_type;
1958                 case TypeCode.UInt16:
1959                         return TypeManager.ushort_type;
1960                 case TypeCode.Int32:
1961                         return TypeManager.int32_type;
1962                 case TypeCode.UInt32:
1963                         return TypeManager.uint32_type;
1964                 case TypeCode.Int64:
1965                         return TypeManager.int64_type;
1966                 case TypeCode.UInt64:
1967                         return TypeManager.uint64_type;
1968                 case TypeCode.String:
1969                         return TypeManager.string_type;
1970                 default:
1971                         if (t == typeof (void))
1972                                 return TypeManager.void_type;
1973                         if (t == typeof (object))
1974                                 return TypeManager.object_type;
1975                         if (t == typeof (System.Type))
1976                                 return TypeManager.type_type;
1977                         return t;
1978                 }
1979         }
1980
1981         /// <summary>
1982         ///   Utility function that can be used to probe whether a type
1983         ///   is managed or not.  
1984         /// </summary>
1985         public static bool VerifyUnManaged (Type t, Location loc)
1986         {
1987                 if (t.IsValueType || t.IsPointer){
1988                         //
1989                         // FIXME: this is more complex, we actually need to
1990                         // make sure that the type does not contain any
1991                         // classes itself
1992                         //
1993                         return true;
1994                 }
1995
1996                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1997                         // We need this explicit check here to make it work when
1998                         // compiling corlib.
1999                         return true;
2000
2001                 Report.Error (
2002                         208, loc,
2003                         "Cannot take the address or size of a variable of a managed type ('" +
2004                         CSharpName (t) + "')");
2005                 return false;   
2006         }
2007         
2008         /// <summary>
2009         ///   Returns the name of the indexer in a given type.
2010         /// </summary>
2011         /// <remarks>
2012         ///   The default is not always `Item'.  The user can change this behaviour by
2013         ///   using the DefaultMemberAttribute in the class.
2014         ///
2015         ///   For example, the String class indexer is named `Chars' not `Item' 
2016         /// </remarks>
2017         public static string IndexerPropertyName (Type t)
2018         {
2019                 if (t is TypeBuilder) {
2020                         if (t.IsInterface) {
2021                                 Interface i = LookupInterface (t);
2022
2023                                 if ((i == null) || (i.IndexerName == null))
2024                                         return "Item";
2025
2026                                 return i.IndexerName;
2027                         } else {
2028                                 TypeContainer tc = LookupTypeContainer (t);
2029
2030                                 if ((tc == null) || (tc.IndexerName == null))
2031                                         return "Item";
2032
2033                                 return tc.IndexerName;
2034                         }
2035                 }
2036                 
2037                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2038                         t, TypeManager.default_member_type);
2039                 if (attr != null){
2040                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2041                         return dma.MemberName;
2042                 }
2043
2044                 return "Item";
2045         }
2046
2047         public static void MakePinned (LocalBuilder builder)
2048         {
2049                 //
2050                 // FIXME: Flag the "LocalBuilder" type as being
2051                 // pinned.  Figure out API.
2052                 //
2053         }
2054
2055
2056         //
2057         // Returns whether the array of memberinfos contains the given method
2058         //
2059         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2060         {
2061                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2062                 
2063                 foreach (MethodBase method in array) {
2064                         if (method.Name != new_method.Name)
2065                                 continue;
2066
2067                         if (method is MethodInfo && new_method is MethodInfo)
2068                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2069                                         continue;
2070
2071                         
2072                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2073                         int old_count = old_args.Length;
2074                         int i;
2075                         
2076                         if (new_args.Length != old_count)
2077                                 continue;
2078                         
2079                         for (i = 0; i < old_count; i++){
2080                                 if (old_args [i] != new_args [i])
2081                                         break;
2082                         }
2083                         if (i != old_count)
2084                                 continue;
2085
2086                         return true;
2087                 }
2088                 
2089                 return false;
2090         }
2091         
2092         //
2093         // We copy methods from `new_members' into `target_list' if the signature
2094         // for the method from in the new list does not exist in the target_list
2095         //
2096         // The name is assumed to be the same.
2097         //
2098         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
2099         {
2100                 if (target_list == null){
2101                         target_list = new ArrayList ();
2102
2103                         foreach (MemberInfo mi in new_members){
2104                                 if (mi is MethodBase)
2105                                         target_list.Add (mi);
2106                         }
2107                         return target_list;
2108                 }
2109                 
2110                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2111                 target_list.CopyTo (target_array, 0);
2112                 
2113                 foreach (MemberInfo mi in new_members){
2114                         MethodBase new_method = (MethodBase) mi;
2115                         
2116                         if (!ArrayContainsMethod (target_array, new_method))
2117                                 target_list.Add (new_method);
2118                 }
2119                 return target_list;
2120         }
2121
2122         [Flags]
2123         public enum MethodFlags {
2124                 IsObsolete = 1,
2125                 IsObsoleteError = 2,
2126                 ShouldIgnore = 3
2127         }
2128         
2129         //
2130         // Returns the TypeManager.MethodFlags for this method.
2131         // This emits an error 619 / warning 618 if the method is obsolete.
2132         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2133         //
2134         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2135         {
2136                 MethodFlags flags = 0;
2137                 
2138                 if (mb.DeclaringType is TypeBuilder){
2139                         MethodData method = (MethodData) builder_to_method [mb];
2140                         if (method == null) {
2141                                 // FIXME: implement Obsolete attribute on Property,
2142                                 //        Indexer and Event.
2143                                 return 0;
2144                         }
2145
2146                         return method.GetMethodFlags (loc);
2147                 }
2148
2149                 object [] attrs = mb.GetCustomAttributes (true);
2150                 foreach (object ta in attrs){
2151                         if (!(ta is System.Attribute)){
2152                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2153                                 continue;
2154                         }
2155                         System.Attribute a = (System.Attribute) ta;
2156                         if (a.TypeId == TypeManager.obsolete_attribute_type){
2157                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2158
2159                                 string method_desc = TypeManager.CSharpSignature (mb);
2160
2161                                 if (oa.IsError) {
2162                                         Report.Error (619, loc, "Method `" + method_desc +
2163                                                       "' is obsolete: `" + oa.Message + "'");
2164                                         return MethodFlags.IsObsoleteError;
2165                                 } else
2166                                         Report.Warning (618, loc, "Method `" + method_desc +
2167                                                         "' is obsolete: `" + oa.Message + "'");
2168
2169                                 flags |= MethodFlags.IsObsolete;
2170
2171                                 continue;
2172                         }
2173                         
2174                         //
2175                         // Skip over conditional code.
2176                         //
2177                         if (a.TypeId == TypeManager.conditional_attribute_type){
2178                                 ConditionalAttribute ca = (ConditionalAttribute) a;
2179
2180                                 if (RootContext.AllDefines [ca.ConditionString] == null)
2181                                         flags |= MethodFlags.ShouldIgnore;
2182                         }
2183                 }
2184
2185                 return flags;
2186         }
2187         
2188 #region MemberLookup implementation
2189         
2190         //
2191         // Name of the member
2192         //
2193         static string   closure_name;
2194
2195         //
2196         // Whether we allow private members in the result (since FindMembers
2197         // uses NonPublic for both protected and private), we need to distinguish.
2198         //
2199         static bool     closure_private_ok;
2200
2201         //
2202         // Who is invoking us and which type is being queried currently.
2203         //
2204         static Type     closure_invocation_type;
2205         static Type     closure_queried_type;
2206         static Type     closure_qualifier_type;
2207
2208         //
2209         // The assembly that defines the type is that is calling us
2210         //
2211         static Assembly closure_invocation_assembly;
2212
2213         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2214         {
2215                 return true;
2216         }
2217         
2218         //
2219         // This filter filters by name + whether it is ok to include private
2220         // members in the search
2221         //
2222         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2223         {
2224                 //
2225                 // Hack: we know that the filter criteria will always be in the `closure'
2226                 // fields. 
2227                 //
2228
2229                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2230                         return false;
2231
2232                 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2233                     (m.DeclaringType == closure_invocation_type))
2234                         return true;
2235
2236                 //
2237                 // Ugly: we need to find out the type of `m', and depending
2238                 // on this, tell whether we accept or not
2239                 //
2240                 if (m is MethodBase){
2241                         MethodBase mb = (MethodBase) m;
2242                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2243
2244                         if (ma == MethodAttributes.Private)
2245                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2246                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2247
2248                         //
2249                         // FamAndAssem requires that we not only derivate, but we are on the
2250                         // same assembly.  
2251                         //
2252                         if (ma == MethodAttributes.FamANDAssem){
2253                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2254                                         return false;
2255                         }
2256
2257                         // Assembly and FamORAssem succeed if we're in the same assembly.
2258                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2259                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2260                                         return true;
2261                         }
2262
2263                         // We already know that we aren't in the same assembly.
2264                         if (ma == MethodAttributes.Assembly)
2265                                 return false;
2266
2267                         // Family and FamANDAssem require that we derive.
2268                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2269                                 if (closure_invocation_type == null)
2270                                         return false;
2271
2272                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2273                                         return false;
2274
2275                                 // Although a derived class can access protected members of its base class
2276                                 // it cannot do so through an instance of the base class (CS1540).
2277                                 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2278                                     (closure_qualifier_type != null) &&
2279                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2280                                         return false;
2281
2282                                 return true;
2283                         }
2284
2285                         // Public.
2286                         return true;
2287                 }
2288
2289                 if (m is FieldInfo){
2290                         FieldInfo fi = (FieldInfo) m;
2291                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2292
2293                         if (fa == FieldAttributes.Private)
2294                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2295                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2296
2297                         //
2298                         // FamAndAssem requires that we not only derivate, but we are on the
2299                         // same assembly.  
2300                         //
2301                         if (fa == FieldAttributes.FamANDAssem){
2302                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2303                                         return false;
2304                         }
2305
2306                         // Assembly and FamORAssem succeed if we're in the same assembly.
2307                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2308                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2309                                         return true;
2310                         }
2311
2312                         // We already know that we aren't in the same assembly.
2313                         if (fa == FieldAttributes.Assembly)
2314                                 return false;
2315
2316                         // Family and FamANDAssem require that we derive.
2317                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2318                                 if (closure_invocation_type == null)
2319                                         return false;
2320
2321                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2322                                         return false;
2323
2324                                 // Although a derived class can access protected members of its base class
2325                                 // it cannot do so through an instance of the base class (CS1540).
2326                                 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2327                                     (closure_qualifier_type != null) &&
2328                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2329                                         return false;
2330
2331                                 return true;
2332                         }
2333
2334                         // Public.
2335                         return true;
2336                 }
2337
2338                 //
2339                 // EventInfos and PropertyInfos, return true because they lack permission
2340                 // informaiton, so we need to check later on the methods.
2341                 //
2342                 return true;
2343         }
2344
2345         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2346         static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2347
2348         //
2349         // Looks up a member called `name' in the `queried_type'.  This lookup
2350         // is done by code that is contained in the definition for `invocation_type'
2351         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2352         //
2353         // `invocation_type' is used to check whether we're allowed to access the requested
2354         // member wrt its protection level.
2355         //
2356         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2357         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2358         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2359         //
2360         // When resolving a SimpleName, `qualifier_type' is null.
2361         //
2362         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2363         // the same than `queried_type' - except when we're being called from BaseAccess;
2364         // in this case, `invocation_type' is the current type and `queried_type' the base
2365         // type, so this'd normally trigger a CS1540.
2366         //
2367         // The binding flags are `bf' and the kind of members being looked up are `mt'
2368         //
2369         // The return value always includes private members which code in `invocation_type'
2370         // is allowed to access (using the specified `qualifier_type' if given); only use
2371         // BindingFlags.NonPublic to bypass the permission check.
2372         //
2373         // Returns an array of a single element for everything but Methods/Constructors
2374         // that might return multiple matches.
2375         //
2376         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2377                                                   Type queried_type,  MemberTypes mt,
2378                                                   BindingFlags original_bf, string name)
2379         {
2380                 Timer.StartTimer (TimerType.MemberLookup);
2381
2382                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2383                                                         queried_type, mt, original_bf, name);
2384
2385                 Timer.StopTimer (TimerType.MemberLookup);
2386
2387                 return retval;
2388         }
2389
2390         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2391                                                Type queried_type, MemberTypes mt,
2392                                                BindingFlags original_bf, string name)
2393         {
2394                 BindingFlags bf = original_bf;
2395                 
2396                 ArrayList method_list = null;
2397                 Type current_type = queried_type;
2398                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2399                 bool skip_iface_check = true, used_cache = false;
2400                 bool always_ok_flag = false;
2401
2402                 closure_name = name;
2403                 closure_invocation_type = invocation_type;
2404                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2405                 closure_qualifier_type = qualifier_type;
2406
2407                 //
2408                 // If we are a nested class, we always have access to our container
2409                 // type names
2410                 //
2411                 if (invocation_type != null){
2412                         string invocation_name = invocation_type.FullName;
2413                         if (invocation_name.IndexOf ('+') != -1){
2414                                 string container = queried_type.FullName + "+";
2415                                 int container_length = container.Length;
2416
2417                                 if (invocation_name.Length > container_length){
2418                                         string shared = invocation_name.Substring (0, container_length);
2419                                 
2420                                         if (shared == container)
2421                                                 always_ok_flag = true;
2422                                 }
2423                         }
2424                 }
2425                 
2426                 do {
2427                         MemberList list;
2428
2429                         //
2430                         // `NonPublic' is lame, because it includes both protected and
2431                         // private methods, so we need to control this behavior by
2432                         // explicitly tracking if a private method is ok or not.
2433                         //
2434                         // The possible cases are:
2435                         //    public, private and protected (internal does not come into the
2436                         //    equation)
2437                         //
2438                         if ((invocation_type != null) &&
2439                             ((invocation_type == current_type) ||
2440                              IsNestedChildOf (invocation_type, current_type)) ||
2441                             always_ok_flag)
2442                                 bf = original_bf | BindingFlags.NonPublic;
2443                         else
2444                                 bf = original_bf;
2445
2446                         closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2447                         closure_queried_type = current_type;
2448
2449                         Timer.StopTimer (TimerType.MemberLookup);
2450
2451                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2452
2453                         Timer.StartTimer (TimerType.MemberLookup);
2454
2455                         //
2456                         // When queried for an interface type, the cache will automatically check all
2457                         // inherited members, so we don't need to do this here.  However, this only
2458                         // works if we already used the cache in the first iteration of this loop.
2459                         //
2460                         // If we used the cache in any further iteration, we can still terminate the
2461                         // loop since the cache always looks in all parent classes.
2462                         //
2463
2464                         if (used_cache)
2465                                 searching = false;
2466                         else
2467                                 skip_iface_check = false;
2468
2469                         if (current_type == TypeManager.object_type)
2470                                 searching = false;
2471                         else {
2472                                 current_type = current_type.BaseType;
2473                                 
2474                                 //
2475                                 // This happens with interfaces, they have a null
2476                                 // basetype.  Look members up in the Object class.
2477                                 //
2478                                 if (current_type == null)
2479                                         current_type = TypeManager.object_type;
2480                         }
2481                         
2482                         if (list.Count == 0)
2483                                 continue;
2484
2485                         //
2486                         // Events and types are returned by both `static' and `instance'
2487                         // searches, which means that our above FindMembers will
2488                         // return two copies of the same.
2489                         //
2490                         if (list.Count == 1 && !(list [0] is MethodBase)){
2491                                 return (MemberInfo []) list;
2492                         }
2493
2494                         //
2495                         // Multiple properties: we query those just to find out the indexer
2496                         // name
2497                         //
2498                         if (list [0] is PropertyInfo)
2499                                 return (MemberInfo []) list;
2500
2501                         //
2502                         // We found an event: the cache lookup returns both the event and
2503                         // its private field.
2504                         //
2505                         if (list [0] is EventInfo) {
2506                                 if ((list.Count == 2) && (list [1] is FieldInfo))
2507                                         return new MemberInfo [] { list [0] };
2508
2509                                 // Oooops
2510                                 return null;
2511                         }
2512
2513                         //
2514                         // We found methods, turn the search into "method scan"
2515                         // mode.
2516                         //
2517
2518                         method_list = CopyNewMethods (method_list, list);
2519                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2520                 } while (searching);
2521
2522                 if (method_list != null && method_list.Count > 0) {
2523                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2524                 }
2525                 //
2526                 // This happens if we already used the cache in the first iteration, in this case
2527                 // the cache already looked in all interfaces.
2528                 //
2529                 if (skip_iface_check)
2530                         return null;
2531
2532                 //
2533                 // Interfaces do not list members they inherit, so we have to
2534                 // scan those.
2535                 // 
2536                 if (!queried_type.IsInterface)
2537                         return null;
2538
2539                 if (queried_type.IsArray)
2540                         queried_type = TypeManager.array_type;
2541                 
2542                 Type [] ifaces = GetInterfaces (queried_type);
2543                 if (ifaces == null)
2544                         return null;
2545                 
2546                 foreach (Type itype in ifaces){
2547                         MemberInfo [] x;
2548
2549                         x = MemberLookup (null, null, itype, mt, bf, name);
2550                         if (x != null)
2551                                 return x;
2552                 }
2553                                         
2554                 return null;
2555         }
2556
2557         //
2558         // This is used to extract properties and event declarations from a type
2559         //
2560         static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2561         {
2562                 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2563
2564                 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2565                 
2566                 if (t is TypeBuilder) {
2567                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2568
2569                         return (MemberInfo []) decl.FindMembers (
2570                                 MemberTypes.Property | MemberTypes.Event,
2571                                 bf, FilterNone_delegate, null);
2572                 } else {
2573                         return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2574                                               bf, FilterNone_delegate, null);
2575
2576                 }
2577         }
2578         
2579         public static bool IsSpecialMethod (MethodBase mb)
2580         {
2581                 Type t = mb.DeclaringType;
2582                 
2583                 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2584                 if (matches == null)
2585                         return false;
2586                 
2587                 foreach (MemberInfo mi in matches){
2588                         if (mi is PropertyBuilder){
2589                                 Pair p = (Pair) properties [mi];
2590
2591                                 if (p.First == mb || p.Second == mb)
2592                                         return true;
2593                         } else if (mi is PropertyInfo){
2594                                 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2595                                 
2596                                 foreach (MethodInfo m in methods){
2597                                         if (m == mb)
2598                                                 return true;
2599                                 }
2600                         } else if (mi is MyEventBuilder){
2601                                 Pair p = (Pair) events [mi];
2602
2603                                 if (p.First == mb || p.Second == mb)
2604                                         return true;
2605                         } else if (mi is EventInfo){
2606                                 EventInfo ei = ((EventInfo) mi);
2607                                 
2608                                 if (ei.GetAddMethod (true) == mb)
2609                                         return true;
2610                                 
2611                                 if (ei.GetRemoveMethod (true) == mb)
2612                                         return true;
2613                                 
2614                                 if (ei.GetRaiseMethod (true) == mb)
2615                                         return true;
2616                         }
2617                 }
2618
2619                 //
2620                 // Now check if it is an operator method
2621                 //
2622                 string s = mb.Name;
2623
2624                 if (s.StartsWith ("op_")){
2625                         foreach (string name in Unary.oper_names){
2626                                 if (s == name)
2627                                         return true;
2628                         }
2629
2630                         foreach (string name in Binary.oper_names){
2631                                 if (s == name)
2632                                         return true;
2633                         }
2634                 }
2635                 
2636                 return false;
2637         }
2638                 
2639 #endregion
2640         
2641 }
2642
2643 /// <summary>
2644 ///   There is exactly one instance of this class per type.
2645 /// </summary>
2646 public sealed class TypeHandle : IMemberContainer {
2647         public readonly TypeHandle BaseType;
2648
2649         readonly int id = ++next_id;
2650         static int next_id = 0;
2651
2652         /// <summary>
2653         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2654         ///   a TypeHandle yet, a new instance of it is created.  This static method
2655         ///   ensures that we'll only have one TypeHandle instance per type.
2656         /// </summary>
2657         public static TypeHandle GetTypeHandle (Type t)
2658         {
2659                 TypeHandle handle = (TypeHandle) type_hash [t];
2660                 if (handle != null)
2661                         return handle;
2662
2663                 handle = new TypeHandle (t);
2664                 type_hash.Add (t, handle);
2665                 return handle;
2666         }
2667
2668         /// <summary>
2669         ///   Returns the TypeHandle for TypeManager.object_type.
2670         /// </summary>
2671         public static IMemberContainer ObjectType {
2672                 get {
2673                         if (object_type != null)
2674                                 return object_type;
2675
2676                         object_type = GetTypeHandle (TypeManager.object_type);
2677
2678                         return object_type;
2679                 }
2680         }
2681
2682         /// <summary>
2683         ///   Returns the TypeHandle for TypeManager.array_type.
2684         /// </summary>
2685         public static IMemberContainer ArrayType {
2686                 get {
2687                         if (array_type != null)
2688                                 return array_type;
2689
2690                         array_type = GetTypeHandle (TypeManager.array_type);
2691
2692                         return array_type;
2693                 }
2694         }
2695
2696         private static PtrHashtable type_hash = new PtrHashtable ();
2697
2698         private static TypeHandle object_type = null;
2699         private static TypeHandle array_type = null;
2700
2701         private Type type;
2702         private bool is_interface;
2703         private MemberCache member_cache;
2704
2705         private TypeHandle (Type type)
2706         {
2707                 this.type = type;
2708                 if (type.BaseType != null)
2709                         BaseType = GetTypeHandle (type.BaseType);
2710                 else if ((type != TypeManager.object_type) && (type != typeof (object)))
2711                         is_interface = true;
2712                 this.member_cache = new MemberCache (this);
2713         }
2714
2715         // IMemberContainer methods
2716
2717         public string Name {
2718                 get {
2719                         return type.FullName;
2720                 }
2721         }
2722
2723         public Type Type {
2724                 get {
2725                         return type;
2726                 }
2727         }
2728
2729         public IMemberContainer Parent {
2730                 get {
2731                         return BaseType;
2732                 }
2733         }
2734
2735         public bool IsInterface {
2736                 get {
2737                         return is_interface;
2738                 }
2739         }
2740
2741         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2742         {
2743                 MemberInfo [] members;
2744                 if (mt == MemberTypes.Event)
2745                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2746                 else
2747                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2748                                                     null, null);
2749                 Array.Reverse (members);
2750
2751                 return new MemberList (members);
2752         }
2753
2754         // IMemberFinder methods
2755
2756         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2757                                        MemberFilter filter, object criteria)
2758         {
2759                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2760         }
2761
2762         public MemberCache MemberCache {
2763                 get {
2764                         return member_cache;
2765                 }
2766         }
2767
2768         public override string ToString ()
2769         {
2770                 if (BaseType != null)
2771                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2772                 else
2773                         return "TypeHandle (" + id + "," + Name + ")";
2774         }
2775 }
2776
2777 }