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