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 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
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;
25 using System.Reflection;
26 using System.Reflection.Emit;
28 using System.Text.RegularExpressions;
29 using System.Runtime.CompilerServices;
30 using System.Diagnostics;
32 namespace Mono.CSharp {
39 // A list of core types that the compiler requires or uses
41 static public Type object_type;
42 static public Type value_type;
43 static public Type string_type;
44 static public Type int32_type;
45 static public Type uint32_type;
46 static public Type int64_type;
47 static public Type uint64_type;
48 static public Type float_type;
49 static public Type double_type;
50 static public Type char_type;
51 static public Type char_ptr_type;
52 static public Type short_type;
53 static public Type decimal_type;
54 static public Type bool_type;
55 static public Type sbyte_type;
56 static public Type byte_type;
57 static public Type ushort_type;
58 static public Type enum_type;
59 static public Type delegate_type;
60 static public Type multicast_delegate_type;
61 static public Type void_type;
62 static public Type null_type;
63 static public Type array_type;
64 static public Type runtime_handle_type;
65 static public Type icloneable_type;
66 static public Type type_type;
67 static public Type ienumerator_type;
68 static public Type ienumerable_type;
69 static public Type idisposable_type;
70 static public Type iconvertible_type;
71 static public Type default_member_type;
72 static public Type iasyncresult_type;
73 static public Type asynccallback_type;
74 static public Type intptr_type;
75 static public Type uintptr_type;
76 static public Type monitor_type;
77 static public Type interlocked_type;
78 static public Type runtime_field_handle_type;
79 static public Type runtime_argument_handle_type;
80 static public Type attribute_type;
81 static public Type attribute_usage_type;
82 static public Type decimal_constant_attribute_type;
83 static public Type dllimport_type;
84 static public Type unverifiable_code_type;
85 static public Type methodimpl_attr_type;
86 static public Type marshal_as_attr_type;
87 static public Type param_array_type;
88 static public Type void_ptr_type;
89 static public Type indexer_name_type;
90 static public Type exception_type;
91 static public Type invalid_operation_exception_type;
92 static public Type not_supported_exception_type;
93 static public Type obsolete_attribute_type;
94 static public Type conditional_attribute_type;
95 static public Type in_attribute_type;
96 static public Type out_attribute_type;
97 static public Type extension_attribute_type;
98 static public Type default_parameter_value_attribute_type;
100 static public Type anonymous_method_type;
101 static public Type cls_compliant_attribute_type;
102 static public Type typed_reference_type;
103 static public Type arg_iterator_type;
104 static public Type mbr_type;
105 static public Type struct_layout_attribute_type;
106 static public Type field_offset_attribute_type;
107 static public Type security_attr_type;
108 static public Type required_attr_type;
109 static public Type guid_attr_type;
110 static public Type assembly_culture_attribute_type;
111 static public Type coclass_attr_type;
112 static public Type comimport_attr_type;
118 static internal Type runtime_compatibility_attr_type;
119 static internal Type compiler_generated_attr_type;
120 static internal Type fixed_buffer_attr_type;
121 static internal Type default_charset_type;
122 static internal Type internals_visible_attr_type;
123 static internal Type type_forwarder_attr_type;
127 // Expressions representing the internal types. Used during declaration
130 static public TypeExpr system_object_expr, system_string_expr;
131 static public TypeExpr system_boolean_expr, system_decimal_expr;
132 static public TypeExpr system_single_expr, system_double_expr;
133 static public TypeExpr system_sbyte_expr, system_byte_expr;
134 static public TypeExpr system_int16_expr, system_uint16_expr;
135 static public TypeExpr system_int32_expr, system_uint32_expr;
136 static public TypeExpr system_int64_expr, system_uint64_expr;
137 static public TypeExpr system_char_expr, system_void_expr;
138 static public TypeExpr system_asynccallback_expr;
139 static public TypeExpr system_iasyncresult_expr;
140 static public TypeExpr system_valuetype_expr;
141 static public TypeExpr system_intptr_expr;
144 // This is only used when compiling corlib
146 static public Type system_int32_type;
147 static public Type system_array_type;
148 static public Type system_type_type;
149 static public Type system_assemblybuilder_type;
150 static public MethodInfo system_int_array_get_length;
151 static public MethodInfo system_int_array_get_rank;
152 static public MethodInfo system_object_array_clone;
153 static public MethodInfo system_int_array_get_length_int;
154 static public MethodInfo system_int_array_get_lower_bound_int;
155 static public MethodInfo system_int_array_get_upper_bound_int;
156 static public MethodInfo system_void_array_copyto_array_int;
160 // Internal, not really used outside
162 static Type runtime_helpers_type;
165 // These methods are called by code generated by the compiler
167 static public MethodInfo string_concat_string_string;
168 static public MethodInfo string_concat_string_string_string;
169 static public MethodInfo string_concat_string_string_string_string;
170 static public MethodInfo string_concat_string_dot_dot_dot;
171 static public MethodInfo string_concat_object_object;
172 static public MethodInfo string_concat_object_object_object;
173 static public MethodInfo string_concat_object_dot_dot_dot;
174 static public MethodInfo string_isinterned_string;
175 static public MethodInfo system_type_get_type_from_handle;
176 static public MethodInfo bool_movenext_void;
177 static public MethodInfo ienumerable_getenumerator_void;
178 static public MethodInfo void_reset_void;
179 static public MethodInfo void_dispose_void;
180 static public MethodInfo void_monitor_enter_object;
181 static public MethodInfo void_monitor_exit_object;
182 static public MethodInfo void_initializearray_array_fieldhandle;
183 static public MethodInfo int_getlength_int;
184 static public MethodInfo delegate_combine_delegate_delegate;
185 static public MethodInfo delegate_remove_delegate_delegate;
186 static public MethodInfo int_get_offset_to_string_data;
187 static public MethodInfo int_array_get_length;
188 static public MethodInfo int_array_get_rank;
189 static public MethodInfo object_array_clone;
190 static public MethodInfo int_array_get_length_int;
191 static public MethodInfo int_array_get_lower_bound_int;
192 static public MethodInfo int_array_get_upper_bound_int;
193 static public MethodInfo void_array_copyto_array_int;
194 static public MethodInfo int_interlocked_compare_exchange;
195 static public PropertyInfo ienumerator_getcurrent;
198 // The attribute constructors.
200 static public ConstructorInfo object_ctor;
201 static public ConstructorInfo cons_param_array_attribute;
202 static public ConstructorInfo void_decimal_ctor_five_args;
203 static public ConstructorInfo void_decimal_ctor_int_arg;
204 static public ConstructorInfo unverifiable_code_ctor;
205 static public ConstructorInfo default_member_ctor;
206 static public ConstructorInfo decimal_constant_attribute_ctor;
207 static internal ConstructorInfo struct_layout_attribute_ctor;
208 static public ConstructorInfo field_offset_attribute_ctor;
212 static internal CustomAttributeBuilder compiler_generated_attr;
213 static internal ConstructorInfo fixed_buffer_attr_ctor;
217 static internal CustomAttributeBuilder extension_attribute_attr;
219 static PtrHashtable builder_to_declspace;
221 static PtrHashtable builder_to_member_cache;
224 // Tracks the interfaces implemented by typebuilders. We only
225 // enter those who do implement or or more interfaces
227 static PtrHashtable builder_to_ifaces;
230 // Maps PropertyBuilder to a Type array that contains
231 // the arguments to the indexer
233 static Hashtable indexer_arguments;
236 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
238 static Hashtable method_params;
241 // A hash table from override methods to their base virtual method.
243 static Hashtable method_overrides;
246 // Keeps track of methods
249 static Hashtable builder_to_method;
252 // Contains all public types from referenced assemblies.
253 // This member is used only if CLS Compliance verification is required.
255 public static Hashtable AllClsTopLevelTypes;
257 static Hashtable fieldbuilders_to_fields;
258 static Hashtable propertybuilder_to_property;
259 static Hashtable fields;
260 static Hashtable events;
263 static PtrHashtable assembly_internals_vis_attrs;
271 public static void CleanUp ()
273 // Lets get everything clean so that we can collect before generating code
274 builder_to_declspace = null;
275 builder_to_member_cache = null;
276 builder_to_ifaces = null;
277 builder_to_type_param = null;
278 indexer_arguments = null;
279 method_params = null;
280 builder_to_method = null;
285 propertybuilder_to_property = null;
288 assembly_internals_vis_attrs = null;
291 TypeHandle.CleanUp ();
295 /// A filter for Findmembers that uses the Signature object to
298 static bool SignatureFilter (MemberInfo mi, object criteria)
300 Signature sig = (Signature) criteria;
302 if (!(mi is MethodBase))
305 if (mi.Name != sig.name)
308 int count = sig.args.Length;
310 if (mi is MethodBuilder || mi is ConstructorBuilder){
311 Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
313 if (candidate_args.Length != count)
316 for (int i = 0; i < count; i++)
317 if (candidate_args [i] != sig.args [i])
322 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
324 if (pars.Length != count)
327 for (int i = 0; i < count; i++)
328 if (pars [i].ParameterType != sig.args [i])
334 // A delegate that points to the filter above.
335 static MemberFilter signature_filter;
338 // These are expressions that represent some of the internal data types, used
341 static void InitExpressionTypes ()
343 system_object_expr = new TypeLookupExpression ("System.Object");
344 system_string_expr = new TypeLookupExpression ("System.String");
345 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
346 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
347 system_single_expr = new TypeLookupExpression ("System.Single");
348 system_double_expr = new TypeLookupExpression ("System.Double");
349 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
350 system_byte_expr = new TypeLookupExpression ("System.Byte");
351 system_int16_expr = new TypeLookupExpression ("System.Int16");
352 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
353 system_int32_expr = new TypeLookupExpression ("System.Int32");
354 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
355 system_int64_expr = new TypeLookupExpression ("System.Int64");
356 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
357 system_char_expr = new TypeLookupExpression ("System.Char");
358 system_void_expr = new TypeLookupExpression ("System.Void");
359 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
360 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
361 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
362 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
365 static TypeManager ()
369 signature_filter = new MemberFilter (SignatureFilter);
370 InitExpressionTypes ();
373 static public void Reset ()
375 builder_to_declspace = new PtrHashtable ();
376 builder_to_member_cache = new PtrHashtable ();
377 builder_to_method = new PtrHashtable ();
378 builder_to_type_param = new PtrHashtable ();
379 method_params = new PtrHashtable ();
380 method_overrides = new PtrHashtable ();
381 indexer_arguments = new PtrHashtable ();
382 builder_to_ifaces = new PtrHashtable ();
384 fieldbuilders_to_fields = new Hashtable ();
385 propertybuilder_to_property = new Hashtable ();
386 fields = new Hashtable ();
387 type_hash = new DoubleHash ();
390 assembly_internals_vis_attrs = new PtrHashtable ();
393 // to uncover regressions
394 AllClsTopLevelTypes = null;
397 public static void AddUserType (DeclSpace ds)
399 builder_to_declspace.Add (ds.TypeBuilder, ds);
403 // This entry point is used by types that we define under the covers
405 public static void RegisterBuilder (Type tb, Type [] ifaces)
408 builder_to_ifaces [tb] = ifaces;
411 public static void AddMethod (MethodBase builder, IMethodData method)
413 builder_to_method.Add (builder, method);
414 method_params.Add (builder, method.ParameterInfo);
417 public static IMethodData GetMethod (MethodBase builder)
419 return (IMethodData) builder_to_method [builder];
423 /// Returns the DeclSpace whose Type is `t' or null if there is no
424 /// DeclSpace for `t' (ie, the Type comes from a library)
426 public static DeclSpace LookupDeclSpace (Type t)
428 return builder_to_declspace [t] as DeclSpace;
432 /// Returns the TypeContainer whose Type is `t' or null if there is no
433 /// TypeContainer for `t' (ie, the Type comes from a library)
435 public static TypeContainer LookupTypeContainer (Type t)
437 return builder_to_declspace [t] as TypeContainer;
440 public static MemberCache LookupMemberCache (Type t)
442 if (t.Assembly == CodeGen.Assembly.Builder) {
443 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
444 if (container != null)
445 return container.MemberCache;
449 if (t is GenericTypeParameterBuilder) {
450 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
452 if (container != null)
453 return container.MemberCache;
457 return TypeHandle.GetMemberCache (t);
460 public static MemberCache LookupBaseInterfacesCache (Type t)
462 Type [] ifaces = GetInterfaces (t);
464 if (ifaces != null && ifaces.Length == 1)
465 return LookupMemberCache (ifaces [0]);
467 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
468 MemberCache cache = builder_to_member_cache [t] as MemberCache;
472 cache = new MemberCache (ifaces);
473 builder_to_member_cache.Add (t, cache);
477 public static TypeContainer LookupInterface (Type t)
479 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
480 if ((tc == null) || (tc.Kind != Kind.Interface))
486 public static Delegate LookupDelegate (Type t)
488 return builder_to_declspace [t] as Delegate;
491 public static Class LookupClass (Type t)
493 return (Class) builder_to_declspace [t];
497 // We use this hash for multiple kinds of constructed types:
499 // (T, "&") Given T, get T &
500 // (T, "*") Given T, get T *
501 // (T, "[]") Given T and a array dimension, get T []
502 // (T, X) Given a type T and a simple name X, get the type T+X
504 // Accessibility tests, if necessary, should be done by the user
506 static DoubleHash type_hash = new DoubleHash ();
509 // Gets the reference to T version of the Type (T&)
511 public static Type GetReferenceType (Type t)
514 return t.MakeByRefType ();
516 return GetConstructedType (t, "&");
521 // Gets the pointer to T version of the Type (T*)
523 public static Type GetPointerType (Type t)
525 return GetConstructedType (t, "*");
528 public static Type GetConstructedType (Type t, string dim)
531 if (type_hash.Lookup (t, dim, out ret))
534 ret = t.Module.GetType (t.ToString () + dim);
536 type_hash.Insert (t, dim, ret);
541 ret = GetReferenceType (t);
542 type_hash.Insert (t, dim, ret);
547 if (t.IsGenericParameter || t.IsGenericType) {
550 while ((pos < dim.Length) && (dim [pos] == '[')) {
553 if (dim [pos] == ']') {
554 result = result.MakeArrayType ();
557 if (pos < dim.Length)
560 type_hash.Insert (t, dim, result);
565 while (dim [pos] == ',') {
569 if ((dim [pos] != ']') || (pos != dim.Length-1))
572 result = result.MakeArrayType (rank + 1);
573 type_hash.Insert (t, dim, result);
579 type_hash.Insert (t, dim, null);
583 public static Type GetNestedType (Type t, string name)
586 if (!type_hash.Lookup (t, name, out ret)) {
587 ret = t.GetNestedType (name,
588 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
589 type_hash.Insert (t, name, ret);
595 /// Fills static table with exported types from all referenced assemblies.
596 /// This information is required for CLS Compliance tests.
598 public static void LoadAllImportedTypes ()
600 AllClsTopLevelTypes = new Hashtable (1500);
601 foreach (Assembly a in RootNamespace.Global.Assemblies) {
602 foreach (Type t in a.GetExportedTypes ()) {
603 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
608 public static bool NamespaceClash (string name, Location loc)
610 if (! RootNamespace.Global.IsNamespace (name))
613 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
618 /// Returns the C# name of a type if possible, or the full type name otherwise
620 static public string CSharpName (Type t)
622 if (t == typeof(NullType))
625 if (t == typeof (ArglistParameter))
628 return CSharpName (GetFullName (t));
631 public static string CSharpName (string name)
633 if (name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
634 return AnonymousTypeClass.SignatureForError;
636 return Regex.Replace (name,
638 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
639 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
640 @"Boolean|String|Void|Null)" +
642 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
645 static public string CSharpName (Type[] types)
647 StringBuilder sb = new StringBuilder ();
648 foreach (Type t in types) {
649 sb.Append (CSharpName (t));
652 sb.Remove (sb.Length - 1, 1);
653 return sb.ToString ();
656 static String CSharpNameMatch (Match match)
658 string s = match.Groups [1].Captures [0].Value;
660 Replace ("int32", "int").
661 Replace ("uint32", "uint").
662 Replace ("int16", "short").
663 Replace ("uint16", "ushort").
664 Replace ("int64", "long").
665 Replace ("uint64", "ulong").
666 Replace ("single", "float").
667 Replace ("boolean", "bool")
668 + match.Groups [2].Captures [0].Value;
671 // Used for error reporting to show symbolic name instead of underlying value
672 public static string CSharpEnumValue (Type t, object value)
674 t = DropGenericTypeArguments (t);
675 Enum e = LookupDeclSpace (t) as Enum;
677 return System.Enum.GetName (t, value);
679 return e.GetDefinition (value).GetSignatureForError ();
683 /// Returns the signature of the method with full namespace classification
685 static public string GetFullNameSignature (MemberInfo mi)
687 PropertyInfo pi = mi as PropertyInfo;
689 MethodBase pmi = pi.GetGetMethod (true);
691 pmi = pi.GetSetMethod (true);
692 if (GetParameterData (pmi).Count > 0)
695 return (mi is MethodBase)
696 ? CSharpSignature (mi as MethodBase)
697 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
701 private static int GetFullName (Type t, StringBuilder sb)
705 if (!t.IsGenericType) {
706 sb.Append (t.FullName);
710 if (t.DeclaringType != null) {
711 pos = GetFullName (t.DeclaringType, sb);
713 } else if (t.Namespace != null && t.Namespace.Length != 0) {
714 sb.Append (t.Namespace);
717 sb.Append (RemoveGenericArity (t.Name));
719 Type[] this_args = GetTypeArguments (t);
721 if (this_args.Length < pos)
722 throw new InternalErrorException (
723 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
724 if (this_args.Length == pos)
729 sb.Append (CSharpName (this_args [pos++]));
730 if (pos == this_args.Length)
738 static string GetFullName (Type t)
741 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
742 return GetFullName (t.GetElementType ()) + dimension;
745 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
746 t = GetTypeArguments (t)[0];
747 return CSharpName (t) + "?";
750 if (t.IsGenericParameter)
752 if (!t.IsGenericType)
755 StringBuilder sb = new StringBuilder ();
756 int pos = GetFullName (t, sb);
758 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
759 return sb.ToString ();
762 public static string GetFullName (Type t)
768 public static string RemoveGenericArity (string from)
770 int i = from.IndexOf ('`');
772 return from.Substring (0, i);
777 /// When we need to report accessors as well
779 static public string CSharpSignature (MethodBase mb)
781 return CSharpSignature (mb, false);
785 /// Returns the signature of the method
787 static public string CSharpSignature (MethodBase mb, bool show_accessor)
789 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
792 ParameterData iparams = GetParameterData (mb);
793 string parameters = iparams.GetSignatureForError ();
794 int accessor_end = 0;
796 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
797 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
798 if (ot != Operator.OpType.TOP) {
799 sig.Append ("operator ");
800 sig.Append (Operator.GetName (ot));
801 sig.Append (parameters);
802 return sig.ToString ();
805 bool is_getter = mb.Name.StartsWith ("get_");
806 bool is_setter = mb.Name.StartsWith ("set_");
807 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
809 } else if (mb.Name.StartsWith ("remove_")) {
814 if (iparams.Count > (is_getter ? 0 : 1)) {
815 sig.Append ("this[");
817 sig.Append (parameters.Substring (1, parameters.Length - 2));
819 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
822 sig.Append (mb.Name.Substring (accessor_end + 1));
825 if (mb.Name == ".ctor")
826 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
828 sig.Append (mb.Name);
831 if (TypeManager.IsGenericMethod (mb)) {
832 Type[] args = mb.GetGenericArguments ();
834 for (int i = 0; i < args.Length; i++) {
837 sig.Append (CSharpName (args [i]));
844 sig.Append (parameters);
847 if (show_accessor && accessor_end > 0) {
849 sig.Append (mb.Name.Substring (0, accessor_end));
852 return sig.ToString ();
855 public static string GetMethodName (MethodInfo m)
858 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
861 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
867 static public string CSharpSignature (EventInfo ei)
869 return CSharpName (ei.DeclaringType) + "." + ei.Name;
873 /// Looks up a type, and aborts if it is not found. This is used
874 /// by types required by the compiler
876 public static Type CoreLookupType (string namespaceName, string name)
878 return CoreLookupType (namespaceName, name, false);
881 static Type CoreLookupType (string ns_name, string name, bool mayFail)
883 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
884 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
885 Type t = fne == null ? null : fne.Type;
888 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
892 AttributeTester.RegisterNonObsoleteType (t);
897 /// Returns the MethodInfo for a method named `name' defined
898 /// in type `t' which takes arguments of types `args'
900 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
904 BindingFlags flags = instance_and_static | BindingFlags.Public;
910 flags |= BindingFlags.NonPublic;
912 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
913 if (list.Count == 0) {
915 Report.Error (-19, "Can not find the core function `" + name + "'");
919 MethodInfo mi = list [0] as MethodInfo;
922 Report.Error (-19, "Can not find the core function `" + name + "'");
929 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
931 return GetMethod (t, name, args, false, report_errors);
934 public static MethodInfo GetMethod (Type t, string name, Type [] args)
936 return GetMethod (t, name, args, true);
940 /// Returns the PropertyInfo for a property named `name' defined
943 public static PropertyInfo GetProperty (Type t, string name)
945 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
946 BindingFlags.Instance, Type.FilterName, name);
947 if (list.Count == 0) {
948 Report.Error (-19, "Can not find the core property `" + name + "'");
952 PropertyInfo pi = list [0] as PropertyInfo;
954 Report.Error (-19, "Can not find the core function `" + name + "'");
962 /// Returns the ConstructorInfo for "args"
964 public static ConstructorInfo GetConstructor (Type t, Type [] args)
966 return GetConstructor (t, args, true);
969 public static ConstructorInfo GetConstructor (Type t, Type [] args, bool report_errors)
978 throw new InternalErrorException ("Core types haven't been initialized yet?");
980 list = FindMembers (t, MemberTypes.Constructor,
981 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
982 signature_filter, sig);
983 if (list.Count == 0){
985 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
989 ConstructorInfo ci = list [0] as ConstructorInfo;
992 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
999 public static void InitEnumUnderlyingTypes ()
1001 int32_type = CoreLookupType ("System", "Int32");
1002 int64_type = CoreLookupType ("System", "Int64");
1003 uint32_type = CoreLookupType ("System", "UInt32");
1004 uint64_type = CoreLookupType ("System", "UInt64");
1005 byte_type = CoreLookupType ("System", "Byte");
1006 sbyte_type = CoreLookupType ("System", "SByte");
1007 short_type = CoreLookupType ("System", "Int16");
1008 ushort_type = CoreLookupType ("System", "UInt16");
1010 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
1011 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
1013 idisposable_type = CoreLookupType ("System", "IDisposable");
1016 InitGenericCoreTypes ();
1021 /// The types have to be initialized after the initial
1022 /// population of the type has happened (for example, to
1023 /// bootstrap the corlib.dll
1025 public static void InitCoreTypes ()
1027 object_type = CoreLookupType ("System", "Object");
1028 system_object_expr.Type = object_type;
1029 value_type = CoreLookupType ("System", "ValueType");
1030 system_valuetype_expr.Type = value_type;
1032 InitEnumUnderlyingTypes ();
1034 char_type = CoreLookupType ("System", "Char");
1035 string_type = CoreLookupType ("System", "String");
1036 float_type = CoreLookupType ("System", "Single");
1037 double_type = CoreLookupType ("System", "Double");
1038 char_ptr_type = GetPointerType (char_type);
1039 decimal_type = CoreLookupType ("System", "Decimal");
1040 bool_type = CoreLookupType ("System", "Boolean");
1041 enum_type = CoreLookupType ("System", "Enum");
1043 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1044 delegate_type = CoreLookupType ("System", "Delegate");
1046 array_type = CoreLookupType ("System", "Array");
1047 void_type = CoreLookupType ("System", "Void");
1048 type_type = CoreLookupType ("System", "Type");
1050 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1051 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1052 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1053 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1054 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1055 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1056 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1057 icloneable_type = CoreLookupType ("System", "ICloneable");
1058 iconvertible_type = CoreLookupType ("System", "IConvertible");
1059 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1060 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1061 intptr_type = CoreLookupType ("System", "IntPtr");
1062 uintptr_type = CoreLookupType ("System", "UIntPtr");
1064 attribute_type = CoreLookupType ("System", "Attribute");
1065 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1066 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1067 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1068 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1069 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1070 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1071 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1073 // needed before any call susceptible to fail, as it is used during resolution
1074 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1076 // this can fail if the user doesn't have an -r:System.dll
1077 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", true);
1079 typed_reference_type = CoreLookupType ("System", "TypedReference");
1080 arg_iterator_type = CoreLookupType ("System", "ArgIterator", true);
1081 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1082 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1084 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1086 void_ptr_type = GetPointerType (void_type);
1088 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1090 exception_type = CoreLookupType ("System", "Exception");
1091 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1092 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1097 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1098 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1099 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1100 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1101 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1102 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1103 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", true);
1104 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1105 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1106 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1107 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1113 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1114 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1115 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1116 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1117 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", true);
1122 extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
1126 // When compiling corlib, store the "real" types here.
1128 if (!RootContext.StdLib) {
1129 system_int32_type = typeof (System.Int32);
1130 system_array_type = typeof (System.Array);
1131 system_type_type = typeof (System.Type);
1132 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1134 system_int_array_get_length = GetMethod (
1135 system_array_type, "get_Length", Type.EmptyTypes);
1136 system_int_array_get_rank = GetMethod (
1137 system_array_type, "get_Rank", Type.EmptyTypes);
1138 system_object_array_clone = GetMethod (
1139 system_array_type, "Clone", Type.EmptyTypes);
1141 Type [] system_int_arg = { system_int32_type };
1142 system_int_array_get_length_int = GetMethod (
1143 system_array_type, "GetLength", system_int_arg);
1144 system_int_array_get_upper_bound_int = GetMethod (
1145 system_array_type, "GetUpperBound", system_int_arg);
1146 system_int_array_get_lower_bound_int = GetMethod (
1147 system_array_type, "GetLowerBound", system_int_arg);
1149 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1150 system_void_array_copyto_array_int = GetMethod (
1151 system_array_type, "CopyTo", system_array_int_arg);
1153 Type [] system_3_type_arg = {
1154 system_type_type, system_type_type, system_type_type };
1155 Type [] system_4_type_arg = {
1156 system_type_type, system_type_type, system_type_type, system_type_type };
1158 MethodInfo set_corlib_type_builders = GetMethod (
1159 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1160 system_4_type_arg, true, false);
1162 if (set_corlib_type_builders != null) {
1163 object[] args = new object [4];
1164 args [0] = object_type;
1165 args [1] = value_type;
1166 args [2] = enum_type;
1167 args [3] = void_type;
1169 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1171 // Compatibility for an older version of the class libs.
1172 set_corlib_type_builders = GetMethod (
1173 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1174 system_3_type_arg, true, true);
1176 if (set_corlib_type_builders == null) {
1177 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1181 object[] args = new object [3];
1182 args [0] = object_type;
1183 args [1] = value_type;
1184 args [2] = enum_type;
1186 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1190 system_string_expr.Type = string_type;
1191 system_boolean_expr.Type = bool_type;
1192 system_decimal_expr.Type = decimal_type;
1193 system_single_expr.Type = float_type;
1194 system_double_expr.Type = double_type;
1195 system_sbyte_expr.Type = sbyte_type;
1196 system_byte_expr.Type = byte_type;
1197 system_int16_expr.Type = short_type;
1198 system_uint16_expr.Type = ushort_type;
1199 system_int32_expr.Type = int32_type;
1200 system_uint32_expr.Type = uint32_type;
1201 system_int64_expr.Type = int64_type;
1202 system_uint64_expr.Type = uint64_type;
1203 system_char_expr.Type = char_type;
1204 system_void_expr.Type = void_type;
1205 system_asynccallback_expr.Type = asynccallback_type;
1206 system_iasyncresult_expr.Type = iasyncresult_type;
1209 // These are only used for compare purposes
1211 anonymous_method_type = typeof (AnonymousMethod);
1212 null_type = typeof (NullType);
1216 // The helper methods that are used by the compiler
1218 public static void InitCodeHelpers ()
1221 // Now load the default methods that we use.
1223 Type [] string_string = { string_type, string_type };
1224 string_concat_string_string = GetMethod (
1225 string_type, "Concat", string_string);
1226 Type [] string_string_string = { string_type, string_type, string_type };
1227 string_concat_string_string_string = GetMethod (
1228 string_type, "Concat", string_string_string);
1229 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1230 string_concat_string_string_string_string = GetMethod (
1231 string_type, "Concat", string_string_string_string);
1232 Type[] params_string = { GetConstructedType (string_type, "[]") };
1233 string_concat_string_dot_dot_dot = GetMethod (
1234 string_type, "Concat", params_string);
1236 Type [] object_object = { object_type, object_type };
1237 string_concat_object_object = GetMethod (
1238 string_type, "Concat", object_object);
1239 Type [] object_object_object = { object_type, object_type, object_type };
1240 string_concat_object_object_object = GetMethod (
1241 string_type, "Concat", object_object_object);
1242 Type[] params_object = { GetConstructedType (object_type, "[]") };
1243 string_concat_object_dot_dot_dot = GetMethod (
1244 string_type, "Concat", params_object);
1246 Type [] string_ = { string_type };
1247 string_isinterned_string = GetMethod (
1248 string_type, "IsInterned", string_);
1250 Type [] runtime_type_handle = { runtime_handle_type };
1251 system_type_get_type_from_handle = GetMethod (
1252 type_type, "GetTypeFromHandle", runtime_type_handle);
1254 Type [] delegate_delegate = { delegate_type, delegate_type };
1255 delegate_combine_delegate_delegate = GetMethod (
1256 delegate_type, "Combine", delegate_delegate);
1258 delegate_remove_delegate_delegate = GetMethod (
1259 delegate_type, "Remove", delegate_delegate);
1264 ienumerator_getcurrent = GetProperty (
1265 ienumerator_type, "Current");
1266 bool_movenext_void = GetMethod (
1267 ienumerator_type, "MoveNext", Type.EmptyTypes);
1268 void_reset_void = GetMethod (
1269 ienumerator_type, "Reset", Type.EmptyTypes);
1270 void_dispose_void = GetMethod (
1271 idisposable_type, "Dispose", Type.EmptyTypes);
1272 int_get_offset_to_string_data = GetMethod (
1273 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1274 int_array_get_length = GetMethod (
1275 array_type, "get_Length", Type.EmptyTypes);
1276 int_array_get_rank = GetMethod (
1277 array_type, "get_Rank", Type.EmptyTypes);
1278 ienumerable_getenumerator_void = GetMethod (
1279 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1284 Type [] int_arg = { int32_type };
1285 int_array_get_length_int = GetMethod (
1286 array_type, "GetLength", int_arg);
1287 int_array_get_upper_bound_int = GetMethod (
1288 array_type, "GetUpperBound", int_arg);
1289 int_array_get_lower_bound_int = GetMethod (
1290 array_type, "GetLowerBound", int_arg);
1293 // System.Array methods
1295 object_array_clone = GetMethod (
1296 array_type, "Clone", Type.EmptyTypes);
1297 Type [] array_int_arg = { array_type, int32_type };
1298 void_array_copyto_array_int = GetMethod (
1299 array_type, "CopyTo", array_int_arg);
1304 Type [] object_arg = { object_type };
1305 void_monitor_enter_object = GetMethod (
1306 monitor_type, "Enter", object_arg);
1307 void_monitor_exit_object = GetMethod (
1308 monitor_type, "Exit", object_arg);
1310 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1312 void_initializearray_array_fieldhandle = GetMethod (
1313 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1318 int_getlength_int = GetMethod (
1319 array_type, "GetLength", int_arg);
1322 // Decimal constructors
1324 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1325 void_decimal_ctor_five_args = GetConstructor (
1326 decimal_type, dec_arg);
1328 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1333 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1334 default_member_ctor = GetConstructor (default_member_type, string_);
1335 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1337 Type[] short_arg = { short_type };
1338 // fails for .net 2.1
1339 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg, false);
1341 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1342 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1344 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1348 // System.Threading.CompareExchange
1350 Type[] compare_exchange_types = {
1351 GetReferenceType (int32_type), int32_type, int32_type };
1352 int_interlocked_compare_exchange = GetMethod (
1353 interlocked_type, "CompareExchange", compare_exchange_types);
1359 compiler_generated_attr = new CustomAttributeBuilder (
1360 GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1362 Type[] type_int_arg = { type_type, int32_type };
1363 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1370 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1373 InitGenericCodeHelpers ();
1378 static void InitSystemCore ()
1380 if (RootContext.Version != LanguageVersion.LINQ)
1383 if (extension_attribute_type != null)
1384 extension_attribute_attr = new CustomAttributeBuilder (
1385 GetConstructor (extension_attribute_type, Type.EmptyTypes), new object[0]);
1389 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1392 /// This is the "old", non-cache based FindMembers() function. We cannot use
1393 /// the cache here because there is no member name argument.
1395 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1396 MemberFilter filter, object criteria)
1398 #if MS_COMPATIBLE && GMCS_SOURCE
1399 if (t.IsGenericType)
1400 t = t.GetGenericTypeDefinition ();
1403 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1406 // `builder_to_declspace' contains all dynamic types.
1410 Timer.StartTimer (TimerType.FindMembers);
1411 list = decl.FindMembers (mt, bf, filter, criteria);
1412 Timer.StopTimer (TimerType.FindMembers);
1417 // We have to take care of arrays specially, because GetType on
1418 // a TypeBuilder array will return a Type, not a TypeBuilder,
1419 // and we can not call FindMembers on this type.
1422 #if MS_COMPATIBLE && GMCS_SOURCE
1425 t.IsSubclassOf (TypeManager.array_type))
1426 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1429 if (t is GenericTypeParameterBuilder) {
1430 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1432 Timer.StartTimer (TimerType.FindMembers);
1433 MemberList list = tparam.FindMembers (
1434 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1435 Timer.StopTimer (TimerType.FindMembers);
1441 // Since FindMembers will not lookup both static and instance
1442 // members, we emulate this behaviour here.
1444 if ((bf & instance_and_static) == instance_and_static){
1445 MemberInfo [] i_members = t.FindMembers (
1446 mt, bf & ~BindingFlags.Static, filter, criteria);
1448 int i_len = i_members.Length;
1450 MemberInfo one = i_members [0];
1453 // If any of these are present, we are done!
1455 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1456 return new MemberList (i_members);
1459 MemberInfo [] s_members = t.FindMembers (
1460 mt, bf & ~BindingFlags.Instance, filter, criteria);
1462 int s_len = s_members.Length;
1463 if (i_len > 0 || s_len > 0)
1464 return new MemberList (i_members, s_members);
1467 return new MemberList (i_members);
1469 return new MemberList (s_members);
1473 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1478 /// This method is only called from within MemberLookup. It tries to use the member
1479 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1480 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1481 /// our return value will already contain all inherited members and the caller don't need
1482 /// to check base classes and interfaces anymore.
1484 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1485 string name, out bool used_cache)
1490 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1491 // and we can ask the DeclSpace for the MemberCache.
1494 if (t.Assembly == CodeGen.Assembly.Builder) {
1495 if (t.IsGenericParameter) {
1496 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1499 if (tparam.MemberCache == null)
1500 return new MemberInfo[0];
1502 return tparam.MemberCache.FindMembers (
1503 mt, bf, name, FilterWithClosure_delegate, null);
1506 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1507 t = t.GetGenericTypeDefinition ();
1509 if (t is TypeBuilder) {
1511 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1512 cache = decl.MemberCache;
1515 // If this DeclSpace has a MemberCache, use it.
1518 if (cache != null) {
1520 return cache.FindMembers (
1521 mt, bf, name, FilterWithClosure_delegate, null);
1524 // If there is no MemberCache, we need to use the "normal" FindMembers.
1525 // Note, this is a VERY uncommon route!
1528 Timer.StartTimer (TimerType.FindMembers);
1529 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1530 FilterWithClosure_delegate, name);
1531 Timer.StopTimer (TimerType.FindMembers);
1533 return (MemberInfo []) list;
1537 // We have to take care of arrays specially, because GetType on
1538 // a TypeBuilder array will return a Type, not a TypeBuilder,
1539 // and we can not call FindMembers on this type.
1543 return TypeHandle.ArrayType.MemberCache.FindMembers (
1544 mt, bf, name, FilterWithClosure_delegate, null);
1548 if (t is GenericTypeParameterBuilder) {
1549 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1552 if (tparam.MemberCache == null)
1553 return new MemberInfo [0];
1555 return tparam.MemberCache.FindMembers (
1556 mt, bf, name, FilterWithClosure_delegate, null);
1560 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1562 // This happens if we're resolving a class'es base class and interfaces
1563 // in TypeContainer.DefineType(). At this time, the types aren't
1564 // populated yet, so we can't use the cache.
1566 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1567 FilterWithClosure_delegate, name);
1573 // This call will always succeed. There is exactly one TypeHandle instance per
1574 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1575 // the corresponding MemberCache.
1577 cache = TypeHandle.GetMemberCache (t);
1580 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1583 public static bool IsBuiltinType (Type t)
1585 t = TypeToCoreType (t);
1586 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1587 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1588 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1589 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1595 public static bool IsBuiltinType (TypeContainer tc)
1597 return IsBuiltinType (tc.TypeBuilder);
1601 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1602 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1604 public static bool IsPrimitiveType (Type t)
1606 return (t == int32_type || t == uint32_type ||
1607 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1608 t == char_type || t == short_type || t == bool_type ||
1609 t == sbyte_type || t == byte_type || t == ushort_type);
1612 public static bool IsDelegateType (Type t)
1615 if (t.IsGenericParameter)
1619 t = DropGenericTypeArguments (t);
1620 if (t.IsSubclassOf (TypeManager.delegate_type))
1626 public static bool IsEnumType (Type t)
1628 t = DropGenericTypeArguments (t);
1629 if (builder_to_declspace [t] is Enum)
1632 #if MS_COMPATIBLE && GMCS_SOURCE
1633 if (t.IsGenericParameter || t.IsGenericType)
1639 public static bool IsBuiltinOrEnum (Type t)
1641 if (IsBuiltinType (t))
1650 public static bool IsNullType (Type t)
1652 return t == null_type;
1655 public static bool IsAttributeType (Type t)
1657 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1660 static Stack unmanaged_enclosing_types = new Stack (4);
1663 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1665 public static bool IsUnmanagedType (Type t)
1667 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1668 if (unmanaged_enclosing_types.Contains (t))
1671 // builtins that are not unmanaged types
1672 if (t == TypeManager.object_type || t == TypeManager.string_type)
1675 if (IsGenericType (t) || IsGenericParameter (t))
1678 if (IsBuiltinOrEnum (t))
1681 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1685 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1689 if (!IsValueType (t))
1693 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1694 if (p.IsGenericTypeDefinition)
1699 unmanaged_enclosing_types.Push (t);
1703 if (t is TypeBuilder) {
1704 TypeContainer tc = LookupTypeContainer (t);
1705 if (tc.Fields != null){
1706 foreach (FieldBase f in tc.Fields){
1707 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1708 if ((f.ModFlags & Modifiers.STATIC) != 0)
1710 if (f.MemberType == null)
1712 if (!IsUnmanagedType (f.MemberType)){
1713 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1719 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1721 foreach (FieldInfo f in fields){
1722 if (!IsUnmanagedType (f.FieldType)){
1723 Report.SymbolRelatedToPreviousError (f);
1729 unmanaged_enclosing_types.Pop ();
1734 public static bool IsValueType (Type t)
1736 return t.IsValueType || IsGenericParameter (t);
1739 public static bool IsInterfaceType (Type t)
1741 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1745 return tc.Kind == Kind.Interface;
1748 public static bool IsSubclassOf (Type type, Type base_type)
1750 TypeParameter tparam = LookupTypeParameter (type);
1751 TypeParameter pparam = LookupTypeParameter (base_type);
1753 if ((tparam != null) && (pparam != null)) {
1754 if (tparam == pparam)
1757 return tparam.IsSubclassOf (base_type);
1760 #if MS_COMPATIBLE && GMCS_SOURCE
1761 if (type.IsGenericType)
1762 type = type.GetGenericTypeDefinition ();
1765 if (type.IsSubclassOf (base_type))
1769 if (IsEqual (type, base_type))
1772 type = type.BaseType;
1773 } while (type != null);
1778 public static bool IsPrivateAccessible (Type type, Type parent)
1783 if (type.Equals (parent))
1786 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1789 public static bool IsFamilyAccessible (Type type, Type parent)
1791 TypeParameter tparam = LookupTypeParameter (type);
1792 TypeParameter pparam = LookupTypeParameter (parent);
1794 if ((tparam != null) && (pparam != null)) {
1795 if (tparam == pparam)
1798 return tparam.IsSubclassOf (parent);
1802 if (IsInstantiationOfSameGenericType (type, parent))
1805 type = type.BaseType;
1806 } while (type != null);
1812 // Checks whether `type' is a subclass or nested child of `base_type'.
1814 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1817 if (IsFamilyAccessible (type, base_type))
1820 // Handle nested types.
1821 type = type.DeclaringType;
1822 } while (type != null);
1828 // Checks whether `type' is a nested child of `parent'.
1830 public static bool IsNestedChildOf (Type type, Type parent)
1835 type = DropGenericTypeArguments (type);
1836 parent = DropGenericTypeArguments (parent);
1838 if (IsEqual (type, parent))
1841 type = type.DeclaringType;
1842 while (type != null) {
1843 if (IsEqual (type, parent))
1846 type = type.DeclaringType;
1854 // Checks whether `extern_type' is friend of the output assembly
1856 public static bool IsFriendAssembly (Assembly assembly)
1858 // FIXME: This should not be reached
1859 if (assembly == CodeGen.Assembly.Builder)
1862 if (assembly_internals_vis_attrs.Contains (assembly))
1863 return (bool)(assembly_internals_vis_attrs [assembly]);
1865 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1866 if (attrs.Length == 0) {
1867 assembly_internals_vis_attrs.Add (assembly, false);
1871 AssemblyName this_name = CodeGen.Assembly.Name;
1872 byte [] this_token = this_name.GetPublicKeyToken ();
1873 bool is_friend = false;
1874 foreach (InternalsVisibleToAttribute attr in attrs) {
1875 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1878 AssemblyName aname = null;
1880 aname = new AssemblyName (attr.AssemblyName);
1881 } catch (FileLoadException) {
1882 } catch (ArgumentException) {
1885 if (aname == null || aname.Name != this_name.Name)
1888 byte [] key_token = aname.GetPublicKeyToken ();
1889 if (key_token != null) {
1890 if (this_token == null) {
1891 // Same name, but key token is null
1892 Error_FriendAccessNameNotMatching (aname.FullName);
1896 if (!CompareKeyTokens (this_token, key_token))
1904 assembly_internals_vis_attrs.Add (assembly, is_friend);
1908 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1910 for (int i = 0; i < token1.Length; i++)
1911 if (token1 [i] != token2 [i])
1917 static void Error_FriendAccessNameNotMatching (string other_name)
1919 Report.Error (281, "Friend access was granted to `" + other_name +
1920 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1921 "'. Try adding a reference to `" + other_name +
1922 "' or change the output assembly name to match it");
1925 public static bool IsFriendAssembly (Assembly assembly)
1932 // Do the right thing when returning the element type of an
1933 // array type based on whether we are compiling corlib or not
1935 public static Type GetElementType (Type t)
1937 if (RootContext.StdLib)
1938 return t.GetElementType ();
1940 return TypeToCoreType (t.GetElementType ());
1944 /// This method is not implemented by MS runtime for dynamic types
1946 public static bool HasElementType (Type t)
1948 return t.IsArray || t.IsPointer || t.IsByRef;
1952 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1956 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1957 /// for anything which is dynamic, and we need this in a number of places,
1958 /// we register this information here, and use it afterwards.
1960 static public void RegisterMethod (MethodBase mb, Parameters ip)
1962 method_params.Add (mb, ip);
1965 static public ParameterData GetParameterData (MethodBase mb)
1967 ParameterData pd = (ParameterData)method_params [mb];
1970 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1971 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1972 pd = GetParameterData (mi);
1973 if (mi.IsGenericMethod)
1974 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1976 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1977 method_params.Add (mb, pd);
1981 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1982 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1983 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1986 pd = new ReflectionParameters (mb);
1987 method_params.Add (mb, pd);
1992 public static ParameterData GetDelegateParameters (Type t)
1994 Delegate d = builder_to_declspace [t] as Delegate;
1996 return d.Parameters;
1998 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1999 return GetParameterData (invoke_mb);
2002 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
2004 if (!method_overrides.Contains (override_method))
2005 method_overrides [override_method] = base_method;
2006 if (method_overrides [override_method] != base_method)
2007 throw new InternalErrorException ("Override mismatch: " + override_method);
2010 static public bool IsOverride (MethodBase m)
2012 m = DropGenericMethodArguments (m);
2014 return m.IsVirtual &&
2015 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
2016 (m is MethodBuilder || method_overrides.Contains (m));
2019 static public MethodBase TryGetBaseDefinition (MethodBase m)
2021 m = DropGenericMethodArguments (m);
2023 return (MethodBase) method_overrides [m];
2027 /// Returns the argument types for an indexer based on its PropertyInfo
2029 /// For dynamic indexers, we use the compiler provided types, for
2030 /// indexers from existing assemblies we load them from GetParameters,
2031 /// and insert them into the cache
2033 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2035 if (indexer_arguments.Contains (indexer))
2036 return (Type []) indexer_arguments [indexer];
2037 else if (indexer is PropertyBuilder)
2038 // If we're a PropertyBuilder and not in the
2039 // `indexer_arguments' hash, then we're a property and
2041 return Type.EmptyTypes;
2043 ParameterInfo [] pi = indexer.GetIndexParameters ();
2044 // Property, not an indexer.
2046 return Type.EmptyTypes;
2048 Type [] types = new Type [c];
2050 for (int i = 0; i < c; i++)
2051 types [i] = pi [i].ParameterType;
2053 indexer_arguments.Add (indexer, types);
2058 public static void RegisterConstant (FieldInfo fb, IConstant ic)
2060 fields.Add (fb, ic);
2063 public static IConstant GetConstant (FieldInfo fb)
2068 return (IConstant)fields [fb];
2071 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
2073 propertybuilder_to_property.Add (pi, pb);
2076 public static PropertyBase GetProperty (PropertyInfo pi)
2078 return (PropertyBase)propertybuilder_to_property [pi];
2081 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
2083 fieldbuilders_to_fields.Add (fb, f);
2087 // The return value can be null; This will be the case for
2088 // auxiliary FieldBuilders created by the compiler that have no
2089 // real field being declared on the source code
2091 static public FieldBase GetField (FieldInfo fb)
2094 fb = GetGenericFieldDefinition (fb);
2096 return (FieldBase) fieldbuilders_to_fields [fb];
2099 static public MethodInfo GetAddMethod (EventInfo ei)
2101 if (ei is MyEventBuilder) {
2102 return ((MyEventBuilder)ei).GetAddMethod (true);
2104 return ei.GetAddMethod (true);
2107 static public MethodInfo GetRemoveMethod (EventInfo ei)
2109 if (ei is MyEventBuilder) {
2110 return ((MyEventBuilder)ei).GetRemoveMethod (true);
2112 return ei.GetRemoveMethod (true);
2115 static public void RegisterEventField (EventInfo einfo, EventField e)
2118 events = new Hashtable ();
2120 events.Add (einfo, e);
2123 static public EventField GetEventField (EventInfo ei)
2128 return (EventField) events [ei];
2131 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2132 MethodBase set, Type[] args)
2134 indexer_arguments.Add (pb, args);
2139 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2141 Hashtable hash = new Hashtable ();
2142 return CheckStructCycles (tc, seen, hash);
2145 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2148 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2152 // `seen' contains all types we've already visited.
2154 if (seen.Contains (tc))
2156 seen.Add (tc, null);
2158 if (tc.Fields == null)
2161 foreach (FieldBase field in tc.Fields) {
2162 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2165 Type ftype = field.FieldBuilder.FieldType;
2166 TypeContainer ftc = LookupTypeContainer (ftype);
2170 if (hash.Contains (ftc)) {
2171 Report.Error (523, tc.Location,
2172 "Struct member `{0}.{1}' of type `{2}' " +
2173 "causes a cycle in the struct layout",
2174 tc.Name, field.Name, ftc.Name);
2179 // `hash' contains all types in the current path.
2181 hash.Add (tc, null);
2183 bool ok = CheckStructCycles (ftc, seen, hash);
2190 if (!seen.Contains (ftc))
2191 seen.Add (ftc, null);
2198 /// Given an array of interface types, expand and eliminate repeated ocurrences
2199 /// of an interface.
2203 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2206 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2208 ArrayList new_ifaces = new ArrayList ();
2210 foreach (TypeExpr iface in base_interfaces){
2211 Type itype = iface.Type;
2213 if (new_ifaces.Contains (itype))
2216 new_ifaces.Add (itype);
2218 Type [] implementing = GetInterfaces (itype);
2220 foreach (Type imp in implementing){
2221 if (!new_ifaces.Contains (imp))
2222 new_ifaces.Add (imp);
2225 Type [] ret = new Type [new_ifaces.Count];
2226 new_ifaces.CopyTo (ret, 0);
2230 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2232 ArrayList new_ifaces = new ArrayList ();
2234 foreach (Type itype in base_interfaces){
2235 if (new_ifaces.Contains (itype))
2238 new_ifaces.Add (itype);
2240 Type [] implementing = GetInterfaces (itype);
2242 foreach (Type imp in implementing){
2243 if (!new_ifaces.Contains (imp))
2244 new_ifaces.Add (imp);
2247 Type [] ret = new Type [new_ifaces.Count];
2248 new_ifaces.CopyTo (ret, 0);
2252 static PtrHashtable iface_cache = new PtrHashtable ();
2255 /// This function returns the interfaces in the type `t'. Works with
2256 /// both types and TypeBuilders.
2258 public static Type [] GetInterfaces (Type t)
2260 Type [] cached = iface_cache [t] as Type [];
2265 // The reason for catching the Array case is that Reflection.Emit
2266 // will not return a TypeBuilder for Array types of TypeBuilder types,
2267 // but will still throw an exception if we try to call GetInterfaces
2270 // Since the array interfaces are always constant, we return those for
2275 t = TypeManager.array_type;
2277 if ((t is TypeBuilder) || IsGenericType (t)) {
2278 Type [] base_ifaces;
2280 if (t.BaseType == null)
2281 base_ifaces = Type.EmptyTypes;
2283 base_ifaces = GetInterfaces (t.BaseType);
2285 if (IsGenericType (t))
2286 #if MS_COMPATIBLE && GMCS_SOURCE
2287 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2289 type_ifaces = t.GetInterfaces ();
2292 type_ifaces = (Type []) builder_to_ifaces [t];
2293 if (type_ifaces == null || type_ifaces.Length == 0)
2294 type_ifaces = Type.EmptyTypes;
2296 int base_count = base_ifaces.Length;
2297 Type [] result = new Type [base_count + type_ifaces.Length];
2298 base_ifaces.CopyTo (result, 0);
2299 type_ifaces.CopyTo (result, base_count);
2301 iface_cache [t] = result;
2304 } else if (t is GenericTypeParameterBuilder){
2305 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2306 if (type_ifaces == null || type_ifaces.Length == 0)
2307 type_ifaces = Type.EmptyTypes;
2309 iface_cache [t] = type_ifaces;
2313 Type[] ifaces = t.GetInterfaces ();
2314 iface_cache [t] = ifaces;
2320 // gets the interfaces that are declared explicitly on t
2322 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2324 return (Type []) builder_to_ifaces [t];
2328 /// The following is used to check if a given type implements an interface.
2329 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2331 public static bool ImplementsInterface (Type t, Type iface)
2336 // FIXME OPTIMIZATION:
2337 // as soon as we hit a non-TypeBuiler in the interface
2338 // chain, we could return, as the `Type.GetInterfaces'
2339 // will return all the interfaces implement by the type
2343 interfaces = GetInterfaces (t);
2345 if (interfaces != null){
2346 foreach (Type i in interfaces){
2353 } while (t != null);
2358 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2360 // This is a custom version of Convert.ChangeType() which works
2361 // with the TypeBuilder defined types when compiling corlib.
2362 public static object ChangeType (object value, Type conversionType, out bool error)
2364 IConvertible convert_value = value as IConvertible;
2366 if (convert_value == null){
2373 // We must use Type.Equals() here since `conversionType' is
2374 // the TypeBuilder created version of a system type and not
2375 // the system type itself. You cannot use Type.GetTypeCode()
2376 // on such a type - it'd always return TypeCode.Object.
2379 // We cannot rely on build-in type conversions as they are
2380 // more limited than what C# supports.
2381 // See char -> float/decimal/double conversion
2386 if (conversionType.Equals (typeof (Boolean)))
2387 return (object)(convert_value.ToBoolean (nf_provider));
2388 if (conversionType.Equals (typeof (Byte)))
2389 return (object)(convert_value.ToByte (nf_provider));
2390 if (conversionType.Equals (typeof (Char)))
2391 return (object)(convert_value.ToChar (nf_provider));
2392 if (conversionType.Equals (typeof (DateTime)))
2393 return (object)(convert_value.ToDateTime (nf_provider));
2395 if (conversionType.Equals (TypeManager.decimal_type)) {
2396 if (convert_value.GetType () == TypeManager.char_type)
2397 return (decimal)convert_value.ToInt32 (nf_provider);
2398 return convert_value.ToDecimal (nf_provider);
2401 if (conversionType.Equals (typeof (Double))) {
2402 if (convert_value.GetType () == TypeManager.char_type)
2403 return (double)convert_value.ToInt32 (nf_provider);
2404 return convert_value.ToDouble (nf_provider);
2407 if (conversionType.Equals (typeof (Int16)))
2408 return (object)(convert_value.ToInt16 (nf_provider));
2409 if (conversionType.Equals (typeof (Int32)))
2410 return (object)(convert_value.ToInt32 (nf_provider));
2411 if (conversionType.Equals (typeof (Int64)))
2412 return (object)(convert_value.ToInt64 (nf_provider));
2413 if (conversionType.Equals (typeof (SByte)))
2414 return (object)(convert_value.ToSByte (nf_provider));
2416 if (conversionType.Equals (typeof (Single))) {
2417 if (convert_value.GetType () == TypeManager.char_type)
2418 return (float)convert_value.ToInt32 (nf_provider);
2419 return convert_value.ToSingle (nf_provider);
2422 if (conversionType.Equals (typeof (String)))
2423 return (object)(convert_value.ToString (nf_provider));
2424 if (conversionType.Equals (typeof (UInt16)))
2425 return (object)(convert_value.ToUInt16 (nf_provider));
2426 if (conversionType.Equals (typeof (UInt32)))
2427 return (object)(convert_value.ToUInt32 (nf_provider));
2428 if (conversionType.Equals (typeof (UInt64)))
2429 return (object)(convert_value.ToUInt64 (nf_provider));
2430 if (conversionType.Equals (typeof (Object)))
2431 return (object)(value);
2441 // This is needed, because enumerations from assemblies
2442 // do not report their underlyingtype, but they report
2445 public static Type EnumToUnderlying (Type t)
2447 t = DropGenericTypeArguments (t);
2448 if (t == TypeManager.enum_type)
2451 t = t.UnderlyingSystemType;
2452 if (!TypeManager.IsEnumType (t))
2455 if (t is TypeBuilder) {
2456 // slow path needed to compile corlib
2457 if (t == TypeManager.bool_type ||
2458 t == TypeManager.byte_type ||
2459 t == TypeManager.sbyte_type ||
2460 t == TypeManager.char_type ||
2461 t == TypeManager.short_type ||
2462 t == TypeManager.ushort_type ||
2463 t == TypeManager.int32_type ||
2464 t == TypeManager.uint32_type ||
2465 t == TypeManager.int64_type ||
2466 t == TypeManager.uint64_type)
2469 TypeCode tc = Type.GetTypeCode (t);
2472 case TypeCode.Boolean:
2473 return TypeManager.bool_type;
2475 return TypeManager.byte_type;
2476 case TypeCode.SByte:
2477 return TypeManager.sbyte_type;
2479 return TypeManager.char_type;
2480 case TypeCode.Int16:
2481 return TypeManager.short_type;
2482 case TypeCode.UInt16:
2483 return TypeManager.ushort_type;
2484 case TypeCode.Int32:
2485 return TypeManager.int32_type;
2486 case TypeCode.UInt32:
2487 return TypeManager.uint32_type;
2488 case TypeCode.Int64:
2489 return TypeManager.int64_type;
2490 case TypeCode.UInt64:
2491 return TypeManager.uint64_type;
2493 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2497 // When compiling corlib and called with one of the core types, return
2498 // the corresponding typebuilder for that type.
2500 public static Type TypeToCoreType (Type t)
2502 if (RootContext.StdLib || (t is TypeBuilder))
2505 TypeCode tc = Type.GetTypeCode (t);
2508 case TypeCode.Boolean:
2509 return TypeManager.bool_type;
2511 return TypeManager.byte_type;
2512 case TypeCode.SByte:
2513 return TypeManager.sbyte_type;
2515 return TypeManager.char_type;
2516 case TypeCode.Int16:
2517 return TypeManager.short_type;
2518 case TypeCode.UInt16:
2519 return TypeManager.ushort_type;
2520 case TypeCode.Int32:
2521 return TypeManager.int32_type;
2522 case TypeCode.UInt32:
2523 return TypeManager.uint32_type;
2524 case TypeCode.Int64:
2525 return TypeManager.int64_type;
2526 case TypeCode.UInt64:
2527 return TypeManager.uint64_type;
2528 case TypeCode.Single:
2529 return TypeManager.float_type;
2530 case TypeCode.Double:
2531 return TypeManager.double_type;
2532 case TypeCode.String:
2533 return TypeManager.string_type;
2534 case TypeCode.Decimal:
2535 return TypeManager.decimal_type;
2537 if (t == typeof (void))
2538 return TypeManager.void_type;
2539 if (t == typeof (object))
2540 return TypeManager.object_type;
2541 if (t == typeof (System.Type))
2542 return TypeManager.type_type;
2543 if (t == typeof (System.IntPtr))
2544 return TypeManager.intptr_type;
2550 /// Utility function that can be used to probe whether a type
2551 /// is managed or not.
2553 public static bool VerifyUnManaged (Type t, Location loc)
2555 if (IsUnmanagedType (t))
2558 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2565 /// Returns the name of the indexer in a given type.
2568 /// The default is not always `Item'. The user can change this behaviour by
2569 /// using the IndexerNameAttribute in the container.
2570 /// For example, the String class indexer is named `Chars' not `Item'
2572 public static string IndexerPropertyName (Type t)
2574 t = DropGenericTypeArguments (t);
2575 if (t is TypeBuilder) {
2576 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2577 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2580 System.Attribute attr = System.Attribute.GetCustomAttribute (
2581 t, TypeManager.default_member_type);
2583 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2584 return dma.MemberName;
2587 return TypeContainer.DefaultIndexerName;
2590 static MethodInfo declare_local_method = null;
2592 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2594 if (declare_local_method == null){
2595 declare_local_method = typeof (ILGenerator).GetMethod (
2597 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2599 new Type [] { typeof (Type), typeof (bool)},
2601 if (declare_local_method == null){
2602 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2603 return ig.DeclareLocal (t);
2606 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2609 private static bool IsSignatureEqual (Type a, Type b)
2612 /// Consider the following example (bug #77674):
2614 /// public abstract class A
2616 /// public abstract T Foo<T> ();
2619 /// public abstract class B : A
2621 /// public override U Foo<T> ()
2622 /// { return default (U); }
2625 /// Here, `T' and `U' are method type parameters from different methods
2626 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2628 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2629 /// we need to do a signature based comparision and consider them equal.
2635 if (a.IsGenericParameter && b.IsGenericParameter &&
2636 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2637 return a.GenericParameterPosition == b.GenericParameterPosition;
2641 if (a.IsArray && b.IsArray) {
2642 if (a.GetArrayRank () != b.GetArrayRank ())
2645 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2648 if (a.IsByRef && b.IsByRef)
2649 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2652 if (a.IsGenericType && b.IsGenericType) {
2653 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2656 Type[] aargs = a.GetGenericArguments ();
2657 Type[] bargs = b.GetGenericArguments ();
2659 if (aargs.Length != bargs.Length)
2662 for (int i = 0; i < aargs.Length; i++) {
2663 if (!IsSignatureEqual (aargs [i], bargs [i]))
2675 // Returns whether the array of memberinfos contains the given method
2677 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2679 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2681 foreach (MethodBase method in array) {
2682 if (method.Name != new_method.Name)
2685 if (method is MethodInfo && new_method is MethodInfo)
2686 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2687 ((MethodInfo) new_method).ReturnType))
2691 Type [] old_args = TypeManager.GetParameterData (method).Types;
2692 int old_count = old_args.Length;
2695 if (new_args.Length != old_count)
2698 for (i = 0; i < old_count; i++){
2699 if (!IsSignatureEqual (old_args [i], new_args [i]))
2712 // We copy methods from `new_members' into `target_list' if the signature
2713 // for the method from in the new list does not exist in the target_list
2715 // The name is assumed to be the same.
2717 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2719 if (target_list == null){
2720 target_list = new ArrayList ();
2722 foreach (MemberInfo mi in new_members){
2723 if (mi is MethodBase)
2724 target_list.Add (mi);
2729 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2730 target_list.CopyTo (target_array, 0);
2732 foreach (MemberInfo mi in new_members){
2733 MethodBase new_method = (MethodBase) mi;
2735 if (!ArrayContainsMethod (target_array, new_method))
2736 target_list.Add (new_method);
2743 // Tracks the generic parameters.
2745 static PtrHashtable builder_to_type_param;
2747 public static void AddTypeParameter (Type t, TypeParameter tparam)
2749 if (!builder_to_type_param.Contains (t))
2750 builder_to_type_param.Add (t, tparam);
2753 public static TypeParameter LookupTypeParameter (Type t)
2755 return (TypeParameter) builder_to_type_param [t];
2758 // This method always return false for non-generic compiler,
2759 // while Type.IsGenericParameter is returned if it is supported.
2760 public static bool IsGenericParameter (Type type)
2763 return type.IsGenericParameter;
2769 public static int GenericParameterPosition (Type type)
2772 return type.GenericParameterPosition;
2774 throw new InternalErrorException ("should not be called");
2778 public static bool IsGenericType (Type type)
2781 return type.IsGenericType;
2787 public static bool IsGenericTypeDefinition (Type type)
2790 return type.IsGenericTypeDefinition;
2796 public static bool ContainsGenericParameters (Type type)
2799 return type.ContainsGenericParameters;
2805 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2808 if (fi.DeclaringType.IsGenericTypeDefinition ||
2809 !fi.DeclaringType.IsGenericType)
2812 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2813 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2814 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2816 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2817 foreach (FieldInfo f in t.GetFields (bf))
2818 if (f.MetadataToken == fi.MetadataToken)
2825 public static bool IsEqual (Type a, Type b)
2828 // MS BCL returns true even if enum types are different
2829 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2830 return a.FullName == b.FullName;
2836 if (a.IsGenericParameter && b.IsGenericParameter) {
2837 if (a.DeclaringMethod != b.DeclaringMethod &&
2838 (a.DeclaringMethod == null || b.DeclaringMethod == null))
2840 return a.GenericParameterPosition == b.GenericParameterPosition;
2843 if (a.IsArray && b.IsArray) {
2844 if (a.GetArrayRank () != b.GetArrayRank ())
2846 return IsEqual (a.GetElementType (), b.GetElementType ());
2849 if (a.IsByRef && b.IsByRef)
2850 return IsEqual (a.GetElementType (), b.GetElementType ());
2852 if (a.IsGenericType && b.IsGenericType) {
2853 Type adef = a.GetGenericTypeDefinition ();
2854 Type bdef = b.GetGenericTypeDefinition ();
2859 if (adef.IsEnum && bdef.IsEnum)
2862 Type[] aargs = a.GetGenericArguments ();
2863 Type[] bargs = b.GetGenericArguments ();
2865 if (aargs.Length != bargs.Length)
2868 for (int i = 0; i < aargs.Length; i++) {
2869 if (!IsEqual (aargs [i], bargs [i]))
2880 public static Type DropGenericTypeArguments (Type t)
2883 if (!t.IsGenericType)
2885 // Micro-optimization: a generic typebuilder is always a generic type definition
2886 if (t is TypeBuilder)
2888 return t.GetGenericTypeDefinition ();
2894 public static MethodBase DropGenericMethodArguments (MethodBase m)
2897 if (m.IsGenericMethodDefinition)
2899 if (m.IsGenericMethod)
2900 return ((MethodInfo) m).GetGenericMethodDefinition ();
2901 if (!m.DeclaringType.IsGenericType)
2904 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2905 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2906 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2909 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2913 if (m is ConstructorInfo) {
2914 foreach (ConstructorInfo c in t.GetConstructors (bf))
2915 if (c.MetadataToken == m.MetadataToken)
2918 foreach (MethodBase mb in t.GetMethods (bf))
2919 if (mb.MetadataToken == m.MetadataToken)
2927 public static Type[] GetGenericArguments (MethodInfo mi)
2930 return mi.GetGenericArguments ();
2932 return Type.EmptyTypes;
2936 public static Type[] GetTypeArguments (Type t)
2939 DeclSpace tc = LookupDeclSpace (t);
2942 return Type.EmptyTypes;
2944 TypeParameter[] tparam = tc.TypeParameters;
2945 Type[] ret = new Type [tparam.Length];
2946 for (int i = 0; i < tparam.Length; i++) {
2947 ret [i] = tparam [i].Type;
2948 if (ret [i] == null)
2949 throw new InternalErrorException ();
2954 return t.GetGenericArguments ();
2956 throw new InternalErrorException ();
2960 public static bool HasGenericArguments (Type t)
2962 return GetNumberOfTypeArguments (t) > 0;
2965 public static int GetNumberOfTypeArguments (Type t)
2968 if (t.IsGenericParameter)
2970 DeclSpace tc = LookupDeclSpace (t);
2972 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2974 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2981 /// Check whether `type' and `parent' are both instantiations of the same
2982 /// generic type. Note that we do not check the type parameters here.
2984 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2986 int tcount = GetNumberOfTypeArguments (type);
2987 int pcount = GetNumberOfTypeArguments (parent);
2989 if (tcount != pcount)
2992 type = DropGenericTypeArguments (type);
2993 parent = DropGenericTypeArguments (parent);
2995 return type.Equals (parent);
2999 /// Whether `mb' is a generic method definition.
3001 public static bool IsGenericMethodDefinition (MethodBase mb)
3004 if (mb.DeclaringType is TypeBuilder) {
3005 IMethodData method = (IMethodData) builder_to_method [mb];
3009 return method.GenericMethod != null;
3012 return mb.IsGenericMethodDefinition;
3019 /// Whether `mb' is a generic method.
3021 public static bool IsGenericMethod (MethodBase mb)
3024 return mb.IsGenericMethod;
3030 public static bool IsNullableType (Type t)
3033 return generic_nullable_type == DropGenericTypeArguments (t);
3039 public static bool IsNullableTypeOf (Type t, Type nullable)
3042 if (!IsNullableType (t))
3045 return GetTypeArguments (t) [0] == nullable;
3051 public static bool IsNullableValueType (Type t)
3054 if (!IsNullableType (t))
3057 return GetTypeArguments (t) [0].IsValueType;
3064 #region MemberLookup implementation
3067 // Whether we allow private members in the result (since FindMembers
3068 // uses NonPublic for both protected and private), we need to distinguish.
3071 internal class Closure {
3072 internal bool private_ok;
3074 // Who is invoking us and which type is being queried currently.
3075 internal Type invocation_type;
3076 internal Type qualifier_type;
3078 // The assembly that defines the type is that is calling us
3079 internal Assembly invocation_assembly;
3080 internal IList almost_match;
3082 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3084 if (invocation_type == null)
3087 if (is_static && qualifier_type == null)
3088 // It resolved from a simple name, so it should be visible.
3091 if (IsNestedChildOf (invocation_type, m.DeclaringType))
3094 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
3095 if (!IsFamilyAccessible (t, m.DeclaringType))
3098 // Although a derived class can access protected members of its base class
3099 // it cannot do so through an instance of the base class (CS1540).
3100 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3101 if (is_static || qualifier_type == null ||
3102 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3103 IsFamilyAccessible (qualifier_type, t))
3107 if (almost_match != null)
3108 almost_match.Add (m);
3114 // This filter filters by name + whether it is ok to include private
3115 // members in the search
3117 internal bool Filter (MemberInfo m, object filter_criteria)
3120 // Hack: we know that the filter criteria will always be in the
3121 // `closure' // fields.
3124 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3127 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3128 (invocation_type != null) &&
3129 IsPrivateAccessible (m.DeclaringType, invocation_type))
3133 // Ugly: we need to find out the type of `m', and depending
3134 // on this, tell whether we accept or not
3136 if (m is MethodBase){
3137 MethodBase mb = (MethodBase) m;
3138 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3140 if (ma == MethodAttributes.Public)
3143 if (ma == MethodAttributes.PrivateScope)
3146 if (ma == MethodAttributes.Private)
3147 return private_ok ||
3148 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3149 IsNestedChildOf (invocation_type, m.DeclaringType);
3151 if (invocation_assembly == mb.DeclaringType.Assembly ||
3152 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3153 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3156 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3160 // Family, FamORAssem or FamANDAssem
3161 return CheckValidFamilyAccess (mb.IsStatic, m);
3164 if (m is FieldInfo){
3165 FieldInfo fi = (FieldInfo) m;
3166 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3168 if (fa == FieldAttributes.Public)
3171 if (fa == FieldAttributes.PrivateScope)
3174 if (fa == FieldAttributes.Private)
3175 return private_ok ||
3176 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3177 IsNestedChildOf (invocation_type, m.DeclaringType);
3179 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3180 (invocation_assembly == null) ||
3181 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3182 if ((fa == FieldAttributes.Assembly) ||
3183 (fa == FieldAttributes.FamORAssem))
3186 if ((fa == FieldAttributes.Assembly) ||
3187 (fa == FieldAttributes.FamANDAssem))
3191 // Family, FamORAssem or FamANDAssem
3192 return CheckValidFamilyAccess (fi.IsStatic, m);
3196 // EventInfos and PropertyInfos, return true because they lack
3197 // permission information, so we need to check later on the methods.
3203 static Closure closure = new Closure ();
3204 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3207 // Looks up a member called `name' in the `queried_type'. This lookup
3208 // is done by code that is contained in the definition for `invocation_type'
3209 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3211 // `invocation_type' is used to check whether we're allowed to access the requested
3212 // member wrt its protection level.
3214 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3215 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3216 // is B and qualifier_type is A). This is used to do the CS1540 check.
3218 // When resolving a SimpleName, `qualifier_type' is null.
3220 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3221 // the same than `queried_type' - except when we're being called from BaseAccess;
3222 // in this case, `invocation_type' is the current type and `queried_type' the base
3223 // type, so this'd normally trigger a CS1540.
3225 // The binding flags are `bf' and the kind of members being looked up are `mt'
3227 // The return value always includes private members which code in `invocation_type'
3228 // is allowed to access (using the specified `qualifier_type' if given); only use
3229 // BindingFlags.NonPublic to bypass the permission check.
3231 // The 'almost_match' argument is used for reporting error CS1540.
3233 // Returns an array of a single element for everything but Methods/Constructors
3234 // that might return multiple matches.
3236 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3237 Type queried_type, MemberTypes mt,
3238 BindingFlags original_bf, string name, IList almost_match)
3240 Timer.StartTimer (TimerType.MemberLookup);
3242 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3243 queried_type, mt, original_bf, name, almost_match);
3245 Timer.StopTimer (TimerType.MemberLookup);
3250 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3251 Type queried_type, MemberTypes mt,
3252 BindingFlags original_bf, string name, IList almost_match)
3254 BindingFlags bf = original_bf;
3256 ArrayList method_list = null;
3257 Type current_type = queried_type;
3258 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3259 bool skip_iface_check = true, used_cache = false;
3260 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3262 closure.invocation_type = invocation_type;
3263 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3264 closure.qualifier_type = qualifier_type;
3265 closure.almost_match = almost_match;
3267 // This is from the first time we find a method
3268 // in most cases, we do not actually find a method in the base class
3269 // so we can just ignore it, and save the arraylist allocation
3270 MemberInfo [] first_members_list = null;
3271 bool use_first_members_list = false;
3277 // `NonPublic' is lame, because it includes both protected and
3278 // private methods, so we need to control this behavior by
3279 // explicitly tracking if a private method is ok or not.
3281 // The possible cases are:
3282 // public, private and protected (internal does not come into the
3285 if ((invocation_type != null) &&
3286 ((invocation_type == current_type) ||
3287 IsNestedChildOf (invocation_type, current_type)) ||
3289 bf = original_bf | BindingFlags.NonPublic;
3293 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3295 Timer.StopTimer (TimerType.MemberLookup);
3297 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3299 Timer.StartTimer (TimerType.MemberLookup);
3302 // When queried for an interface type, the cache will automatically check all
3303 // inherited members, so we don't need to do this here. However, this only
3304 // works if we already used the cache in the first iteration of this loop.
3306 // If we used the cache in any further iteration, we can still terminate the
3307 // loop since the cache always looks in all base classes.
3313 skip_iface_check = false;
3315 if (current_type == TypeManager.object_type)
3318 current_type = current_type.BaseType;
3321 // This happens with interfaces, they have a null
3322 // basetype. Look members up in the Object class.
3324 if (current_type == null) {
3325 current_type = TypeManager.object_type;
3330 if (list.Length == 0)
3334 // Events and types are returned by both `static' and `instance'
3335 // searches, which means that our above FindMembers will
3336 // return two copies of the same.
3338 if (list.Length == 1 && !(list [0] is MethodBase)){
3343 // Multiple properties: we query those just to find out the indexer
3346 if (list [0] is PropertyInfo)
3350 // We found an event: the cache lookup returns both the event and
3351 // its private field.
3353 if (list [0] is EventInfo) {
3354 if ((list.Length == 2) && (list [1] is FieldInfo))
3355 return new MemberInfo [] { list [0] };
3361 // We found methods, turn the search into "method scan"
3365 if (first_members_list != null) {
3366 if (use_first_members_list) {
3367 method_list = CopyNewMethods (method_list, first_members_list);
3368 use_first_members_list = false;
3371 method_list = CopyNewMethods (method_list, list);
3373 first_members_list = list;
3374 use_first_members_list = true;
3375 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3377 } while (searching);
3379 if (use_first_members_list)
3380 return first_members_list;
3382 if (method_list != null && method_list.Count > 0) {
3383 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3386 // This happens if we already used the cache in the first iteration, in this case
3387 // the cache already looked in all interfaces.
3389 if (skip_iface_check)
3393 // Interfaces do not list members they inherit, so we have to
3396 if (!queried_type.IsInterface)
3399 if (queried_type.IsArray)
3400 queried_type = TypeManager.array_type;
3402 Type [] ifaces = GetInterfaces (queried_type);
3406 foreach (Type itype in ifaces){
3409 x = MemberLookup (null, null, itype, mt, bf, name, null);
3417 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3418 BindingFlags.Static | BindingFlags.Instance |
3419 BindingFlags.DeclaredOnly;
3421 // Currently is designed to work with external types only
3422 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3424 if (!mb.IsSpecialName)
3427 string name = mb.Name;
3428 if (name.Length < 5)
3431 if (name [3] != '_')
3434 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3435 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3436 Type.FilterName, name.Substring (4));
3441 // This can happen when property is indexer (it can have same name but different parameters)
3442 foreach (PropertyInfo p in pi) {
3443 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3444 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3453 // Currently is designed to work with external types only
3454 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3456 if (!mb.IsSpecialName)
3459 string name = mb.Name;
3460 if (name.Length < 5)
3463 if (name.StartsWith ("add_"))
3464 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3466 if (name.StartsWith ("remove_"))
3467 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3472 // Tests whether external method is really special
3473 public static bool IsSpecialMethod (MethodBase mb)
3475 if (!mb.IsSpecialName)
3478 IMethodData md = TypeManager.GetMethod (mb);
3480 return (md is AbstractPropertyEventMethod || md is Operator);
3482 PropertyInfo pi = GetPropertyFromAccessor (mb);
3484 return IsValidProperty (pi);
3486 if (GetEventFromAccessor (mb) != null)
3489 string name = mb.Name;
3490 if (name.StartsWith ("op_")){
3491 foreach (string oname in Unary.oper_names) {
3496 foreach (string oname in Binary.oper_names) {
3504 // Tests whether imported property is valid C# property.
3505 // TODO: It seems to me that we should do a lot of sanity tests before
3506 // we accept property as C# property
3507 static bool IsValidProperty (PropertyInfo pi)
3509 MethodInfo get_method = pi.GetGetMethod (true);
3510 MethodInfo set_method = pi.GetSetMethod (true);
3511 if (get_method != null && set_method != null) {
3512 int g_count = get_method.GetParameters ().Length;
3513 int s_count = set_method.GetParameters ().Length;
3514 if (g_count + 1 != s_count)
3525 /// There is exactly one instance of this class per type.
3527 public sealed class TypeHandle : IMemberContainer {
3528 public readonly IMemberContainer BaseType;
3530 readonly int id = ++next_id;
3531 static int next_id = 0;
3533 static TypeHandle ()
3539 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3540 /// a TypeHandle yet, a new instance of it is created. This static method
3541 /// ensures that we'll only have one TypeHandle instance per type.
3543 private static TypeHandle GetTypeHandle (Type t)
3545 TypeHandle handle = (TypeHandle) type_hash [t];
3549 handle = new TypeHandle (t);
3550 type_hash.Add (t, handle);
3554 public static MemberCache GetMemberCache (Type t)
3556 return GetTypeHandle (t).MemberCache;
3559 public static void CleanUp ()
3564 public static void Reset ()
3566 type_hash = new PtrHashtable ();
3570 /// Returns the TypeHandle for TypeManager.object_type.
3572 public static IMemberContainer ObjectType {
3574 if (object_type != null)
3577 object_type = GetTypeHandle (TypeManager.object_type);
3584 /// Returns the TypeHandle for TypeManager.array_type.
3586 public static IMemberContainer ArrayType {
3588 if (array_type != null)
3591 array_type = GetTypeHandle (TypeManager.array_type);
3597 private static PtrHashtable type_hash;
3599 private static TypeHandle object_type = null;
3600 private static TypeHandle array_type = null;
3603 private string full_name;
3604 private bool is_interface;
3605 private MemberCache member_cache;
3606 private MemberCache base_cache;
3608 private TypeHandle (Type type)
3611 #if MS_COMPATIBLE && GMCS_SOURCE
3612 if (type.IsGenericType && !type.IsGenericTypeDefinition)
3613 this.type = this.type.GetGenericTypeDefinition ();
3615 full_name = type.FullName != null ? type.FullName : type.Name;
3616 if (type.BaseType != null) {
3617 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3618 BaseType = base_cache.Container;
3619 } else if (type.IsInterface)
3620 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3621 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3622 this.member_cache = new MemberCache (this);
3625 // IMemberContainer methods
3627 public string Name {
3639 public MemberCache BaseCache {
3645 public bool IsInterface {
3647 return is_interface;
3651 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3653 MemberInfo [] members;
3656 if (type is GenericTypeParameterBuilder)
3657 return MemberList.Empty;
3660 if (mt == MemberTypes.Event)
3661 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3663 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3665 Array.Reverse (members);
3667 return new MemberList (members);
3670 // IMemberFinder methods
3672 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3673 MemberFilter filter, object criteria)
3675 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3678 public MemberCache MemberCache {
3680 return member_cache;
3684 public override string ToString ()
3686 if (BaseType != null)
3687 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3689 return "TypeHandle (" + id + "," + Name + ")";