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