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