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