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