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