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