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