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