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