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