2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2008 Novell, Inc.
15 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
16 // the behavior of the compilation. This can be removed if we rework
17 // the code to get a list of namespaces available.
19 #define SIMPLE_SPEEDUP
23 using System
.Globalization
;
24 using System
.Collections
.Generic
;
25 using System
.Reflection
;
26 using System
.Reflection
.Emit
;
28 using System
.Runtime
.CompilerServices
;
29 using System
.Diagnostics
;
31 namespace Mono
.CSharp
{
33 partial class TypeManager
{
35 // A list of core types that the compiler requires or uses
37 static public Type object_type
;
38 static public Type value_type
;
39 static public Type string_type
;
40 static public Type int32_type
;
41 static public Type uint32_type
;
42 static public Type int64_type
;
43 static public Type uint64_type
;
44 static public Type float_type
;
45 static public Type double_type
;
46 static public Type char_type
;
47 static public Type short_type
;
48 static public Type decimal_type
;
49 static public Type bool_type
;
50 static public Type sbyte_type
;
51 static public Type byte_type
;
52 static public Type ushort_type
;
53 static public Type enum_type
;
54 static public Type delegate_type
;
55 static public Type multicast_delegate_type
;
56 static public Type void_type
;
57 static public Type null_type
;
58 static public Type array_type
;
59 static public Type runtime_handle_type
;
60 static public Type type_type
;
61 static public Type ienumerator_type
;
62 static public Type ienumerable_type
;
63 static public Type idisposable_type
;
64 static public Type iasyncresult_type
;
65 static public Type asynccallback_type
;
66 static public Type intptr_type
;
67 static public Type uintptr_type
;
68 static public Type runtime_field_handle_type
;
69 static public Type runtime_argument_handle_type
;
70 static public Type attribute_type
;
71 static public Type void_ptr_type
;
72 static public Type exception_type
;
74 static public Type typed_reference_type
;
75 static public Type arg_iterator_type
;
76 static public Type mbr_type
;
77 public static Type runtime_helpers_type
;
82 static internal Type isvolatile_type
;
83 static public Type generic_ilist_type
;
84 static public Type generic_icollection_type
;
85 static public Type generic_ienumerator_type
;
86 static public Type generic_ienumerable_type
;
87 static public Type generic_nullable_type
;
92 static internal Type expression_type
;
93 public static Type parameter_expression_type
;
94 public static Type fieldinfo_type
;
95 public static Type methodinfo_type
;
96 public static Type ctorinfo_type
;
101 public static Type call_site_type
;
102 public static Type generic_call_site_type
;
103 public static TypeExpr binder_type
;
104 public static Type binder_flags
;
107 // Expressions representing the internal types. Used during declaration
110 static public TypeExpr system_object_expr
, system_string_expr
;
111 static public TypeExpr system_boolean_expr
, system_decimal_expr
;
112 static public TypeExpr system_single_expr
, system_double_expr
;
113 static public TypeExpr system_sbyte_expr
, system_byte_expr
;
114 static public TypeExpr system_int16_expr
, system_uint16_expr
;
115 static public TypeExpr system_int32_expr
, system_uint32_expr
;
116 static public TypeExpr system_int64_expr
, system_uint64_expr
;
117 static public TypeExpr system_char_expr
, system_void_expr
;
118 static public TypeExpr system_valuetype_expr
;
119 static public TypeExpr system_intptr_expr
;
120 public static TypeExpr expression_type_expr
;
124 // These methods are called by code generated by the compiler
126 static public FieldInfo string_empty
;
127 static public MethodSpec system_type_get_type_from_handle
;
128 static public MethodSpec bool_movenext_void
;
129 static public MethodSpec void_dispose_void
;
130 static public MethodSpec void_monitor_enter_object
;
131 static public MethodSpec void_monitor_exit_object
;
132 static public MethodSpec void_initializearray_array_fieldhandle
;
133 static public MethodSpec delegate_combine_delegate_delegate
;
134 static public MethodSpec delegate_remove_delegate_delegate
;
135 static public PropertySpec int_get_offset_to_string_data
;
136 static public MethodSpec int_interlocked_compare_exchange
;
137 static public PropertySpec ienumerator_getcurrent
;
138 public static MethodSpec methodbase_get_type_from_handle
;
139 public static MethodSpec methodbase_get_type_from_handle_generic
;
140 public static MethodSpec fieldinfo_get_field_from_handle
;
141 public static MethodSpec fieldinfo_get_field_from_handle_generic
;
142 static public MethodSpec activator_create_instance
;
147 static public ConstructorInfo void_decimal_ctor_five_args
;
148 static public ConstructorInfo void_decimal_ctor_int_arg
;
149 public static ConstructorInfo void_decimal_ctor_long_arg
;
151 static Dictionary
<TypeBuilder
, DeclSpace
> builder_to_declspace
;
153 static Dictionary
<Type
, MemberCache
> builder_to_member_cache
;
156 // Tracks the interfaces implemented by typebuilders. We only
157 // enter those who do implement or or more interfaces
159 static Dictionary
<Type
, Type
[]> builder_to_ifaces
;
162 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
164 static Dictionary
<MemberInfo
, AParametersCollection
> method_params
;
167 // A hash table from override methods to their base virtual method.
169 static Dictionary
<MethodBase
, MethodBase
> method_overrides
;
172 // Keeps track of methods
175 static Dictionary
<MethodBase
, IMethodData
> builder_to_method
;
178 // Contains all public types from referenced assemblies.
179 // This member is used only if CLS Compliance verification is required.
181 public static Dictionary
<string, object> AllClsTopLevelTypes
;
183 static Dictionary
<FieldInfo
, FieldBase
> fieldbuilders_to_fields
;
184 static Dictionary
<PropertyInfo
, PropertyBase
> propertybuilder_to_property
;
185 static Dictionary
<FieldInfo
, ConstSpec
> fields
;
186 static Dictionary
<EventInfo
, EventSpec
> events
;
187 static Dictionary
<Assembly
, bool> assembly_internals_vis_attrs
;
188 static Dictionary
<GenericTypeParameterBuilder
, TypeParameter
> builder_to_type_param
;
189 static Dictionary
<Type
, Type
[]> iface_cache
;
191 public static void CleanUp ()
193 // Lets get everything clean so that we can collect before generating code
194 builder_to_declspace
= null;
195 builder_to_member_cache
= null;
196 builder_to_ifaces
= null;
197 builder_to_type_param
= null;
198 method_params
= null;
199 builder_to_method
= null;
205 propertybuilder_to_property
= null;
207 TypeHandle
.CleanUp ();
211 // These are expressions that represent some of the internal data types, used
214 static void InitExpressionTypes ()
216 system_object_expr
= new TypeLookupExpression ("System", "Object");
217 system_string_expr
= new TypeLookupExpression ("System", "String");
218 system_boolean_expr
= new TypeLookupExpression ("System", "Boolean");
219 system_decimal_expr
= new TypeLookupExpression ("System", "Decimal");
220 system_single_expr
= new TypeLookupExpression ("System", "Single");
221 system_double_expr
= new TypeLookupExpression ("System", "Double");
222 system_sbyte_expr
= new TypeLookupExpression ("System", "SByte");
223 system_byte_expr
= new TypeLookupExpression ("System", "Byte");
224 system_int16_expr
= new TypeLookupExpression ("System", "Int16");
225 system_uint16_expr
= new TypeLookupExpression ("System", "UInt16");
226 system_int32_expr
= new TypeLookupExpression ("System", "Int32");
227 system_uint32_expr
= new TypeLookupExpression ("System", "UInt32");
228 system_int64_expr
= new TypeLookupExpression ("System", "Int64");
229 system_uint64_expr
= new TypeLookupExpression ("System", "UInt64");
230 system_char_expr
= new TypeLookupExpression ("System", "Char");
231 system_void_expr
= new TypeLookupExpression ("System", "Void");
232 system_valuetype_expr
= new TypeLookupExpression ("System", "ValueType");
233 system_intptr_expr
= new TypeLookupExpression ("System", "IntPtr");
236 static TypeManager ()
241 static public void Reset ()
245 InitExpressionTypes ();
247 builder_to_declspace
= new Dictionary
<TypeBuilder
, DeclSpace
> (ReferenceEquality
<TypeBuilder
>.Default
);
248 builder_to_member_cache
= new Dictionary
<Type
, MemberCache
> (ReferenceEquality
<Type
>.Default
);
249 builder_to_method
= new Dictionary
<MethodBase
, IMethodData
> (ReferenceEquality
<MethodBase
>.Default
);
250 builder_to_type_param
= new Dictionary
<GenericTypeParameterBuilder
, TypeParameter
> (ReferenceEquality
<GenericTypeParameterBuilder
>.Default
);
251 method_params
= new Dictionary
<MemberInfo
, AParametersCollection
> (ReferenceEquality
<MemberInfo
>.Default
);
252 method_overrides
= new Dictionary
<MethodBase
, MethodBase
> (ReferenceEquality
<MethodBase
>.Default
);
253 builder_to_ifaces
= new Dictionary
<Type
, Type
[]> (ReferenceEquality
<Type
>.Default
);
255 fieldbuilders_to_fields
= new Dictionary
<FieldInfo
, FieldBase
> (ReferenceEquality
<FieldInfo
>.Default
);
256 propertybuilder_to_property
= new Dictionary
<PropertyInfo
, PropertyBase
> (ReferenceEquality
<PropertyInfo
>.Default
);
257 fields
= new Dictionary
<FieldInfo
, ConstSpec
> (ReferenceEquality
<FieldInfo
>.Default
);
258 type_hash
= new DoubleHash ();
259 assembly_internals_vis_attrs
= new Dictionary
<Assembly
, bool> ();
260 iface_cache
= new Dictionary
<Type
, Type
[]> (ReferenceEquality
<Type
>.Default
);
262 closure
= new Closure ();
263 FilterWithClosure_delegate
= new MemberFilter (closure
.Filter
);
265 // TODO: I am really bored by all this static stuff
266 system_type_get_type_from_handle
=
269 void_monitor_enter_object
=
270 void_monitor_exit_object
=
271 void_initializearray_array_fieldhandle
=
272 int_interlocked_compare_exchange
=
273 methodbase_get_type_from_handle
=
274 methodbase_get_type_from_handle_generic
=
275 fieldinfo_get_field_from_handle
=
276 fieldinfo_get_field_from_handle_generic
=
277 activator_create_instance
=
278 delegate_combine_delegate_delegate
=
279 delegate_remove_delegate_delegate
= null;
281 int_get_offset_to_string_data
=
282 ienumerator_getcurrent
= null;
284 void_decimal_ctor_five_args
=
285 void_decimal_ctor_int_arg
=
286 void_decimal_ctor_long_arg
= null;
288 isvolatile_type
= null;
291 generic_call_site_type
=
296 // to uncover regressions
297 AllClsTopLevelTypes
= null;
300 public static void AddUserType (DeclSpace ds
)
302 builder_to_declspace
.Add (ds
.TypeBuilder
, ds
);
306 // This entry point is used by types that we define under the covers
308 public static void RegisterBuilder (Type tb
, Type
[] ifaces
)
311 builder_to_ifaces
[tb
] = ifaces
;
314 public static void AddMethod (MethodBase builder
, IMethodData method
)
316 builder_to_method
.Add (builder
, method
);
317 method_params
.Add (builder
, method
.ParameterInfo
);
320 public static IMethodData
GetMethod (MethodBase builder
)
323 if (builder_to_method
.TryGetValue (builder
, out md
))
329 /// Returns the DeclSpace whose Type is `t' or null if there is no
330 /// DeclSpace for `t' (ie, the Type comes from a library)
332 public static DeclSpace
LookupDeclSpace (Type t
)
335 var tb
= t
as TypeBuilder
;
336 if (tb
!= null && builder_to_declspace
.TryGetValue (tb
, out ds
))
343 /// Returns the TypeContainer whose Type is `t' or null if there is no
344 /// TypeContainer for `t' (ie, the Type comes from a library)
346 public static TypeContainer
LookupTypeContainer (Type t
)
348 return LookupDeclSpace (t
) as TypeContainer
;
351 public static MemberCache
LookupMemberCache (Type t
)
353 if (IsBeingCompiled (t
)) {
354 DeclSpace container
= LookupDeclSpace (t
);
355 if (container
!= null)
356 return container
.MemberCache
;
359 if (t
is GenericTypeParameterBuilder
) {
360 TypeParameter container
;
361 if (builder_to_type_param
.TryGetValue ((GenericTypeParameterBuilder
) t
, out container
))
362 return container
.MemberCache
;
365 return TypeHandle
.GetMemberCache (t
);
368 public static MemberCache
LookupBaseInterfacesCache (Type t
)
370 Type
[] ifaces
= GetInterfaces (t
);
372 if (ifaces
!= null && ifaces
.Length
== 1)
373 return LookupMemberCache (ifaces
[0]);
375 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
377 if (builder_to_member_cache
.TryGetValue (t
, out cache
))
380 cache
= new MemberCache (ifaces
);
381 builder_to_member_cache
.Add (t
, cache
);
385 public static TypeContainer
LookupInterface (Type t
)
387 TypeContainer tc
= LookupTypeContainer (t
);
388 if ((tc
== null) || (tc
.Kind
!= MemberKind
.Interface
))
394 public static Delegate
LookupDelegate (Type t
)
396 return LookupDeclSpace (t
) as Delegate
;
399 public static Class
LookupClass (Type t
)
401 return LookupDeclSpace (t
) as Class
;
405 // We use this hash for multiple kinds of constructed types:
407 // (T, "&") Given T, get T &
408 // (T, "*") Given T, get T *
409 // (T, "[]") Given T and a array dimension, get T []
410 // (T, X) Given a type T and a simple name X, get the type T+X
412 // Accessibility tests, if necessary, should be done by the user
414 static DoubleHash type_hash
= new DoubleHash ();
417 // Gets the reference to T version of the Type (T&)
419 public static Type
GetReferenceType (Type t
)
421 return t
.MakeByRefType ();
425 // Gets the pointer to T version of the Type (T*)
427 public static Type
GetPointerType (Type t
)
429 return GetConstructedType (t
, "*");
432 public static Type
GetConstructedType (Type t
, string dim
)
435 if (type_hash
.Lookup (t
, dim
, out ret
))
438 if (IsDynamicType (t
)) {
439 ret
= new DynamicArrayType (dim
.Length
- 1);
440 type_hash
.Insert (t
, dim
, ret
);
444 ret
= t
.Module
.GetType (t
.ToString () + dim
);
446 type_hash
.Insert (t
, dim
, ret
);
451 ret
= GetReferenceType (t
);
452 type_hash
.Insert (t
, dim
, ret
);
456 if (t
.IsGenericParameter
|| t
.IsGenericType
) {
459 while ((pos
< dim
.Length
) && (dim
[pos
] == '[')) {
462 if (dim
[pos
] == ']') {
463 result
= result
.MakeArrayType ();
466 if (pos
< dim
.Length
)
469 type_hash
.Insert (t
, dim
, result
);
474 while (dim
[pos
] == ',') {
478 if ((dim
[pos
] != ']') || (pos
!= dim
.Length
-1))
481 result
= result
.MakeArrayType (rank
+ 1);
482 type_hash
.Insert (t
, dim
, result
);
487 type_hash
.Insert (t
, dim
, null);
491 public static Type
GetNestedType (Type t
, string name
)
494 if (!type_hash
.Lookup (t
, name
, out ret
)) {
495 ret
= t
.GetNestedType (name
,
496 BindingFlags
.Static
| BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.DeclaredOnly
);
497 type_hash
.Insert (t
, name
, ret
);
503 /// Fills static table with exported types from all referenced assemblies.
504 /// This information is required for CLS Compliance tests.
506 public static void LoadAllImportedTypes ()
508 AllClsTopLevelTypes
= new Dictionary
<string, object> (1500);
509 foreach (Assembly a
in GlobalRootNamespace
.Instance
.Assemblies
) {
510 foreach (Type t
in a
.GetExportedTypes ()) {
511 AllClsTopLevelTypes
[t
.FullName
.ToLower (System
.Globalization
.CultureInfo
.InvariantCulture
)] = null;
517 /// Returns the C# name of a type if possible, or the full type name otherwise
519 static public string CSharpName (Type t
)
524 if (t
== typeof (ArglistAccess
))
527 if (t
== typeof (AnonymousMethodBody
))
528 return "anonymous method";
530 if (t
== typeof (MethodGroupExpr
))
531 return "method group";
533 if (IsDynamicType (t
))
537 return "internal error";
539 return CSharpName (GetFullName (t
), t
);
542 static readonly char [] elements
= new char [] { '*', '[' }
;
544 public static string CSharpName (string name
, Type type
)
546 if (name
.Length
> 10) {
549 case "System.Int32": s
= "int"; break;
550 case "System.Int64": s
= "long"; break;
551 case "System.String": s
= "string"; break;
552 case "System.Boolean": s
= "bool"; break;
553 case "System.Void": s
= "void"; break;
554 case "System.Object": s
= "object"; break;
555 case "System.UInt32": s
= "uint"; break;
556 case "System.Int16": s
= "short"; break;
557 case "System.UInt16": s
= "ushort"; break;
558 case "System.UInt64": s
= "ulong"; break;
559 case "System.Single": s
= "float"; break;
560 case "System.Double": s
= "double"; break;
561 case "System.Decimal": s
= "decimal"; break;
562 case "System.Char": s
= "char"; break;
563 case "System.Byte": s
= "byte"; break;
564 case "System.SByte": s
= "sbyte"; break;
565 default: s
= null; break;
570 // Predefined names can come from mscorlib only
572 if (type
== null || type
.Module
.Name
== "mscorlib.dll" || !RootContext
.StdLib
)
578 if (name
[0] == AnonymousTypeClass
.ClassNamePrefix
[0] && name
.StartsWith (AnonymousTypeClass
.ClassNamePrefix
))
579 return AnonymousTypeClass
.SignatureForError
;
581 int idx
= name
.IndexOfAny (elements
, 10);
583 return CSharpName (name
.Substring (0, idx
), type
) + name
.Substring (idx
);
586 return name
.Replace ('+', '.');
589 static public string CSharpName (Type
[] types
)
591 if (types
.Length
== 0)
594 StringBuilder sb
= new StringBuilder ();
595 for (int i
= 0; i
< types
.Length
; ++i
) {
599 sb
.Append (CSharpName (types
[i
]));
601 return sb
.ToString ();
605 /// Returns the signature of the method with full namespace classification
607 static public string GetFullNameSignature (MemberInfo mi
)
609 PropertyInfo pi
= mi
as PropertyInfo
;
611 MethodBase pmi
= pi
.GetGetMethod (true);
613 pmi
= pi
.GetSetMethod (true);
614 if (GetParameterData (pmi
).Count
> 0)
617 return (mi
is MethodBase
)
618 ? CSharpSignature (mi
as MethodBase
)
619 : CSharpName (mi
.DeclaringType
) + '.' + mi
.Name
;
622 private static int GetFullName (Type t
, StringBuilder sb
)
626 if (!t
.IsGenericType
) {
627 sb
.Append (t
.FullName
);
631 if (t
.DeclaringType
!= null) {
632 pos
= GetFullName (t
.DeclaringType
, sb
);
634 } else if (t
.Namespace
!= null && t
.Namespace
.Length
!= 0) {
635 sb
.Append (t
.Namespace
);
638 sb
.Append (RemoveGenericArity (t
.Name
));
640 Type
[] this_args
= GetTypeArguments (t
);
642 if (this_args
.Length
< pos
)
643 throw new InternalErrorException (
644 "Enclosing class " + t
.DeclaringType
+ " has more type arguments than " + t
);
645 if (this_args
.Length
== pos
)
650 sb
.Append (CSharpName (this_args
[pos
++]));
651 if (pos
== this_args
.Length
)
659 static string GetFullName (Type t
)
662 string dimension
= t
.Name
.Substring (t
.Name
.LastIndexOf ('['));
663 return GetFullName (GetElementType (t
)) + dimension
;
666 if (IsNullableType (t
) && !t
.IsGenericTypeDefinition
) {
667 t
= TypeToCoreType (GetTypeArguments (t
)[0]);
668 return CSharpName (t
) + "?";
671 if (t
.IsGenericParameter
)
673 if (!t
.IsGenericType
)
676 StringBuilder sb
= new StringBuilder ();
677 int pos
= GetFullName (t
, sb
);
679 throw new InternalErrorException ("Generic Type " + t
+ " doesn't have type arguments");
680 return sb
.ToString ();
683 public static string RemoveGenericArity (string from)
685 int i
= from.IndexOf ('`');
687 return from.Substring (0, i
);
692 /// When we need to report accessors as well
694 static public string CSharpSignature (MethodBase mb
)
696 return CSharpSignature (mb
, false);
699 static public string CSharpSignature (MethodSpec ms
)
701 return CSharpSignature (ms
.MetaInfo
);
705 /// Returns the signature of the method
707 static public string CSharpSignature (MethodBase mb
, bool show_accessor
)
709 StringBuilder sig
= new StringBuilder (CSharpName (mb
.DeclaringType
));
712 AParametersCollection iparams
= GetParameterData (mb
);
713 string parameters
= iparams
.GetSignatureForError ();
714 int accessor_end
= 0;
716 if (!mb
.IsConstructor
&& TypeManager
.IsSpecialMethod (mb
)) {
717 string op_name
= Operator
.GetName (mb
.Name
);
718 if (op_name
!= null) {
719 if (op_name
== "explicit" || op_name
== "implicit") {
720 sig
.Append (op_name
);
721 sig
.Append (" operator ");
722 sig
.Append (CSharpName (((MethodInfo
)mb
).ReturnType
));
724 sig
.Append ("operator ");
725 sig
.Append (op_name
);
727 sig
.Append (parameters
);
728 return sig
.ToString ();
731 bool is_getter
= mb
.Name
.StartsWith ("get_");
732 bool is_setter
= mb
.Name
.StartsWith ("set_");
733 if (is_getter
|| is_setter
|| mb
.Name
.StartsWith ("add_")) {
735 } else if (mb
.Name
.StartsWith ("remove_")) {
740 if (iparams
.Count
> (is_getter
? 0 : 1)) {
741 sig
.Append ("this[");
743 sig
.Append (parameters
.Substring (1, parameters
.Length
- 2));
745 sig
.Append (parameters
.Substring (1, parameters
.LastIndexOf (',') - 1));
748 sig
.Append (mb
.Name
.Substring (accessor_end
+ 1));
751 if (mb
.Name
== ".ctor")
752 sig
.Append (RemoveGenericArity (mb
.DeclaringType
.Name
));
754 sig
.Append (mb
.Name
);
756 if (IsGenericMethod (mb
)) {
757 Type
[] args
= GetGenericArguments (mb
);
759 for (int i
= 0; i
< args
.Length
; i
++) {
762 sig
.Append (CSharpName (args
[i
]));
768 sig
.Append (parameters
);
771 if (show_accessor
&& accessor_end
> 0) {
773 sig
.Append (mb
.Name
.Substring (0, accessor_end
));
776 return sig
.ToString ();
779 public static string GetMethodName (MethodInfo m
)
781 if (!IsGenericMethodDefinition (m
) && !IsGenericMethod (m
))
784 return MemberName
.MakeName (m
.Name
, TypeManager
.GetGenericArguments (m
).Length
);
787 static public string CSharpSignature (EventInfo ei
)
789 return CSharpName (ei
.DeclaringType
) + "." + ei
.Name
;
793 // Looks up a type, and aborts if it is not found. This is used
794 // by predefined types required by the compiler
796 public static Type
CoreLookupType (CompilerContext ctx
, string ns_name
, string name
, MemberKind type_kind
, bool required
)
798 Namespace ns
= GlobalRootNamespace
.Instance
.GetNamespace (ns_name
, true);
799 Expression expr
= ns
.Lookup (ctx
, name
, Location
.Null
);
803 ctx
.Report
.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
810 if (RootContext
.StdLib
|| t
== null || !required
)
813 // TODO: All predefined imported types have to have correct signature
814 if (!IsBeingCompiled (t
))
817 DeclSpace ds
= (DeclSpace
)RootContext
.ToplevelTypes
.GetDefinition (t
.FullName
);
818 if (ds
is Delegate
) {
819 if (type_kind
== MemberKind
.Delegate
)
822 TypeContainer tc
= (TypeContainer
)ds
;
823 if (tc
.Kind
== type_kind
)
827 ctx
.Report
.Error (520, ds
.Location
, "The predefined type `{0}.{1}' is not declared correctly",
832 static MemberInfo
GetPredefinedMember (Type t
, string name
, MemberTypes mt
, Location loc
, params Type
[] args
)
834 const BindingFlags flags
= instance_and_static
| BindingFlags
.Public
| BindingFlags
.DeclaredOnly
;
836 MemberInfo
[] members
= MemberLookup (null, null, t
, mt
, flags
, name
, null);
837 if (members
!= null) {
838 for (int i
= 0; i
< members
.Length
; ++i
) {
839 MemberInfo member
= members
[i
];
840 if (mt
== MemberTypes
.Method
|| mt
== MemberTypes
.Constructor
) {
841 MethodBase mb
= member
as MethodBase
;
845 AParametersCollection pd
= TypeManager
.GetParameterData (mb
);
846 if (IsEqual (pd
.Types
, args
))
849 if (mt
== MemberTypes
.Field
) {
850 FieldInfo fi
= member
as FieldInfo
;
854 if (args
.Length
>= 1 && !IsEqual (TypeToCoreType (fi
.FieldType
), args
[0]))
860 if (mt
== MemberTypes
.Property
) {
861 PropertyInfo pi
= member
as PropertyInfo
;
865 if (args
.Length
>= 1 && !IsEqual (TypeToCoreType (pi
.PropertyType
), args
[0]))
873 string method_args
= null;
874 if (mt
== MemberTypes
.Method
|| mt
== MemberTypes
.Constructor
)
875 method_args
= "(" + TypeManager
.CSharpName (args
) + ")";
877 RootContext
.ToplevelTypes
.Compiler
.Report
.Error (656, loc
, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
878 TypeManager
.CSharpName (t
), name
, method_args
);
884 // Returns the ConstructorInfo for "args"
886 public static ConstructorInfo
GetPredefinedConstructor (Type t
, Location loc
, params Type
[] args
)
888 return (ConstructorInfo
) GetPredefinedMember (t
, ConstructorInfo
.ConstructorName
, MemberTypes
.Constructor
, loc
, args
);
892 // Returns the MethodInfo for a method named `name' defined
893 // in type `t' which takes arguments of types `args'
895 public static MethodSpec
GetPredefinedMethod (Type t
, string name
, Location loc
, params Type
[] args
)
897 var m
= GetPredefinedMember (t
, name
, MemberTypes
.Method
, loc
, args
) as MethodBase
;
901 return Import
.CreateMethod (m
);
904 public static FieldInfo
GetPredefinedField (Type t
, string name
, Location loc
, params Type
[] args
)
906 return (FieldInfo
) GetPredefinedMember (t
, name
, MemberTypes
.Field
, loc
, args
);
909 public static PropertySpec
GetPredefinedProperty (Type t
, string name
, Location loc
, params Type
[] args
)
911 var p
= GetPredefinedMember (t
, name
, MemberTypes
.Property
, loc
, args
) as PropertyInfo
;
914 return Import
.CreateProperty (p
);
918 /// The types have to be initialized after the initial
919 /// population of the type has happened (for example, to
920 /// bootstrap the corlib.dll
922 public static bool InitCoreTypes (CompilerContext ctx
)
924 object_type
= CoreLookupType (ctx
, "System", "Object", MemberKind
.Class
, true);
925 system_object_expr
.Type
= object_type
;
926 value_type
= CoreLookupType (ctx
, "System", "ValueType", MemberKind
.Class
, true);
927 system_valuetype_expr
.Type
= value_type
;
928 attribute_type
= CoreLookupType (ctx
, "System", "Attribute", MemberKind
.Class
, true);
930 int32_type
= CoreLookupType (ctx
, "System", "Int32", MemberKind
.Struct
, true);
931 system_int32_expr
.Type
= int32_type
;
932 int64_type
= CoreLookupType (ctx
, "System", "Int64", MemberKind
.Struct
, true);
933 system_int64_expr
.Type
= int64_type
;
934 uint32_type
= CoreLookupType (ctx
, "System", "UInt32", MemberKind
.Struct
, true);
935 system_uint32_expr
.Type
= uint32_type
;
936 uint64_type
= CoreLookupType (ctx
, "System", "UInt64", MemberKind
.Struct
, true);
937 system_uint64_expr
.Type
= uint64_type
;
938 byte_type
= CoreLookupType (ctx
, "System", "Byte", MemberKind
.Struct
, true);
939 system_byte_expr
.Type
= byte_type
;
940 sbyte_type
= CoreLookupType (ctx
, "System", "SByte", MemberKind
.Struct
, true);
941 system_sbyte_expr
.Type
= sbyte_type
;
942 short_type
= CoreLookupType (ctx
, "System", "Int16", MemberKind
.Struct
, true);
943 system_int16_expr
.Type
= short_type
;
944 ushort_type
= CoreLookupType (ctx
, "System", "UInt16", MemberKind
.Struct
, true);
945 system_uint16_expr
.Type
= ushort_type
;
947 ienumerator_type
= CoreLookupType (ctx
, "System.Collections", "IEnumerator", MemberKind
.Interface
, true);
948 ienumerable_type
= CoreLookupType (ctx
, "System.Collections", "IEnumerable", MemberKind
.Interface
, true);
949 idisposable_type
= CoreLookupType (ctx
, "System", "IDisposable", MemberKind
.Interface
, true);
951 // HACK: DefineType immediately resolves iterators (very wrong)
952 generic_ienumerator_type
= CoreLookupType (ctx
, "System.Collections.Generic", "IEnumerator`1", MemberKind
.Interface
, false);
954 char_type
= CoreLookupType (ctx
, "System", "Char", MemberKind
.Struct
, true);
955 system_char_expr
.Type
= char_type
;
956 string_type
= CoreLookupType (ctx
, "System", "String", MemberKind
.Class
, true);
957 system_string_expr
.Type
= string_type
;
958 float_type
= CoreLookupType (ctx
, "System", "Single", MemberKind
.Struct
, true);
959 system_single_expr
.Type
= float_type
;
960 double_type
= CoreLookupType (ctx
, "System", "Double", MemberKind
.Struct
, true);
961 system_double_expr
.Type
= double_type
;
962 decimal_type
= CoreLookupType (ctx
, "System", "Decimal", MemberKind
.Struct
, true);
963 system_decimal_expr
.Type
= decimal_type
;
964 bool_type
= CoreLookupType (ctx
, "System", "Boolean", MemberKind
.Struct
, true);
965 system_boolean_expr
.Type
= bool_type
;
966 intptr_type
= CoreLookupType (ctx
, "System", "IntPtr", MemberKind
.Struct
, true);
967 system_intptr_expr
.Type
= intptr_type
;
968 uintptr_type
= CoreLookupType (ctx
, "System", "UIntPtr", MemberKind
.Struct
, true);
970 multicast_delegate_type
= CoreLookupType (ctx
, "System", "MulticastDelegate", MemberKind
.Class
, true);
971 delegate_type
= CoreLookupType (ctx
, "System", "Delegate", MemberKind
.Class
, true);
973 enum_type
= CoreLookupType (ctx
, "System", "Enum", MemberKind
.Class
, true);
974 array_type
= CoreLookupType (ctx
, "System", "Array", MemberKind
.Class
, true);
975 void_type
= CoreLookupType (ctx
, "System", "Void", MemberKind
.Struct
, true);
976 system_void_expr
.Type
= void_type
;
977 type_type
= CoreLookupType (ctx
, "System", "Type", MemberKind
.Class
, true);
978 exception_type
= CoreLookupType (ctx
, "System", "Exception", MemberKind
.Class
, true);
980 runtime_field_handle_type
= CoreLookupType (ctx
, "System", "RuntimeFieldHandle", MemberKind
.Struct
, true);
981 runtime_handle_type
= CoreLookupType (ctx
, "System", "RuntimeTypeHandle", MemberKind
.Struct
, true);
983 PredefinedAttributes
.Get
.ParamArray
.Initialize (ctx
, false);
984 PredefinedAttributes
.Get
.Out
.Initialize (ctx
, false);
986 return ctx
.Report
.Errors
== 0;
990 // Initializes optional core types
992 public static void InitOptionalCoreTypes (CompilerContext ctx
)
995 // These are only used for compare purposes
997 null_type
= typeof (NullLiteral
);
999 void_ptr_type
= GetPointerType (void_type
);
1002 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
1003 // types cache with incorrect accessiblity when any of optional types is internal.
1005 PredefinedAttributes
.Get
.Initialize (ctx
);
1007 runtime_argument_handle_type
= CoreLookupType (ctx
, "System", "RuntimeArgumentHandle", MemberKind
.Struct
, false);
1008 asynccallback_type
= CoreLookupType (ctx
, "System", "AsyncCallback", MemberKind
.Delegate
, false);
1009 iasyncresult_type
= CoreLookupType (ctx
, "System", "IAsyncResult", MemberKind
.Interface
, false);
1010 typed_reference_type
= CoreLookupType (ctx
, "System", "TypedReference", MemberKind
.Struct
, false);
1011 arg_iterator_type
= CoreLookupType (ctx
, "System", "ArgIterator", MemberKind
.Struct
, false);
1012 mbr_type
= CoreLookupType (ctx
, "System", "MarshalByRefObject", MemberKind
.Class
, false);
1015 // Optional attributes, used for error reporting only
1017 //if (PredefinedAttributes.Get.Obsolete.IsDefined) {
1018 // Class c = TypeManager.LookupClass (PredefinedAttributes.Get.Obsolete.Type);
1023 generic_ilist_type
= CoreLookupType (ctx
, "System.Collections.Generic", "IList`1", MemberKind
.Interface
, false);
1024 generic_icollection_type
= CoreLookupType (ctx
, "System.Collections.Generic", "ICollection`1", MemberKind
.Interface
, false);
1025 generic_ienumerable_type
= CoreLookupType (ctx
, "System.Collections.Generic", "IEnumerable`1", MemberKind
.Interface
, false);
1026 generic_nullable_type
= CoreLookupType (ctx
, "System", "Nullable`1", MemberKind
.Struct
, false);
1029 // Optional types which are used as types and for member lookup
1031 runtime_helpers_type
= CoreLookupType (ctx
, "System.Runtime.CompilerServices", "RuntimeHelpers", MemberKind
.Class
, false);
1034 // Note: extension_attribute_type is already loaded
1035 expression_type
= CoreLookupType (ctx
, "System.Linq.Expressions", "Expression`1", MemberKind
.Class
, false);
1037 if (!RootContext
.StdLib
) {
1039 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1040 // has different predefined types and this method sets mscorlib types
1041 // to be same to avoid any type check errors.
1044 Type type
= typeof (Type
);
1045 Type
[] system_4_type_arg
= { type, type, type, type }
;
1047 MethodInfo set_corlib_type_builders
=
1048 typeof (System
.Reflection
.Emit
.AssemblyBuilder
).GetMethod (
1049 "SetCorlibTypeBuilders", BindingFlags
.NonPublic
| BindingFlags
.Instance
, null,
1050 system_4_type_arg
, null);
1052 if (set_corlib_type_builders
!= null) {
1053 object[] args
= new object [4];
1054 args
[0] = object_type
;
1055 args
[1] = value_type
;
1056 args
[2] = enum_type
;
1057 args
[3] = void_type
;
1059 set_corlib_type_builders
.Invoke (CodeGen
.Assembly
.Builder
, args
);
1061 ctx
.Report
.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1062 TypeManager
.CSharpName (typeof (System
.Reflection
.Emit
.AssemblyBuilder
)),
1063 TypeManager
.CSharpName (system_4_type_arg
));
1068 const BindingFlags instance_and_static
= BindingFlags
.Static
| BindingFlags
.Instance
;
1071 /// This is the "old", non-cache based FindMembers() function. We cannot use
1072 /// the cache here because there is no member name argument.
1074 public static MemberList
FindMembers (Type t
, MemberTypes mt
, BindingFlags bf
,
1075 MemberFilter filter
, object criteria
)
1078 if (t
.IsGenericType
)
1079 t
= t
.GetGenericTypeDefinition ();
1082 DeclSpace decl
= LookupDeclSpace (t
);
1085 // `builder_to_declspace' contains all dynamic types.
1089 Timer
.StartTimer (TimerType
.FindMembers
);
1090 list
= decl
.FindMembers (mt
, bf
, filter
, criteria
);
1091 Timer
.StopTimer (TimerType
.FindMembers
);
1096 // We have to take care of arrays specially, because GetType on
1097 // a TypeBuilder array will return a Type, not a TypeBuilder,
1098 // and we can not call FindMembers on this type.
1104 t
.IsSubclassOf (TypeManager
.array_type
))
1105 return new MemberList (TypeManager
.array_type
.FindMembers (mt
, bf
, filter
, criteria
));
1107 if (t
is GenericTypeParameterBuilder
) {
1108 TypeParameter tparam
= builder_to_type_param
[(GenericTypeParameterBuilder
) t
];
1110 Timer
.StartTimer (TimerType
.FindMembers
);
1111 MemberList list
= tparam
.FindMembers (
1112 mt
, bf
| BindingFlags
.DeclaredOnly
, filter
, criteria
);
1113 Timer
.StopTimer (TimerType
.FindMembers
);
1118 // Since FindMembers will not lookup both static and instance
1119 // members, we emulate this behaviour here.
1121 if ((bf
& instance_and_static
) == instance_and_static
){
1122 MemberInfo
[] i_members
= t
.FindMembers (
1123 mt
, bf
& ~BindingFlags
.Static
, filter
, criteria
);
1125 int i_len
= i_members
.Length
;
1127 MemberInfo one
= i_members
[0];
1130 // If any of these are present, we are done!
1132 if ((one
is Type
) || (one
is EventInfo
) || (one
is FieldInfo
))
1133 return new MemberList (i_members
);
1136 MemberInfo
[] s_members
= t
.FindMembers (
1137 mt
, bf
& ~BindingFlags
.Instance
, filter
, criteria
);
1139 int s_len
= s_members
.Length
;
1140 if (i_len
> 0 || s_len
> 0)
1141 return new MemberList (i_members
, s_members
);
1144 return new MemberList (i_members
);
1146 return new MemberList (s_members
);
1150 return new MemberList (t
.FindMembers (mt
, bf
, filter
, criteria
));
1155 /// This method is only called from within MemberLookup. It tries to use the member
1156 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1157 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1158 /// our return value will already contain all inherited members and the caller don't need
1159 /// to check base classes and interfaces anymore.
1161 private static MemberInfo
[] MemberLookup_FindMembers (Type t
, MemberTypes mt
, BindingFlags bf
,
1162 string name
, out bool used_cache
)
1167 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1168 // and we can ask the DeclSpace for the MemberCache.
1171 if (t
.Assembly
== CodeGen
.Assembly
.Builder
) {
1172 if (t
.IsGenericParameter
) {
1173 TypeParameter tparam
= builder_to_type_param
[(GenericTypeParameterBuilder
) t
];
1176 if (tparam
.MemberCache
== null)
1177 return new MemberInfo
[0];
1179 return tparam
.MemberCache
.FindMembers (
1180 mt
, bf
, name
, FilterWithClosure_delegate
, null);
1184 // We have to take care of arrays specially, because GetType on
1185 // a TypeBuilder array will return a Type, not a TypeBuilder,
1186 // and we can not call FindMembers on this type.
1190 return TypeHandle
.ArrayType
.MemberCache
.FindMembers (
1191 mt
, bf
, name
, FilterWithClosure_delegate
, null);
1194 if (t
.IsGenericType
&& !t
.IsGenericTypeDefinition
)
1195 t
= t
.GetGenericTypeDefinition ();
1197 if (t
is TypeBuilder
) {
1199 DeclSpace decl
= LookupDeclSpace (t
);
1200 cache
= decl
.MemberCache
;
1203 // If this DeclSpace has a MemberCache, use it.
1206 if (cache
!= null) {
1208 return cache
.FindMembers (
1209 mt
, bf
, name
, FilterWithClosure_delegate
, null);
1212 // If there is no MemberCache, we need to use the "normal" FindMembers.
1213 // Note, this is a VERY uncommon route!
1216 Timer
.StartTimer (TimerType
.FindMembers
);
1217 list
= decl
.FindMembers (mt
, bf
| BindingFlags
.DeclaredOnly
,
1218 FilterWithClosure_delegate
, name
);
1219 Timer
.StopTimer (TimerType
.FindMembers
);
1221 return (MemberInfo
[]) list
;
1225 // We have to take care of arrays specially, because GetType on
1226 // a TypeBuilder array will return a Type, not a TypeBuilder,
1227 // and we can not call FindMembers on this type.
1231 return TypeHandle
.ArrayType
.MemberCache
.FindMembers (
1232 mt
, bf
, name
, FilterWithClosure_delegate
, null);
1235 if (t
is GenericTypeParameterBuilder
) {
1236 TypeParameter tparam
= builder_to_type_param
[(GenericTypeParameterBuilder
) t
];
1239 if (tparam
.MemberCache
== null)
1240 return new MemberInfo
[0];
1242 return tparam
.MemberCache
.FindMembers (
1243 mt
, bf
, name
, FilterWithClosure_delegate
, null);
1246 if (IsGenericType (t
) && (mt
== MemberTypes
.NestedType
)) {
1248 // This happens if we're resolving a class'es base class and interfaces
1249 // in TypeContainer.DefineType(). At this time, the types aren't
1250 // populated yet, so we can't use the cache.
1252 MemberInfo
[] info
= t
.FindMembers (mt
, bf
| BindingFlags
.DeclaredOnly
,
1253 FilterWithClosure_delegate
, name
);
1259 // This call will always succeed. There is exactly one TypeHandle instance per
1260 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1261 // the corresponding MemberCache.
1263 cache
= TypeHandle
.GetMemberCache (t
);
1266 return cache
.FindMembers (mt
, bf
, name
, FilterWithClosure_delegate
, null);
1270 // Return true for SRE dynamic/unclosed members
1272 public static bool IsBeingCompiled (MemberInfo mi
)
1274 return mi
.Module
.Assembly
== CodeGen
.Assembly
.Builder
;
1277 public static bool IsBuiltinType (Type t
)
1279 t
= TypeToCoreType (t
);
1280 if (t
== object_type
|| t
== string_type
|| t
== int32_type
|| t
== uint32_type
||
1281 t
== int64_type
|| t
== uint64_type
|| t
== float_type
|| t
== double_type
||
1282 t
== char_type
|| t
== short_type
|| t
== decimal_type
|| t
== bool_type
||
1283 t
== sbyte_type
|| t
== byte_type
|| t
== ushort_type
|| t
== void_type
)
1290 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1291 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1293 public static bool IsPrimitiveType (Type t
)
1295 return (t
== int32_type
|| t
== uint32_type
||
1296 t
== int64_type
|| t
== uint64_type
|| t
== float_type
|| t
== double_type
||
1297 t
== char_type
|| t
== short_type
|| t
== bool_type
||
1298 t
== sbyte_type
|| t
== byte_type
|| t
== ushort_type
);
1301 public static bool IsDelegateType (Type t
)
1303 if (TypeManager
.IsGenericParameter (t
))
1306 if (t
== TypeManager
.delegate_type
|| t
== TypeManager
.multicast_delegate_type
)
1309 t
= DropGenericTypeArguments (t
);
1310 return IsSubclassOf (t
, TypeManager
.delegate_type
);
1314 // Is a type of dynamic type
1316 public static bool IsDynamicType (Type t
)
1318 if (object.ReferenceEquals (InternalType
.Dynamic
, t
))
1321 if (t
!= object_type
)
1324 if (IsBeingCompiled (t
))
1327 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Dynamic
;
1331 object[] res
= t
.GetCustomAttributes (pa
.Type
, false);
1332 return res
!= null && res
.Length
!= 0;
1336 // When any element of the type is a dynamic type
1338 // This method builds a transformation array for dynamic types
1339 // used in places where DynamicAttribute cannnot be applied to.
1340 // It uses bool flag when type is of dynamic type and each
1341 // section always starts with "false" for some reason.
1343 // LAMESPEC: This should be part of C# specification !
1345 // Example: Func<dynamic, int, dynamic[]>
1346 // Transformation: { false, true, false, false, true }
1348 public static bool[] HasDynamicTypeUsed (Type t
)
1350 if (t
is DynamicArrayType
)
1351 return new bool[] { false, true }
;
1356 if (IsGenericType (t
)) {
1357 List
<bool> transform
= null;
1358 var targs
= GetTypeArguments (t
);
1359 for (int i
= 0; i
< targs
.Length
; ++i
) {
1360 var element
= HasDynamicTypeUsed (targs
[i
]);
1361 if (element
!= null) {
1362 if (transform
== null) {
1363 transform
= new List
<bool> ();
1364 for (int ii
= 0; ii
<= i
; ++ii
)
1365 transform
.Add (false);
1368 transform
.AddRange (element
);
1369 } else if (transform
!= null) {
1370 transform
.Add (false);
1374 if (transform
!= null)
1375 return transform
.ToArray ();
1378 if (object.ReferenceEquals (InternalType
.Dynamic
, t
))
1379 return new bool [] { true }
;
1384 public static bool IsEnumType (Type t
)
1386 t
= DropGenericTypeArguments (t
);
1387 return t
.BaseType
== TypeManager
.enum_type
;
1390 public static bool IsBuiltinOrEnum (Type t
)
1392 if (IsBuiltinType (t
))
1401 public static bool IsAttributeType (Type t
)
1403 return t
== attribute_type
&& t
.BaseType
!= null || IsSubclassOf (t
, attribute_type
);
1407 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1409 // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
1410 public static bool IsUnmanagedType (Type t
)
1412 DeclSpace ds
= TypeManager
.LookupDeclSpace (t
);
1414 return ds
.IsUnmanagedType ();
1416 // builtins that are not unmanaged types
1417 if (t
== TypeManager
.object_type
|| t
== TypeManager
.string_type
)
1420 if (IsGenericType (t
) || IsGenericParameter (t
))
1423 if (IsBuiltinOrEnum (t
))
1426 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1428 return IsUnmanagedType (GetElementType (t
));
1430 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1434 if (!IsValueType (t
))
1437 for (Type p
= t
.DeclaringType
; p
!= null; p
= p
.DeclaringType
) {
1438 if (IsGenericTypeDefinition (p
))
1444 FieldInfo
[] fields
= t
.GetFields (BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
);
1446 foreach (FieldInfo f
in fields
){
1447 if (!IsUnmanagedType (f
.FieldType
)){
1457 // Null is considered to be a reference type
1459 public static bool IsReferenceType (Type t
)
1461 if (TypeManager
.IsGenericParameter (t
)) {
1462 GenericConstraints constraints
= TypeManager
.GetTypeParameterConstraints (t
);
1463 if (constraints
== null)
1466 return constraints
.IsReferenceType
;
1469 return !IsStruct (t
) && !IsEnumType (t
);
1472 public static bool IsValueType (Type t
)
1474 if (TypeManager
.IsGenericParameter (t
)) {
1475 GenericConstraints constraints
= TypeManager
.GetTypeParameterConstraints (t
);
1476 if (constraints
== null)
1479 return constraints
.IsValueType
;
1482 return IsStruct (t
) || IsEnumType (t
);
1485 public static bool IsStruct (Type t
)
1487 return t
.BaseType
== value_type
&& t
!= enum_type
&& t
.IsSealed
;
1490 public static bool IsInterfaceType (Type t
)
1492 TypeContainer tc
= LookupTypeContainer (t
);
1496 return tc
.Kind
== MemberKind
.Interface
;
1499 public static bool IsSubclassOf (Type type
, Type base_type
)
1501 TypeParameter tparam
= LookupTypeParameter (type
);
1502 TypeParameter pparam
= LookupTypeParameter (base_type
);
1504 if ((tparam
!= null) && (pparam
!= null)) {
1505 if (tparam
== pparam
)
1508 return tparam
.IsSubclassOf (base_type
);
1512 if (tparam
!= pparam
)
1515 if (type
.IsGenericType
)
1516 type
= type
.GetGenericTypeDefinition ();
1519 if (type
.IsSubclassOf (base_type
))
1523 if (IsEqual (type
, base_type
))
1526 type
= type
.BaseType
;
1527 } while (type
!= null);
1532 public static bool IsPrivateAccessible (Type type
, Type parent
)
1537 if (type
.Equals (parent
))
1540 return DropGenericTypeArguments (type
) == DropGenericTypeArguments (parent
);
1543 public static bool IsFamilyAccessible (Type type
, Type parent
)
1545 TypeParameter tparam
= LookupTypeParameter (type
);
1546 TypeParameter pparam
= LookupTypeParameter (parent
);
1548 if ((tparam
!= null) && (pparam
!= null)) {
1549 if (tparam
== pparam
)
1552 return tparam
.IsSubclassOf (parent
);
1556 if (IsInstantiationOfSameGenericType (type
, parent
))
1559 type
= type
.BaseType
;
1560 } while (type
!= null);
1566 // Checks whether `type' is a subclass or nested child of `base_type'.
1568 public static bool IsNestedFamilyAccessible (Type type
, Type base_type
)
1571 if (IsFamilyAccessible (type
, base_type
))
1574 // Handle nested types.
1575 type
= type
.DeclaringType
;
1576 } while (type
!= null);
1582 // Checks whether `type' is a nested child of `parent'.
1584 public static bool IsNestedChildOf (Type type
, Type parent
)
1589 type
= DropGenericTypeArguments (type
);
1590 parent
= DropGenericTypeArguments (parent
);
1592 if (IsEqual (type
, parent
))
1595 type
= type
.DeclaringType
;
1596 while (type
!= null) {
1597 if (IsEqual (type
, parent
))
1600 type
= type
.DeclaringType
;
1606 public static bool IsSpecialType (Type t
)
1608 return t
== arg_iterator_type
|| t
== typed_reference_type
;
1612 // Checks whether `invocationAssembly' is same or a friend of the assembly
1614 public static bool IsThisOrFriendAssembly (Assembly invocationAssembly
, Assembly assembly
)
1616 if (assembly
== null)
1617 throw new ArgumentNullException ("assembly");
1619 // TODO: This can happen for constants used at assembly level and
1620 // predefined members
1621 // But there is no way to test for it for now, so it could be abused
1623 if (invocationAssembly
== null)
1624 invocationAssembly
= CodeGen
.Assembly
.Builder
;
1626 if (invocationAssembly
== assembly
)
1630 if (assembly_internals_vis_attrs
.TryGetValue (assembly
, out value))
1633 PredefinedAttribute pa
= PredefinedAttributes
.Get
.InternalsVisibleTo
;
1634 // HACK: Do very early resolve of SRE type checking
1635 if (pa
.Type
== null)
1641 object [] attrs
= assembly
.GetCustomAttributes (pa
.Type
, false);
1642 if (attrs
.Length
== 0) {
1643 assembly_internals_vis_attrs
.Add (assembly
, false);
1647 bool is_friend
= false;
1649 AssemblyName this_name
= CodeGen
.Assembly
.Name
;
1650 byte [] this_token
= this_name
.GetPublicKeyToken ();
1651 foreach (InternalsVisibleToAttribute attr
in attrs
) {
1652 if (attr
.AssemblyName
== null || attr
.AssemblyName
.Length
== 0)
1655 AssemblyName aname
= null;
1657 aname
= new AssemblyName (attr
.AssemblyName
);
1658 } catch (FileLoadException
) {
1659 } catch (ArgumentException
) {
1662 if (aname
== null || aname
.Name
!= this_name
.Name
)
1665 byte [] key_token
= aname
.GetPublicKeyToken ();
1666 if (key_token
!= null) {
1667 if (this_token
.Length
== 0) {
1668 // Same name, but assembly is not strongnamed
1669 Error_FriendAccessNameNotMatching (aname
.FullName
, RootContext
.ToplevelTypes
.Compiler
.Report
);
1673 if (!CompareKeyTokens (this_token
, key_token
))
1681 assembly_internals_vis_attrs
.Add (assembly
, is_friend
);
1685 static bool CompareKeyTokens (byte [] token1
, byte [] token2
)
1687 for (int i
= 0; i
< token1
.Length
; i
++)
1688 if (token1
[i
] != token2
[i
])
1694 static void Error_FriendAccessNameNotMatching (string other_name
, Report Report
)
1697 "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",
1698 other_name
, CodeGen
.Assembly
.Name
.FullName
);
1702 // Do the right thing when returning the element type of an
1703 // array type based on whether we are compiling corlib or not
1705 public static Type
GetElementType (Type t
)
1707 if (RootContext
.StdLib
)
1708 return t
.GetElementType ();
1710 return TypeToCoreType (t
.GetElementType ());
1714 /// This method is not implemented by MS runtime for dynamic types
1716 public static bool HasElementType (Type t
)
1718 return t
.IsArray
|| t
.IsPointer
|| t
.IsByRef
;
1721 public static Type
GetEnumUnderlyingType (Type t
)
1723 t
= DropGenericTypeArguments (t
);
1724 Enum e
= LookupTypeContainer (t
) as Enum
;
1726 return e
.UnderlyingType
;
1729 FieldInfo fi
= GetPredefinedField (t
, Enum
.UnderlyingValueField
, Location
.Null
, Type
.EmptyTypes
);
1731 return TypeManager
.int32_type
;
1733 return TypeToCoreType (fi
.FieldType
);
1737 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1741 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1742 /// for anything which is dynamic, and we need this in a number of places,
1743 /// we register this information here, and use it afterwards.
1745 static public void RegisterMethod (MethodBase mb
, AParametersCollection ip
)
1747 method_params
.Add (mb
, ip
);
1750 static public void RegisterIndexer (PropertyBuilder pb
, AParametersCollection p
)
1752 method_params
.Add (pb
, p
);
1755 static public AParametersCollection
GetParameterData (MethodBase mb
)
1757 AParametersCollection pd
;
1758 if (!method_params
.TryGetValue (mb
, out pd
)) {
1760 if (mb
.IsGenericMethod
&& !mb
.IsGenericMethodDefinition
) {
1761 MethodInfo mi
= ((MethodInfo
) mb
).GetGenericMethodDefinition ();
1762 pd
= GetParameterData (mi
);
1764 if (mi.IsGenericMethod)
1765 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1767 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1769 method_params
.Add (mb
, pd
);
1773 if (mb
.DeclaringType
.Assembly
== CodeGen
.Assembly
.Builder
) {
1774 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1775 TypeManager
.CSharpName (mb
.DeclaringType
) + "." + mb
.Name
);
1778 pd
= ParametersImported
.Create (mb
);
1780 MethodBase generic
= TypeManager
.DropGenericMethodArguments (mb
);
1781 if (generic
!= mb
) {
1782 pd
= TypeManager
.GetParameterData (generic
);
1783 pd
= ParametersImported
.Create (pd
, mb
);
1785 pd
= ParametersImported
.Create (mb
);
1788 method_params
.Add (mb
, pd
);
1793 public static AParametersCollection
GetParameterData (PropertyInfo pi
)
1795 AParametersCollection pd
;
1796 if (!method_params
.TryGetValue (pi
, out pd
)) {
1797 if (pi
is PropertyBuilder
)
1798 return ParametersCompiled
.EmptyReadOnlyParameters
;
1800 ParameterInfo
[] p
= pi
.GetIndexParameters ();
1802 return ParametersCompiled
.EmptyReadOnlyParameters
;
1804 pd
= ParametersImported
.Create (p
, null);
1805 method_params
.Add (pi
, pd
);
1811 public static AParametersCollection
GetDelegateParameters (ResolveContext ec
, Type t
)
1813 Delegate d
= LookupDelegate (t
);
1815 return d
.Parameters
;
1817 var invoke_mb
= Delegate
.GetInvokeMethod (ec
.Compiler
, t
, t
);
1818 return invoke_mb
.Parameters
;
1821 static public void RegisterOverride (MethodBase override_method
, MethodBase base_method
)
1823 if (!method_overrides
.ContainsKey (override_method
))
1824 method_overrides
[override_method
] = base_method
;
1825 if (method_overrides
[override_method
] != base_method
)
1826 throw new InternalErrorException ("Override mismatch: " + override_method
);
1829 static public bool IsOverride (MethodSpec ms
)
1831 MethodBase m
= ms
.MetaInfo
;
1832 m
= DropGenericMethodArguments (m
);
1834 return m
.IsVirtual
&&
1835 (m
.Attributes
& MethodAttributes
.NewSlot
) == 0 &&
1836 (m
is MethodBuilder
|| method_overrides
.ContainsKey (m
));
1839 static public MethodBase
TryGetBaseDefinition (MethodBase m
)
1841 m
= DropGenericMethodArguments (m
);
1843 if (method_overrides
.TryGetValue (m
, out mb
))
1849 public static void RegisterConstant (FieldInfo fb
, ConstSpec ic
)
1851 fields
.Add (fb
, ic
);
1854 public static ConstSpec
GetConstant (FieldInfo fb
)
1860 if (fields
.TryGetValue (fb
, out ic
))
1866 public static void RegisterProperty (PropertyInfo pi
, PropertyBase pb
)
1868 propertybuilder_to_property
.Add (pi
, pb
);
1871 public static PropertyBase
GetProperty (PropertyInfo pi
)
1874 if (propertybuilder_to_property
.TryGetValue (pi
, out pb
))
1880 static public void RegisterFieldBase (FieldBuilder fb
, FieldBase f
)
1882 fieldbuilders_to_fields
.Add (fb
, f
);
1886 // The return value can be null; This will be the case for
1887 // auxiliary FieldBuilders created by the compiler that have no
1888 // real field being declared on the source code
1890 static public FieldBase
GetField (FieldInfo fb
)
1892 return GetFieldCore (GetGenericFieldDefinition (fb
));
1895 static public FieldBase
GetFieldCore (FieldInfo fb
)
1898 if (fieldbuilders_to_fields
.TryGetValue (fb
, out f
))
1904 static public MethodInfo
GetAddMethod (EventInfo ei
)
1906 if (ei
is MyEventBuilder
) {
1907 return ((MyEventBuilder
)ei
).GetAddMethod (true);
1909 return ei
.GetAddMethod (true);
1912 static public MethodInfo
GetRemoveMethod (EventInfo ei
)
1914 if (ei
is MyEventBuilder
) {
1915 return ((MyEventBuilder
)ei
).GetRemoveMethod (true);
1917 return ei
.GetRemoveMethod (true);
1920 static public void RegisterEventField (EventInfo einfo
, EventSpec e
)
1923 events
= new Dictionary
<EventInfo
, EventSpec
> (ReferenceEquality
<EventInfo
>.Default
);
1925 events
.Add (einfo
, e
);
1928 static public EventSpec
GetEventField (EventInfo ei
)
1934 if (events
.TryGetValue (ei
, out value))
1940 public static bool CheckStructCycles (TypeContainer tc
, Dictionary
<TypeContainer
, object> seen
)
1942 var hash
= new Dictionary
<TypeContainer
, object> ();
1943 return CheckStructCycles (tc
, seen
, hash
);
1946 public static bool CheckStructCycles (TypeContainer tc
, Dictionary
<TypeContainer
, object> seen
,
1947 Dictionary
<TypeContainer
, object> hash
)
1949 if ((tc
.Kind
!= MemberKind
.Struct
) || IsBuiltinType (tc
.TypeBuilder
))
1953 // `seen' contains all types we've already visited.
1955 if (seen
.ContainsKey (tc
))
1957 seen
.Add (tc
, null);
1959 if (tc
.Fields
== null)
1962 foreach (FieldBase field
in tc
.Fields
) {
1963 if (field
.Spec
== null || field
.Spec
.IsStatic
)
1966 Type ftype
= field
.Spec
.FieldType
;
1967 TypeContainer ftc
= LookupTypeContainer (ftype
);
1971 if (hash
.ContainsKey (ftc
)) {
1972 tc
.Compiler
.Report
.Error (523, tc
.Location
,
1973 "Struct member `{0}.{1}' of type `{2}' " +
1974 "causes a cycle in the struct layout",
1975 tc
.Name
, field
.Name
, ftc
.Name
);
1980 // `hash' contains all types in the current path.
1982 hash
.Add (tc
, null);
1984 bool ok
= CheckStructCycles (ftc
, seen
, hash
);
1991 if (!seen
.ContainsKey (ftc
))
1992 seen
.Add (ftc
, null);
1999 /// Given an array of interface types, expand and eliminate repeated ocurrences
2000 /// of an interface.
2004 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2007 public static Type
[] ExpandInterfaces (TypeExpr
[] base_interfaces
)
2009 var new_ifaces
= new List
<Type
> ();
2011 foreach (TypeExpr iface
in base_interfaces
){
2012 Type itype
= iface
.Type
;
2014 if (new_ifaces
.Contains (itype
))
2017 new_ifaces
.Add (itype
);
2019 Type
[] implementing
= GetInterfaces (itype
);
2021 foreach (Type imp
in implementing
){
2022 if (!new_ifaces
.Contains (imp
))
2023 new_ifaces
.Add (imp
);
2027 return new_ifaces
.ToArray ();
2030 public static Type
[] ExpandInterfaces (Type
[] base_interfaces
)
2032 var new_ifaces
= new List
<Type
> ();
2034 foreach (Type itype
in base_interfaces
){
2035 if (new_ifaces
.Contains (itype
))
2038 new_ifaces
.Add (itype
);
2040 Type
[] implementing
= GetInterfaces (itype
);
2042 foreach (Type imp
in implementing
){
2043 if (!new_ifaces
.Contains (imp
))
2044 new_ifaces
.Add (imp
);
2048 return new_ifaces
.ToArray ();
2052 /// This function returns the interfaces in the type `t'. Works with
2053 /// both types and TypeBuilders.
2055 public static Type
[] GetInterfaces (Type t
)
2058 if (iface_cache
.TryGetValue (t
, out cached
))
2063 // The reason for catching the Array case is that Reflection.Emit
2064 // will not return a TypeBuilder for Array types of TypeBuilder types,
2065 // but will still throw an exception if we try to call GetInterfaces
2068 // Since the array interfaces are always constant, we return those for
2073 t
= TypeManager
.array_type
;
2075 if ((t
is TypeBuilder
) || IsGenericType (t
)) {
2076 Type
[] base_ifaces
;
2078 if (t
.BaseType
== null)
2079 base_ifaces
= Type
.EmptyTypes
;
2081 base_ifaces
= GetInterfaces (t
.BaseType
);
2083 if (IsGenericType (t
))
2085 type_ifaces
= t
.GetGenericTypeDefinition().GetInterfaces ();
2087 type_ifaces
= t
.GetInterfaces ();
2090 type_ifaces
= GetExplicitInterfaces (t
);
2091 if (type_ifaces
== null || type_ifaces
.Length
== 0)
2092 type_ifaces
= Type
.EmptyTypes
;
2094 int base_count
= base_ifaces
.Length
;
2095 Type
[] result
= new Type
[base_count
+ type_ifaces
.Length
];
2096 base_ifaces
.CopyTo (result
, 0);
2097 type_ifaces
.CopyTo (result
, base_count
);
2099 iface_cache
[t
] = result
;
2101 } else if (t
is GenericTypeParameterBuilder
){
2102 Type
[] type_ifaces
= GetExplicitInterfaces (t
);
2103 if (type_ifaces
== null || type_ifaces
.Length
== 0)
2104 type_ifaces
= Type
.EmptyTypes
;
2106 iface_cache
[t
] = type_ifaces
;
2109 Type
[] ifaces
= t
.GetInterfaces ();
2110 iface_cache
[t
] = ifaces
;
2116 // gets the interfaces that are declared explicitly on t
2118 public static Type
[] GetExplicitInterfaces (Type t
)
2121 if (builder_to_ifaces
.TryGetValue (t
, out ifaces
))
2128 /// The following is used to check if a given type implements an interface.
2129 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2131 public static bool ImplementsInterface (Type t
, Type iface
)
2136 // FIXME OPTIMIZATION:
2137 // as soon as we hit a non-TypeBuiler in the interface
2138 // chain, we could return, as the `Type.GetInterfaces'
2139 // will return all the interfaces implement by the type
2143 interfaces
= GetInterfaces (t
);
2145 if (interfaces
!= null){
2146 foreach (Type i
in interfaces
){
2147 if (i
== iface
|| IsVariantOf (i
, iface
))
2153 } while (t
!= null);
2158 static NumberFormatInfo nf_provider
= CultureInfo
.CurrentCulture
.NumberFormat
;
2160 // This is a custom version of Convert.ChangeType() which works
2161 // with the TypeBuilder defined types when compiling corlib.
2162 public static object ChangeType (object value, Type conversionType
, out bool error
)
2164 IConvertible convert_value
= value as IConvertible
;
2166 if (convert_value
== null){
2173 // We must use Type.Equals() here since `conversionType' is
2174 // the TypeBuilder created version of a system type and not
2175 // the system type itself. You cannot use Type.GetTypeCode()
2176 // on such a type - it'd always return TypeCode.Object.
2179 // We cannot rely on build-in type conversions as they are
2180 // more limited than what C# supports.
2181 // See char -> float/decimal/double conversion
2186 if (conversionType
.Equals (typeof (Boolean
)))
2187 return (object)(convert_value
.ToBoolean (nf_provider
));
2188 if (conversionType
.Equals (typeof (Byte
)))
2189 return (object)(convert_value
.ToByte (nf_provider
));
2190 if (conversionType
.Equals (typeof (Char
)))
2191 return (object)(convert_value
.ToChar (nf_provider
));
2192 if (conversionType
.Equals (typeof (DateTime
)))
2193 return (object)(convert_value
.ToDateTime (nf_provider
));
2195 if (conversionType
.Equals (decimal_type
)) {
2196 if (convert_value
.GetType () == TypeManager
.char_type
)
2197 return (decimal)convert_value
.ToInt32 (nf_provider
);
2198 return convert_value
.ToDecimal (nf_provider
);
2201 if (conversionType
.Equals (typeof (Double
))) {
2202 if (convert_value
.GetType () == TypeManager
.char_type
)
2203 return (double)convert_value
.ToInt32 (nf_provider
);
2204 return convert_value
.ToDouble (nf_provider
);
2207 if (conversionType
.Equals (typeof (Int16
)))
2208 return (object)(convert_value
.ToInt16 (nf_provider
));
2209 if (conversionType
.Equals (int32_type
))
2210 return (object)(convert_value
.ToInt32 (nf_provider
));
2211 if (conversionType
.Equals (int64_type
))
2212 return (object)(convert_value
.ToInt64 (nf_provider
));
2213 if (conversionType
.Equals (typeof (SByte
)))
2214 return (object)(convert_value
.ToSByte (nf_provider
));
2216 if (conversionType
.Equals (typeof (Single
))) {
2217 if (convert_value
.GetType () == TypeManager
.char_type
)
2218 return (float)convert_value
.ToInt32 (nf_provider
);
2219 return convert_value
.ToSingle (nf_provider
);
2222 if (conversionType
.Equals (typeof (String
)))
2223 return (object)(convert_value
.ToString (nf_provider
));
2224 if (conversionType
.Equals (typeof (UInt16
)))
2225 return (object)(convert_value
.ToUInt16 (nf_provider
));
2226 if (conversionType
.Equals (typeof (UInt32
)))
2227 return (object)(convert_value
.ToUInt32 (nf_provider
));
2228 if (conversionType
.Equals (typeof (UInt64
)))
2229 return (object)(convert_value
.ToUInt64 (nf_provider
));
2230 if (conversionType
.Equals (typeof (Object
)))
2231 return (object)(value);
2241 // When compiling with -nostdlib and the type is imported from an external assembly
2242 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2244 public static Type
TypeToCoreType (Type t
)
2246 if (RootContext
.StdLib
|| t
.Module
!= typeof (object).Module
)
2249 // TODO: GetTypeCode returns underlying type for enums !!
2250 TypeCode tc
= Type
.GetTypeCode (t
);
2253 case TypeCode
.Boolean
:
2254 return TypeManager
.bool_type
;
2256 return TypeManager
.byte_type
;
2257 case TypeCode
.SByte
:
2258 return TypeManager
.sbyte_type
;
2260 return TypeManager
.char_type
;
2261 case TypeCode
.Int16
:
2262 return TypeManager
.short_type
;
2263 case TypeCode
.UInt16
:
2264 return TypeManager
.ushort_type
;
2265 case TypeCode
.Int32
:
2266 return TypeManager
.int32_type
;
2267 case TypeCode
.UInt32
:
2268 return TypeManager
.uint32_type
;
2269 case TypeCode
.Int64
:
2270 return TypeManager
.int64_type
;
2271 case TypeCode
.UInt64
:
2272 return TypeManager
.uint64_type
;
2273 case TypeCode
.Single
:
2274 return TypeManager
.float_type
;
2275 case TypeCode
.Double
:
2276 return TypeManager
.double_type
;
2277 case TypeCode
.String
:
2278 return TypeManager
.string_type
;
2279 case TypeCode
.Decimal
:
2280 return TypeManager
.decimal_type
;
2283 if (t
== typeof (void))
2284 return TypeManager
.void_type
;
2285 if (t
== typeof (object))
2286 return TypeManager
.object_type
;
2287 if (t
== typeof (System
.Type
))
2288 return TypeManager
.type_type
;
2289 if (t
== typeof (System
.IntPtr
))
2290 return TypeManager
.intptr_type
;
2291 if (t
== typeof (System
.UIntPtr
))
2292 return TypeManager
.uintptr_type
;
2295 int dim
= t
.GetArrayRank ();
2296 t
= GetElementType (t
);
2297 return t
.MakeArrayType (dim
);
2300 t
= GetElementType (t
);
2301 return t
.MakeByRefType ();
2304 t
= GetElementType (t
);
2305 return t
.MakePointerType ();
2312 // Converts any type to reflection supported type
2314 public static Type
TypeToReflectionType (Type type
)
2316 // TODO: Very lame and painful, GetReference () is enough for mcs-cecil
2317 if (IsDynamicType (type
))
2320 if (type
is DynamicArrayType
)
2321 return type
.UnderlyingSystemType
;
2327 /// Utility function that can be used to probe whether a type
2328 /// is managed or not.
2330 public static bool VerifyUnmanaged (CompilerContext ctx
, Type t
, Location loc
)
2332 if (IsUnmanagedType (t
))
2336 t
= GetElementType (t
);
2338 ctx
.Report
.SymbolRelatedToPreviousError (t
);
2339 ctx
.Report
.Error (208, loc
,
2340 "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2347 /// Returns the name of the indexer in a given type.
2350 /// The default is not always `Item'. The user can change this behaviour by
2351 /// using the IndexerNameAttribute in the container.
2352 /// For example, the String class indexer is named `Chars' not `Item'
2354 public static string IndexerPropertyName (Type t
)
2356 t
= DropGenericTypeArguments (t
);
2357 if (t
is TypeBuilder
) {
2358 TypeContainer tc
= t
.IsInterface
? LookupInterface (t
) : LookupTypeContainer (t
);
2359 return tc
== null ? TypeContainer
.DefaultIndexerName
: tc
.IndexerName
;
2362 PredefinedAttribute pa
= PredefinedAttributes
.Get
.DefaultMember
;
2364 System
.Attribute attr
= System
.Attribute
.GetCustomAttribute (
2367 DefaultMemberAttribute dma
= (DefaultMemberAttribute
) attr
;
2368 return dma
.MemberName
;
2372 return TypeContainer
.DefaultIndexerName
;
2375 private static bool IsSignatureEqual (Type a
, Type b
)
2378 /// Consider the following example (bug #77674):
2380 /// public abstract class A
2382 /// public abstract T Foo<T> ();
2385 /// public abstract class B : A
2387 /// public override U Foo<T> ()
2388 /// { return default (U); }
2391 /// Here, `T' and `U' are method type parameters from different methods
2392 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2394 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2395 /// we need to do a signature based comparision and consider them equal.
2400 if (a
.IsGenericParameter
&& b
.IsGenericParameter
&&
2401 (a
.DeclaringMethod
!= null) && (b
.DeclaringMethod
!= null)) {
2402 return a
.GenericParameterPosition
== b
.GenericParameterPosition
;
2405 if (a
.IsArray
&& b
.IsArray
) {
2406 if (a
.GetArrayRank () != b
.GetArrayRank ())
2409 return IsSignatureEqual (GetElementType (a
), GetElementType (b
));
2412 if (a
.IsByRef
&& b
.IsByRef
)
2413 return IsSignatureEqual (GetElementType (a
), GetElementType (b
));
2415 if (IsGenericType (a
) && IsGenericType (b
)) {
2416 if (DropGenericTypeArguments (a
) != DropGenericTypeArguments (b
))
2419 Type
[] aargs
= GetTypeArguments (a
);
2420 Type
[] bargs
= GetTypeArguments (b
);
2422 if (aargs
.Length
!= bargs
.Length
)
2425 for (int i
= 0; i
< aargs
.Length
; i
++) {
2426 if (!IsSignatureEqual (aargs
[i
], bargs
[i
]))
2437 // Returns whether the array of memberinfos contains the given method
2439 public static bool ArrayContainsMethod (MethodBase
[] array
, MethodBase new_method
, bool ignoreDeclType
)
2441 Type
[] new_args
= TypeManager
.GetParameterData (new_method
).Types
;
2443 foreach (MethodBase method
in array
) {
2444 if (!ignoreDeclType
&& method
.DeclaringType
!= new_method
.DeclaringType
)
2447 if (method
.Name
!= new_method
.Name
)
2450 if (method
is MethodInfo
&& new_method
is MethodInfo
&&
2452 TypeToCoreType (((MethodInfo
) method
).ReturnType
),
2453 TypeToCoreType (((MethodInfo
) new_method
).ReturnType
)))
2456 Type
[] old_args
= TypeManager
.GetParameterData (method
).Types
;
2457 int old_count
= old_args
.Length
;
2460 if (new_args
.Length
!= old_count
)
2463 for (i
= 0; i
< old_count
; i
++){
2464 if (!IsSignatureEqual (old_args
[i
], new_args
[i
]))
2477 // We copy methods from `new_members' into `target_list' if the signature
2478 // for the method from in the new list does not exist in the target_list
2480 // The name is assumed to be the same.
2482 public static List
<MethodBase
> CopyNewMethods (List
<MethodBase
> target_list
, IList
<MemberInfo
> new_members
)
2484 if (target_list
== null){
2485 target_list
= new List
<MethodBase
> ();
2487 foreach (MemberInfo mi
in new_members
){
2488 if (mi
is MethodBase
)
2489 target_list
.Add ((MethodBase
) mi
);
2494 MethodBase
[] target_array
= new MethodBase
[target_list
.Count
];
2495 target_list
.CopyTo (target_array
, 0);
2497 foreach (MemberInfo mi
in new_members
){
2498 MethodBase new_method
= (MethodBase
) mi
;
2500 if (!ArrayContainsMethod (target_array
, new_method
, true))
2501 target_list
.Add (new_method
);
2508 // Tracks the generic parameters.
2511 public static void AddTypeParameter (GenericTypeParameterBuilder t
, TypeParameter tparam
)
2513 builder_to_type_param
[t
] = tparam
;
2516 public static TypeParameter
LookupTypeParameter (Type t
)
2519 var gtp
= t
as GenericTypeParameterBuilder
;
2520 if (gtp
!= null && builder_to_type_param
.TryGetValue (gtp
, out tp
))
2526 // This method always return false for non-generic compiler,
2527 // while Type.IsGenericParameter is returned if it is supported.
2528 public static bool IsGenericParameter (Type type
)
2530 return type
.IsGenericParameter
;
2533 public static int GenericParameterPosition (Type type
)
2535 return type
.GenericParameterPosition
;
2538 public static bool IsGenericType (Type type
)
2540 return type
.IsGenericType
;
2543 public static bool IsGenericTypeDefinition (Type type
)
2545 return type
.IsGenericTypeDefinition
;
2548 public static bool ContainsGenericParameters (Type type
)
2550 return type
.ContainsGenericParameters
;
2553 public static FieldInfo
GetGenericFieldDefinition (FieldInfo fi
)
2555 if (fi
.DeclaringType
.IsGenericTypeDefinition
||
2556 !fi
.DeclaringType
.IsGenericType
)
2559 Type t
= fi
.DeclaringType
.GetGenericTypeDefinition ();
2560 BindingFlags bf
= BindingFlags
.Public
| BindingFlags
.NonPublic
|
2561 BindingFlags
.Static
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
;
2563 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2564 foreach (FieldInfo f
in t
.GetFields (bf
))
2565 if (f
.MetadataToken
== fi
.MetadataToken
)
2571 public static bool IsEqual (Type a
, Type b
)
2574 // MS BCL returns true even if enum types are different
2575 if (a
.BaseType
== TypeManager
.enum_type
|| b
.BaseType
== TypeManager
.enum_type
)
2576 return a
.FullName
== b
.FullName
;
2578 // Some types are never equal
2579 if (a
== TypeManager
.null_type
|| a
== InternalType
.AnonymousMethod
)
2585 if (IsGenericParameter (a
) && IsGenericParameter (b
)) {
2586 // TODO: needs more testing before cleaning up
2587 //if (a.DeclaringMethod != b.DeclaringMethod &&
2588 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2590 return a
.GenericParameterPosition
== b
.GenericParameterPosition
;
2593 if (a
.IsArray
&& b
.IsArray
) {
2594 if (a
.GetArrayRank () != b
.GetArrayRank ())
2596 return IsEqual (GetElementType (a
), GetElementType (b
));
2599 if (a
.IsByRef
&& b
.IsByRef
)
2600 return IsEqual (a
.GetElementType (), b
.GetElementType ());
2602 if (IsGenericType (a
) && IsGenericType (b
)) {
2603 Type adef
= DropGenericTypeArguments (a
);
2604 Type bdef
= DropGenericTypeArguments (b
);
2609 if (adef
.IsEnum
&& bdef
.IsEnum
)
2612 Type
[] aargs
= GetTypeArguments (a
);
2613 Type
[] bargs
= GetTypeArguments (b
);
2615 if (aargs
.Length
!= bargs
.Length
)
2618 for (int i
= 0; i
< aargs
.Length
; i
++) {
2619 if (!IsEqual (aargs
[i
], bargs
[i
]))
2629 public static bool IsEqual (Type
[] a
, Type
[] b
)
2631 if (a
== null || b
== null || a
.Length
!= b
.Length
)
2634 for (int i
= 0; i
< a
.Length
; ++i
) {
2635 if (a
[i
] == null || b
[i
] == null) {
2642 if (!IsEqual (a
[i
], b
[i
]))
2649 public static Type
DropGenericTypeArguments (Type t
)
2651 if (!t
.IsGenericType
)
2653 // Micro-optimization: a generic typebuilder is always a generic type definition
2654 if (t
is TypeBuilder
)
2656 return t
.GetGenericTypeDefinition ();
2659 public static MethodBase
DropGenericMethodArguments (MethodSpec m
)
2661 return DropGenericMethodArguments (m
.MetaInfo
);
2664 public static MethodBase
DropGenericMethodArguments (MethodBase m
)
2666 if (m
.IsGenericMethod
)
2667 m
= ((MethodInfo
) m
).GetGenericMethodDefinition ();
2669 Type t
= m
.DeclaringType
;
2670 if (!t
.IsGenericType
|| t
.IsGenericTypeDefinition
)
2673 t
= t
.GetGenericTypeDefinition ();
2674 BindingFlags bf
= BindingFlags
.Public
| BindingFlags
.NonPublic
|
2675 BindingFlags
.Static
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
;
2678 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2682 if (m
is ConstructorInfo
) {
2683 foreach (ConstructorInfo c
in t
.GetConstructors (bf
))
2684 if (c
.MetadataToken
== m
.MetadataToken
)
2687 foreach (MethodBase mb
in t
.GetMethods (bf
))
2688 if (mb
.MetadataToken
== m
.MetadataToken
)
2695 public static Type
[] GetGenericArguments (MethodBase mi
)
2697 return mi
.GetGenericArguments () ?? Type
.EmptyTypes
;
2700 public static Type
[] GetTypeArguments (Type t
)
2702 DeclSpace tc
= LookupDeclSpace (t
);
2705 return Type
.EmptyTypes
;
2707 TypeParameter
[] tparam
= tc
.TypeParameters
;
2708 Type
[] ret
= new Type
[tparam
.Length
];
2709 for (int i
= 0; i
< tparam
.Length
; i
++) {
2710 ret
[i
] = tparam
[i
].Type
;
2711 if (ret
[i
] == null)
2712 throw new InternalErrorException ();
2717 return t
.GetGenericArguments ();
2720 public static GenericConstraints
GetTypeParameterConstraints (Type t
)
2722 if (!t
.IsGenericParameter
)
2723 throw new InvalidOperationException ();
2725 TypeParameter tparam
= LookupTypeParameter (t
);
2727 return tparam
.GenericConstraints
;
2729 return ReflectionConstraints
.GetConstraints (t
);
2732 public static bool HasGenericArguments (Type t
)
2734 return GetNumberOfTypeArguments (t
) > 0;
2737 public static int GetNumberOfTypeArguments (Type t
)
2739 if (t
.IsGenericParameter
)
2741 DeclSpace tc
= LookupDeclSpace (t
);
2743 return tc
.IsGeneric
? tc
.CountTypeParameters
: 0;
2745 return t
.IsGenericType
? t
.GetGenericArguments ().Length
: 0;
2749 /// Check whether `type' and `parent' are both instantiations of the same
2750 /// generic type. Note that we do not check the type parameters here.
2752 public static bool IsInstantiationOfSameGenericType (Type type
, Type parent
)
2754 int tcount
= GetNumberOfTypeArguments (type
);
2755 int pcount
= GetNumberOfTypeArguments (parent
);
2757 if (tcount
!= pcount
)
2760 type
= DropGenericTypeArguments (type
);
2761 parent
= DropGenericTypeArguments (parent
);
2763 return type
.Equals (parent
);
2767 /// Whether `mb' is a generic method definition.
2769 public static bool IsGenericMethodDefinition (MethodBase mb
)
2771 if (mb
.DeclaringType
is TypeBuilder
) {
2772 IMethodData method
= GetMethod (mb
);
2776 return method
.GenericMethod
!= null;
2779 return mb
.IsGenericMethodDefinition
;
2783 /// Whether `mb' is a generic method.
2785 public static bool IsGenericMethod (MethodBase mb
)
2787 return mb
.IsGenericMethod
;
2790 public static bool IsNullableType (Type t
)
2792 return generic_nullable_type
== DropGenericTypeArguments (t
);
2795 public static MethodInfo
MakeGenericMethod (MethodInfo gmd
, Type
[] methodArguments
)
2797 if (!gmd
.IsGenericMethodDefinition
)
2798 gmd
= gmd
.GetGenericMethodDefinition ();
2799 return gmd
.MakeGenericMethod (methodArguments
);
2803 #region MemberLookup implementation
2806 // Whether we allow private members in the result (since FindMembers
2807 // uses NonPublic for both protected and private), we need to distinguish.
2810 internal class Closure
{
2811 internal bool private_ok
;
2813 // Who is invoking us and which type is being queried currently.
2814 internal Type invocation_type
;
2815 internal Type qualifier_type
;
2817 // The assembly that defines the type is that is calling us
2818 internal Assembly invocation_assembly
;
2819 internal IList
<MemberInfo
> almost_match
;
2821 private bool CheckValidFamilyAccess (bool is_static
, MemberInfo m
)
2823 if (invocation_type
== null)
2826 if (is_static
&& qualifier_type
== null)
2827 // It resolved from a simple name, so it should be visible.
2830 if (IsNestedChildOf (invocation_type
, m
.DeclaringType
))
2833 for (Type t
= invocation_type
; t
!= null; t
= t
.DeclaringType
) {
2834 if (!IsFamilyAccessible (t
, m
.DeclaringType
))
2837 // Although a derived class can access protected members of its base class
2838 // it cannot do so through an instance of the base class (CS1540).
2839 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2840 if (is_static
|| qualifier_type
== null ||
2841 IsInstantiationOfSameGenericType (t
, qualifier_type
) ||
2842 IsFamilyAccessible (qualifier_type
, t
))
2846 if (almost_match
!= null)
2847 almost_match
.Add (m
);
2853 // This filter filters by name + whether it is ok to include private
2854 // members in the search
2856 internal bool Filter (MemberInfo m
, object filter_criteria
)
2859 // Hack: we know that the filter criteria will always be in the
2860 // `closure' // fields.
2863 if ((filter_criteria
!= null) && (m
.Name
!= (string) filter_criteria
))
2866 if (((qualifier_type
== null) || (qualifier_type
== invocation_type
)) &&
2867 (invocation_type
!= null) &&
2868 IsPrivateAccessible (m
.DeclaringType
, invocation_type
))
2872 // Ugly: we need to find out the type of `m', and depending
2873 // on this, tell whether we accept or not
2875 if (m
is MethodBase
){
2876 MethodBase mb
= (MethodBase
) m
;
2877 MethodAttributes ma
= mb
.Attributes
& MethodAttributes
.MemberAccessMask
;
2879 if (ma
== MethodAttributes
.Public
)
2882 if (ma
== MethodAttributes
.PrivateScope
)
2885 if (ma
== MethodAttributes
.Private
)
2886 return private_ok
||
2887 IsPrivateAccessible (invocation_type
, m
.DeclaringType
) ||
2888 IsNestedChildOf (invocation_type
, m
.DeclaringType
);
2890 if (TypeManager
.IsThisOrFriendAssembly (invocation_assembly
, mb
.DeclaringType
.Assembly
)) {
2891 if (ma
== MethodAttributes
.Assembly
|| ma
== MethodAttributes
.FamORAssem
)
2894 if (ma
== MethodAttributes
.Assembly
|| ma
== MethodAttributes
.FamANDAssem
)
2898 // Family, FamORAssem or FamANDAssem
2899 return CheckValidFamilyAccess (mb
.IsStatic
, m
);
2902 if (m
is FieldInfo
){
2903 FieldInfo fi
= (FieldInfo
) m
;
2904 FieldAttributes fa
= fi
.Attributes
& FieldAttributes
.FieldAccessMask
;
2906 if (fa
== FieldAttributes
.Public
)
2909 if (fa
== FieldAttributes
.PrivateScope
)
2912 if (fa
== FieldAttributes
.Private
)
2913 return private_ok
||
2914 IsPrivateAccessible (invocation_type
, m
.DeclaringType
) ||
2915 IsNestedChildOf (invocation_type
, m
.DeclaringType
);
2917 if (TypeManager
.IsThisOrFriendAssembly (invocation_assembly
, fi
.DeclaringType
.Assembly
)) {
2918 if ((fa
== FieldAttributes
.Assembly
) ||
2919 (fa
== FieldAttributes
.FamORAssem
))
2922 if ((fa
== FieldAttributes
.Assembly
) ||
2923 (fa
== FieldAttributes
.FamANDAssem
))
2927 // Family, FamORAssem or FamANDAssem
2928 return CheckValidFamilyAccess (fi
.IsStatic
, m
);
2932 // EventInfos and PropertyInfos, return true because they lack
2933 // permission information, so we need to check later on the methods.
2939 static Closure closure
;
2940 static MemberFilter FilterWithClosure_delegate
;
2943 // Looks up a member called `name' in the `queried_type'. This lookup
2944 // is done by code that is contained in the definition for `invocation_type'
2945 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2947 // `invocation_type' is used to check whether we're allowed to access the requested
2948 // member wrt its protection level.
2950 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2951 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2952 // is B and qualifier_type is A). This is used to do the CS1540 check.
2954 // When resolving a SimpleName, `qualifier_type' is null.
2956 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2957 // the same than `queried_type' - except when we're being called from BaseAccess;
2958 // in this case, `invocation_type' is the current type and `queried_type' the base
2959 // type, so this'd normally trigger a CS1540.
2961 // The binding flags are `bf' and the kind of members being looked up are `mt'
2963 // The return value always includes private members which code in `invocation_type'
2964 // is allowed to access (using the specified `qualifier_type' if given); only use
2965 // BindingFlags.NonPublic to bypass the permission check.
2967 // The 'almost_match' argument is used for reporting error CS1540.
2969 // Returns an array of a single element for everything but Methods/Constructors
2970 // that might return multiple matches.
2972 public static MemberInfo
[] MemberLookup (Type invocation_type
, Type qualifier_type
,
2973 Type queried_type
, MemberTypes mt
,
2974 BindingFlags original_bf
, string name
, IList
<MemberInfo
> almost_match
)
2976 Timer
.StartTimer (TimerType
.MemberLookup
);
2978 MemberInfo
[] retval
= RealMemberLookup (invocation_type
, qualifier_type
,
2979 queried_type
, mt
, original_bf
, name
, almost_match
);
2981 Timer
.StopTimer (TimerType
.MemberLookup
);
2986 static MemberInfo
[] RealMemberLookup (Type invocation_type
, Type qualifier_type
,
2987 Type queried_type
, MemberTypes mt
,
2988 BindingFlags original_bf
, string name
, IList
<MemberInfo
> almost_match
)
2990 BindingFlags bf
= original_bf
;
2992 List
<MethodBase
> method_list
= null;
2993 Type current_type
= queried_type
;
2994 bool searching
= (original_bf
& BindingFlags
.DeclaredOnly
) == 0;
2995 bool skip_iface_check
= true, used_cache
= false;
2996 bool always_ok_flag
= invocation_type
!= null && IsNestedChildOf (invocation_type
, queried_type
);
2998 closure
.invocation_type
= invocation_type
;
2999 closure
.invocation_assembly
= invocation_type
!= null ? invocation_type
.Assembly
: null;
3000 closure
.qualifier_type
= qualifier_type
;
3001 closure
.almost_match
= almost_match
;
3003 // This is from the first time we find a method
3004 // in most cases, we do not actually find a method in the base class
3005 // so we can just ignore it, and save the arraylist allocation
3006 MemberInfo
[] first_members_list
= null;
3007 bool use_first_members_list
= false;
3013 // `NonPublic' is lame, because it includes both protected and
3014 // private methods, so we need to control this behavior by
3015 // explicitly tracking if a private method is ok or not.
3017 // The possible cases are:
3018 // public, private and protected (internal does not come into the
3021 if ((invocation_type
!= null) &&
3022 ((invocation_type
== current_type
) ||
3023 IsNestedChildOf (invocation_type
, current_type
)) ||
3025 bf
= original_bf
| BindingFlags
.NonPublic
;
3029 closure
.private_ok
= (original_bf
& BindingFlags
.NonPublic
) != 0;
3031 Timer
.StopTimer (TimerType
.MemberLookup
);
3033 list
= MemberLookup_FindMembers (current_type
, mt
, bf
, name
, out used_cache
);
3035 Timer
.StartTimer (TimerType
.MemberLookup
);
3038 // When queried for an interface type, the cache will automatically check all
3039 // inherited members, so we don't need to do this here. However, this only
3040 // works if we already used the cache in the first iteration of this loop.
3042 // If we used the cache in any further iteration, we can still terminate the
3043 // loop since the cache always looks in all base classes.
3049 skip_iface_check
= false;
3051 if (current_type
== TypeManager
.object_type
)
3054 current_type
= current_type
.BaseType
;
3057 // This happens with interfaces, they have a null
3058 // basetype. Look members up in the Object class.
3060 if (current_type
== null) {
3061 current_type
= TypeManager
.object_type
;
3066 if (list
.Length
== 0)
3070 // Events and types are returned by both `static' and `instance'
3071 // searches, which means that our above FindMembers will
3072 // return two copies of the same.
3074 if (list
.Length
== 1 && !(list
[0] is MethodBase
)){
3079 // Multiple properties: we query those just to find out the indexer
3082 if (list
[0] is PropertyInfo
)
3086 // We found an event: the cache lookup returns both the event and
3087 // its private field.
3089 if (list
[0] is EventInfo
) {
3090 if ((list
.Length
== 2) && (list
[1] is FieldInfo
))
3091 return new MemberInfo
[] { list [0] }
;
3097 // We found methods, turn the search into "method scan"
3101 if (first_members_list
!= null) {
3102 if (use_first_members_list
) {
3103 method_list
= CopyNewMethods (method_list
, first_members_list
);
3104 use_first_members_list
= false;
3107 method_list
= CopyNewMethods (method_list
, list
);
3109 first_members_list
= list
;
3110 use_first_members_list
= true;
3111 mt
&= (MemberTypes
.Method
| MemberTypes
.Constructor
);
3113 } while (searching
);
3115 if (use_first_members_list
)
3116 return first_members_list
;
3118 if (method_list
!= null && method_list
.Count
> 0) {
3119 return method_list
.ToArray ();
3122 // This happens if we already used the cache in the first iteration, in this case
3123 // the cache already looked in all interfaces.
3125 if (skip_iface_check
)
3129 // Interfaces do not list members they inherit, so we have to
3132 if (!queried_type
.IsInterface
)
3135 if (queried_type
.IsArray
)
3136 queried_type
= TypeManager
.array_type
;
3138 Type
[] ifaces
= GetInterfaces (queried_type
);
3142 foreach (Type itype
in ifaces
){
3145 x
= MemberLookup (null, null, itype
, mt
, bf
, name
, null);
3153 public const BindingFlags AllMembers
= BindingFlags
.Public
| BindingFlags
.NonPublic
|
3154 BindingFlags
.Static
| BindingFlags
.Instance
|
3155 BindingFlags
.DeclaredOnly
;
3157 // Currently is designed to work with external types only
3158 public static PropertyInfo
GetPropertyFromAccessor (MethodBase mb
)
3160 if (!mb
.IsSpecialName
)
3163 string name
= mb
.Name
;
3164 if (name
.Length
< 5)
3167 if (name
[3] != '_')
3170 if (name
.StartsWith ("get") || name
.StartsWith ("set")) {
3171 MemberInfo
[] pi
= mb
.DeclaringType
.FindMembers (MemberTypes
.Property
, AllMembers
,
3172 Type
.FilterName
, name
.Substring (4));
3177 // This can happen when property is indexer (it can have same name but different parameters)
3178 foreach (PropertyInfo p
in pi
) {
3179 foreach (MethodInfo p_mi
in p
.GetAccessors (true)) {
3180 if (p_mi
== mb
|| TypeManager
.GetParameterData (p_mi
).Equals (TypeManager
.GetParameterData (mb
)))
3189 // Currently is designed to work with external types only
3190 public static MemberInfo
GetEventFromAccessor (MethodBase mb
)
3192 if (!mb
.IsSpecialName
)
3195 string name
= mb
.Name
;
3196 if (name
.Length
< 5)
3199 if (name
.StartsWith ("add_"))
3200 return mb
.DeclaringType
.GetEvent (name
.Substring (4), AllMembers
);
3202 if (name
.StartsWith ("remove_"))
3203 return mb
.DeclaringType
.GetEvent (name
.Substring (7), AllMembers
);
3208 // Tests whether external method is really special
3209 public static bool IsSpecialMethod (MethodBase mb
)
3211 if (!mb
.IsSpecialName
)
3214 IMethodData md
= TypeManager
.GetMethod (mb
);
3216 return (md
is AbstractPropertyEventMethod
|| md
is Operator
);
3218 PropertyInfo pi
= GetPropertyFromAccessor (mb
);
3220 return IsValidProperty (pi
);
3222 if (GetEventFromAccessor (mb
) != null)
3225 string name
= mb
.Name
;
3226 if (name
.StartsWith ("op_"))
3227 return Operator
.GetName (name
) != null;
3232 // Tests whether imported property is valid C# property.
3233 // TODO: It seems to me that we should do a lot of sanity tests before
3234 // we accept property as C# property
3235 static bool IsValidProperty (PropertyInfo pi
)
3237 MethodInfo get_method
= pi
.GetGetMethod (true);
3238 MethodInfo set_method
= pi
.GetSetMethod (true);
3241 if (get_method
!= null && set_method
!= null) {
3242 g_count
= get_method
.GetParameters ().Length
;
3243 s_count
= set_method
.GetParameters ().Length
;
3244 if (g_count
+ 1 != s_count
)
3246 } else if (get_method
!= null) {
3247 g_count
= get_method
.GetParameters ().Length
;
3248 } else if (set_method
!= null) {
3249 s_count
= set_method
.GetParameters ().Length
;
3253 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3255 PredefinedAttribute pa
= PredefinedAttributes
.Get
.DefaultMember
;
3256 if ((s_count
> 1 || g_count
> 0) && pa
.IsDefined
) {
3257 object[] o
= pi
.DeclaringType
.GetCustomAttributes (pa
.Type
, false);
3261 DefaultMemberAttribute dma
= (DefaultMemberAttribute
) o
[0];
3262 if (dma
.MemberName
!= pi
.Name
)
3264 if (get_method
!= null && "get_" + dma
.MemberName
!= get_method
.Name
)
3266 if (set_method
!= null && "set_" + dma
.MemberName
!= set_method
.Name
)
3279 public static readonly Type AnonymousMethod
= typeof (AnonymousMethodBody
);
3280 public static readonly Type Arglist
= typeof (ArglistAccess
);
3281 public static readonly Type Dynamic
= new DynamicType ();
3282 public static readonly Type MethodGroup
= typeof (MethodGroupExpr
);
3286 /// There is exactly one instance of this class per type.
3288 sealed class TypeHandle
: IMemberContainer
{
3289 public readonly IMemberContainer BaseType
;
3291 readonly int id
= ++next_id
;
3292 static int next_id
= 0;
3294 static TypeHandle ()
3300 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3301 /// a TypeHandle yet, a new instance of it is created. This static method
3302 /// ensures that we'll only have one TypeHandle instance per type.
3304 private static TypeHandle
GetTypeHandle (Type t
)
3307 if (type_hash
.TryGetValue (t
, out handle
))
3310 handle
= new TypeHandle (t
);
3311 type_hash
.Add (t
, handle
);
3315 public static MemberCache
GetMemberCache (Type t
)
3317 return GetTypeHandle (t
).MemberCache
;
3320 public static void CleanUp ()
3325 public static void Reset ()
3327 type_hash
= new Dictionary
<Type
, TypeHandle
> (ReferenceEquality
<Type
>.Default
);
3331 /// Returns the TypeHandle for TypeManager.object_type.
3333 public static IMemberContainer ObjectType
{
3335 if (object_type
!= null)
3338 object_type
= GetTypeHandle (TypeManager
.object_type
);
3345 /// Returns the TypeHandle for TypeManager.array_type.
3347 public static TypeHandle ArrayType
{
3349 if (array_type
!= null)
3352 array_type
= GetTypeHandle (TypeManager
.array_type
);
3358 static Dictionary
<Type
, TypeHandle
> type_hash
;
3360 private static TypeHandle object_type
;
3361 private static TypeHandle array_type
;
3364 private string full_name
;
3365 private bool is_interface
;
3366 private MemberCache member_cache
;
3367 private MemberCache base_cache
;
3369 private TypeHandle (Type type
)
3372 full_name
= type
.FullName
!= null ? type
.FullName
: type
.Name
;
3373 if (type
.BaseType
!= null) {
3374 base_cache
= TypeManager
.LookupMemberCache (type
.BaseType
);
3375 BaseType
= base_cache
.Container
;
3376 } else if (type
.IsInterface
)
3377 base_cache
= TypeManager
.LookupBaseInterfacesCache (type
);
3378 this.is_interface
= type
.IsInterface
|| TypeManager
.IsGenericParameter (type
);
3379 this.member_cache
= new MemberCache (this);
3382 // IMemberContainer methods
3384 public string Name
{
3396 public MemberCache BaseCache
{
3402 public bool IsInterface
{
3404 return is_interface
;
3408 public MemberList
GetMembers (MemberTypes mt
, BindingFlags bf
)
3410 MemberInfo
[] members
;
3412 if (type
is GenericTypeParameterBuilder
)
3413 return MemberList
.Empty
;
3416 type
= TypeManager
.DropGenericTypeArguments (type
);
3418 if (mt
== MemberTypes
.Event
)
3419 members
= type
.GetEvents (bf
| BindingFlags
.DeclaredOnly
);
3421 members
= type
.FindMembers (mt
, bf
| BindingFlags
.DeclaredOnly
,
3424 if (members
.Length
== 0)
3425 return MemberList
.Empty
;
3427 Array
.Reverse (members
);
3428 return new MemberList (members
);
3431 // IMemberFinder methods
3433 public MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
, string name
,
3434 MemberFilter filter
, object criteria
)
3436 return new MemberList (member_cache
.FindMembers (mt
, bf
, name
, filter
, criteria
));
3439 public MemberCache MemberCache
{
3441 return member_cache
;
3445 public override string ToString ()
3447 if (BaseType
!= null)
3448 return "TypeHandle (" + id
+ "," + Name
+ " : " + BaseType
+ ")";
3450 return "TypeHandle (" + id
+ "," + Name
+ ")";