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