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