2010-07-05 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //         Marek Safar     (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2008 Novell, Inc.
12 //
13
14 using System;
15 using System.IO;
16 using System.Globalization;
17 using System.Collections.Generic;
18 using System.Reflection;
19 using System.Reflection.Emit;
20 using System.Text;
21 using System.Runtime.CompilerServices;
22 using System.Diagnostics;
23 using System.Linq;
24
25 namespace Mono.CSharp {
26
27         partial class TypeManager {
28         //
29         // A list of core types that the compiler requires or uses
30         //
31         static public PredefinedTypeSpec object_type;
32         static public PredefinedTypeSpec value_type;
33         static public PredefinedTypeSpec string_type;
34         static public PredefinedTypeSpec int32_type;
35         static public PredefinedTypeSpec uint32_type;
36         static public PredefinedTypeSpec int64_type;
37         static public PredefinedTypeSpec uint64_type;
38         static public PredefinedTypeSpec float_type;
39         static public PredefinedTypeSpec double_type;
40         static public PredefinedTypeSpec char_type;
41         static public PredefinedTypeSpec short_type;
42         static public PredefinedTypeSpec decimal_type;
43         static public PredefinedTypeSpec bool_type;
44         static public PredefinedTypeSpec sbyte_type;
45         static public PredefinedTypeSpec byte_type;
46         static public PredefinedTypeSpec ushort_type;
47         static public PredefinedTypeSpec enum_type;
48         static public PredefinedTypeSpec delegate_type;
49         static public PredefinedTypeSpec multicast_delegate_type;
50         static public PredefinedTypeSpec void_type;
51         static public PredefinedTypeSpec array_type;
52         static public PredefinedTypeSpec runtime_handle_type;
53         static public PredefinedTypeSpec type_type;
54         static public PredefinedTypeSpec ienumerator_type;
55         static public PredefinedTypeSpec ienumerable_type;
56         static public PredefinedTypeSpec idisposable_type;
57         static public PredefinedTypeSpec intptr_type;
58         static public PredefinedTypeSpec uintptr_type;
59         static public PredefinedTypeSpec runtime_field_handle_type;
60         static public PredefinedTypeSpec attribute_type;
61         static public PredefinedTypeSpec exception_type;
62
63
64         static public TypeSpec null_type;
65         static public TypeSpec typed_reference_type;
66         static public TypeSpec arg_iterator_type;
67         static public TypeSpec mbr_type;
68         public static TypeSpec runtime_helpers_type;
69         static public TypeSpec iasyncresult_type;
70         static public TypeSpec asynccallback_type;
71         static public TypeSpec runtime_argument_handle_type;
72         static public TypeSpec void_ptr_type;
73
74         // 
75         // C# 2.0
76         //
77         static internal TypeSpec isvolatile_type;
78         static public TypeSpec generic_ilist_type;
79         static public TypeSpec generic_icollection_type;
80         static public TypeSpec generic_ienumerator_type;
81         static public TypeSpec generic_ienumerable_type;
82         static public TypeSpec generic_nullable_type;
83
84         //
85         // C# 3.0
86         //
87         static internal TypeSpec expression_type;
88         public static TypeSpec parameter_expression_type;
89         public static TypeSpec fieldinfo_type;
90         public static TypeSpec methodinfo_type;
91         public static TypeSpec ctorinfo_type;
92
93         //
94         // C# 4.0
95         //
96         public static TypeSpec call_site_type;
97         public static TypeSpec generic_call_site_type;
98         public static TypeExpr binder_type;
99         public static TypeSpec binder_flags;
100
101         public static TypeExpr expression_type_expr;
102
103
104         //
105         // These methods are called by code generated by the compiler
106         //
107         static public FieldSpec string_empty;
108         static public MethodSpec system_type_get_type_from_handle;
109         static public MethodSpec bool_movenext_void;
110         static public MethodSpec void_dispose_void;
111         static public MethodSpec void_monitor_enter_object;
112         static public MethodSpec void_monitor_exit_object;
113         static public MethodSpec void_initializearray_array_fieldhandle;
114         static public MethodSpec delegate_combine_delegate_delegate;
115         static public MethodSpec delegate_remove_delegate_delegate;
116         public static MethodSpec delegate_equal, delegate_inequal;
117         static public PropertySpec int_get_offset_to_string_data;
118         static public MethodSpec int_interlocked_compare_exchange;
119         static public PropertySpec ienumerator_getcurrent;
120         public static MethodSpec methodbase_get_type_from_handle;
121         public static MethodSpec methodbase_get_type_from_handle_generic;
122         public static MethodSpec fieldinfo_get_field_from_handle;
123         public static MethodSpec fieldinfo_get_field_from_handle_generic;
124         public static MethodSpec activator_create_instance;
125         public static MethodSpec string_equal, string_inequal;
126
127         //
128         // The constructors.
129         //
130         static public MethodSpec void_decimal_ctor_five_args;
131         static public MethodSpec void_decimal_ctor_int_arg;
132         public static MethodSpec void_decimal_ctor_long_arg;
133
134         static Dictionary<Assembly, bool> assembly_internals_vis_attrs;
135
136         static TypeManager ()
137         {
138                 Reset ();
139         }
140
141         static public void Reset ()
142         {
143 //              object_type = null;
144         
145                 assembly_internals_vis_attrs = new Dictionary<Assembly, bool> ();
146                 
147                 // TODO: I am really bored by all this static stuff
148                 system_type_get_type_from_handle =
149                 bool_movenext_void =
150                 void_dispose_void =
151                 void_monitor_enter_object =
152                 void_monitor_exit_object =
153                 void_initializearray_array_fieldhandle =
154                 int_interlocked_compare_exchange =
155                 methodbase_get_type_from_handle =
156                 methodbase_get_type_from_handle_generic =
157                 fieldinfo_get_field_from_handle =
158                 fieldinfo_get_field_from_handle_generic =
159                 activator_create_instance =
160                 delegate_combine_delegate_delegate =
161                 delegate_remove_delegate_delegate =
162                 string_equal =
163                 string_inequal =
164                 delegate_equal =
165                 delegate_inequal = null;
166
167                 int_get_offset_to_string_data =
168                 ienumerator_getcurrent = null;
169
170                 void_decimal_ctor_five_args =
171                 void_decimal_ctor_int_arg =
172                 void_decimal_ctor_long_arg = null;
173
174                 string_empty = null;
175
176                 call_site_type =
177                 generic_call_site_type =
178                 binder_flags = null;
179
180                 binder_type = null;
181
182                 typed_reference_type = arg_iterator_type = mbr_type =
183                 runtime_helpers_type = iasyncresult_type = asynccallback_type =
184                 runtime_argument_handle_type = void_ptr_type = isvolatile_type =
185                 generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
186                 generic_ienumerable_type = generic_nullable_type = expression_type =
187                 parameter_expression_type = fieldinfo_type = methodinfo_type = ctorinfo_type = null;
188
189                 expression_type_expr = null;
190         }
191
192         /// <summary>
193         ///   Returns the C# name of a type if possible, or the full type name otherwise
194         /// </summary>
195         static public string CSharpName (TypeSpec t)
196         {
197                 return t.GetSignatureForError ();
198         }
199
200         static public string CSharpName (IList<TypeSpec> types)
201         {
202                 if (types.Count == 0)
203                         return string.Empty;
204
205                 StringBuilder sb = new StringBuilder ();
206                 for (int i = 0; i < types.Count; ++i) {
207                         if (i > 0)
208                                 sb.Append (",");
209
210                         sb.Append (CSharpName (types [i]));
211                 }
212                 return sb.ToString ();
213         }
214
215         static public string GetFullNameSignature (MemberSpec mi)
216         {
217                 return mi.GetSignatureForError ();
218         }
219
220         static public string CSharpSignature (MemberSpec mb)
221         {
222                 return mb.GetSignatureForError ();
223         }
224
225         //
226         // Looks up a type, and aborts if it is not found.  This is used
227         // by predefined types required by the compiler
228         //
229         public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, MemberKind kind, bool required)
230         {
231                 return CoreLookupType (ctx, ns_name, name, 0, kind, required);
232         }
233
234         public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, int arity, MemberKind kind, bool required)
235         {
236                 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
237                 var te = ns.LookupType (ctx, name, arity, !required, Location.Null);
238                 var ts = te == null ? null : te.Type;
239
240                 if (!required)
241                         return ts;
242
243                 if (ts == null) {
244                         ctx.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
245                                 ns_name, name);
246                         return null;
247                 }
248
249                 if (ts.Kind != kind) {
250                         ctx.Report.Error (520, "The predefined type `{0}.{1}' is not declared correctly",
251                                 ns_name, name);
252                         return null;
253                 }
254
255                 return ts;
256         }
257
258         static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, Location loc)
259         {
260                 const BindingRestriction restrictions = BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly;
261                 var member = MemberCache.FindMember (t, filter, restrictions);
262
263                 if (member != null)
264                         return member;
265
266                 string method_args = null;
267                 if (filter.Parameters != null)
268                         method_args = filter.Parameters.GetSignatureForError ();
269
270                 RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
271                         TypeManager.CSharpName (t), filter.Name, method_args);
272
273                 return null;
274         }
275
276         //
277         // Returns the ConstructorInfo for "args"
278         //
279         public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
280         {
281                 var pc = ParametersCompiled.CreateFullyResolved (args);
282                 return GetPredefinedMember (t, MemberFilter.Constructor (pc), loc) as MethodSpec;
283         }
284
285         //
286         // Returns the method specification for a method named `name' defined
287         // in type `t' which takes arguments of types `args'
288         //
289         public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
290         {
291                 var pc = ParametersCompiled.CreateFullyResolved (args);
292                 return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), loc);
293         }
294
295         public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
296         {
297                 return GetPredefinedMember (t, filter, loc) as MethodSpec;
298         }
299
300         public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
301         {
302                 return GetPredefinedMember (t, MemberFilter.Field (name, type), loc) as FieldSpec;
303         }
304
305         public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
306         {
307                 return GetPredefinedMember (t, MemberFilter.Property (name, type), loc) as PropertySpec;
308         }
309
310         public static IList<PredefinedTypeSpec> InitCoreTypes ()
311         {
312                 var core_types = new PredefinedTypeSpec[] {
313                         object_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Object"),
314                         value_type = new PredefinedTypeSpec (MemberKind.Class, "System", "ValueType"),
315                         attribute_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Attribute"),
316
317                         int32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int32"),
318                         int64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int64"),
319                         uint32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt32"),
320                         uint64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt64"),
321                         byte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Byte"),
322                         sbyte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "SByte"),
323                         short_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int16"),
324                         ushort_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt16"),
325
326                         ienumerator_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator"),
327                         ienumerable_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable"),
328                         idisposable_type = new PredefinedTypeSpec (MemberKind.Interface, "System", "IDisposable"),
329
330                         char_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Char"),
331                         string_type = new PredefinedTypeSpec (MemberKind.Class, "System", "String"),
332                         float_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Single"),
333                         double_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Double"),
334                         decimal_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Decimal"),
335                         bool_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Boolean"),
336                         intptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "IntPtr"),
337                         uintptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UIntPtr"),
338
339                         multicast_delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "MulticastDelegate"),
340                         delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Delegate"),
341                         enum_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Enum"),
342                         array_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Array"),
343                         void_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Void"),
344                         type_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Type"),
345                         exception_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Exception"),
346                         runtime_field_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle"),
347                         runtime_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle"),
348                 };
349
350                 return core_types;
351         }
352
353         /// <remarks>
354         ///   The types have to be initialized after the initial
355         ///   population of the type has happened (for example, to
356         ///   bootstrap the corlib.dll
357         /// </remarks>
358         public static bool InitCoreTypes (CompilerContext ctx, IList<PredefinedTypeSpec> predefined)
359         {
360                 foreach (var p in predefined) {
361                         var found = CoreLookupType (ctx, p.Namespace, p.Name, p.Kind, true);
362                         if (found == null || found == p)
363                                 continue;
364
365                         if (!RootContext.StdLib) {
366                                 var ns = GlobalRootNamespace.Instance.GetNamespace (p.Namespace, false);
367                                 ns.ReplaceTypeWithPredefined (found, p);
368
369                                 var tc = found.MemberDefinition as TypeContainer;
370                                 tc.SetPredefinedSpec (p);
371                                 p.SetDefinition (found);
372                         }
373                 }
374
375                 PredefinedAttributes.Get.ParamArray.Initialize (ctx, false);
376                 PredefinedAttributes.Get.Out.Initialize (ctx, false);
377
378                 return ctx.Report.Errors == 0;
379         }
380
381         //
382         // Initializes optional core types
383         //
384         public static void InitOptionalCoreTypes (CompilerContext ctx)
385         {
386                 //
387                 // These are only used for compare purposes
388                 //
389                 null_type = InternalType.Null;
390
391                 void_ptr_type = PointerContainer.MakeType (void_type);
392
393                 //
394                 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
395                 // types cache with incorrect accessiblity when any of optional types is internal.
396                 //
397                 PredefinedAttributes.Get.Initialize (ctx);
398
399                 runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", MemberKind.Struct, false);
400                 asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", MemberKind.Delegate, false);
401                 iasyncresult_type = CoreLookupType (ctx, "System", "IAsyncResult", MemberKind.Interface, false);
402                 typed_reference_type = CoreLookupType (ctx, "System", "TypedReference", MemberKind.Struct, false);
403                 arg_iterator_type = CoreLookupType (ctx, "System", "ArgIterator", MemberKind.Struct, false);
404                 mbr_type = CoreLookupType (ctx, "System", "MarshalByRefObject", MemberKind.Class, false);
405
406                 generic_ienumerator_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerator", 1, MemberKind.Interface, false);
407                 generic_ilist_type = CoreLookupType (ctx, "System.Collections.Generic", "IList", 1, MemberKind.Interface, false);
408                 generic_icollection_type = CoreLookupType (ctx, "System.Collections.Generic", "ICollection", 1, MemberKind.Interface, false);
409                 generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable", 1, MemberKind.Interface, false);
410                 generic_nullable_type = CoreLookupType (ctx, "System", "Nullable", 1, MemberKind.Struct, false);
411
412                 //
413                 // Optional types which are used as types and for member lookup
414                 //
415                 runtime_helpers_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "RuntimeHelpers", MemberKind.Class, false);
416
417                 // New in .NET 3.5
418                 // Note: extension_attribute_type is already loaded
419                 expression_type = CoreLookupType (ctx, "System.Linq.Expressions", "Expression", 1, MemberKind.Class, false);
420         }
421
422         public static bool IsBuiltinType (TypeSpec t)
423         {
424                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
425                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
426                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
427                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
428                         return true;
429                 else
430                         return false;
431         }
432
433         //
434         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
435         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
436         // 
437         public static bool IsPrimitiveType (TypeSpec t)
438         {
439                 return (t == int32_type || t == uint32_type ||
440                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
441                     t == char_type || t == short_type || t == bool_type ||
442                     t == sbyte_type || t == byte_type || t == ushort_type);
443         }
444
445         // Obsolete
446         public static bool IsDelegateType (TypeSpec t)
447         {
448                 return t.IsDelegate;
449         }
450
451         //
452         // When any element of the type is a dynamic type
453         //
454         // This method builds a transformation array for dynamic types
455         // used in places where DynamicAttribute cannot be applied to.
456         // It uses bool flag when type is of dynamic type and each
457         // section always starts with "false" for some reason.
458         //
459         // LAMESPEC: This should be part of C# specification !
460         // 
461         // Example: Func<dynamic, int, dynamic[]>
462         // Transformation: { false, true, false, false, true }
463         //
464         public static bool[] HasDynamicTypeUsed (TypeSpec t)
465         {
466                 var ac = t as ArrayContainer;
467                 if (ac != null) {
468                         if (HasDynamicTypeUsed (ac.Element) != null)
469                                 return new bool[] { false, true };
470
471                         return null;
472                 }
473
474                 if (t == null)
475                         return null;
476
477                 if (IsGenericType (t)) {
478                         List<bool> transform = null;
479                         var targs = GetTypeArguments (t);
480                         for (int i = 0; i < targs.Length; ++i) {
481                                 var element = HasDynamicTypeUsed (targs [i]);
482                                 if (element != null) {
483                                         if (transform == null) {
484                                                 transform = new List<bool> ();
485                                                 for (int ii = 0; ii <= i; ++ii)
486                                                         transform.Add (false);
487                                         }
488
489                                         transform.AddRange (element);
490                                 } else if (transform != null) {
491                                         transform.Add (false);
492                                 }
493                         }
494
495                         if (transform != null)
496                                 return transform.ToArray ();
497                 }
498
499                 if (object.ReferenceEquals (InternalType.Dynamic, t))
500                         return new bool [] { true };
501
502                 return null;
503         }
504         
505         // Obsolete
506         public static bool IsEnumType (TypeSpec t)
507         {
508                 return t.IsEnum;
509         }
510
511         public static bool IsBuiltinOrEnum (TypeSpec t)
512         {
513                 if (IsBuiltinType (t))
514                         return true;
515                 
516                 if (IsEnumType (t))
517                         return true;
518
519                 return false;
520         }
521
522         //
523         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
524         //
525         public static bool IsUnmanagedType (TypeSpec t)
526         {
527                 var ds = t.MemberDefinition as DeclSpace;
528                 if (ds != null)
529                         return ds.IsUnmanagedType ();
530
531                 // some builtins that are not unmanaged types
532                 if (t == TypeManager.object_type || t == TypeManager.string_type)
533                         return false;
534
535                 if (IsBuiltinOrEnum (t))
536                         return true;
537
538                 // Someone did the work of checking if the ElementType of t is unmanaged.  Let's not repeat it.
539                 if (t.IsPointer)
540                         return IsUnmanagedType (GetElementType (t));
541
542                 if (!IsValueType (t))
543                         return false;
544
545                 if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
546                         return false;
547
548                 return true;
549         }
550
551         //
552         // Null is considered to be a reference type
553         //                      
554         public static bool IsReferenceType (TypeSpec t)
555         {
556                 if (t.IsGenericParameter)
557                         return ((TypeParameterSpec) t).IsReferenceType;
558
559                 return !t.IsStruct && !IsEnumType (t);
560         }                       
561                 
562         public static bool IsValueType (TypeSpec t)
563         {
564                 if (t.IsGenericParameter)
565                         return ((TypeParameterSpec) t).IsValueType;
566
567                 return t.IsStruct || IsEnumType (t);
568         }
569
570         public static bool IsStruct (TypeSpec t)
571         {
572                 return t.IsStruct;
573         }
574
575         public static bool IsSubclassOf (TypeSpec type, TypeSpec base_type)
576         {
577                 do {
578                         if (type == base_type)
579                                 return true;
580
581                         type = type.BaseType;
582                 } while (type != null);
583
584                 return false;
585         }
586
587         public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
588         {
589 //              TypeParameter tparam = LookupTypeParameter (type);
590 //              TypeParameter pparam = LookupTypeParameter (parent);
591
592                 if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
593                         if (type == parent)
594                                 return true;
595
596                         throw new NotImplementedException ("net");
597 //                      return tparam.IsSubclassOf (parent);
598                 }
599
600                 do {
601                         if (IsInstantiationOfSameGenericType (type, parent))
602                                 return true;
603
604                         type = type.BaseType;
605                 } while (type != null);
606
607                 return false;
608         }
609
610         //
611         // Checks whether `type' is a subclass or nested child of `base_type'.
612         //
613         public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
614         {
615                 do {
616                         if (IsFamilyAccessible (type, base_type))
617                                 return true;
618
619                         // Handle nested types.
620                         type = type.DeclaringType;
621                 } while (type != null);
622
623                 return false;
624         }
625
626         //
627         // Checks whether `type' is a nested child of `parent'.
628         //
629         public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent)
630         {
631                 if (type == null)
632                         return false;
633
634                 type = type.GetDefinition (); // DropGenericTypeArguments (type);
635                 parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);
636
637                 if (IsEqual (type, parent))
638                         return false;
639
640                 type = type.DeclaringType;
641                 while (type != null) {
642                         if (IsEqual (type.GetDefinition (), parent))
643                                 return true;
644
645                         type = type.DeclaringType;
646                 }
647
648                 return false;
649         }
650
651         public static bool IsSpecialType (TypeSpec t)
652         {
653                 return t == arg_iterator_type || t == typed_reference_type;
654         }
655
656         //
657         // Checks whether `invocationAssembly' is same or a friend of the assembly
658         //
659         public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly)
660         {
661                 if (assembly == null)
662                         throw new ArgumentNullException ("assembly");
663
664                 // TODO: This can happen for constants used at assembly level and
665                 // predefined members
666                 // But there is no way to test for it for now, so it could be abused
667                 // elsewhere too.
668                 if (invocationAssembly == null)
669                         invocationAssembly = CodeGen.Assembly.Builder;
670
671                 if (invocationAssembly == assembly)
672                         return true;
673
674                 bool value;
675                 if (assembly_internals_vis_attrs.TryGetValue (assembly, out value))
676                         return value;
677
678                 object[] attrs = assembly.GetCustomAttributes (typeof (InternalsVisibleToAttribute), false);
679                 if (attrs.Length == 0) {
680                         assembly_internals_vis_attrs.Add (assembly, false);
681                         return false;
682                 }
683
684                 bool is_friend = false;
685
686                 AssemblyName this_name = CodeGen.Assembly.Name;
687                 if (this_name == null)
688                         return false;
689
690                 byte [] this_token = this_name.GetPublicKeyToken ();
691                 foreach (InternalsVisibleToAttribute attr in attrs) {
692                         if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
693                                 continue;
694                         
695                         AssemblyName aname = null;
696                         try {
697                                 aname = new AssemblyName (attr.AssemblyName);
698                         } catch (FileLoadException) {
699                         } catch (ArgumentException) {
700                         }
701
702                         if (aname == null || aname.Name != this_name.Name)
703                                 continue;
704                         
705                         byte [] key_token = aname.GetPublicKeyToken ();
706                         if (key_token != null) {
707                                 if (this_token.Length == 0) {
708                                         // Same name, but assembly is not strongnamed
709                                         Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report);
710                                         break;
711                                 }
712                                 
713                                 if (!CompareKeyTokens (this_token, key_token))
714                                         continue;
715                         }
716
717                         is_friend = true;
718                         break;
719                 }
720
721                 assembly_internals_vis_attrs.Add (assembly, is_friend);
722                 return is_friend;
723         }
724
725         static bool CompareKeyTokens (byte [] token1, byte [] token2)
726         {
727                 for (int i = 0; i < token1.Length; i++)
728                         if (token1 [i] != token2 [i])
729                                 return false;
730
731                 return true;
732         }
733
734         static void Error_FriendAccessNameNotMatching (string other_name, Report Report)
735         {
736                 Report.Error (281,
737                         "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
738                         other_name, CodeGen.Assembly.Name.FullName);
739         }
740
741         public static TypeSpec GetElementType (TypeSpec t)
742         {
743                 return ((ElementTypeSpec)t).Element;
744         }
745
746         /// <summary>
747         /// This method is not implemented by MS runtime for dynamic types
748         /// </summary>
749         public static bool HasElementType (TypeSpec t)
750         {
751                 return t is ElementTypeSpec;
752         }
753
754         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
755
756         // This is a custom version of Convert.ChangeType() which works
757         // with the TypeBuilder defined types when compiling corlib.
758         public static object ChangeType (object value, TypeSpec targetType, out bool error)
759         {
760                 IConvertible convert_value = value as IConvertible;
761                 
762                 if (convert_value == null){
763                         error = true;
764                         return null;
765                 }
766                 
767                 //
768                 // We cannot rely on build-in type conversions as they are
769                 // more limited than what C# supports.
770                 // See char -> float/decimal/double conversion
771                 //
772                 error = false;
773                 try {
774                         if (targetType == TypeManager.bool_type)
775                                 return convert_value.ToBoolean (nf_provider);
776                         if (targetType == TypeManager.byte_type)
777                                 return convert_value.ToByte (nf_provider);
778                         if (targetType == TypeManager.char_type)
779                                 return convert_value.ToChar (nf_provider);
780                         if (targetType == TypeManager.short_type)
781                                 return convert_value.ToInt16 (nf_provider);
782                         if (targetType == TypeManager.int32_type)
783                                 return convert_value.ToInt32 (nf_provider);
784                         if (targetType == TypeManager.int64_type)
785                                 return convert_value.ToInt64 (nf_provider);
786                         if (targetType == TypeManager.sbyte_type)
787                                 return convert_value.ToSByte (nf_provider);
788
789                         if (targetType == TypeManager.decimal_type) {
790                                 if (convert_value.GetType () == typeof (char))
791                                         return (decimal) convert_value.ToInt32 (nf_provider);
792                                 return convert_value.ToDecimal (nf_provider);
793                         }
794
795                         if (targetType == TypeManager.double_type) {
796                                 if (convert_value.GetType () == typeof (char))
797                                         return (double) convert_value.ToInt32 (nf_provider);
798                                 return convert_value.ToDouble (nf_provider);
799                         }
800
801                         if (targetType == TypeManager.float_type) {
802                                 if (convert_value.GetType () == typeof (char))
803                                         return (float)convert_value.ToInt32 (nf_provider);
804                                 return convert_value.ToSingle (nf_provider);
805                         }
806
807                         if (targetType == TypeManager.string_type)
808                                 return convert_value.ToString (nf_provider);
809                         if (targetType == TypeManager.ushort_type)
810                                 return convert_value.ToUInt16 (nf_provider);
811                         if (targetType == TypeManager.uint32_type)
812                                 return convert_value.ToUInt32 (nf_provider);
813                         if (targetType == TypeManager.uint64_type)
814                                 return convert_value.ToUInt64 (nf_provider);
815                         if (targetType == TypeManager.object_type)
816                                 return value;
817
818                         error = true;
819                 } catch {
820                         error = true;
821                 }
822                 return null;
823         }
824
825         /// <summary>
826         ///   Utility function that can be used to probe whether a type
827         ///   is managed or not.  
828         /// </summary>
829         public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc)
830         {
831                 while (t.IsPointer)
832                         t = GetElementType (t);
833
834                 if (IsUnmanagedType (t))
835                         return true;
836
837                 ctx.Report.SymbolRelatedToPreviousError (t);
838                 ctx.Report.Error (208, loc,
839                         "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
840                         CSharpName (t));
841
842                 return false;   
843         }
844 #region Generics
845         // This method always return false for non-generic compiler,
846         // while Type.IsGenericParameter is returned if it is supported.
847         public static bool IsGenericParameter (TypeSpec type)
848         {
849                 return type.IsGenericParameter;
850         }
851
852         public static bool IsGenericType (TypeSpec type)
853         {
854                 return type.IsGeneric;
855         }
856
857         // TODO: Implement correctly
858         public static bool ContainsGenericParameters (TypeSpec type)
859         {
860                 return type.GetMetaInfo ().ContainsGenericParameters;
861         }
862
863         public static bool IsEqual (TypeSpec a, TypeSpec b)
864         {
865                 return a == b && !(a is InternalType);
866         }
867
868         public static TypeSpec[] GetTypeArguments (TypeSpec t)
869         {
870                 // TODO: return empty array !!
871                 return t.TypeArguments;
872         }
873
874         /// <summary>
875         ///   Check whether `type' and `parent' are both instantiations of the same
876         ///   generic type.  Note that we do not check the type parameters here.
877         /// </summary>
878         public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
879         {
880                 return type == parent || type.MemberDefinition == parent.MemberDefinition;
881         }
882
883         public static bool IsNullableType (TypeSpec t)
884         {
885                 return generic_nullable_type == t.GetDefinition ();
886         }
887 #endregion
888
889         //
890         // Looks up a member called `name' in the `queried_type'.  This lookup
891         // is done by code that is contained in the definition for `invocation_type'
892         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
893         //
894         // `invocation_type' is used to check whether we're allowed to access the requested
895         // member wrt its protection level.
896         //
897         // When called from MemberAccess, `qualifier_type' is the type which is used to access
898         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
899         // is B and qualifier_type is A).  This is used to do the CS1540 check.
900         //
901         // When resolving a SimpleName, `qualifier_type' is null.
902         //
903         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
904         // the same than `queried_type' - except when we're being called from BaseAccess;
905         // in this case, `invocation_type' is the current type and `queried_type' the base
906         // type, so this'd normally trigger a CS1540.
907         //
908         // The binding flags are `bf' and the kind of members being looked up are `mt'
909         //
910         // The return value always includes private members which code in `invocation_type'
911         // is allowed to access (using the specified `qualifier_type' if given); only use
912         // BindingFlags.NonPublic to bypass the permission check.
913         //
914         // The 'almost_match' argument is used for reporting error CS1540.
915         //
916         // Returns an array of a single element for everything but Methods/Constructors
917         // that might return multiple matches.
918         //
919         public static IList<MemberSpec> MemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
920                                                   TypeSpec queried_type, MemberKind mt,
921                                                   BindingRestriction opt, string name, int arity, IList<MemberSpec> almost_match)
922         {
923                 Timer.StartTimer (TimerType.MemberLookup);
924
925                 var retval = RealMemberLookup (invocation_type, qualifier_type,
926                                                         queried_type, mt, opt, name, arity, almost_match);
927
928                 Timer.StopTimer (TimerType.MemberLookup);
929
930                 return retval;
931         }
932
933         static IList<MemberSpec> RealMemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
934                                                    TypeSpec queried_type, MemberKind mt,
935                                                    BindingRestriction bf, string name, int arity, IList<MemberSpec> almost_match)
936         {
937                 MemberFilter filter = new MemberFilter (name, arity, mt, null, null);
938                 if ((bf & BindingRestriction.AccessibleOnly) != 0) {
939                         filter.InvocationType = invocation_type ?? InternalType.FakeInternalType;
940                 }
941
942                 return MemberCache.FindMembers (queried_type, filter, bf);
943         }       
944 }
945
946 }