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