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