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