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