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