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