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