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