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