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