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