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