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