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