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