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