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