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