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