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