Flush
[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 Type 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                 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
878         }
879                 
880         static public string GetFullNameSignature (MethodBase mb)
881         {
882                 string name = mb.Name;
883                 if (name == ".ctor")
884                         name = mb.DeclaringType.Name;
885
886                 if (mb.IsSpecialName) {
887                         if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
888                                 name = name.Remove (0, 4);
889                         }
890
891                         if (name == "Item")
892                                 name = "this";
893                 }
894
895                 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
896         }
897
898         static public string GetFullName (Type t)
899         {
900                 if (t.FullName == null)
901                         return t.Name;
902
903                 string name = t.FullName.Replace ('+', '.');
904
905                 DeclSpace tc = LookupDeclSpace (t);
906                 if ((tc != null) && tc.IsGeneric) {
907                         TypeParameter[] tparam = tc.TypeParameters;
908
909                         StringBuilder sb = new StringBuilder (name);
910                         sb.Append ("<");
911                         for (int i = 0; i < tparam.Length; i++) {
912                                 if (i > 0)
913                                         sb.Append (",");
914                                 sb.Append (tparam [i].Name);
915                         }
916                         sb.Append (">");
917                         return sb.ToString ();
918                 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
919                         Type[] tparam = t.GetGenericArguments ();
920
921                         StringBuilder sb = new StringBuilder (name);
922                         sb.Append ("<");
923                         for (int i = 0; i < tparam.Length; i++) {
924                                 if (i > 0)
925                                         sb.Append (",");
926                                 sb.Append (tparam [i].Name);
927                         }
928                         sb.Append (">");
929                         return sb.ToString ();
930                 }
931
932                 return name;
933         }
934
935         /// <summary>
936         ///   Returns the signature of the property and indexer
937         /// </summary>
938         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
939         {
940                 if (!is_indexer) {
941                         return GetFullNameSignature (pb);
942                 }
943
944                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
945                 string signature = GetFullNameSignature (mb);
946                 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
947                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
948         }
949
950         /// <summary>
951         ///   Returns the signature of the method
952         /// </summary>
953         static public string CSharpSignature (MethodBase mb)
954         {
955                 StringBuilder sig = new StringBuilder ("(");
956
957                 //
958                 // FIXME: We should really have a single function to do
959                 // everything instead of the following 5 line pattern
960                 //
961                 ParameterData iparams = LookupParametersByBuilder (mb);
962
963                 if (iparams == null)
964                         iparams = new ReflectionParameters (mb);
965                 
966                 // Is property
967                 if (mb.IsSpecialName && iparams.Count == 0)
968                         return GetFullNameSignature (mb);
969                 
970                 for (int i = 0; i < iparams.Count; i++) {
971                         if (i > 0) {
972                                 sig.Append (", ");
973                         }
974                         sig.Append (iparams.ParameterDesc (i));
975                 }
976                 sig.Append (")");
977
978                 // Is indexer
979                 if (mb.IsSpecialName && iparams.Count == 1) {
980                         sig.Replace ('(', '[');
981                         sig.Replace (')', ']');
982                 }
983
984                 return GetFullNameSignature (mb) + sig.ToString ();
985         }
986
987         /// <summary>
988         ///   Looks up a type, and aborts if it is not found.  This is used
989         ///   by types required by the compiler
990         /// </summary>
991         static Type CoreLookupType (string name)
992         {
993                 Type t = LookupTypeDirect (name);
994
995                 if (t == null){
996                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
997                         Environment.Exit (1);
998                 }
999
1000                 return t;
1001         }
1002
1003         /// <summary>
1004         ///   Returns the MethodInfo for a method named `name' defined
1005         ///   in type `t' which takes arguments of types `args'
1006         /// </summary>
1007         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1008         {
1009                 MemberList list;
1010                 Signature sig;
1011                 BindingFlags flags = instance_and_static | BindingFlags.Public;
1012
1013                 sig.name = name;
1014                 sig.args = args;
1015                 
1016                 if (is_private)
1017                         flags |= BindingFlags.NonPublic;
1018
1019                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1020                 if (list.Count == 0) {
1021                         if (report_errors)
1022                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1023                         return null;
1024                 }
1025
1026                 MethodInfo mi = list [0] as MethodInfo;
1027                 if (mi == null) {
1028                         if (report_errors)
1029                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1030                         return null;
1031                 }
1032
1033                 return mi;
1034         }
1035
1036         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1037         {
1038                 return GetMethod (t, name, args, false, report_errors);
1039         }
1040
1041         static MethodInfo GetMethod (Type t, string name, Type [] args)
1042         {
1043                 return GetMethod (t, name, args, true);
1044         }
1045
1046
1047         /// <summary>
1048         ///    Returns the ConstructorInfo for "args"
1049         /// </summary>
1050         static ConstructorInfo GetConstructor (Type t, Type [] args)
1051         {
1052                 MemberList list;
1053                 Signature sig;
1054
1055                 sig.name = ".ctor";
1056                 sig.args = args;
1057                 
1058                 list = FindMembers (t, MemberTypes.Constructor,
1059                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1060                                     signature_filter, sig);
1061                 if (list.Count == 0){
1062                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1063                         return null;
1064                 }
1065
1066                 ConstructorInfo ci = list [0] as ConstructorInfo;
1067                 if (ci == null){
1068                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1069                         return null;
1070                 }
1071
1072                 return ci;
1073         }
1074
1075         public static void InitEnumUnderlyingTypes ()
1076         {
1077
1078                 int32_type    = CoreLookupType ("System.Int32");
1079                 int64_type    = CoreLookupType ("System.Int64");
1080                 uint32_type   = CoreLookupType ("System.UInt32"); 
1081                 uint64_type   = CoreLookupType ("System.UInt64"); 
1082                 byte_type     = CoreLookupType ("System.Byte");
1083                 sbyte_type    = CoreLookupType ("System.SByte");
1084                 short_type    = CoreLookupType ("System.Int16");
1085                 ushort_type   = CoreLookupType ("System.UInt16");
1086         }
1087         
1088         /// <remarks>
1089         ///   The types have to be initialized after the initial
1090         ///   population of the type has happened (for example, to
1091         ///   bootstrap the corlib.dll
1092         /// </remarks>
1093         public static void InitCoreTypes ()
1094         {
1095                 object_type   = CoreLookupType ("System.Object");
1096                 value_type    = CoreLookupType ("System.ValueType");
1097
1098                 InitEnumUnderlyingTypes ();
1099
1100                 char_type     = CoreLookupType ("System.Char");
1101                 string_type   = CoreLookupType ("System.String");
1102                 float_type    = CoreLookupType ("System.Single");
1103                 double_type   = CoreLookupType ("System.Double");
1104                 char_ptr_type = CoreLookupType ("System.Char*");
1105                 decimal_type  = CoreLookupType ("System.Decimal");
1106                 bool_type     = CoreLookupType ("System.Boolean");
1107                 enum_type     = CoreLookupType ("System.Enum");
1108
1109                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1110                 delegate_type           = CoreLookupType ("System.Delegate");
1111
1112                 array_type    = CoreLookupType ("System.Array");
1113                 void_type     = CoreLookupType ("System.Void");
1114                 type_type     = CoreLookupType ("System.Type");
1115
1116                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1117                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1118                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1119                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1120                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1121                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1122                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1123                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1124                 idisposable_type     = CoreLookupType ("System.IDisposable");
1125                 icloneable_type      = CoreLookupType ("System.ICloneable");
1126                 iconvertible_type    = CoreLookupType ("System.IConvertible");
1127                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1128                 intptr_type          = CoreLookupType ("System.IntPtr");
1129
1130                 attribute_type       = CoreLookupType ("System.Attribute");
1131                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1132                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1133                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1134                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1135                 new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
1136                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1137                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1138                 typed_reference_type = CoreLookupType ("System.TypedReference");
1139                 arg_iterator_type    = CoreLookupType ("System.ArgIterator");
1140                 mbr_type             = CoreLookupType ("System.MarshalByRefObject");
1141
1142                 //
1143                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1144                 // people are running.
1145                 //
1146                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1147
1148                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1149
1150                 void_ptr_type         = CoreLookupType ("System.Void*");
1151
1152                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1153
1154                 exception_type        = CoreLookupType ("System.Exception");
1155                 activator_type        = CoreLookupType ("System.Activator");
1156                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1157
1158                 //
1159                 // Attribute types
1160                 //
1161                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1162                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1163                 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1164                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1165                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1166
1167                 //
1168                 // When compiling corlib, store the "real" types here.
1169                 //
1170                 if (!RootContext.StdLib) {
1171                         system_int32_type = typeof (System.Int32);
1172                         system_array_type = typeof (System.Array);
1173                         system_type_type = typeof (System.Type);
1174                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1175
1176                         Type [] void_arg = {  };
1177                         system_int_array_get_length = GetMethod (
1178                                 system_array_type, "get_Length", void_arg);
1179                         system_int_array_get_rank = GetMethod (
1180                                 system_array_type, "get_Rank", void_arg);
1181                         system_object_array_clone = GetMethod (
1182                                 system_array_type, "Clone", void_arg);
1183
1184                         Type [] system_int_arg = { system_int32_type };
1185                         system_int_array_get_length_int = GetMethod (
1186                                 system_array_type, "GetLength", system_int_arg);
1187                         system_int_array_get_upper_bound_int = GetMethod (
1188                                 system_array_type, "GetUpperBound", system_int_arg);
1189                         system_int_array_get_lower_bound_int = GetMethod (
1190                                 system_array_type, "GetLowerBound", system_int_arg);
1191
1192                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1193                         system_void_array_copyto_array_int = GetMethod (
1194                                 system_array_type, "CopyTo", system_array_int_arg);
1195
1196                         Type [] system_3_type_arg = {
1197                                 system_type_type, system_type_type, system_type_type };
1198                         Type [] system_4_type_arg = {
1199                                 system_type_type, system_type_type, system_type_type, system_type_type };
1200
1201                         MethodInfo set_corlib_type_builders = GetMethod (
1202                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1203                                 system_4_type_arg, true, false);
1204
1205                         if (set_corlib_type_builders != null) {
1206                                 object[] args = new object [4];
1207                                 args [0] = object_type;
1208                                 args [1] = value_type;
1209                                 args [2] = enum_type;
1210                                 args [3] = void_type;
1211                                 
1212                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1213                         } else {
1214                                 // Compatibility for an older version of the class libs.
1215                                 set_corlib_type_builders = GetMethod (
1216                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1217                                         system_3_type_arg, true, true);
1218
1219                                 if (set_corlib_type_builders == null) {
1220                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1221                                         return;
1222                                 }
1223
1224                                 object[] args = new object [3];
1225                                 args [0] = object_type;
1226                                 args [1] = value_type;
1227                                 args [2] = enum_type;
1228                                 
1229                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1230                         }
1231                 }
1232
1233                 system_object_expr.Type = object_type;
1234                 system_string_expr.Type = string_type;
1235                 system_boolean_expr.Type = bool_type;
1236                 system_decimal_expr.Type = decimal_type;
1237                 system_single_expr.Type = float_type;
1238                 system_double_expr.Type = double_type;
1239                 system_sbyte_expr.Type = sbyte_type;
1240                 system_byte_expr.Type = byte_type;
1241                 system_int16_expr.Type = short_type;
1242                 system_uint16_expr.Type = ushort_type;
1243                 system_int32_expr.Type = int32_type;
1244                 system_uint32_expr.Type = uint32_type;
1245                 system_int64_expr.Type = int64_type;
1246                 system_uint64_expr.Type = uint64_type;
1247                 system_char_expr.Type = char_type;
1248                 system_void_expr.Type = void_type;
1249                 system_asynccallback_expr.Type = asynccallback_type;
1250                 system_iasyncresult_expr.Type = iasyncresult_type;
1251                 system_valuetype_expr.Type = value_type;
1252         }
1253
1254         //
1255         // The helper methods that are used by the compiler
1256         //
1257         public static void InitCodeHelpers ()
1258         {
1259                 //
1260                 // Now load the default methods that we use.
1261                 //
1262                 Type [] string_string = { string_type, string_type };
1263                 string_concat_string_string = GetMethod (
1264                         string_type, "Concat", string_string);
1265                 Type [] string_string_string = { string_type, string_type, string_type };
1266                 string_concat_string_string_string = GetMethod (
1267                         string_type, "Concat", string_string_string);
1268                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1269                 string_concat_string_string_string_string = GetMethod (
1270                         string_type, "Concat", string_string_string_string);
1271                 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1272                 string_concat_string_dot_dot_dot = GetMethod (
1273                         string_type, "Concat", params_string);
1274
1275                 Type [] object_object = { object_type, object_type };
1276                 string_concat_object_object = GetMethod (
1277                         string_type, "Concat", object_object);
1278                 Type [] object_object_object = { object_type, object_type, object_type };
1279                 string_concat_object_object_object = GetMethod (
1280                         string_type, "Concat", object_object_object);
1281                 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1282                 string_concat_object_dot_dot_dot = GetMethod (
1283                         string_type, "Concat", params_object);
1284
1285                 Type [] string_ = { string_type };
1286                 string_isinterneted_string = GetMethod (
1287                         string_type, "IsInterned", string_);
1288                 
1289                 Type [] runtime_type_handle = { runtime_handle_type };
1290                 system_type_get_type_from_handle = GetMethod (
1291                         type_type, "GetTypeFromHandle", runtime_type_handle);
1292
1293                 Type [] delegate_delegate = { delegate_type, delegate_type };
1294                 delegate_combine_delegate_delegate = GetMethod (
1295                                 delegate_type, "Combine", delegate_delegate);
1296
1297                 delegate_remove_delegate_delegate = GetMethod (
1298                                 delegate_type, "Remove", delegate_delegate);
1299
1300                 //
1301                 // Void arguments
1302                 //
1303                 Type [] void_arg = {  };
1304                 object_getcurrent_void = GetMethod (
1305                         ienumerator_type, "get_Current", void_arg);
1306                 bool_movenext_void = GetMethod (
1307                         ienumerator_type, "MoveNext", void_arg);
1308                 void_reset_void = GetMethod (
1309                         ienumerator_type, "Reset", void_arg);
1310                 void_dispose_void = GetMethod (
1311                         idisposable_type, "Dispose", void_arg);
1312                 int_get_offset_to_string_data = GetMethod (
1313                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1314                 int_array_get_length = GetMethod (
1315                         array_type, "get_Length", void_arg);
1316                 int_array_get_rank = GetMethod (
1317                         array_type, "get_Rank", void_arg);
1318                 ienumerable_getenumerator_void = GetMethod (
1319                         ienumerable_type, "GetEnumerator", void_arg);
1320                 
1321                 //
1322                 // Int32 arguments
1323                 //
1324                 Type [] int_arg = { int32_type };
1325                 int_array_get_length_int = GetMethod (
1326                         array_type, "GetLength", int_arg);
1327                 int_array_get_upper_bound_int = GetMethod (
1328                         array_type, "GetUpperBound", int_arg);
1329                 int_array_get_lower_bound_int = GetMethod (
1330                         array_type, "GetLowerBound", int_arg);
1331
1332                 //
1333                 // System.Array methods
1334                 //
1335                 object_array_clone = GetMethod (
1336                         array_type, "Clone", void_arg);
1337                 Type [] array_int_arg = { array_type, int32_type };
1338                 void_array_copyto_array_int = GetMethod (
1339                         array_type, "CopyTo", array_int_arg);
1340                 
1341                 //
1342                 // object arguments
1343                 //
1344                 Type [] object_arg = { object_type };
1345                 void_monitor_enter_object = GetMethod (
1346                         monitor_type, "Enter", object_arg);
1347                 void_monitor_exit_object = GetMethod (
1348                         monitor_type, "Exit", object_arg);
1349
1350                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1351                 
1352                 void_initializearray_array_fieldhandle = GetMethod (
1353                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1354
1355                 //
1356                 // Array functions
1357                 //
1358                 int_getlength_int = GetMethod (
1359                         array_type, "GetLength", int_arg);
1360
1361                 //
1362                 // Decimal constructors
1363                 //
1364                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1365                 void_decimal_ctor_five_args = GetConstructor (
1366                         decimal_type, dec_arg);
1367                 
1368                 //
1369                 // Attributes
1370                 //
1371                 cons_param_array_attribute = GetConstructor (
1372                         param_array_type, void_arg);
1373
1374                 unverifiable_code_ctor = GetConstructor (
1375                         unverifiable_code_type, void_arg);
1376
1377                 //
1378                 // InvalidOperationException
1379                 //
1380                 invalid_operation_ctor = GetConstructor (
1381                         invalid_operation_exception_type, void_arg);
1382
1383
1384                 // Object
1385                 object_ctor = GetConstructor (object_type, void_arg);
1386
1387                 // Activator
1388                 Type [] type_arg = { type_type };
1389                 activator_create_instance = GetMethod (
1390                         activator_type, "CreateInstance", type_arg);
1391         }
1392
1393         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1394
1395         /// <remarks>
1396         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1397         ///   the cache here because there is no member name argument.
1398         /// </remarks>
1399         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1400                                               MemberFilter filter, object criteria)
1401         {
1402                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1403
1404                 //
1405                 // `builder_to_declspace' contains all dynamic types.
1406                 //
1407                 if (decl != null) {
1408                         MemberList list;
1409                         Timer.StartTimer (TimerType.FindMembers);
1410                         list = decl.FindMembers (mt, bf, filter, criteria);
1411                         Timer.StopTimer (TimerType.FindMembers);
1412                         return list;
1413                 }
1414
1415                 //
1416                 // We have to take care of arrays specially, because GetType on
1417                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1418                 // and we can not call FindMembers on this type.
1419                 //
1420                 if (t.IsSubclassOf (TypeManager.array_type))
1421                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1422
1423                 //
1424                 // Since FindMembers will not lookup both static and instance
1425                 // members, we emulate this behaviour here.
1426                 //
1427                 if ((bf & instance_and_static) == instance_and_static){
1428                         MemberInfo [] i_members = t.FindMembers (
1429                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1430
1431                         int i_len = i_members.Length;
1432                         if (i_len == 1){
1433                                 MemberInfo one = i_members [0];
1434
1435                                 //
1436                                 // If any of these are present, we are done!
1437                                 //
1438                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1439                                         return new MemberList (i_members);
1440                         }
1441                                 
1442                         MemberInfo [] s_members = t.FindMembers (
1443                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1444
1445                         int s_len = s_members.Length;
1446                         if (i_len > 0 || s_len > 0)
1447                                 return new MemberList (i_members, s_members);
1448                         else {
1449                                 if (i_len > 0)
1450                                         return new MemberList (i_members);
1451                                 else
1452                                         return new MemberList (s_members);
1453                         }
1454                 }
1455
1456                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1457         }
1458
1459
1460         /// <summary>
1461         ///   This method is only called from within MemberLookup.  It tries to use the member
1462         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1463         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1464         ///   our return value will already contain all inherited members and the caller don't need
1465         ///   to check base classes and interfaces anymore.
1466         /// </summary>
1467         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1468                                                             string name, out bool used_cache)
1469         {
1470                 //
1471                 // We have to take care of arrays specially, because GetType on
1472                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1473                 // and we can not call FindMembers on this type.
1474                 //
1475                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1476                         used_cache = true;
1477                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1478                                 mt, bf, name, FilterWithClosure_delegate, null);
1479                 }
1480
1481                 //
1482                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1483                 // and we can ask the DeclSpace for the MemberCache.
1484                 //
1485                 if (t is TypeBuilder) {
1486                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1487                         MemberCache cache = decl.MemberCache;
1488
1489                         //
1490                         // If this DeclSpace has a MemberCache, use it.
1491                         //
1492
1493                         if (cache != null) {
1494                                 used_cache = true;
1495                                 return cache.FindMembers (
1496                                         mt, bf, name, FilterWithClosure_delegate, null);
1497                         }
1498
1499                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1500                         // Note, this is a VERY uncommon route!
1501
1502                         MemberList list;
1503                         Timer.StartTimer (TimerType.FindMembers);
1504                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1505                                                  FilterWithClosure_delegate, name);
1506                         Timer.StopTimer (TimerType.FindMembers);
1507                         used_cache = false;
1508                         return (MemberInfo []) list;
1509                 }
1510
1511                 if (t is GenericTypeParameterBuilder) {
1512                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1513
1514                         MemberList list;
1515                         Timer.StartTimer (TimerType.FindMembers);
1516                         list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1517                                                    FilterWithClosure_delegate, name);
1518                         Timer.StopTimer (TimerType.FindMembers);
1519                         used_cache = false;
1520                         return (MemberInfo []) list;
1521                 }
1522
1523                 //
1524                 // This call will always succeed.  There is exactly one TypeHandle instance per
1525                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1526                 // if it didn't already exist.
1527                 //
1528                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1529
1530                 used_cache = true;
1531                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1532         }
1533
1534         public static bool IsBuiltinType (Type t)
1535         {
1536                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1537                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1538                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1539                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1540                         return true;
1541                 else
1542                         return false;
1543         }
1544
1545         public static bool IsBuiltinType (TypeContainer tc)
1546         {
1547                 return IsBuiltinType (tc.TypeBuilder);
1548         }
1549
1550         //
1551         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1552         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1553         // 
1554         public static bool IsCLRType (Type t)
1555         {
1556                 if (t == object_type || t == int32_type || t == uint32_type ||
1557                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1558                     t == char_type || t == short_type || t == bool_type ||
1559                     t == sbyte_type || t == byte_type || t == ushort_type)
1560                         return true;
1561                 else
1562                         return false;
1563         }
1564
1565         public static bool IsDelegateType (Type t)
1566         {
1567                 if (t.IsGenericInstance)
1568                         t = t.GetGenericTypeDefinition ();
1569
1570                 if (t.IsSubclassOf (TypeManager.delegate_type))
1571                         return true;
1572                 else
1573                         return false;
1574         }
1575         
1576         public static bool IsEnumType (Type t)
1577         {
1578                 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1579                         return true;
1580                 else
1581                         return false;
1582         }
1583         public static bool IsBuiltinOrEnum (Type t)
1584         {
1585                 if (IsBuiltinType (t))
1586                         return true;
1587                 
1588                 if (IsEnumType (t))
1589                         return true;
1590
1591                 return false;
1592         }
1593
1594         //
1595         // Only a quick hack to get things moving, while real runtime support appears
1596         //
1597         public static bool IsGeneric (Type t)
1598         {
1599                 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1600
1601                 return ds.IsGeneric;
1602         }
1603
1604         public static bool HasGenericArguments (Type t)
1605         {
1606                 return GetNumberOfTypeArguments (t) > 0;
1607         }
1608
1609         public static int GetNumberOfTypeArguments (Type t)
1610         {
1611                 DeclSpace tc = LookupDeclSpace (t);
1612                 if (tc != null)
1613                         return tc.IsGeneric ? tc.CountTypeParameters : 0;
1614                 else
1615                         return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1616         }
1617
1618         public static Type[] GetTypeArguments (Type t)
1619         {
1620                 DeclSpace tc = LookupDeclSpace (t);
1621                 if (tc != null) {
1622                         if (!tc.IsGeneric)
1623                                 throw new InvalidOperationException ();
1624
1625                         TypeParameter[] tparam = tc.TypeParameters;
1626                         Type[] ret = new Type [tparam.Length];
1627                         for (int i = 0; i < tparam.Length; i++) {
1628                                 ret [i] = tparam [i].Type;
1629                                 if (ret [i] == null)
1630                                         throw new InternalErrorException ();
1631                         }
1632
1633                         return ret;
1634                 } else
1635                         return t.GetGenericArguments ();
1636         }
1637         
1638         //
1639         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1640         //
1641         public static bool IsUnmanagedType (Type t)
1642         {
1643                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1644                         return true;
1645
1646                 if (IsEnumType (t))
1647                         return true;
1648
1649                 if (t.IsPointer)
1650                         return true;
1651
1652                 if (IsValueType (t)){
1653                         if (t is TypeBuilder){
1654                                 TypeContainer tc = LookupTypeContainer (t);
1655
1656                                 if (tc.Fields != null){
1657                                 foreach (Field f in tc.Fields){
1658                                         if (f.FieldBuilder.IsStatic)
1659                                                 continue;
1660                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1661                                                 return false;
1662                                 }
1663                                 } else
1664                                         return true;
1665                         } else {
1666                                 FieldInfo [] fields = t.GetFields ();
1667
1668                                 foreach (FieldInfo f in fields){
1669                                         if (f.IsStatic)
1670                                                 continue;
1671                                         if (!IsUnmanagedType (f.FieldType))
1672                                                 return false;
1673                                 }
1674                         }
1675                         return true;
1676                 }
1677
1678                 return false;
1679         }
1680                 
1681         public static bool IsValueType (Type t)
1682         {
1683                 return t.IsGenericParameter || t.IsValueType;
1684         }
1685         
1686         public static bool IsInterfaceType (Type t)
1687         {
1688                 Interface iface = builder_to_declspace [t] as Interface;
1689
1690                 if (iface != null)
1691                         return true;
1692                 else
1693                         return false;
1694         }
1695
1696         public static bool IsEqualGenericType (Type a, Type b)
1697         {
1698                 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1699                         //
1700                         // `a' is a generic type definition's TypeBuilder and `b' is a
1701                         // generic instance of the same type.
1702                         //
1703                         // Example:
1704                         //
1705                         // class Stack<T>
1706                         // {
1707                         //     void Test (Stack<T> stack) { }
1708                         // }
1709                         //
1710                         // The first argument of `Test' will be the generic instance
1711                         // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1712                         //
1713                         if (a != b.GetGenericTypeDefinition ())
1714                                 return false;
1715
1716                         Type[] aparams = a.GetGenericArguments ();
1717                         Type[] bparams = b.GetGenericArguments ();
1718
1719                         if (aparams.Length != bparams.Length)
1720                                 return false;
1721
1722                         for (int i = 0; i < aparams.Length; i++)
1723                                 if (!aparams [i].Equals (bparams [i]))
1724                                         return false;
1725
1726                         return true;
1727                 }
1728
1729                 return false;
1730         }
1731
1732         public static bool IsEqual (Type a, Type b)
1733         {
1734                 if (a.Equals (b))
1735                         return true;
1736                 else
1737                         return IsEqualGenericType (a, b);
1738         }
1739
1740         public static bool MayBecomeEqualGenericTypes (Type a, Type b)
1741         {
1742                 if (a.IsGenericParameter) {
1743                         //
1744                         // If a is an array of a's type, they may never
1745                         // become equal.
1746                         //
1747                         while (b.IsArray) {
1748                                 b = b.GetElementType ();
1749                                 if (a.Equals (b))
1750                                         return false;
1751                         }
1752
1753                         //
1754                         // If b is a generic parameter or an actual type,
1755                         // they may become equal:
1756                         //
1757                         //    class X<T,U> : I<T>, I<U>
1758                         //    class X<T> : I<T>, I<float>
1759                         // 
1760                         if (b.IsGenericParameter || !b.IsGenericInstance)
1761                                 return true;
1762
1763                         //
1764                         // We're now comparing a type parameter with a
1765                         // generic instance.  They may become equal unless
1766                         // the type parameter appears anywhere in the
1767                         // generic instance:
1768                         //
1769                         //    class X<T,U> : I<T>, I<X<U>>
1770                         //        -> error because you could instanciate it as
1771                         //           X<X<int>,int>
1772                         //
1773                         //    class X<T> : I<T>, I<X<T>> -> ok
1774                         //
1775
1776                         Type[] bargs = GetTypeArguments (b);
1777                         for (int i = 0; i < bargs.Length; i++) {
1778                                 if (a.Equals (bargs [i]))
1779                                         return false;
1780                         }
1781
1782                         return true;
1783                 }
1784
1785                 if (b.IsGenericParameter)
1786                         return MayBecomeEqualGenericTypes (b, a);
1787
1788                 //
1789                 // At this point, neither a nor b are a type parameter.
1790                 //
1791                 // If one of them is a generic instance, let
1792                 // MayBecomeEqualGenericInstances() compare them (if the
1793                 // other one is not a generic instance, they can never
1794                 // become equal).
1795                 //
1796
1797                 if (a.IsGenericInstance || b.IsGenericInstance)
1798                         return MayBecomeEqualGenericInstances (a, b);
1799
1800                 //
1801                 // If both of them are arrays.
1802                 //
1803
1804                 if (a.IsArray && b.IsArray) {
1805                         if (a.GetArrayRank () != b.GetArrayRank ())
1806                                 return false;
1807                         
1808                         a = a.GetElementType ();
1809                         b = b.GetElementType ();
1810
1811                         return MayBecomeEqualGenericTypes (a, b);
1812                 }
1813
1814                 //
1815                 // Ok, two ordinary types.
1816                 //
1817
1818                 return a.Equals (b);
1819         }
1820
1821         //
1822         // Checks whether two generic instances may become equal for some
1823         // particular instantiation (26.3.1).
1824         //
1825         public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1826         {
1827                 if (!a.IsGenericInstance || !b.IsGenericInstance)
1828                         return false;
1829                 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1830                         return false;
1831
1832                 Type[] aargs = GetTypeArguments (a);
1833                 Type[] bargs = GetTypeArguments (b);
1834
1835                 if (aargs.Length != bargs.Length)
1836                         return false;
1837
1838                 for (int i = 0; i < aargs.Length; i++) {
1839                         if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1840                                 return true;
1841                 }
1842
1843                 return false;
1844         }
1845
1846         public static bool IsSubclassOf (Type type, Type parent)
1847         {
1848                 if (type.IsGenericInstance && !parent.IsGenericInstance)
1849                         type = type.GetGenericTypeDefinition ();
1850
1851                 return type.IsSubclassOf (parent);
1852         }
1853
1854         //
1855         // Checks whether `type' is a subclass or nested child of `parent'.
1856         //
1857         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1858         {
1859                 do {
1860                         if ((type == parent) || type.IsSubclassOf (parent) ||
1861                             IsEqualGenericType (type, parent))
1862                                 return true;
1863
1864                         // Handle nested types.
1865                         type = type.DeclaringType;
1866                 } while (type != null);
1867
1868                 return false;
1869         }
1870
1871         //
1872         // Checks whether `type' is a nested child of `parent'.
1873         //
1874         public static bool IsNestedChildOf (Type type, Type parent)
1875         {
1876                 if (type == parent)
1877                         return false;
1878
1879                 type = type.DeclaringType;
1880                 while (type != null) {
1881                         if (type == parent)
1882                                 return true;
1883
1884                         type = type.DeclaringType;
1885                 }
1886
1887                 return false;
1888         }
1889
1890         //
1891         // Do the right thing when returning the element type of an
1892         // array type based on whether we are compiling corlib or not
1893         //
1894         public static Type GetElementType (Type t)
1895         {
1896                 if (RootContext.StdLib)
1897                         return t.GetElementType ();
1898                 else
1899                         return TypeToCoreType (t.GetElementType ());
1900         }
1901
1902         /// <summary>
1903         ///   Returns the User Defined Types
1904         /// </summary>
1905         public static ArrayList UserTypes {
1906                 get {
1907                         return user_types;
1908                 }
1909         }
1910
1911         public static Hashtable TypeContainers {
1912                 get {
1913                         return typecontainers;
1914                 }
1915         }
1916
1917         static Hashtable builder_to_constant;
1918
1919         public static void RegisterConstant (FieldBuilder fb, Const c)
1920         {
1921                 if (builder_to_constant == null)
1922                         builder_to_constant = new PtrHashtable ();
1923
1924                 if (builder_to_constant.Contains (fb))
1925                         return;
1926
1927                 builder_to_constant.Add (fb, c);
1928         }
1929
1930         public static Const LookupConstant (FieldBuilder fb)
1931         {
1932                 if (builder_to_constant == null)
1933                         return null;
1934                 
1935                 return (Const) builder_to_constant [fb];
1936         }
1937         
1938         /// <summary>
1939         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1940         /// </summary>
1941         ///
1942         /// <remarks>
1943         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1944         ///   for anything which is dynamic, and we need this in a number of places,
1945         ///   we register this information here, and use it afterwards.
1946         /// </remarks>
1947         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1948         {
1949                 if (args == null)
1950                         args = NoTypes;
1951                                 
1952                 method_arguments.Add (mb, args);
1953                 method_internal_params.Add (mb, ip);
1954                 
1955                 return true;
1956         }
1957         
1958         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1959         {
1960                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1961                         return null;
1962                 
1963                 if (method_internal_params.Contains (mb))
1964                         return (InternalParameters) method_internal_params [mb];
1965                 else
1966                         throw new Exception ("Argument for Method not registered" + mb);
1967         }
1968
1969         /// <summary>
1970         ///    Returns the argument types for a method based on its methodbase
1971         ///
1972         ///    For dynamic methods, we use the compiler provided types, for
1973         ///    methods from existing assemblies we load them from GetParameters,
1974         ///    and insert them into the cache
1975         /// </summary>
1976         static public Type [] GetArgumentTypes (MethodBase mb)
1977         {
1978                 if (method_arguments.Contains (mb))
1979                         return (Type []) method_arguments [mb];
1980                 else {
1981                         ParameterInfo [] pi = mb.GetParameters ();
1982                         int c = pi.Length;
1983                         Type [] types = new Type [c];
1984                         
1985                         for (int i = 0; i < c; i++)
1986                                 types [i] = pi [i].ParameterType;
1987
1988                         method_arguments.Add (mb, types);
1989                         return types;
1990                 }
1991         }
1992
1993         /// <summary>
1994         ///    Returns the argument types for an indexer based on its PropertyInfo
1995         ///
1996         ///    For dynamic indexers, we use the compiler provided types, for
1997         ///    indexers from existing assemblies we load them from GetParameters,
1998         ///    and insert them into the cache
1999         /// </summary>
2000         static public Type [] GetArgumentTypes (PropertyInfo indexer)
2001         {
2002                 if (indexer_arguments.Contains (indexer))
2003                         return (Type []) indexer_arguments [indexer];
2004                 else if (indexer is PropertyBuilder)
2005                         // If we're a PropertyBuilder and not in the
2006                         // `indexer_arguments' hash, then we're a property and
2007                         // not an indexer.
2008                         return NoTypes;
2009                 else {
2010                         ParameterInfo [] pi = indexer.GetIndexParameters ();
2011                         // Property, not an indexer.
2012                         if (pi == null)
2013                                 return NoTypes;
2014                         int c = pi.Length;
2015                         Type [] types = new Type [c];
2016                         
2017                         for (int i = 0; i < c; i++)
2018                                 types [i] = pi [i].ParameterType;
2019
2020                         indexer_arguments.Add (indexer, types);
2021                         return types;
2022                 }
2023         }
2024         
2025         // <remarks>
2026         //  This is a workaround the fact that GetValue is not
2027         //  supported for dynamic types
2028         // </remarks>
2029         static Hashtable fields = new Hashtable ();
2030         static public bool RegisterFieldValue (FieldBuilder fb, object value)
2031         {
2032                 if (fields.Contains (fb))
2033                         return false;
2034
2035                 fields.Add (fb, value);
2036
2037                 return true;
2038         }
2039
2040         static public object GetValue (FieldBuilder fb)
2041         {
2042                 return fields [fb];
2043         }
2044
2045         static Hashtable fieldbuilders_to_fields = new Hashtable ();
2046         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2047         {
2048                 if (fieldbuilders_to_fields.Contains (fb))
2049                         return false;
2050
2051                 fieldbuilders_to_fields.Add (fb, f);
2052                 return true;
2053         }
2054
2055         //
2056         // The return value can be null;  This will be the case for
2057         // auxiliary FieldBuilders created by the compiler that have no
2058         // real field being declared on the source code
2059         //
2060         static public FieldBase GetField (FieldInfo fb)
2061         {
2062                 return (FieldBase) fieldbuilders_to_fields [fb];
2063         }
2064         
2065         static Hashtable events;
2066
2067         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2068         {
2069                 if (events == null)
2070                         events = new Hashtable ();
2071
2072                 if (events.Contains (eb))
2073                         return false;
2074
2075                 events.Add (eb, new Pair (add, remove));
2076
2077                 return true;
2078         }
2079
2080         static public MethodInfo GetAddMethod (EventInfo ei)
2081         {
2082                 if (ei is MyEventBuilder) {
2083                         Pair pair = (Pair) events [ei];
2084
2085                         return (MethodInfo) pair.First;
2086                 } else
2087                         return ei.GetAddMethod ();
2088         }
2089
2090         static public MethodInfo GetRemoveMethod (EventInfo ei)
2091         {
2092                 if (ei is MyEventBuilder) {
2093                         Pair pair = (Pair) events [ei];
2094
2095                         return (MethodInfo) pair.Second;
2096                 } else
2097                         return ei.GetRemoveMethod ();
2098         }
2099
2100         static Hashtable priv_fields_events;
2101
2102         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2103         {
2104                 if (priv_fields_events == null)
2105                         priv_fields_events = new Hashtable ();
2106
2107                 if (priv_fields_events.Contains (einfo))
2108                         return false;
2109
2110                 priv_fields_events.Add (einfo, builder);
2111
2112                 return true;
2113         }
2114
2115         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2116         {
2117                 if (priv_fields_events == null)
2118                         return null;
2119                 else
2120                         return (MemberInfo) priv_fields_events [ei];
2121         }
2122                 
2123         static Hashtable properties;
2124         
2125         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2126         {
2127                 if (properties == null)
2128                         properties = new Hashtable ();
2129
2130                 if (properties.Contains (pb))
2131                         return false;
2132
2133                 properties.Add (pb, new Pair (get, set));
2134
2135                 return true;
2136         }
2137
2138         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2139                                             MethodBase set, Type[] args)
2140         {
2141                 if (!RegisterProperty (pb, get,set))
2142                         return false;
2143
2144                 indexer_arguments.Add (pb, args);
2145
2146                 return true;
2147         }
2148
2149         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2150         {
2151                 Hashtable hash = new Hashtable ();
2152                 return CheckStructCycles (tc, seen, hash);
2153         }
2154
2155         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2156                                               Hashtable hash)
2157         {
2158                 if (!(tc is Struct) || IsBuiltinType (tc))
2159                         return true;
2160
2161                 //
2162                 // `seen' contains all types we've already visited.
2163                 //
2164                 if (seen.Contains (tc))
2165                         return true;
2166                 seen.Add (tc, null);
2167
2168                 if (tc.Fields == null)
2169                         return true;
2170
2171                 foreach (Field field in tc.Fields) {
2172                         if (field.FieldBuilder.IsStatic)
2173                                 continue;
2174
2175                         Type ftype = field.FieldBuilder.FieldType;
2176                         TypeContainer ftc = LookupTypeContainer (ftype);
2177                         if (ftc == null)
2178                                 continue;
2179
2180                         if (hash.Contains (ftc)) {
2181                                 Report.Error (523, tc.Location,
2182                                               "Struct member `{0}.{1}' of type `{2}' " +
2183                                               "causes a cycle in the struct layout",
2184                                               tc.Name, field.Name, ftc.Name);
2185                                 return false;
2186                         }
2187
2188                         //
2189                         // `hash' contains all types in the current path.
2190                         //
2191                         hash.Add (tc, null);
2192
2193                         bool ok = CheckStructCycles (ftc, seen, hash);
2194
2195                         hash.Remove (tc);
2196
2197                         if (!ok)
2198                                 return false;
2199
2200                         if (!seen.Contains (ftc))
2201                                 seen.Add (ftc, null);
2202                 }
2203
2204                 return true;
2205         }
2206
2207         /// <summary>
2208         ///   Given an array of interface types, expand and eliminate repeated ocurrences
2209         ///   of an interface.  
2210         /// </summary>
2211         ///
2212         /// <remarks>
2213         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2214         ///   be IA, IB, IC.
2215         /// </remarks>
2216         public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
2217         {
2218                 ArrayList new_ifaces = new ArrayList ();
2219                 
2220                 foreach (TypeExpr iface in base_interfaces){
2221                         if (!new_ifaces.Contains (iface))
2222                                 new_ifaces.Add (iface);
2223                         
2224                         TypeExpr [] implementing = iface.GetInterfaces ();
2225                         
2226                         foreach (TypeExpr imp in implementing){
2227                                 if (!new_ifaces.Contains (imp))
2228                                         new_ifaces.Add (imp);
2229                         }
2230                 }
2231                 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
2232                 new_ifaces.CopyTo (ret, 0);
2233                 return ret;
2234         }
2235                 
2236         static PtrHashtable iface_cache = new PtrHashtable ();
2237                 
2238         /// <summary>
2239         ///   This function returns the interfaces in the type `t'.  Works with
2240         ///   both types and TypeBuilders.
2241         /// </summary>
2242         public static TypeExpr [] GetInterfaces (Type t)
2243         {
2244                 
2245                 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
2246                 if (cached != null)
2247                         return cached;
2248                 
2249                 //
2250                 // The reason for catching the Array case is that Reflection.Emit
2251                 // will not return a TypeBuilder for Array types of TypeBuilder types,
2252                 // but will still throw an exception if we try to call GetInterfaces
2253                 // on the type.
2254                 //
2255                 // Since the array interfaces are always constant, we return those for
2256                 // the System.Array
2257                 //
2258                 
2259                 if (t.IsArray)
2260                         t = TypeManager.array_type;
2261                 
2262                 if (t is TypeBuilder){
2263                         TypeExpr [] parent_ifaces;
2264                         
2265                         if (t.BaseType == null)
2266                                 parent_ifaces = NoTypeExprs;
2267                         else
2268                                 parent_ifaces = GetInterfaces (t.BaseType);
2269                         TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2270                         if (type_ifaces == null)
2271                                 type_ifaces = NoTypeExprs;
2272
2273                         int parent_count = parent_ifaces.Length;
2274                         TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2275                         parent_ifaces.CopyTo (result, 0);
2276                         type_ifaces.CopyTo (result, parent_count);
2277
2278                         iface_cache [t] = result;
2279                         return result;
2280                 } else if (t is GenericTypeParameterBuilder){
2281                         TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2282                         if (type_ifaces == null)
2283                                 type_ifaces = NoTypeExprs;
2284
2285                         iface_cache [t] = type_ifaces;
2286                         return type_ifaces;
2287                 } else {
2288                         Type [] ifaces = t.GetInterfaces ();
2289                         if (ifaces.Length == 0)
2290                                 return NoTypeExprs;
2291
2292                         TypeExpr [] result = new TypeExpr [ifaces.Length];
2293                         for (int i = 0; i < ifaces.Length; i++)
2294                                 result [i] = new TypeExpression (ifaces [i], Location.Null);
2295                         
2296                         iface_cache [t] = result;
2297                         return result;
2298                 }
2299         }
2300         
2301         //
2302         // gets the interfaces that are declared explicitly on t
2303         //
2304         public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2305         {
2306                 return (TypeExpr []) builder_to_ifaces [t];
2307         }
2308         
2309         /// <remarks>
2310         ///  The following is used to check if a given type implements an interface.
2311         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2312         /// </remarks>
2313         public static bool ImplementsInterface (Type t, Type iface)
2314         {
2315                 TypeExpr [] interfaces;
2316
2317                 //
2318                 // FIXME OPTIMIZATION:
2319                 // as soon as we hit a non-TypeBuiler in the interface
2320                 // chain, we could return, as the `Type.GetInterfaces'
2321                 // will return all the interfaces implement by the type
2322                 // or its parents.
2323                 //
2324                 do {
2325                         interfaces = GetInterfaces (t);
2326
2327                         if (interfaces != null){
2328                                 foreach (TypeExpr i in interfaces){
2329                                         if (i.Type == iface)
2330                                                 return true;
2331                                 }
2332                         }
2333                         
2334                         t = t.BaseType;
2335                 } while (t != null);
2336                 
2337                 return false;
2338         }
2339
2340         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2341
2342         // This is a custom version of Convert.ChangeType() which works
2343         // with the TypeBuilder defined types when compiling corlib.
2344         public static object ChangeType (object value, Type conversionType, out bool error)
2345         {
2346                 IConvertible convert_value = value as IConvertible;
2347                 
2348                 if (convert_value == null){
2349                         error = true;
2350                         return null;
2351                 }
2352                 
2353                 //
2354                 // We must use Type.Equals() here since `conversionType' is
2355                 // the TypeBuilder created version of a system type and not
2356                 // the system type itself.  You cannot use Type.GetTypeCode()
2357                 // on such a type - it'd always return TypeCode.Object.
2358                 //
2359                 error = false;
2360                 try {
2361                         if (conversionType.Equals (typeof (Boolean)))
2362                                 return (object)(convert_value.ToBoolean (nf_provider));
2363                         else if (conversionType.Equals (typeof (Byte)))
2364                                 return (object)(convert_value.ToByte (nf_provider));
2365                         else if (conversionType.Equals (typeof (Char)))
2366                                 return (object)(convert_value.ToChar (nf_provider));
2367                         else if (conversionType.Equals (typeof (DateTime)))
2368                                 return (object)(convert_value.ToDateTime (nf_provider));
2369                         else if (conversionType.Equals (typeof (Decimal)))
2370                                 return (object)(convert_value.ToDecimal (nf_provider));
2371                         else if (conversionType.Equals (typeof (Double)))
2372                                 return (object)(convert_value.ToDouble (nf_provider));
2373                         else if (conversionType.Equals (typeof (Int16)))
2374                                 return (object)(convert_value.ToInt16 (nf_provider));
2375                         else if (conversionType.Equals (typeof (Int32)))
2376                                 return (object)(convert_value.ToInt32 (nf_provider));
2377                         else if (conversionType.Equals (typeof (Int64)))
2378                                 return (object)(convert_value.ToInt64 (nf_provider));
2379                         else if (conversionType.Equals (typeof (SByte)))
2380                                 return (object)(convert_value.ToSByte (nf_provider));
2381                         else if (conversionType.Equals (typeof (Single)))
2382                                 return (object)(convert_value.ToSingle (nf_provider));
2383                         else if (conversionType.Equals (typeof (String)))
2384                                 return (object)(convert_value.ToString (nf_provider));
2385                         else if (conversionType.Equals (typeof (UInt16)))
2386                                 return (object)(convert_value.ToUInt16 (nf_provider));
2387                         else if (conversionType.Equals (typeof (UInt32)))
2388                                 return (object)(convert_value.ToUInt32 (nf_provider));
2389                         else if (conversionType.Equals (typeof (UInt64)))
2390                                 return (object)(convert_value.ToUInt64 (nf_provider));
2391                         else if (conversionType.Equals (typeof (Object)))
2392                                 return (object)(value);
2393                         else 
2394                                 error = true;
2395                 } catch {
2396                         error = true;
2397                 }
2398                 return null;
2399         }
2400
2401         //
2402         // This is needed, because enumerations from assemblies
2403         // do not report their underlyingtype, but they report
2404         // themselves
2405         //
2406         public static Type EnumToUnderlying (Type t)
2407         {
2408                 if (t == TypeManager.enum_type)
2409                         return t;
2410
2411                 t = t.UnderlyingSystemType;
2412                 if (!TypeManager.IsEnumType (t))
2413                         return t;
2414         
2415                 if (t is TypeBuilder) {
2416                         // slow path needed to compile corlib
2417                         if (t == TypeManager.bool_type ||
2418                                         t == TypeManager.byte_type ||
2419                                         t == TypeManager.sbyte_type ||
2420                                         t == TypeManager.char_type ||
2421                                         t == TypeManager.short_type ||
2422                                         t == TypeManager.ushort_type ||
2423                                         t == TypeManager.int32_type ||
2424                                         t == TypeManager.uint32_type ||
2425                                         t == TypeManager.int64_type ||
2426                                         t == TypeManager.uint64_type)
2427                                 return t;
2428                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2429                 }
2430                 TypeCode tc = Type.GetTypeCode (t);
2431
2432                 switch (tc){
2433                 case TypeCode.Boolean:
2434                         return TypeManager.bool_type;
2435                 case TypeCode.Byte:
2436                         return TypeManager.byte_type;
2437                 case TypeCode.SByte:
2438                         return TypeManager.sbyte_type;
2439                 case TypeCode.Char:
2440                         return TypeManager.char_type;
2441                 case TypeCode.Int16:
2442                         return TypeManager.short_type;
2443                 case TypeCode.UInt16:
2444                         return TypeManager.ushort_type;
2445                 case TypeCode.Int32:
2446                         return TypeManager.int32_type;
2447                 case TypeCode.UInt32:
2448                         return TypeManager.uint32_type;
2449                 case TypeCode.Int64:
2450                         return TypeManager.int64_type;
2451                 case TypeCode.UInt64:
2452                         return TypeManager.uint64_type;
2453                 }
2454                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2455         }
2456
2457         //
2458         // When compiling corlib and called with one of the core types, return
2459         // the corresponding typebuilder for that type.
2460         //
2461         public static Type TypeToCoreType (Type t)
2462         {
2463                 if (RootContext.StdLib || (t is TypeBuilder))
2464                         return t;
2465
2466                 TypeCode tc = Type.GetTypeCode (t);
2467
2468                 switch (tc){
2469                 case TypeCode.Boolean:
2470                         return TypeManager.bool_type;
2471                 case TypeCode.Byte:
2472                         return TypeManager.byte_type;
2473                 case TypeCode.SByte:
2474                         return TypeManager.sbyte_type;
2475                 case TypeCode.Char:
2476                         return TypeManager.char_type;
2477                 case TypeCode.Int16:
2478                         return TypeManager.short_type;
2479                 case TypeCode.UInt16:
2480                         return TypeManager.ushort_type;
2481                 case TypeCode.Int32:
2482                         return TypeManager.int32_type;
2483                 case TypeCode.UInt32:
2484                         return TypeManager.uint32_type;
2485                 case TypeCode.Int64:
2486                         return TypeManager.int64_type;
2487                 case TypeCode.UInt64:
2488                         return TypeManager.uint64_type;
2489                 case TypeCode.Single:
2490                         return TypeManager.float_type;
2491                 case TypeCode.Double:
2492                         return TypeManager.double_type;
2493                 case TypeCode.String:
2494                         return TypeManager.string_type;
2495                 default:
2496                         if (t == typeof (void))
2497                                 return TypeManager.void_type;
2498                         if (t == typeof (object))
2499                                 return TypeManager.object_type;
2500                         if (t == typeof (System.Type))
2501                                 return TypeManager.type_type;
2502                         if (t == typeof (System.IntPtr))
2503                                 return TypeManager.intptr_type;
2504                         return t;
2505                 }
2506         }
2507
2508         /// <summary>
2509         ///   Utility function that can be used to probe whether a type
2510         ///   is managed or not.  
2511         /// </summary>
2512         public static bool VerifyUnManaged (Type t, Location loc)
2513         {
2514                 if (t.IsValueType || t.IsPointer){
2515                         //
2516                         // FIXME: this is more complex, we actually need to
2517                         // make sure that the type does not contain any
2518                         // classes itself
2519                         //
2520                         return true;
2521                 }
2522
2523                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2524                         // We need this explicit check here to make it work when
2525                         // compiling corlib.
2526                         return true;
2527
2528                 Report.Error (
2529                         208, loc,
2530                         "Cannot take the address or size of a variable of a managed type ('" +
2531                         CSharpName (t) + "')");
2532                 return false;   
2533         }
2534         
2535         /// <summary>
2536         ///   Returns the name of the indexer in a given type.
2537         /// </summary>
2538         /// <remarks>
2539         ///   The default is not always `Item'.  The user can change this behaviour by
2540         ///   using the DefaultMemberAttribute in the class.
2541         ///
2542         ///   For example, the String class indexer is named `Chars' not `Item' 
2543         /// </remarks>
2544         public static string IndexerPropertyName (Type t)
2545         {
2546                 if (t.IsGenericInstance)
2547                         t = t.GetGenericTypeDefinition ();
2548
2549                 if (t is TypeBuilder) {
2550                         if (t.IsInterface) {
2551                                 Interface i = LookupInterface (t);
2552
2553                                 if ((i == null) || (i.IndexerName == null))
2554                                         return "Item";
2555
2556                                 return i.IndexerName;
2557                         } else {
2558                                 TypeContainer tc = LookupTypeContainer (t);
2559
2560                                 if ((tc == null) || (tc.IndexerName == null))
2561                                         return "Item";
2562
2563                                 return tc.IndexerName;
2564                         }
2565                 }
2566                 
2567                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2568                         t, TypeManager.default_member_type);
2569                 if (attr != null){
2570                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2571                         return dma.MemberName;
2572                 }
2573
2574                 return "Item";
2575         }
2576
2577         static MethodInfo pinned_method = null;
2578         public static void MakePinned (LocalBuilder builder)
2579         {
2580                 if (pinned_method == null) {
2581                         pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
2582                         if (pinned_method == null) {
2583                                 Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
2584                                         "This code may cause errors on a runtime with a moving GC");
2585                                 
2586                                 return;
2587                         }
2588                 }
2589                 
2590                 pinned_method.Invoke (builder, null);
2591         }
2592
2593
2594         //
2595         // Returns whether the array of memberinfos contains the given method
2596         //
2597         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2598         {
2599                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2600                 
2601                 foreach (MethodBase method in array) {
2602                         if (method.Name != new_method.Name)
2603                                 continue;
2604
2605                         if (method is MethodInfo && new_method is MethodInfo)
2606                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2607                                         continue;
2608
2609                         
2610                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2611                         int old_count = old_args.Length;
2612                         int i;
2613                         
2614                         if (new_args.Length != old_count)
2615                                 continue;
2616                         
2617                         for (i = 0; i < old_count; i++){
2618                                 if (old_args [i] != new_args [i])
2619                                         break;
2620                         }
2621                         if (i != old_count)
2622                                 continue;
2623
2624                         return true;
2625                 }
2626                 
2627                 return false;
2628         }
2629         
2630         //
2631         // We copy methods from `new_members' into `target_list' if the signature
2632         // for the method from in the new list does not exist in the target_list
2633         //
2634         // The name is assumed to be the same.
2635         //
2636         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2637         {
2638                 if (target_list == null){
2639                         target_list = new ArrayList ();
2640
2641                         foreach (MemberInfo mi in new_members){
2642                                 if (mi is MethodBase)
2643                                         target_list.Add (mi);
2644                         }
2645                         return target_list;
2646                 }
2647                 
2648                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2649                 target_list.CopyTo (target_array, 0);
2650                 
2651                 foreach (MemberInfo mi in new_members){
2652                         MethodBase new_method = (MethodBase) mi;
2653                         
2654                         if (!ArrayContainsMethod (target_array, new_method))
2655                                 target_list.Add (new_method);
2656                 }
2657                 return target_list;
2658         }
2659
2660         static public bool IsGenericMethod (MethodBase mb)
2661         {
2662                 if (mb.DeclaringType is TypeBuilder) {
2663                         IMethodData method = (IMethodData) builder_to_method [mb];
2664                         if (method == null)
2665                                 return false;
2666
2667                         return method.GenericMethod != null;
2668                 }
2669
2670                 return mb.IsGenericMethodDefinition;
2671         }
2672         
2673 #region MemberLookup implementation
2674         
2675         //
2676         // Whether we allow private members in the result (since FindMembers
2677         // uses NonPublic for both protected and private), we need to distinguish.
2678         //
2679
2680         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2681         {
2682                 return true;
2683         }
2684
2685         internal class Closure {
2686                 internal bool     private_ok;
2687
2688         // Who is invoking us and which type is being queried currently.
2689                 internal Type     invocation_type;
2690                 internal Type     qualifier_type;
2691
2692         // The assembly that defines the type is that is calling us
2693                 internal Assembly invocation_assembly;
2694                 internal IList almost_match;
2695
2696                 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2697         {
2698                         if (invocation_type == null)
2699                                 return false;
2700
2701                         Debug.Assert (IsSubclassOrNestedChildOf (invocation_type, m.DeclaringType));
2702
2703                         if (is_static)
2704                                 return true;
2705                         
2706                         // A nested class has access to all the protected members visible to its parent.
2707                         if (qualifier_type != null
2708                             && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2709                                 return true;
2710
2711                         if (invocation_type == m.DeclaringType
2712                             || invocation_type.IsSubclassOf (m.DeclaringType)) {
2713                                 // Although a derived class can access protected members of its base class
2714                                 // it cannot do so through an instance of the base class (CS1540).
2715                                 // => Ancestry should be: declaring_type ->* invocation_type ->*  qualified_type
2716                                 if (qualifier_type == null
2717                                     || qualifier_type == invocation_type
2718                                     || qualifier_type.IsSubclassOf (invocation_type))
2719                 return true;
2720         }
2721         
2722                         if (almost_match != null)
2723                                 almost_match.Add (m);
2724                         return false;
2725                 }
2726                 
2727         //
2728         // This filter filters by name + whether it is ok to include private
2729         // members in the search
2730         //
2731                 internal bool Filter (MemberInfo m, object filter_criteria)
2732         {
2733                 //
2734                 // Hack: we know that the filter criteria will always be in the `closure'
2735                 // fields. 
2736                 //
2737
2738                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2739                         return false;
2740
2741                 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2742                     (invocation_type != null) && IsEqual (m.DeclaringType, invocation_type))
2743                         return true;
2744
2745                 //
2746                 // Ugly: we need to find out the type of `m', and depending
2747                 // on this, tell whether we accept or not
2748                 //
2749                 if (m is MethodBase){
2750                         MethodBase mb = (MethodBase) m;
2751                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2752
2753                         if (ma == MethodAttributes.Private)
2754                                 return private_ok ||
2755                                         IsEqual (invocation_type, m.DeclaringType) ||
2756                                         IsNestedChildOf (invocation_type, m.DeclaringType);
2757
2758                         //
2759                         // FamAndAssem requires that we not only derivate, but we are on the
2760                         // same assembly.  
2761                         //
2762                         if (ma == MethodAttributes.FamANDAssem){
2763                                 if (invocation_assembly != mb.DeclaringType.Assembly)
2764                                         return false;
2765                         }
2766
2767                         // Assembly and FamORAssem succeed if we're in the same assembly.
2768                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2769                                 if (invocation_assembly == mb.DeclaringType.Assembly)
2770                                         return true;
2771                         }
2772
2773                         // We already know that we aren't in the same assembly.
2774                         if (ma == MethodAttributes.Assembly)
2775                                 return false;
2776
2777                         // Family and FamANDAssem require that we derive.
2778                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2779                                 if (invocation_type == null)
2780                                         return false;
2781
2782                                 if (!IsSubclassOrNestedChildOf (invocation_type, mb.DeclaringType))
2783                                         return false;
2784
2785                                 // Although a derived class can access protected members of its base class
2786                                 // it cannot do so through an instance of the base class (CS1540).
2787                                 if (!mb.IsStatic && (invocation_type != qualifier_type) &&
2788                                     (qualifier_type != null) &&
2789                                     invocation_type.IsSubclassOf (qualifier_type) &&
2790                                     !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2791                                         return false;
2792
2793                                 return true;
2794                         }
2795
2796                         // Public.
2797                         return true;
2798                 }
2799
2800                 if (m is FieldInfo){
2801                         FieldInfo fi = (FieldInfo) m;
2802                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2803
2804                         if (fa == FieldAttributes.Private)
2805                                 return private_ok ||
2806                                         IsEqual (invocation_type, m.DeclaringType) ||
2807                                         IsNestedChildOf (invocation_type, m.DeclaringType);
2808
2809                         //
2810                         // FamAndAssem requires that we not only derivate, but we are on the
2811                         // same assembly.  
2812                         //
2813                         if (fa == FieldAttributes.FamANDAssem){
2814                                 if (invocation_assembly != fi.DeclaringType.Assembly)
2815                                         return false;
2816                         }
2817
2818                         // Assembly and FamORAssem succeed if we're in the same assembly.
2819                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2820                                 if (invocation_assembly == fi.DeclaringType.Assembly)
2821                                         return true;
2822                         }
2823
2824                         // We already know that we aren't in the same assembly.
2825                         if (fa == FieldAttributes.Assembly)
2826                                 return false;
2827
2828                         // Family and FamANDAssem require that we derive.
2829                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2830                                 if (invocation_type == null)
2831                                         return false;
2832
2833                                 if (!IsSubclassOrNestedChildOf (invocation_type, fi.DeclaringType))
2834                                         return false;
2835
2836                                 // Although a derived class can access protected members of its base class
2837                                 // it cannot do so through an instance of the base class (CS1540).
2838                                 if (!fi.IsStatic && (invocation_type != qualifier_type) &&
2839                                     (qualifier_type != null) &&
2840                                     invocation_type.IsSubclassOf (qualifier_type) &&
2841                                     !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2842                                         return false;
2843
2844                                 return true;
2845                         }
2846
2847                         // Public.
2848                         return true;
2849                 }
2850
2851                 //
2852                 // EventInfos and PropertyInfos, return true because they lack permission
2853                         // information, so we need to check later on the methods.
2854                 //
2855                 return true;
2856         }
2857         }
2858
2859         static Closure closure = new Closure ();
2860         static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2861         static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2862
2863         //
2864         // Looks up a member called `name' in the `queried_type'.  This lookup
2865         // is done by code that is contained in the definition for `invocation_type'
2866         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2867         //
2868         // `invocation_type' is used to check whether we're allowed to access the requested
2869         // member wrt its protection level.
2870         //
2871         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2872         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2873         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2874         //
2875         // When resolving a SimpleName, `qualifier_type' is null.
2876         //
2877         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2878         // the same than `queried_type' - except when we're being called from BaseAccess;
2879         // in this case, `invocation_type' is the current type and `queried_type' the base
2880         // type, so this'd normally trigger a CS1540.
2881         //
2882         // The binding flags are `bf' and the kind of members being looked up are `mt'
2883         //
2884         // The return value always includes private members which code in `invocation_type'
2885         // is allowed to access (using the specified `qualifier_type' if given); only use
2886         // BindingFlags.NonPublic to bypass the permission check.
2887         //
2888         // The 'almost_match' argument is used for reporting error CS1540.
2889         //
2890         // Returns an array of a single element for everything but Methods/Constructors
2891         // that might return multiple matches.
2892         //
2893         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2894                                                   Type queried_type, MemberTypes mt,
2895                                                   BindingFlags original_bf, string name, IList almost_match)
2896         {
2897                 Timer.StartTimer (TimerType.MemberLookup);
2898
2899                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2900                                                         queried_type, mt, original_bf, name, almost_match);
2901
2902                 Timer.StopTimer (TimerType.MemberLookup);
2903
2904                 return retval;
2905         }
2906
2907         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2908                                                Type queried_type, MemberTypes mt,
2909                                                BindingFlags original_bf, string name, IList almost_match)
2910         {
2911                 BindingFlags bf = original_bf;
2912                 
2913                 ArrayList method_list = null;
2914                 Type current_type = queried_type;
2915                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2916                 bool skip_iface_check = true, used_cache = false;
2917                 bool always_ok_flag = false;
2918
2919                 closure.invocation_type = invocation_type;
2920                 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2921                 closure.qualifier_type = qualifier_type;
2922                 closure.almost_match = almost_match;
2923
2924                 //
2925                 // If we are a nested class, we always have access to our container
2926                 // type names
2927                 //
2928                 if (invocation_type != null){
2929                         string invocation_name = invocation_type.FullName;
2930                         if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
2931                                 string container = queried_type.FullName + "+";
2932                                 int container_length = container.Length;
2933
2934                                 if (invocation_name.Length > container_length){
2935                                         string shared = invocation_name.Substring (0, container_length);
2936                                 
2937                                         if (shared == container)
2938                                                 always_ok_flag = true;
2939                                 }
2940                         }
2941                 }
2942                 
2943                 // This is from the first time we find a method
2944                 // in most cases, we do not actually find a method in the base class
2945                 // so we can just ignore it, and save the arraylist allocation
2946                 MemberInfo [] first_members_list = null;
2947                 bool use_first_members_list = false;
2948                 
2949                 do {
2950                         MemberInfo [] list;
2951
2952                         //
2953                         // `NonPublic' is lame, because it includes both protected and
2954                         // private methods, so we need to control this behavior by
2955                         // explicitly tracking if a private method is ok or not.
2956                         //
2957                         // The possible cases are:
2958                         //    public, private and protected (internal does not come into the
2959                         //    equation)
2960                         //
2961                         if ((invocation_type != null) &&
2962                             ((invocation_type == current_type) ||
2963                              IsNestedChildOf (invocation_type, current_type)) ||
2964                             always_ok_flag)
2965                                 bf = original_bf | BindingFlags.NonPublic;
2966                         else
2967                                 bf = original_bf;
2968
2969                         closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2970
2971                         Timer.StopTimer (TimerType.MemberLookup);
2972
2973                         list = MemberLookup_FindMembers (
2974                                 current_type, mt, bf, name, out used_cache);
2975
2976                         Timer.StartTimer (TimerType.MemberLookup);
2977
2978                         //
2979                         // When queried for an interface type, the cache will automatically check all
2980                         // inherited members, so we don't need to do this here.  However, this only
2981                         // works if we already used the cache in the first iteration of this loop.
2982                         //
2983                         // If we used the cache in any further iteration, we can still terminate the
2984                         // loop since the cache always looks in all parent classes.
2985                         //
2986
2987                         if (used_cache)
2988                                 searching = false;
2989                         else
2990                                 skip_iface_check = false;
2991
2992                         if (current_type == TypeManager.object_type)
2993                                 searching = false;
2994                         else {
2995                                 current_type = current_type.BaseType;
2996                                 
2997                                 //
2998                                 // This happens with interfaces, they have a null
2999                                 // basetype.  Look members up in the Object class.
3000                                 //
3001                                 if (current_type == null)
3002                                         current_type = TypeManager.object_type;
3003                         }
3004                         
3005                         if (list.Length == 0)
3006                                 continue;
3007
3008                         //
3009                         // Events and types are returned by both `static' and `instance'
3010                         // searches, which means that our above FindMembers will
3011                         // return two copies of the same.
3012                         //
3013                         if (list.Length == 1 && !(list [0] is MethodBase)){
3014                                 return list;
3015                         }
3016
3017                         //
3018                         // Multiple properties: we query those just to find out the indexer
3019                         // name
3020                         //
3021                         if (list [0] is PropertyInfo)
3022                                 return list;
3023
3024                         //
3025                         // We found an event: the cache lookup returns both the event and
3026                         // its private field.
3027                         //
3028                         if (list [0] is EventInfo) {
3029                                 if ((list.Length == 2) && (list [1] is FieldInfo))
3030                                         return new MemberInfo [] { list [0] };
3031
3032                                 // Oooops
3033                                 return null;
3034                         }
3035
3036                         //
3037                         // We found methods, turn the search into "method scan"
3038                         // mode.
3039                         //
3040
3041                         if (first_members_list != null) {
3042                                 if (use_first_members_list) {
3043                                         method_list = CopyNewMethods (method_list, first_members_list);
3044                                         use_first_members_list = false;
3045                                 }
3046                                 
3047                                 method_list = CopyNewMethods (method_list, list);
3048                         } else {
3049                                 first_members_list = list;
3050                                 use_first_members_list = true;
3051
3052                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3053                         }
3054                 } while (searching);
3055
3056                 if (use_first_members_list) {
3057                         foreach (MemberInfo mi in first_members_list) {
3058                                 if (! (mi is MethodBase)) {
3059                                         method_list = CopyNewMethods (method_list, first_members_list);
3060                                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3061                                 }
3062                         }
3063                         return (MemberInfo []) first_members_list;
3064                 }
3065
3066                 if (method_list != null && method_list.Count > 0) {
3067                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3068                 }
3069                 //
3070                 // This happens if we already used the cache in the first iteration, in this case
3071                 // the cache already looked in all interfaces.
3072                 //
3073                 if (skip_iface_check)
3074                         return null;
3075
3076                 //
3077                 // Interfaces do not list members they inherit, so we have to
3078                 // scan those.
3079                 // 
3080                 if (!queried_type.IsInterface)
3081                         return null;
3082
3083                 if (queried_type.IsArray)
3084                         queried_type = TypeManager.array_type;
3085                 
3086                 TypeExpr [] ifaces = GetInterfaces (queried_type);
3087                 if (ifaces == null)
3088                         return null;
3089                 
3090                 foreach (TypeExpr itype in ifaces){
3091                         MemberInfo [] x;
3092
3093                         x = MemberLookup (null, null, itype.Type, mt, bf, name, null);
3094                         if (x != null)
3095                                 return x;
3096                 }
3097                                         
3098                 return null;
3099         }
3100
3101         //
3102         // This is used to extract properties and event declarations from a type
3103         //
3104         static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
3105         {
3106                 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
3107
3108                 bf |= BindingFlags.Public | BindingFlags.NonPublic;
3109                 
3110                 if (t is TypeBuilder) {
3111                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
3112
3113                         return (MemberInfo []) decl.FindMembers (
3114                                 MemberTypes.Property | MemberTypes.Event,
3115                                 bf, FilterNone_delegate, null);
3116                 } else {
3117                         return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
3118                                               bf, FilterNone_delegate, null);
3119
3120                 }
3121         }
3122         
3123         public static bool IsSpecialMethod (MethodBase mb)
3124         {
3125                 Type t = mb.DeclaringType;
3126                 
3127                 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
3128                 if (matches == null)
3129                         return false;
3130                 
3131                 foreach (MemberInfo mi in matches){
3132                         if (mi is PropertyBuilder){
3133                                 Pair p = (Pair) properties [mi];
3134
3135                                 if (p.First == mb || p.Second == mb)
3136                                         return true;
3137                         } else if (mi is PropertyInfo){
3138                                 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
3139                                 
3140                                 foreach (MethodInfo m in methods){
3141                                         if (m == mb)
3142                                                 return true;
3143                                 }
3144                         } else if (mi is MyEventBuilder){
3145                                 Pair p = (Pair) events [mi];
3146
3147                                 if (p.First == mb || p.Second == mb)
3148                                         return true;
3149                         } else if (mi is EventInfo){
3150                                 EventInfo ei = ((EventInfo) mi);
3151                                 
3152                                 if (ei.GetAddMethod (true) == mb)
3153                                         return true;
3154                                 
3155                                 if (ei.GetRemoveMethod (true) == mb)
3156                                         return true;
3157                                 
3158                                 if (ei.GetRaiseMethod (true) == mb)
3159                                         return true;
3160                         }
3161                 }
3162
3163                 //
3164                 // Now check if it is an operator method
3165                 //
3166                 string s = mb.Name;
3167
3168                 if (s.StartsWith ("op_")){
3169                         foreach (string name in Unary.oper_names){
3170                                 if (s == name)
3171                                         return true;
3172                         }
3173
3174                         foreach (string name in Binary.oper_names){
3175                                 if (s == name)
3176                                         return true;
3177                         }
3178                 }
3179                 
3180                 return false;
3181         }
3182                 
3183 #endregion
3184         
3185 }
3186
3187 /// <summary>
3188 ///   There is exactly one instance of this class per type.
3189 /// </summary>
3190 public sealed class TypeHandle : IMemberContainer {
3191         public readonly TypeHandle BaseType;
3192
3193         readonly int id = ++next_id;
3194         static int next_id = 0;
3195
3196         /// <summary>
3197         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
3198         ///   a TypeHandle yet, a new instance of it is created.  This static method
3199         ///   ensures that we'll only have one TypeHandle instance per type.
3200         /// </summary>
3201         public static TypeHandle GetTypeHandle (Type t)
3202         {
3203                 TypeHandle handle = (TypeHandle) type_hash [t];
3204                 if (handle != null)
3205                         return handle;
3206
3207                 handle = new TypeHandle (t);
3208                 type_hash.Add (t, handle);
3209                 return handle;
3210         }
3211         
3212         public static void CleanUp ()
3213         {
3214                 type_hash = null;
3215         }
3216
3217         /// <summary>
3218         ///   Returns the TypeHandle for TypeManager.object_type.
3219         /// </summary>
3220         public static IMemberContainer ObjectType {
3221                 get {
3222                         if (object_type != null)
3223                                 return object_type;
3224
3225                         object_type = GetTypeHandle (TypeManager.object_type);
3226
3227                         return object_type;
3228                 }
3229         }
3230
3231         /// <summary>
3232         ///   Returns the TypeHandle for TypeManager.array_type.
3233         /// </summary>
3234         public static IMemberContainer ArrayType {
3235                 get {
3236                         if (array_type != null)
3237                                 return array_type;
3238
3239                         array_type = GetTypeHandle (TypeManager.array_type);
3240
3241                         return array_type;
3242                 }
3243         }
3244
3245         private static PtrHashtable type_hash = new PtrHashtable ();
3246
3247         private static TypeHandle object_type = null;
3248         private static TypeHandle array_type = null;
3249
3250         private Type type;
3251         private string full_name;
3252         private bool is_interface;
3253         private MemberCache member_cache;
3254
3255         private TypeHandle (Type type)
3256         {
3257                 this.type = type;
3258                 full_name = type.FullName != null ? type.FullName : type.Name;
3259                 if (type.BaseType != null)
3260                         BaseType = GetTypeHandle (type.BaseType);
3261                 this.is_interface = type.IsInterface || type.IsGenericParameter;
3262                 this.member_cache = new MemberCache (this);
3263         }
3264
3265         // IMemberContainer methods
3266
3267         public string Name {
3268                 get {
3269                         return full_name;
3270                 }
3271         }
3272
3273         public Type Type {
3274                 get {
3275                         return type;
3276                 }
3277         }
3278
3279         public IMemberContainer Parent {
3280                 get {
3281                         return BaseType;
3282                 }
3283         }
3284
3285         public bool IsInterface {
3286                 get {
3287                         return is_interface;
3288                 }
3289         }
3290
3291         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3292         {
3293                 MemberInfo [] members;
3294                 if (type is GenericTypeParameterBuilder)
3295                         return MemberList.Empty;
3296                 if (mt == MemberTypes.Event)
3297                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3298                 else
3299                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3300                                                     null, null);
3301                 Array.Reverse (members);
3302
3303                 return new MemberList (members);
3304         }
3305
3306         // IMemberFinder methods
3307
3308         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3309                                        MemberFilter filter, object criteria)
3310         {
3311                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3312         }
3313
3314         public MemberCache MemberCache {
3315                 get {
3316                         return member_cache;
3317                 }
3318         }
3319
3320         public override string ToString ()
3321         {
3322                 if (BaseType != null)
3323                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3324                 else
3325                         return "TypeHandle (" + id + "," + Name + ")";
3326         }
3327 }
3328
3329 }