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