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