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