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