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