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