In mcs:
[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 partial 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 interlocked_type;
75         static public Type runtime_field_handle_type;
76         static public Type runtime_argument_handle_type;
77         static public Type attribute_type;
78         static public Type attribute_usage_type;
79         static public Type decimal_constant_attribute_type;
80         static public Type dllimport_type;
81         static public Type unverifiable_code_type;
82         static public Type methodimpl_attr_type;
83         static public Type marshal_as_attr_type;
84         static public Type param_array_type;
85         static public Type void_ptr_type;
86         static public Type indexer_name_type;
87         static public Type exception_type;
88         static public Type invalid_operation_exception_type;
89         static public Type not_supported_exception_type;
90         static public Type obsolete_attribute_type;
91         static public Type conditional_attribute_type;
92         static public Type in_attribute_type;
93         static public Type out_attribute_type;
94         static public Type default_parameter_value_attribute_type;
95
96         static public Type anonymous_method_type;
97         static public Type cls_compliant_attribute_type;
98         static public Type typed_reference_type;
99         static public Type arg_iterator_type;
100         static public Type mbr_type;
101         static public Type struct_layout_attribute_type;
102         static public Type field_offset_attribute_type;
103         static public Type security_attr_type;
104         static public Type required_attr_type;
105         static public Type guid_attr_type;
106         static public Type assembly_culture_attribute_type;
107         static public Type coclass_attr_type;
108         static public Type comimport_attr_type;
109
110         /// 
111         /// .NET 2.0
112         ///
113 #if NET_2_0
114         static internal Type runtime_compatibility_attr_type;
115         static internal Type compiler_generated_attr_type;
116         static internal Type fixed_buffer_attr_type;
117         static internal Type default_charset_type;
118         static internal Type internals_visible_attr_type;
119         static internal Type type_forwarder_attr_type;
120 #endif
121
122         // 
123         // Expressions representing the internal types.  Used during declaration
124         // definition.
125         //
126         static public TypeExpr system_object_expr, system_string_expr; 
127         static public TypeExpr system_boolean_expr, system_decimal_expr;
128         static public TypeExpr system_single_expr, system_double_expr;
129         static public TypeExpr system_sbyte_expr, system_byte_expr;
130         static public TypeExpr system_int16_expr, system_uint16_expr;
131         static public TypeExpr system_int32_expr, system_uint32_expr;
132         static public TypeExpr system_int64_expr, system_uint64_expr;
133         static public TypeExpr system_char_expr, system_void_expr;
134         static public TypeExpr system_asynccallback_expr;
135         static public TypeExpr system_iasyncresult_expr;
136         static public TypeExpr system_valuetype_expr;
137         static public TypeExpr system_intptr_expr;
138
139         //
140         // This is only used when compiling corlib
141         //
142         static public Type system_int32_type;
143         static public Type system_array_type;
144         static public Type system_type_type;
145         static public Type system_assemblybuilder_type;
146         static public MethodInfo system_int_array_get_length;
147         static public MethodInfo system_int_array_get_rank;
148         static public MethodInfo system_object_array_clone;
149         static public MethodInfo system_int_array_get_length_int;
150         static public MethodInfo system_int_array_get_lower_bound_int;
151         static public MethodInfo system_int_array_get_upper_bound_int;
152         static public MethodInfo system_void_array_copyto_array_int;
153
154         
155         //
156         // Internal, not really used outside
157         //
158         static Type runtime_helpers_type;
159         
160         //
161         // These methods are called by code generated by the compiler
162         //
163         static public MethodInfo string_concat_string_string;
164         static public MethodInfo string_concat_string_string_string;
165         static public MethodInfo string_concat_string_string_string_string;
166         static public MethodInfo string_concat_string_dot_dot_dot;
167         static public MethodInfo string_concat_object_object;
168         static public MethodInfo string_concat_object_object_object;
169         static public MethodInfo string_concat_object_dot_dot_dot;
170         static public MethodInfo string_isinterneted_string;
171         static public MethodInfo system_type_get_type_from_handle;
172         static public MethodInfo bool_movenext_void;
173         static public MethodInfo ienumerable_getenumerator_void;
174         static public MethodInfo void_reset_void;
175         static public MethodInfo void_dispose_void;
176         static public MethodInfo void_monitor_enter_object;
177         static public MethodInfo void_monitor_exit_object;
178         static public MethodInfo void_initializearray_array_fieldhandle;
179         static public MethodInfo int_getlength_int;
180         static public MethodInfo delegate_combine_delegate_delegate;
181         static public MethodInfo delegate_remove_delegate_delegate;
182         static public MethodInfo int_get_offset_to_string_data;
183         static public MethodInfo int_array_get_length;
184         static public MethodInfo int_array_get_rank;
185         static public MethodInfo object_array_clone;
186         static public MethodInfo int_array_get_length_int;
187         static public MethodInfo int_array_get_lower_bound_int;
188         static public MethodInfo int_array_get_upper_bound_int;
189         static public MethodInfo void_array_copyto_array_int;
190         static public MethodInfo int_interlocked_compare_exchange;
191         static public PropertyInfo ienumerator_getcurrent;
192         
193         //
194         // The attribute constructors.
195         //
196         static public ConstructorInfo object_ctor;
197         static private ConstructorInfo cons_param_array_attribute;
198         static public ConstructorInfo void_decimal_ctor_five_args;
199         static public ConstructorInfo void_decimal_ctor_int_arg;
200         static public ConstructorInfo unverifiable_code_ctor;
201         static public ConstructorInfo default_member_ctor;
202         static public ConstructorInfo decimal_constant_attribute_ctor;
203         static internal ConstructorInfo struct_layout_attribute_ctor;
204         static public ConstructorInfo field_offset_attribute_ctor;
205         
206         ///
207         /// A new in C# 2.0
208         /// 
209 #if NET_2_0
210         static internal CustomAttributeBuilder compiler_generated_attr;
211         static internal ConstructorInfo fixed_buffer_attr_ctor;
212 #endif
213
214         static PtrHashtable builder_to_declspace;
215
216         static PtrHashtable builder_to_member_cache;
217
218         // <remarks>
219         //   Tracks the interfaces implemented by typebuilders.  We only
220         //   enter those who do implement or or more interfaces
221         // </remarks>
222         static PtrHashtable builder_to_ifaces;
223
224         // <remarks>
225         //   Maps PropertyBuilder to a Type array that contains
226         //   the arguments to the indexer
227         // </remarks>
228         static Hashtable indexer_arguments;
229
230         // <remarks>
231         //   Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
232         // <remarks>
233         static Hashtable method_params;
234
235         // <remarks>
236         //  A hash table from override methods to their base virtual method.
237         // <remarks>
238         static Hashtable method_overrides;
239
240         // <remarks>
241         //  Keeps track of methods
242         // </remarks>
243
244         static Hashtable builder_to_method;
245
246         // <remarks>
247         //  Contains all public types from referenced assemblies.
248         //  This member is used only if CLS Compliance verification is required.
249         // </remarks>
250         public static Hashtable AllClsTopLevelTypes;
251
252         static Hashtable fieldbuilders_to_fields;
253         static Hashtable propertybuilder_to_property;
254         static Hashtable fields;
255         static Hashtable events;
256
257 #if GMCS_SOURCE
258         static PtrHashtable assembly_internals_vis_attrs;
259 #endif
260
261         struct Signature {
262                 public string name;
263                 public Type [] args;
264         }
265         
266         public static void CleanUp ()
267         {
268                 // Lets get everything clean so that we can collect before generating code
269                 builder_to_declspace = null;
270                 builder_to_member_cache = null;
271                 builder_to_ifaces = null;
272                 builder_to_type_param = null;
273                 indexer_arguments = null;
274                 method_params = null;
275                 builder_to_method = null;
276                 
277                 fields = null;
278                 fieldbuilders_to_fields = null;
279                 events = null;
280                 priv_fields_events = null;
281                 type_hash = null;
282                 propertybuilder_to_property = null;
283
284 #if GMCS_SOURCE
285                 assembly_internals_vis_attrs = null;
286 #endif
287
288                 TypeHandle.CleanUp ();
289         }
290
291         /// <summary>
292         ///   A filter for Findmembers that uses the Signature object to
293         ///   extract objects
294         /// </summary>
295         static bool SignatureFilter (MemberInfo mi, object criteria)
296         {
297                 Signature sig = (Signature) criteria;
298
299                 if (!(mi is MethodBase))
300                         return false;
301                 
302                 if (mi.Name != sig.name)
303                         return false;
304
305                 int count = sig.args.Length;
306                 
307                 if (mi is MethodBuilder || mi is ConstructorBuilder){
308                         Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
309
310                         if (candidate_args.Length != count)
311                                 return false;
312                         
313                         for (int i = 0; i < count; i++)
314                                 if (candidate_args [i] != sig.args [i])
315                                         return false;
316                         
317                         return true;
318                 } else {
319                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
320
321                         if (pars.Length != count)
322                                 return false;
323
324                         for (int i = 0; i < count; i++)
325                                 if (pars [i].ParameterType != sig.args [i])
326                                         return false;
327                         return true;
328                 }
329         }
330
331         // A delegate that points to the filter above.
332         static MemberFilter signature_filter;
333
334         //
335         // These are expressions that represent some of the internal data types, used
336         // elsewhere
337         //
338         static void InitExpressionTypes ()
339         {
340                 system_object_expr  = new TypeLookupExpression ("System.Object");
341                 system_string_expr  = new TypeLookupExpression ("System.String");
342                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
343                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
344                 system_single_expr  = new TypeLookupExpression ("System.Single");
345                 system_double_expr  = new TypeLookupExpression ("System.Double");
346                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
347                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
348                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
349                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
350                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
351                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
352                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
353                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
354                 system_char_expr    = new TypeLookupExpression ("System.Char");
355                 system_void_expr    = new TypeLookupExpression ("System.Void");
356                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
357                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
358                 system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
359                 system_intptr_expr  = new TypeLookupExpression ("System.IntPtr");
360         }
361
362         static TypeManager ()
363         {
364                 Reset ();
365
366                 signature_filter = new MemberFilter (SignatureFilter);
367                 InitExpressionTypes ();
368         }
369
370         static public void Reset ()
371         {
372                 builder_to_declspace = new PtrHashtable ();
373                 builder_to_member_cache = new PtrHashtable ();
374                 builder_to_method = new PtrHashtable ();
375                 builder_to_type_param = new PtrHashtable ();
376                 method_params = new PtrHashtable ();
377                 method_overrides = new PtrHashtable ();
378                 indexer_arguments = new PtrHashtable ();
379                 builder_to_ifaces = new PtrHashtable ();
380                 
381                 fieldbuilders_to_fields = new Hashtable ();
382                 propertybuilder_to_property = new Hashtable ();
383                 fields = new Hashtable ();
384                 type_hash = new DoubleHash ();
385
386 #if GMCS_SOURCE
387                 assembly_internals_vis_attrs = new PtrHashtable ();
388 #endif
389
390                 // to uncover regressions
391                 cons_param_array_attribute = null;
392         }
393
394         public static void AddUserType (DeclSpace ds)
395         {
396                 builder_to_declspace.Add (ds.TypeBuilder, ds);
397         }
398
399         //
400         // This entry point is used by types that we define under the covers
401         // 
402         public static void RegisterBuilder (Type tb, Type [] ifaces)
403         {
404                 if (ifaces != null)
405                         builder_to_ifaces [tb] = ifaces;
406         }       
407
408         public static void AddMethod (MethodBase builder, IMethodData method)
409         {
410                 builder_to_method.Add (builder, method);
411                 method_params.Add (builder, method.ParameterInfo);
412         }
413
414         public static IMethodData GetMethod (MethodBase builder)
415         {
416                 return (IMethodData) builder_to_method [builder];
417         }
418
419         /// <summary>
420         ///   Returns the DeclSpace whose Type is `t' or null if there is no
421         ///   DeclSpace for `t' (ie, the Type comes from a library)
422         /// </summary>
423         public static DeclSpace LookupDeclSpace (Type t)
424         {
425                 return builder_to_declspace [t] as DeclSpace;
426         }
427
428         /// <summary>
429         ///   Returns the TypeContainer whose Type is `t' or null if there is no
430         ///   TypeContainer for `t' (ie, the Type comes from a library)
431         /// </summary>
432         public static TypeContainer LookupTypeContainer (Type t)
433         {
434                 return builder_to_declspace [t] as TypeContainer;
435         }
436
437         public static MemberCache LookupMemberCache (Type t)
438         {
439                 if (t is TypeBuilder) {
440                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
441                         if (container != null)
442                                 return container.MemberCache;
443                 }
444
445 #if GMCS_SOURCE
446                 if (t is GenericTypeParameterBuilder) {
447                         IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
448
449                         if (container != null)
450                                 return container.MemberCache;
451                 }
452 #endif
453
454                 return TypeHandle.GetMemberCache (t);
455         }
456
457         public static MemberCache LookupBaseInterfacesCache (Type t)
458         {
459                 Type [] ifaces = GetInterfaces (t);
460
461                 if (ifaces != null && ifaces.Length == 1)
462                         return LookupMemberCache (ifaces [0]);
463
464                 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
465                 MemberCache cache = builder_to_member_cache [t] as MemberCache;
466                 if (cache != null)
467                         return cache;
468
469                 cache = new MemberCache (ifaces);
470                 builder_to_member_cache.Add (t, cache);
471                 return cache;
472         }
473
474         public static TypeContainer LookupInterface (Type t)
475         {
476                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
477                 if ((tc == null) || (tc.Kind != Kind.Interface))
478                         return null;
479
480                 return tc;
481         }
482
483         public static Delegate LookupDelegate (Type t)
484         {
485                 return builder_to_declspace [t] as Delegate;
486         }
487
488         public static Class LookupClass (Type t)
489         {
490                 return (Class) builder_to_declspace [t];
491         }
492
493         //
494         // We use this hash for multiple kinds of constructed types:
495         //
496         //    (T, "&")  Given T, get T &
497         //    (T, "*")  Given T, get T *
498         //    (T, "[]") Given T and a array dimension, get T []
499         //    (T, X)    Given a type T and a simple name X, get the type T+X
500         //
501         // Accessibility tests, if necessary, should be done by the user
502         //
503         static DoubleHash type_hash = new DoubleHash ();
504
505         //
506         // Gets the reference to T version of the Type (T&)
507         //
508         public static Type GetReferenceType (Type t)
509         {
510 #if GMCS_SOURCE
511                 return t.MakeByRefType ();
512 #else
513                 return GetConstructedType (t, "&");
514 #endif
515         }
516
517         //
518         // Gets the pointer to T version of the Type  (T*)
519         //
520         public static Type GetPointerType (Type t)
521         {
522                 return GetConstructedType (t, "*");
523         }
524
525         public static Type GetConstructedType (Type t, string dim)
526         {
527                 object ret = null;
528                 if (type_hash.Lookup (t, dim, out ret))
529                         return (Type) ret;
530
531                 ret = t.Module.GetType (t.ToString () + dim);
532                 if (ret != null) {
533                         type_hash.Insert (t, dim, ret);
534                         return (Type) ret;
535                 }
536
537                 if (dim == "&") {
538                         ret = GetReferenceType (t);
539                         type_hash.Insert (t, dim, ret);
540                         return (Type) ret;
541                 }
542
543 #if GMCS_SOURCE
544                 if (t.IsGenericParameter || t.IsGenericType) {
545                         int pos = 0;
546                         Type result = t;
547                         while ((pos < dim.Length) && (dim [pos] == '[')) {
548                                 pos++;
549
550                                 if (dim [pos] == ']') {
551                                         result = result.MakeArrayType ();
552                                         pos++;
553
554                                         if (pos < dim.Length)
555                                                 continue;
556
557                                         type_hash.Insert (t, dim, result);
558                                         return result;
559                                 }
560
561                                 int rank = 0;
562                                 while (dim [pos] == ',') {
563                                         pos++; rank++;
564                                 }
565
566                                 if ((dim [pos] != ']') || (pos != dim.Length-1))
567                                         break;
568
569                                 result = result.MakeArrayType (rank + 1);
570                                 type_hash.Insert (t, dim, result);
571                                 return result;
572                         }
573                 }
574 #endif
575
576                 type_hash.Insert (t, dim, null);
577                 return null;
578         }
579
580         public static Type GetNestedType (Type t, string name)
581         {
582                 object ret = null;
583                 if (!type_hash.Lookup (t, name, out ret)) {
584                         ret = t.GetNestedType (name,
585                                BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
586                         type_hash.Insert (t, name, ret);
587                 }
588                 return (Type) ret;
589         }
590
591         /// <summary>
592         /// Fills static table with exported types from all referenced assemblies.
593         /// This information is required for CLS Compliance tests.
594         /// </summary>
595         public static void LoadAllImportedTypes ()
596         {
597                 AllClsTopLevelTypes = new Hashtable (1500);
598                 foreach (Assembly a in RootNamespace.Global.Assemblies) {
599                         foreach (Type t in a.GetExportedTypes ()) {
600                                 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
601                         }
602                 }
603         }
604
605         public static bool NamespaceClash (string name, Location loc)
606         {
607                 if (! RootNamespace.Global.IsNamespace (name))
608                         return false;
609
610                 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
611                 return true;
612         }
613
614         /// <summary>
615         ///   Returns the C# name of a type if possible, or the full type name otherwise
616         /// </summary>
617         static public string CSharpName (Type t)
618         {
619                 if (t == typeof(NullType))
620                         return "null";
621
622 #if GMCS_SOURCE 
623                 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
624                         t = GetTypeArguments (t) [0];
625                         return CSharpName (t) + "?";
626                 }
627 #endif
628
629                 string name = GetFullName (t);
630
631                 return Regex.Replace (name, 
632                         @"^System\." +
633                         @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
634                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
635                         @"Boolean|String|Void|Null)" +
636                         @"(\W+|\b)", 
637                         new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
638         }       
639
640         static public string CSharpName (Type[] types)
641         {
642                 StringBuilder sb = new StringBuilder ();
643                 foreach (Type t in types) {
644                         sb.Append (CSharpName (t));
645                         sb.Append (',');
646                 }
647                 sb.Remove (sb.Length - 1, 1);
648                 return sb.ToString ();
649         }
650         
651         static String CSharpNameMatch (Match match) 
652         {
653                 string s = match.Groups [1].Captures [0].Value;
654                 return s.ToLower ().
655                 Replace ("int32", "int").
656                 Replace ("uint32", "uint").
657                 Replace ("int16", "short").
658                 Replace ("uint16", "ushort").
659                 Replace ("int64", "long").
660                 Replace ("uint64", "ulong").
661                 Replace ("single", "float").
662                 Replace ("boolean", "bool")
663                 + match.Groups [2].Captures [0].Value;
664         }
665
666         /// <summary>
667         ///  Returns the signature of the method with full namespace classification
668         /// </summary>
669         static public string GetFullNameSignature (MemberInfo mi)
670         {
671                 PropertyInfo pi = mi as PropertyInfo;
672                 if (pi != null) {
673                         MethodBase pmi = pi.GetGetMethod (true);
674                         if (pmi == null)
675                                 pmi = pi.GetSetMethod (true);
676                         if (GetParameterData (pmi).Count > 0)
677                                 mi = pmi;
678                 }
679                 return (mi is MethodBase)
680                         ? CSharpSignature (mi as MethodBase) 
681                         : CSharpName (mi.DeclaringType) + '.' + mi.Name;
682         }
683
684 #if GMCS_SOURCE
685         private static int GetFullName (Type t, StringBuilder sb)
686         {
687                 int pos = 0;
688
689                 if (!t.IsGenericType) {
690                         sb.Append (t.FullName);
691                         return 0;
692                 }
693
694                 if (t.DeclaringType != null) {
695                         pos = GetFullName (t.DeclaringType, sb);
696                         sb.Append ('.');
697                         sb.Append (RemoveGenericArity (t.Name));
698                 } else {
699                         sb.Append (RemoveGenericArity (t.FullName));
700                 }
701
702                 Type[] this_args = GetTypeArguments (t);
703
704                 if (this_args.Length < pos)
705                         throw new InternalErrorException (
706                                 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
707                 if (this_args.Length == pos)
708                         return pos;
709
710                 sb.Append ('<');
711                 for (;;) {
712                         sb.Append (CSharpName (this_args [pos++]));
713                         if (pos == this_args.Length)
714                                 break;
715                         sb.Append (',');
716                 }
717                 sb.Append ('>');
718                 return pos;
719         }
720
721         public static string GetFullName (Type t)
722         {
723                 if (t.IsGenericParameter)
724                         return t.Name;
725                 if (!t.IsGenericType)
726                         return t.FullName;
727
728                 StringBuilder sb = new StringBuilder ();
729                 int pos = GetFullName (t, sb);
730                 if (pos <= 0)
731                         throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
732                 return sb.ToString ();
733         }
734 #else
735         public static string GetFullName (Type t)
736         {
737                 return t.FullName;
738         }
739 #endif
740
741         public static string RemoveGenericArity (string from)
742         {
743                 int i = from.IndexOf ('`');
744                 if (i > 0)
745                         return from.Substring (0, i);
746                 return from;
747         }
748
749         /// <summary>
750         /// When we need to report accessors as well
751         /// </summary>
752         static public string CSharpSignature (MethodBase mb)
753         {
754                 return CSharpSignature (mb, false);
755         }
756
757         /// <summary>
758         ///   Returns the signature of the method
759         /// </summary>
760         static public string CSharpSignature (MethodBase mb, bool show_accessor)
761         {
762                 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
763                 sig.Append ('.');
764
765                 ParameterData iparams = GetParameterData (mb);
766                 string parameters = iparams.GetSignatureForError ();
767                 string accessor = "";
768
769                 // Is property
770                 if (mb.IsSpecialName) {
771                         Operator.OpType ot = Operator.GetOperatorType (mb.Name);
772                         if (ot != Operator.OpType.TOP) {
773                                 sig.Append ("operator ");
774                                 sig.Append (Operator.GetName (ot));
775                                 sig.Append (parameters);
776                                 return sig.ToString ();
777                         }
778
779                         if (mb.Name.StartsWith ("get_") || mb.Name.StartsWith ("set_")) {
780                                 accessor = mb.Name.Substring (0, 3);
781                         }
782                 }
783
784                 // Is indexer
785                 if (mb.IsSpecialName && !mb.IsConstructor) {
786                         if (iparams.Count > (mb.Name.StartsWith ("get_") ? 0 : 1)) {
787                                 sig.Append ("this[");
788                                 if (show_accessor) {
789                                         sig.Append (parameters.Substring (1, parameters.Length - 2));
790                                 }
791                                 else {
792                                         int before_ret_val = parameters.LastIndexOf (',');
793                                         if (before_ret_val < 0)
794                                                 sig.Append (parameters.Substring (1, parameters.Length - 2));
795                                         else
796                                                 sig.Append (parameters.Substring (1, before_ret_val - 1));
797                                 }
798                                 sig.Append (']');
799                         } else {
800                                 sig.Append (mb.Name.Substring (4));
801                         }
802                 } else {
803                         if (mb.Name == ".ctor")
804                                 sig.Append (mb.DeclaringType.Name);
805                         else {
806                                 sig.Append (mb.Name);
807
808 #if GMCS_SOURCE
809                                 if (TypeManager.IsGenericMethod (mb)) {
810                                         Type[] args = mb.GetGenericArguments ();
811                                         sig.Append ('<');
812                                         for (int i = 0; i < args.Length; i++) {
813                                                 if (i > 0)
814                                                         sig.Append (',');
815                                                 sig.Append (args [i].Name);
816                                         }
817                                         sig.Append ('>');
818                                 }
819 #endif
820                         }
821
822                         sig.Append (parameters);
823                 }
824
825                 if (show_accessor && accessor.Length > 0) {
826                         sig.Append ('.');
827                         sig.Append (accessor);
828                 }
829
830                 return sig.ToString ();
831         }
832
833         public static string GetMethodName (MethodInfo m)
834         {
835 #if GMCS_SOURCE
836                 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
837                         return m.Name;
838
839                 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
840 #else
841                 return m.Name;
842 #endif
843         }
844
845         static public string CSharpSignature (EventInfo ei)
846         {
847                 return CSharpName (ei.DeclaringType) + '.' + ei.Name;
848         }
849
850         /// <summary>
851         ///   Looks up a type, and aborts if it is not found.  This is used
852         ///   by types required by the compiler
853         /// </summary>
854         static Type CoreLookupType (string ns_name, string name)
855         {
856                 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
857                 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
858                 Type t = fne == null ? null : fne.Type;
859                 if (t == null)
860                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
861                 return t;
862         }
863
864         /// <summary>
865         ///   Returns the MethodInfo for a method named `name' defined
866         ///   in type `t' which takes arguments of types `args'
867         /// </summary>
868         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
869         {
870                 MemberList list;
871                 Signature sig;
872                 BindingFlags flags = instance_and_static | BindingFlags.Public;
873
874                 sig.name = name;
875                 sig.args = args;
876
877                 if (is_private)
878                         flags |= BindingFlags.NonPublic;
879
880                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
881                 if (list.Count == 0) {
882                         if (report_errors)
883                                 Report.Error (-19, "Can not find the core function `" + name + "'");
884                         return null;
885                 }
886
887                 MethodInfo mi = list [0] as MethodInfo;
888                 if (mi == null) {
889                         if (report_errors)
890                                 Report.Error (-19, "Can not find the core function `" + name + "'");
891                         return null;
892                 }
893
894                 return mi;
895         }
896
897         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
898         {
899                 return GetMethod (t, name, args, false, report_errors);
900         }
901
902         static MethodInfo GetMethod (Type t, string name, Type [] args)
903         {
904                 return GetMethod (t, name, args, true);
905         }
906
907         /// <summary>
908         ///   Returns the PropertyInfo for a property named `name' defined
909         ///   in type `t'
910         /// </summary>
911         public static PropertyInfo GetProperty (Type t, string name)
912         {
913                 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
914                                                BindingFlags.Instance, Type.FilterName, name);
915                 if (list.Count == 0) {
916                         Report.Error (-19, "Can not find the core property `" + name + "'");
917                         return null;
918                 }
919
920                 PropertyInfo pi = list [0] as PropertyInfo;
921                 if (pi == null) {
922                         Report.Error (-19, "Can not find the core function `" + name + "'");
923                         return null;
924                 }
925
926                 return pi;
927         }
928
929         /// <summary>
930         ///    Returns the ConstructorInfo for "args"
931         /// </summary>
932         public static ConstructorInfo GetConstructor (Type t, Type [] args)
933         {
934                 MemberList list;
935                 Signature sig;
936
937                 sig.name = ".ctor";
938                 sig.args = args;
939
940                 if (t == null)
941                         throw new InternalErrorException ("Core types haven't been initialized yet?");
942                 
943                 list = FindMembers (t, MemberTypes.Constructor,
944                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
945                                     signature_filter, sig);
946                 if (list.Count == 0){
947                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
948                         return null;
949                 }
950
951                 ConstructorInfo ci = list [0] as ConstructorInfo;
952                 if (ci == null){
953                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
954                         return null;
955                 }
956
957                 return ci;
958         }
959
960         public static void InitEnumUnderlyingTypes ()
961         {
962                 int32_type    = CoreLookupType ("System", "Int32");
963                 int64_type    = CoreLookupType ("System", "Int64");
964                 uint32_type   = CoreLookupType ("System", "UInt32"); 
965                 uint64_type   = CoreLookupType ("System", "UInt64"); 
966                 byte_type     = CoreLookupType ("System", "Byte");
967                 sbyte_type    = CoreLookupType ("System", "SByte");
968                 short_type    = CoreLookupType ("System", "Int16");
969                 ushort_type   = CoreLookupType ("System", "UInt16");
970
971                 ienumerator_type     = CoreLookupType ("System.Collections", "IEnumerator");
972                 ienumerable_type     = CoreLookupType ("System.Collections", "IEnumerable");
973
974                 idisposable_type     = CoreLookupType ("System", "IDisposable");
975
976 #if GMCS_SOURCE
977                 InitGenericCoreTypes ();
978 #endif
979         }
980         
981         /// <remarks>
982         ///   The types have to be initialized after the initial
983         ///   population of the type has happened (for example, to
984         ///   bootstrap the corlib.dll
985         /// </remarks>
986         public static void InitCoreTypes ()
987         {
988                 object_type   = CoreLookupType ("System", "Object");
989                 value_type    = CoreLookupType ("System", "ValueType");
990
991                 InitEnumUnderlyingTypes ();
992
993                 char_type     = CoreLookupType ("System", "Char");
994                 string_type   = CoreLookupType ("System", "String");
995                 float_type    = CoreLookupType ("System", "Single");
996                 double_type   = CoreLookupType ("System", "Double");
997                 char_ptr_type = GetPointerType (char_type);
998                 decimal_type  = CoreLookupType ("System", "Decimal");
999                 bool_type     = CoreLookupType ("System", "Boolean");
1000                 enum_type     = CoreLookupType ("System", "Enum");
1001
1002                 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1003                 delegate_type           = CoreLookupType ("System", "Delegate");
1004
1005                 array_type    = CoreLookupType ("System", "Array");
1006                 void_type     = CoreLookupType ("System", "Void");
1007                 type_type     = CoreLookupType ("System", "Type");
1008
1009                 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1010                 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1011                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1012                 default_member_type  = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1013                 runtime_handle_type  = CoreLookupType ("System", "RuntimeTypeHandle");
1014                 asynccallback_type   = CoreLookupType ("System", "AsyncCallback");
1015                 iasyncresult_type    = CoreLookupType ("System", "IAsyncResult");
1016                 icloneable_type      = CoreLookupType ("System", "ICloneable");
1017                 iconvertible_type    = CoreLookupType ("System", "IConvertible");
1018                 interlocked_type     = CoreLookupType ("System.Threading", "Interlocked");
1019                 monitor_type         = CoreLookupType ("System.Threading", "Monitor");
1020                 intptr_type          = CoreLookupType ("System", "IntPtr");
1021
1022                 attribute_type       = CoreLookupType ("System", "Attribute");
1023                 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1024                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1025                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1026                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1027                 param_array_type     = CoreLookupType ("System", "ParamArrayAttribute");
1028                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1029                 out_attribute_type   = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1030 #if NET_2_0
1031                 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1032 #endif
1033                 typed_reference_type = CoreLookupType ("System", "TypedReference");
1034                 arg_iterator_type    = CoreLookupType ("System", "ArgIterator");
1035                 mbr_type             = CoreLookupType ("System", "MarshalByRefObject");
1036                 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1037
1038                 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1039
1040                 void_ptr_type         = GetPointerType (void_type);
1041
1042                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1043
1044                 exception_type        = CoreLookupType ("System", "Exception");
1045                 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1046                 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1047
1048                 //
1049                 // Attribute types
1050                 //
1051                 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1052                 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1053                 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1054                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1055                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1056                 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1057                 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1058                 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1059                 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1060                 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1061                 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1062
1063                 //
1064                 // .NET 2.0
1065                 //
1066 #if NET_2_0
1067                 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1068                 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1069                 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1070                 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1071                 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1072                 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1073 #endif
1074                 //
1075                 // When compiling corlib, store the "real" types here.
1076                 //
1077                 if (!RootContext.StdLib) {
1078                         system_int32_type = typeof (System.Int32);
1079                         system_array_type = typeof (System.Array);
1080                         system_type_type = typeof (System.Type);
1081                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1082
1083                         system_int_array_get_length = GetMethod (
1084                                 system_array_type, "get_Length", Type.EmptyTypes);
1085                         system_int_array_get_rank = GetMethod (
1086                                 system_array_type, "get_Rank", Type.EmptyTypes);
1087                         system_object_array_clone = GetMethod (
1088                                 system_array_type, "Clone", Type.EmptyTypes);
1089
1090                         Type [] system_int_arg = { system_int32_type };
1091                         system_int_array_get_length_int = GetMethod (
1092                                 system_array_type, "GetLength", system_int_arg);
1093                         system_int_array_get_upper_bound_int = GetMethod (
1094                                 system_array_type, "GetUpperBound", system_int_arg);
1095                         system_int_array_get_lower_bound_int = GetMethod (
1096                                 system_array_type, "GetLowerBound", system_int_arg);
1097
1098                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1099                         system_void_array_copyto_array_int = GetMethod (
1100                                 system_array_type, "CopyTo", system_array_int_arg);
1101
1102                         Type [] system_3_type_arg = {
1103                                 system_type_type, system_type_type, system_type_type };
1104                         Type [] system_4_type_arg = {
1105                                 system_type_type, system_type_type, system_type_type, system_type_type };
1106
1107                         MethodInfo set_corlib_type_builders = GetMethod (
1108                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1109                                 system_4_type_arg, true, false);
1110
1111                         if (set_corlib_type_builders != null) {
1112                                 object[] args = new object [4];
1113                                 args [0] = object_type;
1114                                 args [1] = value_type;
1115                                 args [2] = enum_type;
1116                                 args [3] = void_type;
1117                                 
1118                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1119                         } else {
1120                                 // Compatibility for an older version of the class libs.
1121                                 set_corlib_type_builders = GetMethod (
1122                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1123                                         system_3_type_arg, true, true);
1124
1125                                 if (set_corlib_type_builders == null) {
1126                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1127                                         return;
1128                                 }
1129
1130                                 object[] args = new object [3];
1131                                 args [0] = object_type;
1132                                 args [1] = value_type;
1133                                 args [2] = enum_type;
1134                                 
1135                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1136                         }
1137                 }
1138
1139                 system_object_expr.Type = object_type;
1140                 system_string_expr.Type = string_type;
1141                 system_boolean_expr.Type = bool_type;
1142                 system_decimal_expr.Type = decimal_type;
1143                 system_single_expr.Type = float_type;
1144                 system_double_expr.Type = double_type;
1145                 system_sbyte_expr.Type = sbyte_type;
1146                 system_byte_expr.Type = byte_type;
1147                 system_int16_expr.Type = short_type;
1148                 system_uint16_expr.Type = ushort_type;
1149                 system_int32_expr.Type = int32_type;
1150                 system_uint32_expr.Type = uint32_type;
1151                 system_int64_expr.Type = int64_type;
1152                 system_uint64_expr.Type = uint64_type;
1153                 system_char_expr.Type = char_type;
1154                 system_void_expr.Type = void_type;
1155                 system_asynccallback_expr.Type = asynccallback_type;
1156                 system_iasyncresult_expr.Type = iasyncresult_type;
1157                 system_valuetype_expr.Type = value_type;
1158
1159                 //
1160                 // These are only used for compare purposes
1161                 //
1162                 anonymous_method_type = typeof (AnonymousMethod);
1163                 null_type = typeof (NullType);
1164         }
1165
1166         //
1167         // The helper methods that are used by the compiler
1168         //
1169         public static void InitCodeHelpers ()
1170         {
1171                 //
1172                 // Now load the default methods that we use.
1173                 //
1174                 Type [] string_string = { string_type, string_type };
1175                 string_concat_string_string = GetMethod (
1176                         string_type, "Concat", string_string);
1177                 Type [] string_string_string = { string_type, string_type, string_type };
1178                 string_concat_string_string_string = GetMethod (
1179                         string_type, "Concat", string_string_string);
1180                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1181                 string_concat_string_string_string_string = GetMethod (
1182                         string_type, "Concat", string_string_string_string);
1183                 Type[] params_string = { GetConstructedType (string_type, "[]") };
1184                 string_concat_string_dot_dot_dot = GetMethod (
1185                         string_type, "Concat", params_string);
1186
1187                 Type [] object_object = { object_type, object_type };
1188                 string_concat_object_object = GetMethod (
1189                         string_type, "Concat", object_object);
1190                 Type [] object_object_object = { object_type, object_type, object_type };
1191                 string_concat_object_object_object = GetMethod (
1192                         string_type, "Concat", object_object_object);
1193                 Type[] params_object = { GetConstructedType (object_type, "[]") };
1194                 string_concat_object_dot_dot_dot = GetMethod (
1195                         string_type, "Concat", params_object);
1196
1197                 Type [] string_ = { string_type };
1198                 string_isinterneted_string = GetMethod (
1199                         string_type, "IsInterned", string_);
1200                 
1201                 Type [] runtime_type_handle = { runtime_handle_type };
1202                 system_type_get_type_from_handle = GetMethod (
1203                         type_type, "GetTypeFromHandle", runtime_type_handle);
1204
1205                 Type [] delegate_delegate = { delegate_type, delegate_type };
1206                 delegate_combine_delegate_delegate = GetMethod (
1207                                 delegate_type, "Combine", delegate_delegate);
1208
1209                 delegate_remove_delegate_delegate = GetMethod (
1210                                 delegate_type, "Remove", delegate_delegate);
1211
1212                 //
1213                 // Void arguments
1214                 //
1215                 ienumerator_getcurrent = GetProperty (
1216                         ienumerator_type, "Current");
1217                 bool_movenext_void = GetMethod (
1218                         ienumerator_type, "MoveNext", Type.EmptyTypes);
1219                 void_reset_void = GetMethod (
1220                         ienumerator_type, "Reset", Type.EmptyTypes);
1221                 void_dispose_void = GetMethod (
1222                         idisposable_type, "Dispose", Type.EmptyTypes);
1223                 int_get_offset_to_string_data = GetMethod (
1224                         runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1225                 int_array_get_length = GetMethod (
1226                         array_type, "get_Length", Type.EmptyTypes);
1227                 int_array_get_rank = GetMethod (
1228                         array_type, "get_Rank", Type.EmptyTypes);
1229                 ienumerable_getenumerator_void = GetMethod (
1230                         ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1231                 
1232                 //
1233                 // Int32 arguments
1234                 //
1235                 Type [] int_arg = { int32_type };
1236                 int_array_get_length_int = GetMethod (
1237                         array_type, "GetLength", int_arg);
1238                 int_array_get_upper_bound_int = GetMethod (
1239                         array_type, "GetUpperBound", int_arg);
1240                 int_array_get_lower_bound_int = GetMethod (
1241                         array_type, "GetLowerBound", int_arg);
1242
1243                 //
1244                 // System.Array methods
1245                 //
1246                 object_array_clone = GetMethod (
1247                         array_type, "Clone", Type.EmptyTypes);
1248                 Type [] array_int_arg = { array_type, int32_type };
1249                 void_array_copyto_array_int = GetMethod (
1250                         array_type, "CopyTo", array_int_arg);
1251                 
1252                 //
1253                 // object arguments
1254                 //
1255                 Type [] object_arg = { object_type };
1256                 void_monitor_enter_object = GetMethod (
1257                         monitor_type, "Enter", object_arg);
1258                 void_monitor_exit_object = GetMethod (
1259                         monitor_type, "Exit", object_arg);
1260
1261                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1262                 
1263                 void_initializearray_array_fieldhandle = GetMethod (
1264                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1265
1266                 //
1267                 // Array functions
1268                 //
1269                 int_getlength_int = GetMethod (
1270                         array_type, "GetLength", int_arg);
1271
1272                 //
1273                 // Decimal constructors
1274                 //
1275                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1276                 void_decimal_ctor_five_args = GetConstructor (
1277                         decimal_type, dec_arg);
1278                 
1279                 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1280
1281                 //
1282                 // Attributes
1283                 //
1284                 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1285                 default_member_ctor = GetConstructor (default_member_type, string_);
1286
1287                 Type[] short_arg = { short_type };
1288                 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1289
1290                 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1291                         { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1292
1293                 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1294                         { int32_type });
1295
1296                 //
1297                 // System.Threading.CompareExchange
1298                 //
1299                 Type[] compare_exchange_types = {
1300                         GetReferenceType (int32_type), int32_type, int32_type };
1301                 int_interlocked_compare_exchange = GetMethod (
1302                         interlocked_type, "CompareExchange", compare_exchange_types);
1303
1304                 //
1305                 // .NET 2.0 types
1306                 //
1307 #if NET_2_0
1308                 compiler_generated_attr = new CustomAttributeBuilder (
1309                         GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1310
1311                 Type[] type_int_arg = { type_type, int32_type };
1312                 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1313 #endif
1314
1315                 // Object
1316                 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1317
1318 #if GMCS_SOURCE
1319                 InitGenericCodeHelpers ();
1320 #endif
1321         }
1322
1323         static public ConstructorInfo ConsParamArrayAttribute {
1324                 get {
1325                         if (cons_param_array_attribute == null)
1326                                 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1327                         return cons_param_array_attribute;
1328                 }
1329         }
1330
1331         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1332
1333         /// <remarks>
1334         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1335         ///   the cache here because there is no member name argument.
1336         /// </remarks>
1337         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1338                                               MemberFilter filter, object criteria)
1339         {
1340 #if MS_COMPATIBLE && GMCS_SOURCE
1341                 if (t.IsGenericType)
1342                         t = t.GetGenericTypeDefinition ();
1343 #endif
1344
1345                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1346
1347                 //
1348                 // `builder_to_declspace' contains all dynamic types.
1349                 //
1350                 if (decl != null) {
1351                         MemberList list;
1352                         Timer.StartTimer (TimerType.FindMembers);
1353                         list = decl.FindMembers (mt, bf, filter, criteria);
1354                         Timer.StopTimer (TimerType.FindMembers);
1355                         return list;
1356                 }
1357
1358                 //
1359                 // We have to take care of arrays specially, because GetType on
1360                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1361                 // and we can not call FindMembers on this type.
1362                 //
1363                 if (
1364 #if MS_COMPATIBLE && GMCS_SOURCE
1365                         !t.IsGenericType &&
1366 #endif
1367                         t.IsSubclassOf (TypeManager.array_type))
1368                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1369
1370 #if GMCS_SOURCE
1371                 if (t is GenericTypeParameterBuilder) {
1372                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1373
1374                         Timer.StartTimer (TimerType.FindMembers);
1375                         MemberList list = tparam.FindMembers (
1376                                 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1377                         Timer.StopTimer (TimerType.FindMembers);
1378                         return list;
1379                 }
1380 #endif
1381
1382                 //
1383                 // Since FindMembers will not lookup both static and instance
1384                 // members, we emulate this behaviour here.
1385                 //
1386                 if ((bf & instance_and_static) == instance_and_static){
1387                         MemberInfo [] i_members = t.FindMembers (
1388                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1389
1390                         int i_len = i_members.Length;
1391                         if (i_len == 1){
1392                                 MemberInfo one = i_members [0];
1393
1394                                 //
1395                                 // If any of these are present, we are done!
1396                                 //
1397                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1398                                         return new MemberList (i_members);
1399                         }
1400                                 
1401                         MemberInfo [] s_members = t.FindMembers (
1402                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1403
1404                         int s_len = s_members.Length;
1405                         if (i_len > 0 || s_len > 0)
1406                                 return new MemberList (i_members, s_members);
1407                         else {
1408                                 if (i_len > 0)
1409                                         return new MemberList (i_members);
1410                                 else
1411                                         return new MemberList (s_members);
1412                         }
1413                 }
1414
1415                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1416         }
1417
1418
1419         /// <summary>
1420         ///   This method is only called from within MemberLookup.  It tries to use the member
1421         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1422         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1423         ///   our return value will already contain all inherited members and the caller don't need
1424         ///   to check base classes and interfaces anymore.
1425         /// </summary>
1426         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1427                                                                string name, out bool used_cache)
1428         {
1429                 MemberCache cache;
1430
1431                 //
1432                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1433                 // and we can ask the DeclSpace for the MemberCache.
1434                 //
1435                 if (t is TypeBuilder) {
1436                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1437                         cache = decl.MemberCache;
1438
1439                         //
1440                         // If this DeclSpace has a MemberCache, use it.
1441                         //
1442
1443                         if (cache != null) {
1444                                 used_cache = true;
1445                                 return cache.FindMembers (
1446                                         mt, bf, name, FilterWithClosure_delegate, null);
1447                         }
1448
1449                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1450                         // Note, this is a VERY uncommon route!
1451
1452                         MemberList list;
1453                         Timer.StartTimer (TimerType.FindMembers);
1454                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1455                                                  FilterWithClosure_delegate, name);
1456                         Timer.StopTimer (TimerType.FindMembers);
1457                         used_cache = false;
1458                         return (MemberInfo []) list;
1459                 }
1460
1461                 //
1462                 // We have to take care of arrays specially, because GetType on
1463                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1464                 // and we can not call FindMembers on this type.
1465                 //
1466                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1467                         used_cache = true;
1468                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1469                                 mt, bf, name, FilterWithClosure_delegate, null);
1470                 }
1471
1472 #if GMCS_SOURCE
1473                 if (t is GenericTypeParameterBuilder) {
1474                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1475
1476                         MemberList list;
1477                         Timer.StartTimer (TimerType.FindMembers);
1478                         list = tparam.FindMembers (mt, bf & ~BindingFlags.DeclaredOnly,
1479                                                    FilterWithClosure_delegate, name);
1480                         Timer.StopTimer (TimerType.FindMembers);
1481                         used_cache = true;
1482                         return (MemberInfo []) list;
1483                 }
1484
1485                 if (t.IsGenericType && (mt == MemberTypes.NestedType)) {
1486                         //
1487                         // This happens if we're resolving a class'es base class and interfaces
1488                         // in TypeContainer.DefineType().  At this time, the types aren't
1489                         // populated yet, so we can't use the cache.
1490                         //
1491                         MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1492                                                            FilterWithClosure_delegate, name);
1493                         used_cache = false;
1494                         return info;
1495                 }
1496 #endif
1497
1498                 //
1499                 // This call will always succeed.  There is exactly one TypeHandle instance per
1500                 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1501                 // the corresponding MemberCache.
1502                 //
1503                 cache = TypeHandle.GetMemberCache (t);
1504
1505                 used_cache = true;
1506                 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1507         }
1508
1509         public static bool IsBuiltinType (Type t)
1510         {
1511                 t = TypeToCoreType (t);
1512                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1513                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1514                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1515                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1516                         return true;
1517                 else
1518                         return false;
1519         }
1520
1521         public static bool IsBuiltinType (TypeContainer tc)
1522         {
1523                 return IsBuiltinType (tc.TypeBuilder);
1524         }
1525
1526         //
1527         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1528         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1529         // 
1530         public static bool IsPrimitiveType (Type t)
1531         {
1532                 return (t == int32_type || t == uint32_type ||
1533                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1534                     t == char_type || t == short_type || t == bool_type ||
1535                     t == sbyte_type || t == byte_type || t == ushort_type);
1536         }
1537
1538         public static bool IsDelegateType (Type t)
1539         {
1540                 t = DropGenericTypeArguments (t);
1541                 if (t.IsSubclassOf (TypeManager.delegate_type))
1542                         return true;
1543                 else
1544                         return false;
1545         }
1546         
1547         public static bool IsEnumType (Type t)
1548         {
1549                 if (builder_to_declspace [t] is Enum)
1550                         return true;
1551
1552 #if MS_COMPATIBLE && GMCS_SOURCE
1553                 if (t.IsGenericParameter)
1554                         return false;
1555 #endif
1556                 return t.IsEnum;
1557         }
1558
1559         public static bool IsBuiltinOrEnum (Type t)
1560         {
1561                 if (IsBuiltinType (t))
1562                         return true;
1563                 
1564                 if (IsEnumType (t))
1565                         return true;
1566
1567                 return false;
1568         }
1569
1570         public static bool IsNullType (Type t)
1571         {
1572                 return t == null_type;
1573         }
1574
1575         public static bool IsAttributeType (Type t)
1576         {
1577                 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1578         }
1579         
1580         static Stack unmanaged_enclosing_types = new Stack (4);
1581
1582         //
1583         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1584         //
1585         public static bool IsUnmanagedType (Type t)
1586         {
1587                 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1588                 if (unmanaged_enclosing_types.Contains (t))
1589                         return true;
1590
1591                 // builtins that are not unmanaged types
1592                 if (t == TypeManager.object_type || t == TypeManager.string_type)
1593                         return false;
1594
1595                 if (IsGenericType (t) || IsGenericParameter (t))
1596                         return false;
1597
1598                 if (IsBuiltinOrEnum (t))
1599                         return true;
1600
1601                 // Someone did the work of checking if the ElementType of t is unmanaged.  Let's not repeat it.
1602                 if (t.IsPointer)
1603                         return true;
1604
1605                 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1606                 if (t.IsArray)
1607                         return false;
1608
1609                 if (!IsValueType (t))
1610                         return false;
1611
1612 #if GMCS_SOURCE
1613                 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1614                         if (p.IsGenericTypeDefinition)
1615                                 return false;
1616                 }
1617 #endif
1618
1619                 unmanaged_enclosing_types.Push (t);
1620
1621                 bool retval = true;
1622
1623                 if (t is TypeBuilder) {
1624                         TypeContainer tc = LookupTypeContainer (t);
1625                         if (tc.Fields != null){
1626                                 foreach (FieldMember f in tc.Fields){
1627                                         // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1628                                         if ((f.ModFlags & Modifiers.STATIC) != 0)
1629                                                 continue;
1630                                         if (f.MemberType == null)
1631                                                 continue;
1632                                         if (!IsUnmanagedType (f.MemberType)){
1633                                                 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1634                                                 retval = false;
1635                                         }
1636                                 }
1637                         }
1638                 } else {
1639                         FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1640                         
1641                         foreach (FieldInfo f in fields){
1642                                 if (!IsUnmanagedType (f.FieldType)){
1643                                         Report.SymbolRelatedToPreviousError (f);
1644                                         retval = false;
1645                                 }
1646                         }
1647                 }
1648
1649                 unmanaged_enclosing_types.Pop ();
1650
1651                 return retval;
1652         }
1653                 
1654         public static bool IsValueType (Type t)
1655         {
1656                 return t.IsValueType || IsGenericParameter (t);
1657         }
1658         
1659         public static bool IsInterfaceType (Type t)
1660         {
1661                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1662                 if (tc == null)
1663                         return false;
1664
1665                 return tc.Kind == Kind.Interface;
1666         }
1667
1668         public static bool IsSubclassOf (Type type, Type base_type)
1669         {
1670                 TypeParameter tparam = LookupTypeParameter (type);
1671                 TypeParameter pparam = LookupTypeParameter (base_type);
1672
1673                 if ((tparam != null) && (pparam != null)) {
1674                         if (tparam == pparam)
1675                                 return true;
1676
1677                         return tparam.IsSubclassOf (base_type);
1678                 }
1679
1680 #if MS_COMPATIBLE && GMCS_SOURCE
1681                 if (type.IsGenericType)
1682                         type = type.GetGenericTypeDefinition ();
1683 #endif
1684
1685                 if (type.IsSubclassOf (base_type))
1686                         return true;
1687
1688                 do {
1689                         if (IsEqual (type, base_type))
1690                                 return true;
1691
1692                         type = type.BaseType;
1693                 } while (type != null);
1694
1695                 return false;
1696         }
1697
1698         public static bool IsPrivateAccessible (Type type, Type parent)
1699         {
1700                 if (type == null)
1701                         return false;
1702
1703                 if (type.Equals (parent))
1704                         return true;
1705
1706                 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1707         }
1708
1709         public static bool IsFamilyAccessible (Type type, Type parent)
1710         {
1711                 TypeParameter tparam = LookupTypeParameter (type);
1712                 TypeParameter pparam = LookupTypeParameter (parent);
1713
1714                 if ((tparam != null) && (pparam != null)) {
1715                         if (tparam == pparam)
1716                                 return true;
1717
1718                         return tparam.IsSubclassOf (parent);
1719                 }
1720
1721                 do {
1722                         if (IsInstantiationOfSameGenericType (type, parent))
1723                                 return true;
1724
1725                         type = type.BaseType;
1726                 } while (type != null);
1727
1728                 return false;
1729         }
1730
1731         //
1732         // Checks whether `type' is a subclass or nested child of `base_type'.
1733         //
1734         public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1735         {
1736                 do {
1737                         if (IsFamilyAccessible (type, base_type))
1738                                 return true;
1739
1740                         // Handle nested types.
1741                         type = type.DeclaringType;
1742                 } while (type != null);
1743
1744                 return false;
1745         }
1746
1747         //
1748         // Checks whether `type' is a nested child of `parent'.
1749         //
1750         public static bool IsNestedChildOf (Type type, Type parent)
1751         {
1752                 if (type == null)
1753                         return false;
1754
1755                 type = DropGenericTypeArguments (type);
1756                 parent = DropGenericTypeArguments (parent);
1757
1758                 if (IsEqual (type, parent))
1759                         return false;
1760
1761                 type = type.DeclaringType;
1762                 while (type != null) {
1763                         if (IsEqual (type, parent))
1764                                 return true;
1765
1766                         type = type.DeclaringType;
1767                 }
1768
1769                 return false;
1770         }
1771
1772 #if GMCS_SOURCE
1773         //
1774         // Checks whether `extern_type' is friend of the output assembly
1775         //
1776         public static bool IsFriendAssembly (Assembly assembly)
1777         {
1778                 if (assembly_internals_vis_attrs.Contains (assembly))
1779                         return (bool)(assembly_internals_vis_attrs [assembly]);
1780                 
1781                 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1782                 if (attrs.Length == 0) {
1783                         assembly_internals_vis_attrs.Add (assembly, false);
1784                         return false;
1785                 }
1786
1787                 AssemblyName this_name = CodeGen.Assembly.Name;
1788                 byte [] this_token = this_name.GetPublicKeyToken ();
1789                 bool is_friend = false;
1790                 foreach (InternalsVisibleToAttribute attr in attrs) {
1791                         if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1792                                 continue;
1793                         
1794                         AssemblyName aname = null;
1795                         try {
1796                                 aname = new AssemblyName (attr.AssemblyName);
1797                         } catch (FileLoadException) {
1798                         } catch (ArgumentException) {
1799                         }
1800
1801                         if (aname == null || aname.Name != this_name.Name)
1802                                 continue;
1803                         
1804                         byte [] key_token = aname.GetPublicKeyToken ();
1805                         if (key_token != null) {
1806                                 if (this_token == null) {
1807                                         // Same name, but key token is null
1808                                         Error_FriendAccessNameNotMatching (aname.FullName);
1809                                         break;
1810                                 }
1811                                 
1812                                 if (!CompareKeyTokens (this_token, key_token))
1813                                         continue;
1814                         }
1815
1816                         is_friend = true;
1817                         break;
1818                 }
1819
1820                 assembly_internals_vis_attrs.Add (assembly, is_friend);
1821                 return is_friend;
1822         }
1823
1824         static bool CompareKeyTokens (byte [] token1, byte [] token2)
1825         {
1826                 for (int i = 0; i < token1.Length; i++)
1827                         if (token1 [i] != token2 [i])
1828                                 return false;
1829
1830                 return true;
1831         }
1832
1833         static void Error_FriendAccessNameNotMatching (string other_name)
1834         {
1835                 Report.Error (281, "Friend access was granted to `" + other_name + 
1836                                 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1837                                 "'. Try adding a reference to `" + other_name + 
1838                                 "' or change the output assembly name to match it");
1839         }
1840 #else
1841         public static bool IsFriendAssembly (Assembly assembly)
1842         {
1843                 return false;
1844         }
1845 #endif
1846         
1847         //
1848         // Do the right thing when returning the element type of an
1849         // array type based on whether we are compiling corlib or not
1850         //
1851         public static Type GetElementType (Type t)
1852         {
1853                 if (RootContext.StdLib)
1854                         return t.GetElementType ();
1855                 else
1856                         return TypeToCoreType (t.GetElementType ());
1857         }
1858
1859         /// <summary>
1860         /// This method is not implemented by MS runtime for dynamic types
1861         /// </summary>
1862         public static bool HasElementType (Type t)
1863         {
1864                 return t.IsArray || t.IsPointer || t.IsByRef;
1865         }
1866         
1867         /// <summary>
1868         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1869         /// </summary>
1870         ///
1871         /// <remarks>
1872         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1873         ///   for anything which is dynamic, and we need this in a number of places,
1874         ///   we register this information here, and use it afterwards.
1875         /// </remarks>
1876         static public void RegisterMethod (MethodBase mb, Parameters ip)
1877         {
1878                 method_params.Add (mb, ip);
1879         }
1880         
1881         static public ParameterData GetParameterData (MethodBase mb)
1882         {
1883                 ParameterData pd = (ParameterData)method_params [mb];
1884                 if (pd == null) {
1885                         if (mb is MethodBuilder || mb is ConstructorBuilder)
1886                                 throw new InternalErrorException ("Argument for Method not registered" + mb);
1887
1888                         pd = new ReflectionParameters (mb);
1889                         method_params.Add (mb, pd);
1890                 }
1891                 return pd;
1892         }
1893
1894         static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1895         {
1896                 if (!method_overrides.Contains (override_method))
1897                         method_overrides [override_method] = base_method;
1898                 if (method_overrides [override_method] != base_method)
1899                         throw new InternalErrorException ("Override mismatch: " + override_method);
1900         }
1901
1902         static public bool IsOverride (MethodBase m)
1903         {
1904                 m = DropGenericMethodArguments (m);
1905
1906                 return m.IsVirtual &&
1907                         (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1908                         (m is MethodBuilder || method_overrides.Contains (m));
1909         }
1910
1911         static public MethodBase TryGetBaseDefinition (MethodBase m)
1912         {
1913                 m = DropGenericMethodArguments (m);
1914
1915                 return (MethodBase) method_overrides [m];
1916         }
1917
1918         /// <summary>
1919         ///    Returns the argument types for an indexer based on its PropertyInfo
1920         ///
1921         ///    For dynamic indexers, we use the compiler provided types, for
1922         ///    indexers from existing assemblies we load them from GetParameters,
1923         ///    and insert them into the cache
1924         /// </summary>
1925         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1926         {
1927                 if (indexer_arguments.Contains (indexer))
1928                         return (Type []) indexer_arguments [indexer];
1929                 else if (indexer is PropertyBuilder)
1930                         // If we're a PropertyBuilder and not in the
1931                         // `indexer_arguments' hash, then we're a property and
1932                         // not an indexer.
1933                         return Type.EmptyTypes;
1934                 else {
1935                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1936                         // Property, not an indexer.
1937                         if (pi == null)
1938                                 return Type.EmptyTypes;
1939                         int c = pi.Length;
1940                         Type [] types = new Type [c];
1941                         
1942                         for (int i = 0; i < c; i++)
1943                                 types [i] = pi [i].ParameterType;
1944
1945                         indexer_arguments.Add (indexer, types);
1946                         return types;
1947                 }
1948         }
1949         
1950         public static void RegisterConstant (FieldInfo fb, IConstant ic)
1951         {
1952                 fields.Add (fb, ic);
1953         }
1954
1955         public static IConstant GetConstant (FieldInfo fb)
1956         {
1957                 if (fb == null)
1958                         return null;
1959
1960                 return (IConstant)fields [fb];
1961         }
1962
1963         public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1964         {
1965                 propertybuilder_to_property.Add (pi, pb);
1966         }
1967
1968         public static PropertyBase GetProperty (PropertyInfo pi)
1969         {
1970                 return (PropertyBase)propertybuilder_to_property [pi];
1971         }
1972
1973         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1974         {
1975                 if (fieldbuilders_to_fields.Contains (fb))
1976                         return false;
1977
1978                 fieldbuilders_to_fields.Add (fb, f);
1979                 return true;
1980         }
1981
1982         //
1983         // The return value can be null;  This will be the case for
1984         // auxiliary FieldBuilders created by the compiler that have no
1985         // real field being declared on the source code
1986         //
1987         static public FieldBase GetField (FieldInfo fb)
1988         {
1989 #if GMCS_SOURCE
1990                 fb = GetGenericFieldDefinition (fb);
1991 #endif
1992                 return (FieldBase) fieldbuilders_to_fields [fb];
1993         }
1994         
1995         static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1996         {
1997                 if (events == null)
1998                         events = new Hashtable ();
1999
2000                 if (!events.Contains (eb)) {
2001                         events.Add (eb, new Pair (add, remove));
2002                 }
2003         }
2004
2005         static public MethodInfo GetAddMethod (EventInfo ei)
2006         {
2007                 if (ei is MyEventBuilder) {
2008                         Pair pair = (Pair) events [ei];
2009
2010                         return (MethodInfo) pair.First;
2011                 }
2012                 return ei.GetAddMethod (true);
2013         }
2014
2015         static public MethodInfo GetRemoveMethod (EventInfo ei)
2016         {
2017                 if (ei is MyEventBuilder) {
2018                         Pair pair = (Pair) events [ei];
2019
2020                         return (MethodInfo) pair.Second;
2021                 }
2022                 return ei.GetRemoveMethod (true);
2023         }
2024
2025         static Hashtable priv_fields_events;
2026
2027         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2028         {
2029                 if (priv_fields_events == null)
2030                         priv_fields_events = new Hashtable ();
2031
2032                 if (priv_fields_events.Contains (einfo))
2033                         return false;
2034
2035                 priv_fields_events.Add (einfo, builder);
2036
2037                 return true;
2038         }
2039
2040         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2041         {
2042                 if (priv_fields_events == null)
2043                         return null;
2044                 else
2045                         return (MemberInfo) priv_fields_events [ei];
2046         }
2047                 
2048         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2049                                             MethodBase set, Type[] args)
2050         {
2051                 indexer_arguments.Add (pb, args);
2052
2053                 return true;
2054         }
2055
2056         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2057         {
2058                 Hashtable hash = new Hashtable ();
2059                 return CheckStructCycles (tc, seen, hash);
2060         }
2061
2062         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2063                                               Hashtable hash)
2064         {
2065                 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2066                         return true;
2067
2068                 //
2069                 // `seen' contains all types we've already visited.
2070                 //
2071                 if (seen.Contains (tc))
2072                         return true;
2073                 seen.Add (tc, null);
2074
2075                 if (tc.Fields == null)
2076                         return true;
2077
2078                 foreach (FieldMember field in tc.Fields) {
2079                         if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2080                                 continue;
2081
2082                         Type ftype = field.FieldBuilder.FieldType;
2083                         TypeContainer ftc = LookupTypeContainer (ftype);
2084                         if (ftc == null)
2085                                 continue;
2086
2087                         if (hash.Contains (ftc)) {
2088                                 Report.Error (523, tc.Location,
2089                                               "Struct member `{0}.{1}' of type `{2}' " +
2090                                               "causes a cycle in the struct layout",
2091                                               tc.Name, field.Name, ftc.Name);
2092                                 return false;
2093                         }
2094
2095                         //
2096                         // `hash' contains all types in the current path.
2097                         //
2098                         hash.Add (tc, null);
2099
2100                         bool ok = CheckStructCycles (ftc, seen, hash);
2101
2102                         hash.Remove (tc);
2103
2104                         if (!ok)
2105                                 return false;
2106
2107                         if (!seen.Contains (ftc))
2108                                 seen.Add (ftc, null);
2109                 }
2110
2111                 return true;
2112         }
2113
2114         /// <summary>
2115         ///   Given an array of interface types, expand and eliminate repeated ocurrences
2116         ///   of an interface.  
2117         /// </summary>
2118         ///
2119         /// <remarks>
2120         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2121         ///   be IA, IB, IC.
2122         /// </remarks>
2123         public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2124         {
2125                 ArrayList new_ifaces = new ArrayList ();
2126
2127                 foreach (TypeExpr iface in base_interfaces){
2128                         Type itype = iface.Type;
2129
2130                         if (new_ifaces.Contains (itype))
2131                                 continue;
2132
2133                         new_ifaces.Add (itype);
2134                         
2135                         Type [] implementing = GetInterfaces (itype);
2136
2137                         foreach (Type imp in implementing){
2138                                 if (!new_ifaces.Contains (imp))
2139                                         new_ifaces.Add (imp);
2140                         }
2141                 }
2142                 Type [] ret = new Type [new_ifaces.Count];
2143                 new_ifaces.CopyTo (ret, 0);
2144                 return ret;
2145         }
2146
2147         public static Type[] ExpandInterfaces (Type [] base_interfaces)
2148         {
2149                 ArrayList new_ifaces = new ArrayList ();
2150
2151                 foreach (Type itype in base_interfaces){
2152                         if (new_ifaces.Contains (itype))
2153                                 continue;
2154
2155                         new_ifaces.Add (itype);
2156                         
2157                         Type [] implementing = GetInterfaces (itype);
2158
2159                         foreach (Type imp in implementing){
2160                                 if (!new_ifaces.Contains (imp))
2161                                         new_ifaces.Add (imp);
2162                         }
2163                 }
2164                 Type [] ret = new Type [new_ifaces.Count];
2165                 new_ifaces.CopyTo (ret, 0);
2166                 return ret;
2167         }
2168                 
2169         static PtrHashtable iface_cache = new PtrHashtable ();
2170                 
2171         /// <summary>
2172         ///   This function returns the interfaces in the type `t'.  Works with
2173         ///   both types and TypeBuilders.
2174         /// </summary>
2175         public static Type [] GetInterfaces (Type t)
2176         {
2177                 Type [] cached = iface_cache [t] as Type [];
2178                 if (cached != null)
2179                         return cached;
2180                 
2181                 //
2182                 // The reason for catching the Array case is that Reflection.Emit
2183                 // will not return a TypeBuilder for Array types of TypeBuilder types,
2184                 // but will still throw an exception if we try to call GetInterfaces
2185                 // on the type.
2186                 //
2187                 // Since the array interfaces are always constant, we return those for
2188                 // the System.Array
2189                 //
2190                 
2191                 if (t.IsArray)
2192                         t = TypeManager.array_type;
2193                 
2194                 if ((t is TypeBuilder) || IsGenericType (t)) {
2195                         Type [] base_ifaces;
2196                         
2197                         if (t.BaseType == null)
2198                                 base_ifaces = Type.EmptyTypes;
2199                         else
2200                                 base_ifaces = GetInterfaces (t.BaseType);
2201                         Type[] type_ifaces;
2202                         if (IsGenericType (t))
2203 #if MS_COMPATIBLE && GMCS_SOURCE
2204                                 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2205 #else
2206                                 type_ifaces = t.GetInterfaces ();
2207 #endif
2208                         else
2209                                 type_ifaces = (Type []) builder_to_ifaces [t];
2210                         if (type_ifaces == null || type_ifaces.Length == 0)
2211                                 type_ifaces = Type.EmptyTypes;
2212
2213                         int base_count = base_ifaces.Length;
2214                         Type [] result = new Type [base_count + type_ifaces.Length];
2215                         base_ifaces.CopyTo (result, 0);
2216                         type_ifaces.CopyTo (result, base_count);
2217
2218                         iface_cache [t] = result;
2219                         return result;
2220 #if GMCS_SOURCE
2221                 } else if (t is GenericTypeParameterBuilder){
2222                         Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2223                         if (type_ifaces == null || type_ifaces.Length == 0)
2224                                 type_ifaces = Type.EmptyTypes;
2225
2226                         iface_cache [t] = type_ifaces;
2227                         return type_ifaces;
2228 #endif
2229                 } else {
2230                         Type[] ifaces = t.GetInterfaces ();
2231                         iface_cache [t] = ifaces;
2232                         return ifaces;
2233                 }
2234         }
2235         
2236         //
2237         // gets the interfaces that are declared explicitly on t
2238         //
2239         public static Type [] GetExplicitInterfaces (TypeBuilder t)
2240         {
2241                 return (Type []) builder_to_ifaces [t];
2242         }
2243         
2244         /// <remarks>
2245         ///  The following is used to check if a given type implements an interface.
2246         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2247         /// </remarks>
2248         public static bool ImplementsInterface (Type t, Type iface)
2249         {
2250                 Type [] interfaces;
2251
2252                 //
2253                 // FIXME OPTIMIZATION:
2254                 // as soon as we hit a non-TypeBuiler in the interface
2255                 // chain, we could return, as the `Type.GetInterfaces'
2256                 // will return all the interfaces implement by the type
2257                 // or its bases.
2258                 //
2259                 do {
2260                         interfaces = GetInterfaces (t);
2261
2262                         if (interfaces != null){
2263                                 foreach (Type i in interfaces){
2264                                         if (i == iface)
2265                                                 return true;
2266                                 }
2267                         }
2268                         
2269                         t = t.BaseType;
2270                 } while (t != null);
2271                 
2272                 return false;
2273         }
2274
2275         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2276
2277         // This is a custom version of Convert.ChangeType() which works
2278         // with the TypeBuilder defined types when compiling corlib.
2279         public static object ChangeType (object value, Type conversionType, out bool error)
2280         {
2281                 IConvertible convert_value = value as IConvertible;
2282                 
2283                 if (convert_value == null){
2284                         error = true;
2285                         return null;
2286                 }
2287                 
2288                 //
2289                 // We must use Type.Equals() here since `conversionType' is
2290                 // the TypeBuilder created version of a system type and not
2291                 // the system type itself.  You cannot use Type.GetTypeCode()
2292                 // on such a type - it'd always return TypeCode.Object.
2293                 //
2294                 error = false;
2295                 try {
2296                         if (conversionType.Equals (typeof (Boolean)))
2297                                 return (object)(convert_value.ToBoolean (nf_provider));
2298                         else if (conversionType.Equals (typeof (Byte)))
2299                                 return (object)(convert_value.ToByte (nf_provider));
2300                         else if (conversionType.Equals (typeof (Char)))
2301                                 return (object)(convert_value.ToChar (nf_provider));
2302                         else if (conversionType.Equals (typeof (DateTime)))
2303                                 return (object)(convert_value.ToDateTime (nf_provider));
2304                         else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2305                                 return (object)(convert_value.ToDecimal (nf_provider));
2306                         else if (conversionType.Equals (typeof (Double)))
2307                                 return (object)(convert_value.ToDouble (nf_provider));
2308                         else if (conversionType.Equals (typeof (Int16)))
2309                                 return (object)(convert_value.ToInt16 (nf_provider));
2310                         else if (conversionType.Equals (typeof (Int32)))
2311                                 return (object)(convert_value.ToInt32 (nf_provider));
2312                         else if (conversionType.Equals (typeof (Int64)))
2313                                 return (object)(convert_value.ToInt64 (nf_provider));
2314                         else if (conversionType.Equals (typeof (SByte)))
2315                                 return (object)(convert_value.ToSByte (nf_provider));
2316                         else if (conversionType.Equals (typeof (Single)))
2317                                 return (object)(convert_value.ToSingle (nf_provider));
2318                         else if (conversionType.Equals (typeof (String)))
2319                                 return (object)(convert_value.ToString (nf_provider));
2320                         else if (conversionType.Equals (typeof (UInt16)))
2321                                 return (object)(convert_value.ToUInt16 (nf_provider));
2322                         else if (conversionType.Equals (typeof (UInt32)))
2323                                 return (object)(convert_value.ToUInt32 (nf_provider));
2324                         else if (conversionType.Equals (typeof (UInt64)))
2325                                 return (object)(convert_value.ToUInt64 (nf_provider));
2326                         else if (conversionType.Equals (typeof (Object)))
2327                                 return (object)(value);
2328                         else 
2329                                 error = true;
2330                 } catch {
2331                         error = true;
2332                 }
2333                 return null;
2334         }
2335
2336         //
2337         // This is needed, because enumerations from assemblies
2338         // do not report their underlyingtype, but they report
2339         // themselves
2340         //
2341         public static Type EnumToUnderlying (Type t)
2342         {
2343                 if (t == TypeManager.enum_type)
2344                         return t;
2345
2346                 t = t.UnderlyingSystemType;
2347                 if (!TypeManager.IsEnumType (t))
2348                         return t;
2349         
2350                 if (t is TypeBuilder) {
2351                         // slow path needed to compile corlib
2352                         if (t == TypeManager.bool_type ||
2353                             t == TypeManager.byte_type ||
2354                             t == TypeManager.sbyte_type ||
2355                             t == TypeManager.char_type ||
2356                             t == TypeManager.short_type ||
2357                             t == TypeManager.ushort_type ||
2358                             t == TypeManager.int32_type ||
2359                             t == TypeManager.uint32_type ||
2360                             t == TypeManager.int64_type ||
2361                             t == TypeManager.uint64_type)
2362                                 return t;
2363                 }
2364                 TypeCode tc = Type.GetTypeCode (t);
2365
2366                 switch (tc){
2367                 case TypeCode.Boolean:
2368                         return TypeManager.bool_type;
2369                 case TypeCode.Byte:
2370                         return TypeManager.byte_type;
2371                 case TypeCode.SByte:
2372                         return TypeManager.sbyte_type;
2373                 case TypeCode.Char:
2374                         return TypeManager.char_type;
2375                 case TypeCode.Int16:
2376                         return TypeManager.short_type;
2377                 case TypeCode.UInt16:
2378                         return TypeManager.ushort_type;
2379                 case TypeCode.Int32:
2380                         return TypeManager.int32_type;
2381                 case TypeCode.UInt32:
2382                         return TypeManager.uint32_type;
2383                 case TypeCode.Int64:
2384                         return TypeManager.int64_type;
2385                 case TypeCode.UInt64:
2386                         return TypeManager.uint64_type;
2387                 }
2388                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2389         }
2390
2391         //
2392         // When compiling corlib and called with one of the core types, return
2393         // the corresponding typebuilder for that type.
2394         //
2395         public static Type TypeToCoreType (Type t)
2396         {
2397                 if (RootContext.StdLib || (t is TypeBuilder))
2398                         return t;
2399
2400                 TypeCode tc = Type.GetTypeCode (t);
2401
2402                 switch (tc){
2403                 case TypeCode.Boolean:
2404                         return TypeManager.bool_type;
2405                 case TypeCode.Byte:
2406                         return TypeManager.byte_type;
2407                 case TypeCode.SByte:
2408                         return TypeManager.sbyte_type;
2409                 case TypeCode.Char:
2410                         return TypeManager.char_type;
2411                 case TypeCode.Int16:
2412                         return TypeManager.short_type;
2413                 case TypeCode.UInt16:
2414                         return TypeManager.ushort_type;
2415                 case TypeCode.Int32:
2416                         return TypeManager.int32_type;
2417                 case TypeCode.UInt32:
2418                         return TypeManager.uint32_type;
2419                 case TypeCode.Int64:
2420                         return TypeManager.int64_type;
2421                 case TypeCode.UInt64:
2422                         return TypeManager.uint64_type;
2423                 case TypeCode.Single:
2424                         return TypeManager.float_type;
2425                 case TypeCode.Double:
2426                         return TypeManager.double_type;
2427                 case TypeCode.String:
2428                         return TypeManager.string_type;
2429                 case TypeCode.Decimal:
2430                         return TypeManager.decimal_type;
2431                 default:
2432                         if (t == typeof (void))
2433                                 return TypeManager.void_type;
2434                         if (t == typeof (object))
2435                                 return TypeManager.object_type;
2436                         if (t == typeof (System.Type))
2437                                 return TypeManager.type_type;
2438                         if (t == typeof (System.IntPtr))
2439                                 return TypeManager.intptr_type;
2440                         return t;
2441                 }
2442         }
2443
2444         /// <summary>
2445         ///   Utility function that can be used to probe whether a type
2446         ///   is managed or not.  
2447         /// </summary>
2448         public static bool VerifyUnManaged (Type t, Location loc)
2449         {
2450                 if (IsUnmanagedType (t))
2451                         return true;
2452
2453                 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2454                         CSharpName (t));
2455
2456                 return false;   
2457         }
2458         
2459         /// <summary>
2460         ///   Returns the name of the indexer in a given type.
2461         /// </summary>
2462         /// <remarks>
2463         ///   The default is not always `Item'.  The user can change this behaviour by
2464         ///   using the IndexerNameAttribute in the container.
2465         ///   For example, the String class indexer is named `Chars' not `Item' 
2466         /// </remarks>
2467         public static string IndexerPropertyName (Type t)
2468         {
2469                 t = DropGenericTypeArguments (t);
2470                 if (t is TypeBuilder) {
2471                         TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2472                         return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2473                 }
2474                 
2475                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2476                         t, TypeManager.default_member_type);
2477                 if (attr != null){
2478                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2479                         return dma.MemberName;
2480                 }
2481
2482                 return TypeContainer.DefaultIndexerName;
2483         }
2484
2485         static MethodInfo declare_local_method = null;
2486         
2487         public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2488         {
2489                 if (declare_local_method == null){
2490                         declare_local_method = typeof (ILGenerator).GetMethod (
2491                                 "DeclareLocal",
2492                                 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2493                                 null, 
2494                                 new Type [] { typeof (Type), typeof (bool)},
2495                                 null);
2496                         if (declare_local_method == null){
2497                                 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2498                                 return ig.DeclareLocal (t);
2499                         }
2500                 }
2501                 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2502         }
2503
2504         private static bool IsSignatureEqual (Type a, Type b)
2505         {
2506                 ///
2507                 /// Consider the following example (bug #77674):
2508                 ///
2509                 ///     public abstract class A
2510                 ///     {
2511                 ///        public abstract T Foo<T> ();
2512                 ///     }
2513                 ///
2514                 ///     public abstract class B : A
2515                 ///     {
2516                 ///        public override U Foo<T> ()
2517                 ///        { return default (U); }
2518                 ///     }
2519                 ///
2520                 /// Here, `T' and `U' are method type parameters from different methods
2521                 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2522                 ///
2523                 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2524                 /// we need to do a signature based comparision and consider them equal.
2525
2526                 if (a == b)
2527                         return true;
2528
2529 #if GMCS_SOURCE
2530                 if (a.IsGenericParameter && b.IsGenericParameter &&
2531                     (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2532                         return a.GenericParameterPosition == b.GenericParameterPosition;
2533                 }
2534 #endif
2535
2536                 if (a.IsArray && b.IsArray) {
2537                         if (a.GetArrayRank () != b.GetArrayRank ())
2538                                 return false;
2539
2540                         return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2541                 }
2542
2543                 if (a.IsByRef && b.IsByRef)
2544                         return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2545
2546 #if GMCS_SOURCE
2547                 if (a.IsGenericType && b.IsGenericType) {
2548                         if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2549                                 return false;
2550
2551                         Type[] aargs = a.GetGenericArguments ();
2552                         Type[] bargs = b.GetGenericArguments ();
2553
2554                         if (aargs.Length != bargs.Length)
2555                                 return false;
2556
2557                         for (int i = 0; i < aargs.Length; i++) {
2558                                 if (!IsSignatureEqual (aargs [i], bargs [i]))
2559                                         return false;
2560                         }
2561
2562                         return true;
2563                 }
2564 #endif
2565
2566                 return false;
2567         }
2568
2569         //
2570         // Returns whether the array of memberinfos contains the given method
2571         //
2572         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2573         {
2574                 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2575                 
2576                 foreach (MethodBase method in array) {
2577                         if (method.Name != new_method.Name)
2578                                 continue;
2579
2580                         if (method is MethodInfo && new_method is MethodInfo)
2581                                 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2582                                                        ((MethodInfo) new_method).ReturnType))
2583                                         continue;
2584
2585                         
2586                         Type [] old_args = TypeManager.GetParameterData (method).Types;
2587                         int old_count = old_args.Length;
2588                         int i;
2589                         
2590                         if (new_args.Length != old_count)
2591                                 continue;
2592                         
2593                         for (i = 0; i < old_count; i++){
2594                                 if (!IsSignatureEqual (old_args [i], new_args [i]))
2595                                         break;
2596                         }
2597                         if (i != old_count)
2598                                 continue;
2599
2600                         return true;
2601                 }
2602                 
2603                 return false;
2604         }
2605         
2606         //
2607         // We copy methods from `new_members' into `target_list' if the signature
2608         // for the method from in the new list does not exist in the target_list
2609         //
2610         // The name is assumed to be the same.
2611         //
2612         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2613         {
2614                 if (target_list == null){
2615                         target_list = new ArrayList ();
2616
2617                         foreach (MemberInfo mi in new_members){
2618                                 if (mi is MethodBase)
2619                                         target_list.Add (mi);
2620                         }
2621                         return target_list;
2622                 }
2623                 
2624                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2625                 target_list.CopyTo (target_array, 0);
2626                 
2627                 foreach (MemberInfo mi in new_members){
2628                         MethodBase new_method = (MethodBase) mi;
2629                         
2630                         if (!ArrayContainsMethod (target_array, new_method))
2631                                 target_list.Add (new_method);
2632                 }
2633                 return target_list;
2634         }
2635
2636 #region Generics
2637         // <remarks>
2638         //   Tracks the generic parameters.
2639         // </remarks>
2640         static PtrHashtable builder_to_type_param;
2641
2642         public static void AddTypeParameter (Type t, TypeParameter tparam)
2643         {
2644                 if (!builder_to_type_param.Contains (t))
2645                         builder_to_type_param.Add (t, tparam);
2646         }
2647
2648         public static TypeParameter LookupTypeParameter (Type t)
2649         {
2650                 return (TypeParameter) builder_to_type_param [t];
2651         }
2652
2653         // This method always return false for non-generic compiler,
2654         // while Type.IsGenericParameter is returned if it is supported.
2655         public static bool IsGenericParameter (Type type)
2656         {
2657 #if GMCS_SOURCE
2658                 return type.IsGenericParameter;
2659 #else
2660                 return false;
2661 #endif
2662         }
2663
2664         public static int GenericParameterPosition (Type type)
2665         {
2666 #if GMCS_SOURCE
2667                 return type.GenericParameterPosition;
2668 #else
2669                 throw new InternalErrorException ("should not be called");
2670 #endif
2671         }
2672
2673         public static bool IsGenericType (Type type)
2674         {
2675 #if GMCS_SOURCE
2676                 return type.IsGenericType;
2677 #else
2678                 return false;
2679 #endif
2680         }
2681
2682         public static bool ContainsGenericParameters (Type type)
2683         {
2684 #if GMCS_SOURCE
2685                 return type.ContainsGenericParameters;
2686 #else
2687                 return false;
2688 #endif
2689         }
2690
2691         public static bool IsEqual (Type a, Type b)
2692         {
2693                 if (a.Equals (b))
2694                         return true;
2695
2696 #if GMCS_SOURCE
2697                 if (a.IsGenericParameter && b.IsGenericParameter) {
2698                         if (a.DeclaringMethod != b.DeclaringMethod &&
2699                             (a.DeclaringMethod == null || b.DeclaringMethod == null))
2700                                 return false;
2701                         return a.GenericParameterPosition == b.GenericParameterPosition;
2702                 }
2703
2704                 if (a.IsArray && b.IsArray) {
2705                         if (a.GetArrayRank () != b.GetArrayRank ())
2706                                 return false;
2707                         return IsEqual (a.GetElementType (), b.GetElementType ());
2708                 }
2709
2710                 if (a.IsByRef && b.IsByRef)
2711                         return IsEqual (a.GetElementType (), b.GetElementType ());
2712
2713                 if (a.IsGenericType && b.IsGenericType) {
2714                         if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2715                                 return false;
2716
2717                         Type[] aargs = a.GetGenericArguments ();
2718                         Type[] bargs = b.GetGenericArguments ();
2719
2720                         if (aargs.Length != bargs.Length)
2721                                 return false;
2722
2723                         for (int i = 0; i < aargs.Length; i++) {
2724                                 if (!IsEqual (aargs [i], bargs [i]))
2725                                         return false;
2726                         }
2727
2728                         return true;
2729                 }
2730 #endif
2731
2732                 return false;
2733         }
2734
2735         public static Type DropGenericTypeArguments (Type t)
2736         {
2737 #if GMCS_SOURCE
2738                 if (!t.IsGenericType)
2739                         return t;
2740                 // Micro-optimization: a generic typebuilder is always a generic type definition
2741                 if (t is TypeBuilder)
2742                         return t;
2743                 return t.GetGenericTypeDefinition ();
2744 #else
2745                 return t;
2746 #endif
2747         }
2748
2749         public static MethodBase DropGenericMethodArguments (MethodBase m)
2750         {
2751 #if GMCS_SOURCE
2752                 if (m.IsGenericMethodDefinition)
2753                         return m;
2754                 if (m.IsGenericMethod)
2755                         return ((MethodInfo) m).GetGenericMethodDefinition ();
2756                 if (!m.DeclaringType.IsGenericType)
2757                         return m;
2758
2759                 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2760                 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2761                         BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2762
2763                 if (m is ConstructorInfo) {
2764                         foreach (ConstructorInfo c in t.GetConstructors (bf))
2765                                 if (c.MetadataToken == m.MetadataToken)
2766                                         return c;
2767                 } else {
2768                         foreach (MethodBase mb in t.GetMethods (bf))
2769                                 if (mb.MetadataToken == m.MetadataToken)
2770                                         return mb;
2771                 }
2772 #endif
2773
2774                 return m;
2775         }
2776
2777         public static Type[] GetTypeArguments (Type t)
2778         {
2779 #if GMCS_SOURCE
2780                 DeclSpace tc = LookupDeclSpace (t);
2781                 if (tc != null) {
2782                         if (!tc.IsGeneric)
2783                                 return Type.EmptyTypes;
2784
2785                         TypeParameter[] tparam = tc.TypeParameters;
2786                         Type[] ret = new Type [tparam.Length];
2787                         for (int i = 0; i < tparam.Length; i++) {
2788                                 ret [i] = tparam [i].Type;
2789                                 if (ret [i] == null)
2790                                         throw new InternalErrorException ();
2791                         }
2792
2793                         return ret;
2794                 } else
2795                         return t.GetGenericArguments ();
2796 #else
2797                 throw new InternalErrorException ();
2798 #endif
2799         }
2800
2801         public static bool HasGenericArguments (Type t)
2802         {
2803                 return GetNumberOfTypeArguments (t) > 0;
2804         }
2805
2806         public static int GetNumberOfTypeArguments (Type t)
2807         {
2808 #if GMCS_SOURCE
2809                 if (t.IsGenericParameter)
2810                         return 0;
2811                 DeclSpace tc = LookupDeclSpace (t);
2812                 if (tc != null)
2813                         return tc.IsGeneric ? tc.CountTypeParameters : 0;
2814                 else
2815                         return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2816 #else
2817                 return 0;
2818 #endif
2819         }
2820
2821         /// <summary>
2822         ///   Check whether `type' and `parent' are both instantiations of the same
2823         ///   generic type.  Note that we do not check the type parameters here.
2824         /// </summary>
2825         public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2826         {
2827                 int tcount = GetNumberOfTypeArguments (type);
2828                 int pcount = GetNumberOfTypeArguments (parent);
2829
2830                 if (tcount != pcount)
2831                         return false;
2832
2833                 type = DropGenericTypeArguments (type);
2834                 parent = DropGenericTypeArguments (parent);
2835
2836                 return type.Equals (parent);
2837         }
2838
2839         /// <summary>
2840         ///   Whether `mb' is a generic method definition.
2841         /// </summary>
2842         public static bool IsGenericMethodDefinition (MethodBase mb)
2843         {
2844 #if GMCS_SOURCE
2845                 if (mb.DeclaringType is TypeBuilder) {
2846                         IMethodData method = (IMethodData) builder_to_method [mb];
2847                         if (method == null)
2848                                 return false;
2849
2850                         return method.GenericMethod != null;
2851                 }
2852
2853                 return mb.IsGenericMethodDefinition;
2854 #else
2855                 return false;
2856 #endif
2857         }
2858
2859         /// <summary>
2860         ///   Whether `mb' is a generic method.
2861         /// </summary>
2862         public static bool IsGenericMethod (MethodBase mb)
2863         {
2864 #if GMCS_SOURCE
2865                 if (mb.DeclaringType is TypeBuilder) {
2866                         IMethodData method = (IMethodData) builder_to_method [mb];
2867                         if (method == null)
2868                                 return false;
2869
2870                         return method.GenericMethod != null;
2871                 }
2872
2873                 return mb.IsGenericMethod;
2874 #else
2875                 return false;
2876 #endif
2877         }
2878 #endregion
2879
2880 #region MemberLookup implementation
2881         
2882         //
2883         // Whether we allow private members in the result (since FindMembers
2884         // uses NonPublic for both protected and private), we need to distinguish.
2885         //
2886
2887         internal class Closure {
2888                 internal bool     private_ok;
2889
2890                 // Who is invoking us and which type is being queried currently.
2891                 internal Type     invocation_type;
2892                 internal Type     qualifier_type;
2893
2894                 // The assembly that defines the type is that is calling us
2895                 internal Assembly invocation_assembly;
2896                 internal IList almost_match;
2897
2898                 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2899                 {
2900                         if (invocation_type == null)
2901                                 return false;
2902
2903                         if (is_static && qualifier_type == null)
2904                                 // It resolved from a simple name, so it should be visible.
2905                                 return true;
2906
2907                         if (IsNestedChildOf (invocation_type, m.DeclaringType))
2908                                 return true;
2909
2910                         for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2911                                 if (!IsFamilyAccessible (t, m.DeclaringType))
2912                                         continue;
2913
2914                                 // Although a derived class can access protected members of its base class
2915                                 // it cannot do so through an instance of the base class (CS1540).
2916                                 // => Ancestry should be: declaring_type ->* invocation_type ->*  qualified_type
2917                                 if (is_static || qualifier_type == null ||
2918                                     IsInstantiationOfSameGenericType (t, qualifier_type) ||
2919                                     IsFamilyAccessible (qualifier_type, t))
2920                                         return true;
2921                         }
2922
2923                         if (almost_match != null)
2924                                 almost_match.Add (m);
2925
2926                         return false;
2927                 }
2928                 
2929                 //
2930                 // This filter filters by name + whether it is ok to include private
2931                 // members in the search
2932                 //
2933                 internal bool Filter (MemberInfo m, object filter_criteria)
2934                 {
2935                         //
2936                         // Hack: we know that the filter criteria will always be in the
2937                         // `closure' // fields. 
2938                         //
2939
2940                         if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2941                                 return false;
2942
2943                         if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2944                             (invocation_type != null) &&
2945                             IsPrivateAccessible (m.DeclaringType, invocation_type))
2946                                 return true;
2947
2948                         //
2949                         // Ugly: we need to find out the type of `m', and depending
2950                         // on this, tell whether we accept or not
2951                         //
2952                         if (m is MethodBase){
2953                                 MethodBase mb = (MethodBase) m;
2954                                 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2955
2956                                 if (ma == MethodAttributes.Public)
2957                                         return true;
2958                                 
2959                                 if (ma == MethodAttributes.Private)
2960                                         return private_ok ||
2961                                                 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2962                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2963
2964                                 if (invocation_assembly == mb.DeclaringType.Assembly ||
2965                                     TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
2966                                         if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2967                                                 return true;
2968                                 } else {
2969                                         if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2970                                                 return false;
2971                                 }
2972
2973                                 // Family, FamORAssem or FamANDAssem
2974                                 return CheckValidFamilyAccess (mb.IsStatic, m);
2975                         }
2976                         
2977                         if (m is FieldInfo){
2978                                 FieldInfo fi = (FieldInfo) m;
2979                                 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2980                                 
2981                                 if (fa == FieldAttributes.Public)
2982                                         return true;
2983                                 
2984                                 if (fa == FieldAttributes.Private)
2985                                         return private_ok ||
2986                                                 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2987                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2988
2989                                 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
2990                                     (invocation_assembly == null) ||
2991                                     TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
2992                                         if ((fa == FieldAttributes.Assembly) ||
2993                                             (fa == FieldAttributes.FamORAssem))
2994                                                 return true;
2995                                 } else {
2996                                         if ((fa == FieldAttributes.Assembly) ||
2997                                             (fa == FieldAttributes.FamANDAssem))
2998                                                 return false;
2999                                 }
3000
3001                                 // Family, FamORAssem or FamANDAssem
3002                                 return CheckValidFamilyAccess (fi.IsStatic, m);
3003                         }
3004
3005                         //
3006                         // EventInfos and PropertyInfos, return true because they lack
3007                         // permission information, so we need to check later on the methods.
3008                         //
3009                         return true;
3010                 }
3011         }
3012
3013         static Closure closure = new Closure ();
3014         static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3015
3016         //
3017         // Looks up a member called `name' in the `queried_type'.  This lookup
3018         // is done by code that is contained in the definition for `invocation_type'
3019         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3020         //
3021         // `invocation_type' is used to check whether we're allowed to access the requested
3022         // member wrt its protection level.
3023         //
3024         // When called from MemberAccess, `qualifier_type' is the type which is used to access
3025         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3026         // is B and qualifier_type is A).  This is used to do the CS1540 check.
3027         //
3028         // When resolving a SimpleName, `qualifier_type' is null.
3029         //
3030         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3031         // the same than `queried_type' - except when we're being called from BaseAccess;
3032         // in this case, `invocation_type' is the current type and `queried_type' the base
3033         // type, so this'd normally trigger a CS1540.
3034         //
3035         // The binding flags are `bf' and the kind of members being looked up are `mt'
3036         //
3037         // The return value always includes private members which code in `invocation_type'
3038         // is allowed to access (using the specified `qualifier_type' if given); only use
3039         // BindingFlags.NonPublic to bypass the permission check.
3040         //
3041         // The 'almost_match' argument is used for reporting error CS1540.
3042         //
3043         // Returns an array of a single element for everything but Methods/Constructors
3044         // that might return multiple matches.
3045         //
3046         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3047                                                   Type queried_type, MemberTypes mt,
3048                                                   BindingFlags original_bf, string name, IList almost_match)
3049         {
3050                 Timer.StartTimer (TimerType.MemberLookup);
3051
3052                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3053                                                         queried_type, mt, original_bf, name, almost_match);
3054
3055                 Timer.StopTimer (TimerType.MemberLookup);
3056
3057                 return retval;
3058         }
3059
3060         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3061                                                Type queried_type, MemberTypes mt,
3062                                                BindingFlags original_bf, string name, IList almost_match)
3063         {
3064                 BindingFlags bf = original_bf;
3065                 
3066                 ArrayList method_list = null;
3067                 Type current_type = queried_type;
3068                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3069                 bool skip_iface_check = true, used_cache = false;
3070                 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3071
3072                 closure.invocation_type = invocation_type;
3073                 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3074                 closure.qualifier_type = qualifier_type;
3075                 closure.almost_match = almost_match;
3076                 
3077                 // This is from the first time we find a method
3078                 // in most cases, we do not actually find a method in the base class
3079                 // so we can just ignore it, and save the arraylist allocation
3080                 MemberInfo [] first_members_list = null;
3081                 bool use_first_members_list = false;
3082                 
3083                 do {
3084                         MemberInfo [] list;
3085
3086                         //
3087                         // `NonPublic' is lame, because it includes both protected and
3088                         // private methods, so we need to control this behavior by
3089                         // explicitly tracking if a private method is ok or not.
3090                         //
3091                         // The possible cases are:
3092                         //    public, private and protected (internal does not come into the
3093                         //    equation)
3094                         //
3095                         if ((invocation_type != null) &&
3096                             ((invocation_type == current_type) ||
3097                              IsNestedChildOf (invocation_type, current_type)) ||
3098                             always_ok_flag)
3099                                 bf = original_bf | BindingFlags.NonPublic;
3100                         else
3101                                 bf = original_bf;
3102
3103                         closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3104
3105                         Timer.StopTimer (TimerType.MemberLookup);
3106
3107                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3108
3109                         Timer.StartTimer (TimerType.MemberLookup);
3110
3111                         //
3112                         // When queried for an interface type, the cache will automatically check all
3113                         // inherited members, so we don't need to do this here.  However, this only
3114                         // works if we already used the cache in the first iteration of this loop.
3115                         //
3116                         // If we used the cache in any further iteration, we can still terminate the
3117                         // loop since the cache always looks in all base classes.
3118                         //
3119
3120                         if (used_cache)
3121                                 searching = false;
3122                         else
3123                                 skip_iface_check = false;
3124
3125                         if (current_type == TypeManager.object_type)
3126                                 searching = false;
3127                         else {
3128                                 current_type = current_type.BaseType;
3129                                 
3130                                 //
3131                                 // This happens with interfaces, they have a null
3132                                 // basetype.  Look members up in the Object class.
3133                                 //
3134                                 if (current_type == null) {
3135                                         current_type = TypeManager.object_type;
3136                                         searching = true;
3137                                 }
3138                         }
3139                         
3140                         if (list.Length == 0)
3141                                 continue;
3142
3143                         //
3144                         // Events and types are returned by both `static' and `instance'
3145                         // searches, which means that our above FindMembers will
3146                         // return two copies of the same.
3147                         //
3148                         if (list.Length == 1 && !(list [0] is MethodBase)){
3149                                 return list;
3150                         }
3151
3152                         //
3153                         // Multiple properties: we query those just to find out the indexer
3154                         // name
3155                         //
3156                         if (list [0] is PropertyInfo)
3157                                 return list;
3158
3159                         //
3160                         // We found an event: the cache lookup returns both the event and
3161                         // its private field.
3162                         //
3163                         if (list [0] is EventInfo) {
3164                                 if ((list.Length == 2) && (list [1] is FieldInfo))
3165                                         return new MemberInfo [] { list [0] };
3166
3167                                 return list;
3168                         }
3169
3170                         //
3171                         // We found methods, turn the search into "method scan"
3172                         // mode.
3173                         //
3174
3175                         if (first_members_list != null) {
3176                                 if (use_first_members_list) {
3177                                         method_list = CopyNewMethods (method_list, first_members_list);
3178                                         use_first_members_list = false;
3179                                 }
3180                                 
3181                                 method_list = CopyNewMethods (method_list, list);
3182                         } else {
3183                                 first_members_list = list;
3184                                 use_first_members_list = true;
3185                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3186                         }
3187                 } while (searching);
3188
3189                 if (use_first_members_list)
3190                         return first_members_list;
3191
3192                 if (method_list != null && method_list.Count > 0) {
3193                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3194                 }
3195                 //
3196                 // This happens if we already used the cache in the first iteration, in this case
3197                 // the cache already looked in all interfaces.
3198                 //
3199                 if (skip_iface_check)
3200                         return null;
3201
3202                 //
3203                 // Interfaces do not list members they inherit, so we have to
3204                 // scan those.
3205                 // 
3206                 if (!queried_type.IsInterface)
3207                         return null;
3208
3209                 if (queried_type.IsArray)
3210                         queried_type = TypeManager.array_type;
3211                 
3212                 Type [] ifaces = GetInterfaces (queried_type);
3213                 if (ifaces == null)
3214                         return null;
3215                 
3216                 foreach (Type itype in ifaces){
3217                         MemberInfo [] x;
3218
3219                         x = MemberLookup (null, null, itype, mt, bf, name, null);
3220                         if (x != null)
3221                                 return x;
3222                 }
3223                                         
3224                 return null;
3225         }
3226
3227         // Tests whether external method is really special
3228         public static bool IsSpecialMethod (MethodBase mb)
3229         {
3230                 string name = mb.Name;
3231                 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3232                         return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3233                                 
3234                 if (name.StartsWith ("add_"))
3235                         return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3236
3237                 if (name.StartsWith ("remove_"))
3238                         return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3239
3240                 if (name.StartsWith ("op_")){
3241                         foreach (string oname in Unary.oper_names) {
3242                                 if (oname == name)
3243                                         return true;
3244                         }
3245
3246                         foreach (string oname in Binary.oper_names) {
3247                                 if (oname == name)
3248                                         return true;
3249                         }
3250                 }
3251                 return false;
3252         }
3253
3254 #endregion
3255         
3256 }
3257
3258 /// <summary>
3259 ///   There is exactly one instance of this class per type.
3260 /// </summary>
3261 public sealed class TypeHandle : IMemberContainer {
3262         public readonly IMemberContainer BaseType;
3263
3264         readonly int id = ++next_id;
3265         static int next_id = 0;
3266
3267         static TypeHandle ()
3268         {
3269                 Reset ();
3270         }
3271
3272         /// <summary>
3273         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
3274         ///   a TypeHandle yet, a new instance of it is created.  This static method
3275         ///   ensures that we'll only have one TypeHandle instance per type.
3276         /// </summary>
3277         private static TypeHandle GetTypeHandle (Type t)
3278         {
3279                 TypeHandle handle = (TypeHandle) type_hash [t];
3280                 if (handle != null)
3281                         return handle;
3282
3283                 handle = new TypeHandle (t);
3284                 type_hash.Add (t, handle);
3285                 return handle;
3286         }
3287
3288         public static MemberCache GetMemberCache (Type t)
3289         {
3290                 return GetTypeHandle (t).MemberCache;
3291         }
3292         
3293         public static void CleanUp ()
3294         {
3295                 type_hash = null;
3296         }
3297
3298         public static void Reset ()
3299         {
3300                 type_hash = new PtrHashtable ();
3301         }
3302
3303         /// <summary>
3304         ///   Returns the TypeHandle for TypeManager.object_type.
3305         /// </summary>
3306         public static IMemberContainer ObjectType {
3307                 get {
3308                         if (object_type != null)
3309                                 return object_type;
3310
3311                         object_type = GetTypeHandle (TypeManager.object_type);
3312
3313                         return object_type;
3314                 }
3315         }
3316
3317         /// <summary>
3318         ///   Returns the TypeHandle for TypeManager.array_type.
3319         /// </summary>
3320         public static IMemberContainer ArrayType {
3321                 get {
3322                         if (array_type != null)
3323                                 return array_type;
3324
3325                         array_type = GetTypeHandle (TypeManager.array_type);
3326
3327                         return array_type;
3328                 }
3329         }
3330
3331         private static PtrHashtable type_hash;
3332
3333         private static TypeHandle object_type = null;
3334         private static TypeHandle array_type = null;
3335
3336         private Type type;
3337         private string full_name;
3338         private bool is_interface;
3339         private MemberCache member_cache;
3340         private MemberCache base_cache;
3341
3342         private TypeHandle (Type type)
3343         {
3344                 this.type = type;
3345 #if MS_COMPATIBLE && GMCS_SOURCE
3346                 if (type.IsGenericType)
3347                         this.type = this.type.GetGenericTypeDefinition ();
3348 #endif
3349                 full_name = type.FullName != null ? type.FullName : type.Name;
3350                 if (type.BaseType != null) {
3351                         base_cache = TypeManager.LookupMemberCache (type.BaseType);
3352                         BaseType = base_cache.Container;
3353                 } else if (type.IsInterface)
3354                         base_cache = TypeManager.LookupBaseInterfacesCache (type);
3355                 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3356                 this.member_cache = new MemberCache (this);
3357         }
3358
3359         // IMemberContainer methods
3360
3361         public string Name {
3362                 get {
3363                         return full_name;
3364                 }
3365         }
3366
3367         public Type Type {
3368                 get {
3369                         return type;
3370                 }
3371         }
3372
3373         public MemberCache BaseCache {
3374                 get {
3375                         return base_cache;
3376                 }
3377         }
3378
3379         public bool IsInterface {
3380                 get {
3381                         return is_interface;
3382                 }
3383         }
3384
3385         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3386         {
3387                 MemberInfo [] members;
3388 #if GMCS_SOURCE
3389                 if (type is GenericTypeParameterBuilder)
3390                         return MemberList.Empty;
3391 #endif
3392                 if (mt == MemberTypes.Event)
3393                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3394                 else
3395                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3396                                                     null, null);
3397                 Array.Reverse (members);
3398
3399                 return new MemberList (members);
3400         }
3401
3402         // IMemberFinder methods
3403
3404         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3405                                        MemberFilter filter, object criteria)
3406         {
3407                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3408         }
3409
3410         public MemberCache MemberCache {
3411                 get {
3412                         return member_cache;
3413                 }
3414         }
3415
3416         public override string ToString ()
3417         {
3418                 if (BaseType != null)
3419                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3420                 else
3421                         return "TypeHandle (" + id + "," + Name + ")";
3422         }
3423 }
3424
3425 }