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