2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / typemanager.cs
bloba41f4d742e095353d0fe94942cece224fde4cf67
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.
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;
25 namespace Mono.CSharp {
27 partial class TypeManager {
29 // A list of core types that the compiler requires or uses
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;
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;
74 //
75 // C# 2.0
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;
85 // C# 3.0
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;
94 // C# 4.0
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;
102 // Expressions representing the internal types. Used during declaration
103 // definition.
105 static public TypeExpr system_object_expr, system_string_expr;
106 static public TypeExpr system_boolean_expr, system_decimal_expr;
107 static public TypeExpr system_single_expr, system_double_expr;
108 static public TypeExpr system_sbyte_expr, system_byte_expr;
109 static public TypeExpr system_int16_expr, system_uint16_expr;
110 static public TypeExpr system_int32_expr, system_uint32_expr;
111 static public TypeExpr system_int64_expr, system_uint64_expr;
112 static public TypeExpr system_char_expr, system_void_expr;
113 static public TypeExpr system_valuetype_expr;
114 public static TypeExpr expression_type_expr;
118 // These methods are called by code generated by the compiler
120 static public FieldSpec string_empty;
121 static public MethodSpec system_type_get_type_from_handle;
122 static public MethodSpec bool_movenext_void;
123 static public MethodSpec void_dispose_void;
124 static public MethodSpec void_monitor_enter_object;
125 static public MethodSpec void_monitor_exit_object;
126 static public MethodSpec void_initializearray_array_fieldhandle;
127 static public MethodSpec delegate_combine_delegate_delegate;
128 static public MethodSpec delegate_remove_delegate_delegate;
129 static public PropertySpec int_get_offset_to_string_data;
130 static public MethodSpec int_interlocked_compare_exchange;
131 static public PropertySpec ienumerator_getcurrent;
132 public static MethodSpec methodbase_get_type_from_handle;
133 public static MethodSpec methodbase_get_type_from_handle_generic;
134 public static MethodSpec fieldinfo_get_field_from_handle;
135 public static MethodSpec fieldinfo_get_field_from_handle_generic;
136 static public MethodSpec activator_create_instance;
139 // The constructors.
141 static public MethodSpec void_decimal_ctor_five_args;
142 static public MethodSpec void_decimal_ctor_int_arg;
143 public static MethodSpec void_decimal_ctor_long_arg;
145 static Dictionary<Assembly, bool> assembly_internals_vis_attrs;
148 // These are expressions that represent some of the internal data types, used
149 // elsewhere
151 public static void InitExpressionTypes ()
153 system_object_expr = new TypeLookupExpression (object_type);
154 system_string_expr = new TypeLookupExpression (string_type);
155 system_boolean_expr = new TypeLookupExpression (bool_type);
156 system_decimal_expr = new TypeLookupExpression (decimal_type);
157 system_single_expr = new TypeLookupExpression (float_type);
158 system_double_expr = new TypeLookupExpression (double_type);
159 system_sbyte_expr = new TypeLookupExpression (sbyte_type);
160 system_byte_expr = new TypeLookupExpression (byte_type);
161 system_int16_expr = new TypeLookupExpression (short_type);
162 system_uint16_expr = new TypeLookupExpression (ushort_type);
163 system_int32_expr = new TypeLookupExpression (int32_type);
164 system_uint32_expr = new TypeLookupExpression (uint32_type);
165 system_int64_expr = new TypeLookupExpression (int64_type);
166 system_uint64_expr = new TypeLookupExpression (uint64_type);
167 system_char_expr = new TypeLookupExpression (char_type);
168 system_void_expr = new TypeLookupExpression (void_type);
169 system_valuetype_expr = new TypeLookupExpression (value_type);
172 static TypeManager ()
174 Reset ();
177 static public void Reset ()
179 // object_type = null;
181 type_hash = new DoubleHash ();
182 assembly_internals_vis_attrs = new Dictionary<Assembly, bool> ();
184 // TODO: I am really bored by all this static stuff
185 system_type_get_type_from_handle =
186 bool_movenext_void =
187 void_dispose_void =
188 void_monitor_enter_object =
189 void_monitor_exit_object =
190 void_initializearray_array_fieldhandle =
191 int_interlocked_compare_exchange =
192 methodbase_get_type_from_handle =
193 methodbase_get_type_from_handle_generic =
194 fieldinfo_get_field_from_handle =
195 fieldinfo_get_field_from_handle_generic =
196 activator_create_instance =
197 delegate_combine_delegate_delegate =
198 delegate_remove_delegate_delegate = null;
200 int_get_offset_to_string_data =
201 ienumerator_getcurrent = null;
203 void_decimal_ctor_five_args =
204 void_decimal_ctor_int_arg =
205 void_decimal_ctor_long_arg = null;
207 string_empty = null;
209 call_site_type =
210 generic_call_site_type =
211 binder_flags = null;
213 binder_type = null;
215 typed_reference_type = arg_iterator_type = mbr_type =
216 runtime_helpers_type = iasyncresult_type = asynccallback_type =
217 runtime_argument_handle_type = void_ptr_type = isvolatile_type =
218 generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
219 generic_ienumerable_type = generic_nullable_type = expression_type =
220 parameter_expression_type = fieldinfo_type = methodinfo_type = ctorinfo_type = null;
222 expression_type_expr = null;
226 // We use this hash for multiple kinds of constructed types:
228 // (T, "&") Given T, get T &
229 // (T, "*") Given T, get T *
230 // (T, "[]") Given T and a array dimension, get T []
231 // (T, X) Given a type T and a simple name X, get the type T+X
233 // Accessibility tests, if necessary, should be done by the user
235 static DoubleHash type_hash = new DoubleHash ();
238 // Gets the reference to T version of the Type (T&)
240 public static Type GetReferenceType (TypeSpec t)
242 return t.GetMetaInfo ().MakeByRefType ();
245 public static TypeSpec GetConstructedType (TypeSpec t, string dim)
247 object ret = null;
248 if (type_hash.Lookup (t, dim, out ret))
249 return (TypeSpec) ret;
251 TypeSpec ds;
252 if (dim.Length == 1) {
253 if (dim[0] == '*') {
254 ds = PointerContainer.MakeType (t);
255 } else if (dim[0] == '&') {
256 ds = ReferenceContainer.MakeType (t);
257 } else {
258 throw new NotImplementedException ("net");
260 } else if (dim.Length == 2) { // optimizes common "[]"
261 ds = ArrayContainer.MakeType (t);
262 } else {
263 int rank = dim.IndexOf (']');
264 if (rank + 1 != dim.Length)
265 t = GetConstructedType (t, dim.Substring (rank + 1));
267 ds = ArrayContainer.MakeType (t, rank);
270 type_hash.Insert (t, dim, ds);
271 return ds;
274 /// <summary>
275 /// Returns the C# name of a type if possible, or the full type name otherwise
276 /// </summary>
277 static public string CSharpName (TypeSpec t)
279 return t.GetSignatureForError ();
282 static public string CSharpName (IList<TypeSpec> types)
284 if (types.Count == 0)
285 return string.Empty;
287 StringBuilder sb = new StringBuilder ();
288 for (int i = 0; i < types.Count; ++i) {
289 if (i > 0)
290 sb.Append (",");
292 sb.Append (CSharpName (types [i]));
294 return sb.ToString ();
297 static public string GetFullNameSignature (MemberSpec mi)
299 return mi.GetSignatureForError ();
302 static public string CSharpSignature (MemberSpec mb)
304 return mb.GetSignatureForError ();
308 // Looks up a type, and aborts if it is not found. This is used
309 // by predefined types required by the compiler
311 public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, MemberKind kind, bool required)
313 return CoreLookupType (ctx, ns_name, name, 0, kind, required);
316 public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, int arity, MemberKind kind, bool required)
318 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
319 var te = ns.Lookup (ctx, name, arity, Location.Null);
320 var ts = te == null ? null : te.Type;
322 if (!required)
323 return ts;
325 if (ts == null) {
326 ctx.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
327 ns_name, name);
328 return null;
331 if (ts.Kind != kind) {
332 ctx.Report.Error (520, "The predefined type `{0}.{1}' is not declared correctly",
333 ns_name, name);
334 return null;
337 return ts;
340 static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, Location loc)
342 const BindingRestriction restrictions = BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly;
343 var member = MemberCache.FindMember (t, filter, restrictions);
345 if (member != null)
346 return member;
348 string method_args = null;
349 if (filter.Parameters != null)
350 method_args = filter.Parameters.GetSignatureForError ();
352 RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
353 TypeManager.CSharpName (t), filter.Name, method_args);
355 return null;
359 // Returns the ConstructorInfo for "args"
361 public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
363 var pc = ParametersCompiled.CreateFullyResolved (args);
364 return GetPredefinedMember (t, MemberFilter.Constructor (pc), loc) as MethodSpec;
368 // Returns the method specification for a method named `name' defined
369 // in type `t' which takes arguments of types `args'
371 public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
373 var pc = ParametersCompiled.CreateFullyResolved (args);
374 return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), loc);
377 public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
379 return GetPredefinedMember (t, filter, loc) as MethodSpec;
382 public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
384 return GetPredefinedMember (t, MemberFilter.Field (name, type), loc) as FieldSpec;
387 public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
389 return GetPredefinedMember (t, MemberFilter.Property (name, type), loc) as PropertySpec;
392 public static IList<PredefinedTypeSpec> InitCoreTypes ()
394 var core_types = new PredefinedTypeSpec[] {
395 object_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Object"),
396 value_type = new PredefinedTypeSpec (MemberKind.Class, "System", "ValueType"),
397 attribute_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Attribute"),
399 int32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int32"),
400 int64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int64"),
401 uint32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt32"),
402 uint64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt64"),
403 byte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Byte"),
404 sbyte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "SByte"),
405 short_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int16"),
406 ushort_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt16"),
408 ienumerator_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator"),
409 ienumerable_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable"),
410 idisposable_type = new PredefinedTypeSpec (MemberKind.Interface, "System", "IDisposable"),
412 char_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Char"),
413 string_type = new PredefinedTypeSpec (MemberKind.Class, "System", "String"),
414 float_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Single"),
415 double_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Double"),
416 decimal_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Decimal"),
417 bool_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Boolean"),
418 intptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "IntPtr"),
419 uintptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UIntPtr"),
421 multicast_delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "MulticastDelegate"),
422 delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Delegate"),
423 enum_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Enum"),
424 array_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Array"),
425 void_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Void"),
426 type_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Type"),
427 exception_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Exception"),
428 runtime_field_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle"),
429 runtime_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle"),
432 return core_types;
435 /// <remarks>
436 /// The types have to be initialized after the initial
437 /// population of the type has happened (for example, to
438 /// bootstrap the corlib.dll
439 /// </remarks>
440 public static bool InitCoreTypes (CompilerContext ctx, IList<PredefinedTypeSpec> predefined)
442 foreach (var p in predefined) {
443 var found = CoreLookupType (ctx, p.Namespace, p.Name, p.Kind, true);
444 if (found == null || found == p)
445 continue;
447 if (!RootContext.StdLib) {
448 var ns = GlobalRootNamespace.Instance.GetNamespace (p.Namespace, false);
449 ns.ReplaceTypeWithPredefined (found, p);
451 var tc = found.MemberDefinition as TypeContainer;
452 tc.SetPredefinedSpec (p);
453 p.SetDefinition (found);
457 PredefinedAttributes.Get.ParamArray.Initialize (ctx, false);
458 PredefinedAttributes.Get.Out.Initialize (ctx, false);
460 return ctx.Report.Errors == 0;
464 // Initializes optional core types
466 public static void InitOptionalCoreTypes (CompilerContext ctx)
469 // These are only used for compare purposes
471 null_type = InternalType.Null;
473 void_ptr_type = PointerContainer.MakeType (void_type);
476 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
477 // types cache with incorrect accessiblity when any of optional types is internal.
479 PredefinedAttributes.Get.Initialize (ctx);
481 runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", MemberKind.Struct, false);
482 asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", MemberKind.Delegate, false);
483 iasyncresult_type = CoreLookupType (ctx, "System", "IAsyncResult", MemberKind.Interface, false);
484 typed_reference_type = CoreLookupType (ctx, "System", "TypedReference", MemberKind.Struct, false);
485 arg_iterator_type = CoreLookupType (ctx, "System", "ArgIterator", MemberKind.Struct, false);
486 mbr_type = CoreLookupType (ctx, "System", "MarshalByRefObject", MemberKind.Class, false);
488 generic_ienumerator_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerator", 1, MemberKind.Interface, false);
489 generic_ilist_type = CoreLookupType (ctx, "System.Collections.Generic", "IList", 1, MemberKind.Interface, false);
490 generic_icollection_type = CoreLookupType (ctx, "System.Collections.Generic", "ICollection", 1, MemberKind.Interface, false);
491 generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable", 1, MemberKind.Interface, false);
492 generic_nullable_type = CoreLookupType (ctx, "System", "Nullable", 1, MemberKind.Struct, false);
495 // Optional types which are used as types and for member lookup
497 runtime_helpers_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "RuntimeHelpers", MemberKind.Class, false);
499 // New in .NET 3.5
500 // Note: extension_attribute_type is already loaded
501 expression_type = CoreLookupType (ctx, "System.Linq.Expressions", "Expression", 1, MemberKind.Class, false);
504 public static bool IsBuiltinType (TypeSpec t)
506 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
507 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
508 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
509 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
510 return true;
511 else
512 return false;
516 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
517 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
519 public static bool IsPrimitiveType (TypeSpec t)
521 return (t == int32_type || t == uint32_type ||
522 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
523 t == char_type || t == short_type || t == bool_type ||
524 t == sbyte_type || t == byte_type || t == ushort_type);
527 // Obsolete
528 public static bool IsDelegateType (TypeSpec t)
530 return t.IsDelegate;
534 // When any element of the type is a dynamic type
536 // This method builds a transformation array for dynamic types
537 // used in places where DynamicAttribute cannot be applied to.
538 // It uses bool flag when type is of dynamic type and each
539 // section always starts with "false" for some reason.
541 // LAMESPEC: This should be part of C# specification !
543 // Example: Func<dynamic, int, dynamic[]>
544 // Transformation: { false, true, false, false, true }
546 public static bool[] HasDynamicTypeUsed (TypeSpec t)
548 var ac = t as ArrayContainer;
549 if (ac != null) {
550 if (HasDynamicTypeUsed (ac.Element) != null)
551 return new bool[] { false, true };
553 return null;
556 if (t == null)
557 return null;
559 if (IsGenericType (t)) {
560 List<bool> transform = null;
561 var targs = GetTypeArguments (t);
562 for (int i = 0; i < targs.Length; ++i) {
563 var element = HasDynamicTypeUsed (targs [i]);
564 if (element != null) {
565 if (transform == null) {
566 transform = new List<bool> ();
567 for (int ii = 0; ii <= i; ++ii)
568 transform.Add (false);
571 transform.AddRange (element);
572 } else if (transform != null) {
573 transform.Add (false);
577 if (transform != null)
578 return transform.ToArray ();
581 if (object.ReferenceEquals (InternalType.Dynamic, t))
582 return new bool [] { true };
584 return null;
587 // Obsolete
588 public static bool IsEnumType (TypeSpec t)
590 return t.IsEnum;
593 public static bool IsBuiltinOrEnum (TypeSpec t)
595 if (IsBuiltinType (t))
596 return true;
598 if (IsEnumType (t))
599 return true;
601 return false;
605 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
607 public static bool IsUnmanagedType (TypeSpec t)
609 var ds = t.MemberDefinition as DeclSpace;
610 if (ds != null)
611 return ds.IsUnmanagedType ();
613 // some builtins that are not unmanaged types
614 if (t == TypeManager.object_type || t == TypeManager.string_type)
615 return false;
617 if (IsBuiltinOrEnum (t))
618 return true;
620 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
621 if (t.IsPointer)
622 return IsUnmanagedType (GetElementType (t));
624 if (!IsValueType (t))
625 return false;
627 if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
628 return false;
630 return true;
634 // Null is considered to be a reference type
636 public static bool IsReferenceType (TypeSpec t)
638 if (t.IsGenericParameter)
639 return ((TypeParameterSpec) t).IsReferenceType;
641 return !t.IsStruct && !IsEnumType (t);
644 public static bool IsValueType (TypeSpec t)
646 if (t.IsGenericParameter)
647 return ((TypeParameterSpec) t).IsValueType;
649 return t.IsStruct || IsEnumType (t);
652 public static bool IsStruct (TypeSpec t)
654 return t.IsStruct;
657 public static bool IsSubclassOf (TypeSpec type, TypeSpec base_type)
659 do {
660 if (type == base_type)
661 return true;
663 type = type.BaseType;
664 } while (type != null);
666 return false;
669 public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
671 // TypeParameter tparam = LookupTypeParameter (type);
672 // TypeParameter pparam = LookupTypeParameter (parent);
674 if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
675 if (type == parent)
676 return true;
678 throw new NotImplementedException ("net");
679 // return tparam.IsSubclassOf (parent);
682 do {
683 if (IsInstantiationOfSameGenericType (type, parent))
684 return true;
686 type = type.BaseType;
687 } while (type != null);
689 return false;
693 // Checks whether `type' is a subclass or nested child of `base_type'.
695 public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
697 do {
698 if (IsFamilyAccessible (type, base_type))
699 return true;
701 // Handle nested types.
702 type = type.DeclaringType;
703 } while (type != null);
705 return false;
709 // Checks whether `type' is a nested child of `parent'.
711 public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent)
713 if (type == null)
714 return false;
716 type = type.GetDefinition (); // DropGenericTypeArguments (type);
717 parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);
719 if (IsEqual (type, parent))
720 return false;
722 type = type.DeclaringType;
723 while (type != null) {
724 if (IsEqual (type.GetDefinition (), parent))
725 return true;
727 type = type.DeclaringType;
730 return false;
733 public static bool IsSpecialType (TypeSpec t)
735 return t == arg_iterator_type || t == typed_reference_type;
739 // Checks whether `invocationAssembly' is same or a friend of the assembly
741 public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly)
743 if (assembly == null)
744 throw new ArgumentNullException ("assembly");
746 // TODO: This can happen for constants used at assembly level and
747 // predefined members
748 // But there is no way to test for it for now, so it could be abused
749 // elsewhere too.
750 if (invocationAssembly == null)
751 invocationAssembly = CodeGen.Assembly.Builder;
753 if (invocationAssembly == assembly)
754 return true;
756 bool value;
757 if (assembly_internals_vis_attrs.TryGetValue (assembly, out value))
758 return value;
760 object[] attrs = assembly.GetCustomAttributes (typeof (InternalsVisibleToAttribute), false);
761 if (attrs.Length == 0) {
762 assembly_internals_vis_attrs.Add (assembly, false);
763 return false;
766 bool is_friend = false;
768 AssemblyName this_name = CodeGen.Assembly.Name;
769 if (this_name == null)
770 return false;
772 byte [] this_token = this_name.GetPublicKeyToken ();
773 foreach (InternalsVisibleToAttribute attr in attrs) {
774 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
775 continue;
777 AssemblyName aname = null;
778 try {
779 aname = new AssemblyName (attr.AssemblyName);
780 } catch (FileLoadException) {
781 } catch (ArgumentException) {
784 if (aname == null || aname.Name != this_name.Name)
785 continue;
787 byte [] key_token = aname.GetPublicKeyToken ();
788 if (key_token != null) {
789 if (this_token.Length == 0) {
790 // Same name, but assembly is not strongnamed
791 Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report);
792 break;
795 if (!CompareKeyTokens (this_token, key_token))
796 continue;
799 is_friend = true;
800 break;
803 assembly_internals_vis_attrs.Add (assembly, is_friend);
804 return is_friend;
807 static bool CompareKeyTokens (byte [] token1, byte [] token2)
809 for (int i = 0; i < token1.Length; i++)
810 if (token1 [i] != token2 [i])
811 return false;
813 return true;
816 static void Error_FriendAccessNameNotMatching (string other_name, Report Report)
818 Report.Error (281,
819 "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",
820 other_name, CodeGen.Assembly.Name.FullName);
823 public static TypeSpec GetElementType (TypeSpec t)
825 return ((ElementTypeSpec)t).Element;
828 /// <summary>
829 /// This method is not implemented by MS runtime for dynamic types
830 /// </summary>
831 public static bool HasElementType (TypeSpec t)
833 return t is ElementTypeSpec;
836 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
838 // This is a custom version of Convert.ChangeType() which works
839 // with the TypeBuilder defined types when compiling corlib.
840 public static object ChangeType (object value, TypeSpec targetType, out bool error)
842 IConvertible convert_value = value as IConvertible;
844 if (convert_value == null){
845 error = true;
846 return null;
850 // We cannot rely on build-in type conversions as they are
851 // more limited than what C# supports.
852 // See char -> float/decimal/double conversion
854 error = false;
855 try {
856 if (targetType == TypeManager.bool_type)
857 return convert_value.ToBoolean (nf_provider);
858 if (targetType == TypeManager.byte_type)
859 return convert_value.ToByte (nf_provider);
860 if (targetType == TypeManager.char_type)
861 return convert_value.ToChar (nf_provider);
862 if (targetType == TypeManager.short_type)
863 return convert_value.ToInt16 (nf_provider);
864 if (targetType == TypeManager.int32_type)
865 return convert_value.ToInt32 (nf_provider);
866 if (targetType == TypeManager.int64_type)
867 return convert_value.ToInt64 (nf_provider);
868 if (targetType == TypeManager.sbyte_type)
869 return convert_value.ToSByte (nf_provider);
871 if (targetType == TypeManager.decimal_type) {
872 if (convert_value.GetType () == typeof (char))
873 return (decimal) convert_value.ToInt32 (nf_provider);
874 return convert_value.ToDecimal (nf_provider);
877 if (targetType == TypeManager.double_type) {
878 if (convert_value.GetType () == typeof (char))
879 return (double) convert_value.ToInt32 (nf_provider);
880 return convert_value.ToDouble (nf_provider);
883 if (targetType == TypeManager.float_type) {
884 if (convert_value.GetType () == typeof (char))
885 return (float)convert_value.ToInt32 (nf_provider);
886 return convert_value.ToSingle (nf_provider);
889 if (targetType == TypeManager.string_type)
890 return convert_value.ToString (nf_provider);
891 if (targetType == TypeManager.ushort_type)
892 return convert_value.ToUInt16 (nf_provider);
893 if (targetType == TypeManager.uint32_type)
894 return convert_value.ToUInt32 (nf_provider);
895 if (targetType == TypeManager.uint64_type)
896 return convert_value.ToUInt64 (nf_provider);
897 if (targetType == TypeManager.object_type)
898 return value;
900 error = true;
901 } catch {
902 error = true;
904 return null;
907 /// <summary>
908 /// Utility function that can be used to probe whether a type
909 /// is managed or not.
910 /// </summary>
911 public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc)
913 while (t.IsPointer)
914 t = GetElementType (t);
916 if (IsUnmanagedType (t))
917 return true;
919 ctx.Report.SymbolRelatedToPreviousError (t);
920 ctx.Report.Error (208, loc,
921 "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
922 CSharpName (t));
924 return false;
928 // Returns whether the array of memberinfos contains the given method
930 public static bool ArrayContainsMethod (List<MemberSpec> array, MethodSpec new_method, bool ignoreDeclType)
932 AParametersCollection new_args = new_method.Parameters;
934 foreach (MethodSpec method in array) {
935 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
936 continue;
938 if (method.Name != new_method.Name)
939 continue;
941 if (!TypeSpecComparer.Override.IsEqual (method.ReturnType, new_method.ReturnType))
942 continue;
944 AParametersCollection old_args = method.Parameters;
945 int old_count = old_args.Count;
946 int i;
948 if (new_args.Count != old_count)
949 continue;
951 for (i = 0; i < old_count; i++) {
952 if (!TypeSpecComparer.Override.IsEqual (old_args.Types[i], new_args.Types[i]))
953 break;
955 if (i != old_count)
956 continue;
958 return true;
961 return false;
963 #region Generics
964 // This method always return false for non-generic compiler,
965 // while Type.IsGenericParameter is returned if it is supported.
966 public static bool IsGenericParameter (TypeSpec type)
968 return type.IsGenericParameter;
971 public static bool IsGenericType (TypeSpec type)
973 return type.IsGeneric;
976 // TODO: Implement correctly
977 public static bool ContainsGenericParameters (TypeSpec type)
979 return type.GetMetaInfo ().ContainsGenericParameters;
982 public static bool IsEqual (TypeSpec a, TypeSpec b)
984 return a == b && !(a is InternalType);
987 public static TypeSpec[] GetTypeArguments (TypeSpec t)
989 // TODO: return empty array !!
990 return t.TypeArguments;
993 /// <summary>
994 /// Check whether `type' and `parent' are both instantiations of the same
995 /// generic type. Note that we do not check the type parameters here.
996 /// </summary>
997 public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
999 return type == parent || type.MemberDefinition == parent.MemberDefinition;
1002 public static bool IsNullableType (TypeSpec t)
1004 return generic_nullable_type == t.GetDefinition ();
1006 #endregion
1009 // Looks up a member called `name' in the `queried_type'. This lookup
1010 // is done by code that is contained in the definition for `invocation_type'
1011 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
1013 // `invocation_type' is used to check whether we're allowed to access the requested
1014 // member wrt its protection level.
1016 // When called from MemberAccess, `qualifier_type' is the type which is used to access
1017 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
1018 // is B and qualifier_type is A). This is used to do the CS1540 check.
1020 // When resolving a SimpleName, `qualifier_type' is null.
1022 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
1023 // the same than `queried_type' - except when we're being called from BaseAccess;
1024 // in this case, `invocation_type' is the current type and `queried_type' the base
1025 // type, so this'd normally trigger a CS1540.
1027 // The binding flags are `bf' and the kind of members being looked up are `mt'
1029 // The return value always includes private members which code in `invocation_type'
1030 // is allowed to access (using the specified `qualifier_type' if given); only use
1031 // BindingFlags.NonPublic to bypass the permission check.
1033 // The 'almost_match' argument is used for reporting error CS1540.
1035 // Returns an array of a single element for everything but Methods/Constructors
1036 // that might return multiple matches.
1038 public static IList<MemberSpec> MemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
1039 TypeSpec queried_type, MemberKind mt,
1040 BindingRestriction opt, string name, int arity, IList<MemberSpec> almost_match)
1042 Timer.StartTimer (TimerType.MemberLookup);
1044 var retval = RealMemberLookup (invocation_type, qualifier_type,
1045 queried_type, mt, opt, name, arity, almost_match);
1047 Timer.StopTimer (TimerType.MemberLookup);
1049 return retval;
1052 static IList<MemberSpec> RealMemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
1053 TypeSpec queried_type, MemberKind mt,
1054 BindingRestriction bf, string name, int arity, IList<MemberSpec> almost_match)
1056 MemberFilter filter = new MemberFilter (name, arity, mt, null, null);
1057 if ((bf & BindingRestriction.AccessibleOnly) != 0) {
1058 filter.InvocationType = invocation_type ?? InternalType.FakeInternalType;
1061 return MemberCache.FindMembers (queried_type, filter, bf);