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 assembly_version_attribute_type;
112 static public Type coclass_attr_type;
113 static public Type comimport_attr_type;
119 static internal Type runtime_compatibility_attr_type;
120 static internal Type compiler_generated_attr_type;
121 static internal Type fixed_buffer_attr_type;
122 static internal Type default_charset_type;
123 static internal Type internals_visible_attr_type;
124 static internal Type type_forwarder_attr_type;
128 // Expressions representing the internal types. Used during declaration
131 static public TypeExpr system_object_expr, system_string_expr;
132 static public TypeExpr system_boolean_expr, system_decimal_expr;
133 static public TypeExpr system_single_expr, system_double_expr;
134 static public TypeExpr system_sbyte_expr, system_byte_expr;
135 static public TypeExpr system_int16_expr, system_uint16_expr;
136 static public TypeExpr system_int32_expr, system_uint32_expr;
137 static public TypeExpr system_int64_expr, system_uint64_expr;
138 static public TypeExpr system_char_expr, system_void_expr;
139 static public TypeExpr system_asynccallback_expr;
140 static public TypeExpr system_iasyncresult_expr;
141 static public TypeExpr system_valuetype_expr;
142 static public TypeExpr system_intptr_expr;
145 // This is only used when compiling corlib
147 static public Type system_int32_type;
148 static public Type system_array_type;
149 static public Type system_type_type;
150 static public Type system_assemblybuilder_type;
151 static public MethodInfo system_int_array_get_length;
152 static public MethodInfo system_int_array_get_rank;
153 static public MethodInfo system_object_array_clone;
154 static public MethodInfo system_int_array_get_length_int;
155 static public MethodInfo system_int_array_get_lower_bound_int;
156 static public MethodInfo system_int_array_get_upper_bound_int;
157 static public MethodInfo system_void_array_copyto_array_int;
161 // Internal, not really used outside
163 static Type runtime_helpers_type;
166 // These methods are called by code generated by the compiler
168 static public MethodInfo string_concat_string_string;
169 static public MethodInfo string_concat_string_string_string;
170 static public MethodInfo string_concat_string_string_string_string;
171 static public MethodInfo string_concat_string_dot_dot_dot;
172 static public MethodInfo string_concat_object_object;
173 static public MethodInfo string_concat_object_object_object;
174 static public MethodInfo string_concat_object_dot_dot_dot;
175 static public MethodInfo string_isinterned_string;
176 static public MethodInfo system_type_get_type_from_handle;
177 static public MethodInfo bool_movenext_void;
178 static public MethodInfo ienumerable_getenumerator_void;
179 static public MethodInfo void_reset_void;
180 static public MethodInfo void_dispose_void;
181 static public MethodInfo void_monitor_enter_object;
182 static public MethodInfo void_monitor_exit_object;
183 static public MethodInfo void_initializearray_array_fieldhandle;
184 static public MethodInfo int_getlength_int;
185 static public MethodInfo delegate_combine_delegate_delegate;
186 static public MethodInfo delegate_remove_delegate_delegate;
187 static public MethodInfo int_get_offset_to_string_data;
188 static public MethodInfo int_array_get_length;
189 static public MethodInfo int_array_get_rank;
190 static public MethodInfo object_array_clone;
191 static public MethodInfo int_array_get_length_int;
192 static public MethodInfo int_array_get_lower_bound_int;
193 static public MethodInfo int_array_get_upper_bound_int;
194 static public MethodInfo void_array_copyto_array_int;
195 static public MethodInfo int_interlocked_compare_exchange;
196 static public PropertyInfo ienumerator_getcurrent;
199 // The attribute constructors.
201 static public ConstructorInfo object_ctor;
202 static public ConstructorInfo cons_param_array_attribute;
203 static public ConstructorInfo void_decimal_ctor_five_args;
204 static public ConstructorInfo void_decimal_ctor_int_arg;
205 static public ConstructorInfo unverifiable_code_ctor;
206 static public ConstructorInfo default_member_ctor;
207 static public ConstructorInfo decimal_constant_attribute_ctor;
208 static internal ConstructorInfo struct_layout_attribute_ctor;
209 static public ConstructorInfo field_offset_attribute_ctor;
213 static internal CustomAttributeBuilder compiler_generated_attr;
214 static internal ConstructorInfo fixed_buffer_attr_ctor;
218 static internal CustomAttributeBuilder extension_attribute_attr;
220 static PtrHashtable builder_to_declspace;
222 static PtrHashtable builder_to_member_cache;
225 // Tracks the interfaces implemented by typebuilders. We only
226 // enter those who do implement or or more interfaces
228 static PtrHashtable builder_to_ifaces;
231 // Maps PropertyBuilder to a Type array that contains
232 // the arguments to the indexer
234 static Hashtable indexer_arguments;
237 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
239 static Hashtable method_params;
242 // A hash table from override methods to their base virtual method.
244 static Hashtable method_overrides;
247 // Keeps track of methods
250 static Hashtable builder_to_method;
253 // Contains all public types from referenced assemblies.
254 // This member is used only if CLS Compliance verification is required.
256 public static Hashtable AllClsTopLevelTypes;
258 static Hashtable fieldbuilders_to_fields;
259 static Hashtable propertybuilder_to_property;
260 static Hashtable fields;
261 static Hashtable events;
264 static PtrHashtable assembly_internals_vis_attrs;
272 public static void CleanUp ()
274 // Lets get everything clean so that we can collect before generating code
275 builder_to_declspace = null;
276 builder_to_member_cache = null;
277 builder_to_ifaces = null;
278 builder_to_type_param = null;
279 indexer_arguments = null;
280 method_params = null;
281 builder_to_method = null;
286 propertybuilder_to_property = null;
289 assembly_internals_vis_attrs = null;
292 TypeHandle.CleanUp ();
296 /// A filter for Findmembers that uses the Signature object to
299 static bool SignatureFilter (MemberInfo mi, object criteria)
301 Signature sig = (Signature) criteria;
303 if (!(mi is MethodBase))
306 if (mi.Name != sig.name)
309 int count = sig.args.Length;
311 if (mi is MethodBuilder || mi is ConstructorBuilder){
312 Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
314 if (candidate_args.Length != count)
317 for (int i = 0; i < count; i++)
318 if (candidate_args [i] != sig.args [i])
323 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
325 if (pars.Length != count)
328 for (int i = 0; i < count; i++)
329 if (pars [i].ParameterType != sig.args [i])
335 // A delegate that points to the filter above.
336 static MemberFilter signature_filter;
339 // These are expressions that represent some of the internal data types, used
342 static void InitExpressionTypes ()
344 system_object_expr = new TypeLookupExpression ("System.Object");
345 system_string_expr = new TypeLookupExpression ("System.String");
346 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
347 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
348 system_single_expr = new TypeLookupExpression ("System.Single");
349 system_double_expr = new TypeLookupExpression ("System.Double");
350 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
351 system_byte_expr = new TypeLookupExpression ("System.Byte");
352 system_int16_expr = new TypeLookupExpression ("System.Int16");
353 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
354 system_int32_expr = new TypeLookupExpression ("System.Int32");
355 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
356 system_int64_expr = new TypeLookupExpression ("System.Int64");
357 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
358 system_char_expr = new TypeLookupExpression ("System.Char");
359 system_void_expr = new TypeLookupExpression ("System.Void");
360 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
361 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
362 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
363 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
366 static TypeManager ()
370 signature_filter = new MemberFilter (SignatureFilter);
371 InitExpressionTypes ();
374 static public void Reset ()
376 builder_to_declspace = new PtrHashtable ();
377 builder_to_member_cache = new PtrHashtable ();
378 builder_to_method = new PtrHashtable ();
379 builder_to_type_param = new PtrHashtable ();
380 method_params = new PtrHashtable ();
381 method_overrides = new PtrHashtable ();
382 indexer_arguments = new PtrHashtable ();
383 builder_to_ifaces = new PtrHashtable ();
385 fieldbuilders_to_fields = new Hashtable ();
386 propertybuilder_to_property = new Hashtable ();
387 fields = new Hashtable ();
388 type_hash = new DoubleHash ();
391 assembly_internals_vis_attrs = new PtrHashtable ();
394 // to uncover regressions
395 AllClsTopLevelTypes = null;
398 public static void AddUserType (DeclSpace ds)
400 builder_to_declspace.Add (ds.TypeBuilder, ds);
404 // This entry point is used by types that we define under the covers
406 public static void RegisterBuilder (Type tb, Type [] ifaces)
409 builder_to_ifaces [tb] = ifaces;
412 public static void AddMethod (MethodBase builder, IMethodData method)
414 builder_to_method.Add (builder, method);
415 method_params.Add (builder, method.ParameterInfo);
418 public static IMethodData GetMethod (MethodBase builder)
420 return (IMethodData) builder_to_method [builder];
424 /// Returns the DeclSpace whose Type is `t' or null if there is no
425 /// DeclSpace for `t' (ie, the Type comes from a library)
427 public static DeclSpace LookupDeclSpace (Type t)
429 return builder_to_declspace [t] as DeclSpace;
433 /// Returns the TypeContainer whose Type is `t' or null if there is no
434 /// TypeContainer for `t' (ie, the Type comes from a library)
436 public static TypeContainer LookupTypeContainer (Type t)
438 return builder_to_declspace [t] as TypeContainer;
441 public static MemberCache LookupMemberCache (Type t)
443 if (t.Module == CodeGen.Module.Builder) {
444 DeclSpace container = (DeclSpace)builder_to_declspace [t];
445 if (container != null)
446 return container.MemberCache;
450 if (t is GenericTypeParameterBuilder) {
451 TypeParameter container = builder_to_type_param [t] as TypeParameter;
453 if (container != null)
454 return container.MemberCache;
458 return TypeHandle.GetMemberCache (t);
461 public static MemberCache LookupBaseInterfacesCache (Type t)
463 Type [] ifaces = GetInterfaces (t);
465 if (ifaces != null && ifaces.Length == 1)
466 return LookupMemberCache (ifaces [0]);
468 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
469 MemberCache cache = builder_to_member_cache [t] as MemberCache;
473 cache = new MemberCache (ifaces);
474 builder_to_member_cache.Add (t, cache);
478 public static TypeContainer LookupInterface (Type t)
480 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
481 if ((tc == null) || (tc.Kind != Kind.Interface))
487 public static Delegate LookupDelegate (Type t)
489 return builder_to_declspace [t] as Delegate;
492 public static Class LookupClass (Type t)
494 return (Class) builder_to_declspace [t];
498 // We use this hash for multiple kinds of constructed types:
500 // (T, "&") Given T, get T &
501 // (T, "*") Given T, get T *
502 // (T, "[]") Given T and a array dimension, get T []
503 // (T, X) Given a type T and a simple name X, get the type T+X
505 // Accessibility tests, if necessary, should be done by the user
507 static DoubleHash type_hash = new DoubleHash ();
510 // Gets the reference to T version of the Type (T&)
512 public static Type GetReferenceType (Type t)
515 return t.MakeByRefType ();
517 return GetConstructedType (t, "&");
522 // Gets the pointer to T version of the Type (T*)
524 public static Type GetPointerType (Type t)
526 return GetConstructedType (t, "*");
529 public static Type GetConstructedType (Type t, string dim)
532 if (type_hash.Lookup (t, dim, out ret))
535 ret = t.Module.GetType (t.ToString () + dim);
537 type_hash.Insert (t, dim, ret);
542 ret = GetReferenceType (t);
543 type_hash.Insert (t, dim, ret);
548 if (t.IsGenericParameter || t.IsGenericType) {
551 while ((pos < dim.Length) && (dim [pos] == '[')) {
554 if (dim [pos] == ']') {
555 result = result.MakeArrayType ();
558 if (pos < dim.Length)
561 type_hash.Insert (t, dim, result);
566 while (dim [pos] == ',') {
570 if ((dim [pos] != ']') || (pos != dim.Length-1))
573 result = result.MakeArrayType (rank + 1);
574 type_hash.Insert (t, dim, result);
580 type_hash.Insert (t, dim, null);
584 public static Type GetNestedType (Type t, string name)
587 if (!type_hash.Lookup (t, name, out ret)) {
588 ret = t.GetNestedType (name,
589 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
590 type_hash.Insert (t, name, ret);
596 /// Fills static table with exported types from all referenced assemblies.
597 /// This information is required for CLS Compliance tests.
599 public static void LoadAllImportedTypes ()
601 AllClsTopLevelTypes = new Hashtable (1500);
602 foreach (Assembly a in RootNamespace.Global.Assemblies) {
603 foreach (Type t in a.GetExportedTypes ()) {
604 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
609 public static bool NamespaceClash (string name, Location loc)
611 if (! RootNamespace.Global.IsNamespace (name))
614 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
619 /// Returns the C# name of a type if possible, or the full type name otherwise
621 static public string CSharpName (Type t)
623 if (t == typeof(NullType))
626 if (t == typeof (ArglistParameter))
629 return CSharpName (GetFullName (t));
632 public static string CSharpName (string name)
634 if (name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
635 return AnonymousTypeClass.SignatureForError;
637 return Regex.Replace (name,
639 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
640 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
641 @"Boolean|String|Void|Null)" +
643 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
646 static public string CSharpName (Type[] types)
648 StringBuilder sb = new StringBuilder ();
649 foreach (Type t in types) {
650 sb.Append (CSharpName (t));
653 sb.Remove (sb.Length - 1, 1);
654 return sb.ToString ();
657 static String CSharpNameMatch (Match match)
659 string s = match.Groups [1].Captures [0].Value;
661 Replace ("int32", "int").
662 Replace ("uint32", "uint").
663 Replace ("int16", "short").
664 Replace ("uint16", "ushort").
665 Replace ("int64", "long").
666 Replace ("uint64", "ulong").
667 Replace ("single", "float").
668 Replace ("boolean", "bool")
669 + match.Groups [2].Captures [0].Value;
672 // Used for error reporting to show symbolic name instead of underlying value
673 public static string CSharpEnumValue (Type t, object value)
675 t = DropGenericTypeArguments (t);
676 Enum e = LookupDeclSpace (t) as Enum;
678 return System.Enum.GetName (t, value);
680 return e.GetDefinition (value).GetSignatureForError ();
684 /// Returns the signature of the method with full namespace classification
686 static public string GetFullNameSignature (MemberInfo mi)
688 PropertyInfo pi = mi as PropertyInfo;
690 MethodBase pmi = pi.GetGetMethod (true);
692 pmi = pi.GetSetMethod (true);
693 if (GetParameterData (pmi).Count > 0)
696 return (mi is MethodBase)
697 ? CSharpSignature (mi as MethodBase)
698 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
702 private static int GetFullName (Type t, StringBuilder sb)
706 if (!t.IsGenericType) {
707 sb.Append (t.FullName);
711 if (t.DeclaringType != null) {
712 pos = GetFullName (t.DeclaringType, sb);
714 } else if (t.Namespace != null && t.Namespace.Length != 0) {
715 sb.Append (t.Namespace);
718 sb.Append (RemoveGenericArity (t.Name));
720 Type[] this_args = GetTypeArguments (t);
722 if (this_args.Length < pos)
723 throw new InternalErrorException (
724 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
725 if (this_args.Length == pos)
730 sb.Append (CSharpName (this_args [pos++]));
731 if (pos == this_args.Length)
739 static string GetFullName (Type t)
742 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
743 return GetFullName (t.GetElementType ()) + dimension;
746 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
747 t = GetTypeArguments (t)[0];
748 return CSharpName (t) + "?";
751 if (t.IsGenericParameter)
753 if (!t.IsGenericType)
756 StringBuilder sb = new StringBuilder ();
757 int pos = GetFullName (t, sb);
759 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
760 return sb.ToString ();
763 public static string GetFullName (Type t)
769 public static string RemoveGenericArity (string from)
771 int i = from.IndexOf ('`');
773 return from.Substring (0, i);
778 /// When we need to report accessors as well
780 static public string CSharpSignature (MethodBase mb)
782 return CSharpSignature (mb, false);
786 /// Returns the signature of the method
788 static public string CSharpSignature (MethodBase mb, bool show_accessor)
790 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
793 ParameterData iparams = GetParameterData (mb);
794 string parameters = iparams.GetSignatureForError ();
795 int accessor_end = 0;
797 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
798 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
799 if (ot != Operator.OpType.TOP) {
800 sig.Append ("operator ");
801 sig.Append (Operator.GetName (ot));
802 sig.Append (parameters);
803 return sig.ToString ();
806 bool is_getter = mb.Name.StartsWith ("get_");
807 bool is_setter = mb.Name.StartsWith ("set_");
808 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
810 } else if (mb.Name.StartsWith ("remove_")) {
815 if (iparams.Count > (is_getter ? 0 : 1)) {
816 sig.Append ("this[");
818 sig.Append (parameters.Substring (1, parameters.Length - 2));
820 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
823 sig.Append (mb.Name.Substring (accessor_end + 1));
826 if (mb.Name == ".ctor")
827 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
829 sig.Append (mb.Name);
832 if (TypeManager.IsGenericMethod (mb)) {
833 Type[] args = mb.GetGenericArguments ();
835 for (int i = 0; i < args.Length; i++) {
838 sig.Append (CSharpName (args [i]));
845 sig.Append (parameters);
848 if (show_accessor && accessor_end > 0) {
850 sig.Append (mb.Name.Substring (0, accessor_end));
853 return sig.ToString ();
856 public static string GetMethodName (MethodInfo m)
859 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
862 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
868 static public string CSharpSignature (EventInfo ei)
870 return CSharpName (ei.DeclaringType) + "." + ei.Name;
874 /// Looks up a type, and aborts if it is not found. This is used
875 /// by types required by the compiler
877 public static Type CoreLookupType (string namespaceName, string name)
879 return CoreLookupType (namespaceName, name, false);
882 static Type CoreLookupType (string ns_name, string name, bool mayFail)
884 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
885 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
886 Type t = fne == null ? null : fne.Type;
889 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
893 AttributeTester.RegisterNonObsoleteType (t);
898 /// Returns the MethodInfo for a method named `name' defined
899 /// in type `t' which takes arguments of types `args'
901 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
905 BindingFlags flags = instance_and_static | BindingFlags.Public;
911 flags |= BindingFlags.NonPublic;
913 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
914 if (list.Count == 0) {
916 Report.Error (-19, "Can not find the core function `" + name + "'");
920 MethodInfo mi = list [0] as MethodInfo;
923 Report.Error (-19, "Can not find the core function `" + name + "'");
930 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
932 return GetMethod (t, name, args, false, report_errors);
935 public static MethodInfo GetMethod (Type t, string name, Type [] args)
937 return GetMethod (t, name, args, true);
941 /// Returns the PropertyInfo for a property named `name' defined
944 public static PropertyInfo GetProperty (Type t, string name)
946 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
947 BindingFlags.Instance, Type.FilterName, name);
948 if (list.Count == 0) {
949 Report.Error (-19, "Can not find the core property `" + name + "'");
953 PropertyInfo pi = list [0] as PropertyInfo;
955 Report.Error (-19, "Can not find the core function `" + name + "'");
963 /// Returns the ConstructorInfo for "args"
965 public static ConstructorInfo GetConstructor (Type t, Type [] args)
967 return GetConstructor (t, args, true);
970 public static ConstructorInfo GetConstructor (Type t, Type [] args, bool report_errors)
979 throw new InternalErrorException ("Core types haven't been initialized yet?");
981 list = FindMembers (t, MemberTypes.Constructor,
982 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
983 signature_filter, sig);
984 if (list.Count == 0){
986 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
990 ConstructorInfo ci = list [0] as ConstructorInfo;
993 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1000 public static void InitEnumUnderlyingTypes ()
1002 int32_type = CoreLookupType ("System", "Int32");
1003 int64_type = CoreLookupType ("System", "Int64");
1004 uint32_type = CoreLookupType ("System", "UInt32");
1005 uint64_type = CoreLookupType ("System", "UInt64");
1006 byte_type = CoreLookupType ("System", "Byte");
1007 sbyte_type = CoreLookupType ("System", "SByte");
1008 short_type = CoreLookupType ("System", "Int16");
1009 ushort_type = CoreLookupType ("System", "UInt16");
1011 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
1012 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
1014 idisposable_type = CoreLookupType ("System", "IDisposable");
1017 InitGenericCoreTypes ();
1022 /// The types have to be initialized after the initial
1023 /// population of the type has happened (for example, to
1024 /// bootstrap the corlib.dll
1026 public static void InitCoreTypes ()
1028 object_type = CoreLookupType ("System", "Object");
1029 system_object_expr.Type = object_type;
1030 value_type = CoreLookupType ("System", "ValueType");
1031 system_valuetype_expr.Type = value_type;
1033 InitEnumUnderlyingTypes ();
1035 char_type = CoreLookupType ("System", "Char");
1036 string_type = CoreLookupType ("System", "String");
1037 float_type = CoreLookupType ("System", "Single");
1038 double_type = CoreLookupType ("System", "Double");
1039 char_ptr_type = GetPointerType (char_type);
1040 decimal_type = CoreLookupType ("System", "Decimal");
1041 bool_type = CoreLookupType ("System", "Boolean");
1042 enum_type = CoreLookupType ("System", "Enum");
1044 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1045 delegate_type = CoreLookupType ("System", "Delegate");
1047 array_type = CoreLookupType ("System", "Array");
1048 void_type = CoreLookupType ("System", "Void");
1049 type_type = CoreLookupType ("System", "Type");
1051 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1052 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1053 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1054 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1055 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1056 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1057 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1058 icloneable_type = CoreLookupType ("System", "ICloneable");
1059 iconvertible_type = CoreLookupType ("System", "IConvertible");
1060 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1061 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1062 intptr_type = CoreLookupType ("System", "IntPtr");
1063 uintptr_type = CoreLookupType ("System", "UIntPtr");
1065 attribute_type = CoreLookupType ("System", "Attribute");
1066 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1067 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1068 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1069 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1070 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1071 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1072 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1074 // needed before any call susceptible to fail, as it is used during resolution
1075 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1077 // this can fail if the user doesn't have an -r:System.dll
1078 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", true);
1080 typed_reference_type = CoreLookupType ("System", "TypedReference");
1081 arg_iterator_type = CoreLookupType ("System", "ArgIterator", true);
1082 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1083 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1085 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1087 void_ptr_type = GetPointerType (void_type);
1089 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1091 exception_type = CoreLookupType ("System", "Exception");
1092 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1093 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1098 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1099 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1100 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1101 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1102 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1103 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1104 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", true);
1105 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1106 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1107 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute");
1108 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1109 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1115 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1116 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1117 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1118 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1119 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", true);
1124 extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
1128 // When compiling corlib, store the "real" types here.
1130 if (!RootContext.StdLib) {
1131 system_int32_type = typeof (System.Int32);
1132 system_array_type = typeof (System.Array);
1133 system_type_type = typeof (System.Type);
1134 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1136 system_int_array_get_length = GetMethod (
1137 system_array_type, "get_Length", Type.EmptyTypes);
1138 system_int_array_get_rank = GetMethod (
1139 system_array_type, "get_Rank", Type.EmptyTypes);
1140 system_object_array_clone = GetMethod (
1141 system_array_type, "Clone", Type.EmptyTypes);
1143 Type [] system_int_arg = { system_int32_type };
1144 system_int_array_get_length_int = GetMethod (
1145 system_array_type, "GetLength", system_int_arg);
1146 system_int_array_get_upper_bound_int = GetMethod (
1147 system_array_type, "GetUpperBound", system_int_arg);
1148 system_int_array_get_lower_bound_int = GetMethod (
1149 system_array_type, "GetLowerBound", system_int_arg);
1151 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1152 system_void_array_copyto_array_int = GetMethod (
1153 system_array_type, "CopyTo", system_array_int_arg);
1155 Type [] system_3_type_arg = {
1156 system_type_type, system_type_type, system_type_type };
1157 Type [] system_4_type_arg = {
1158 system_type_type, system_type_type, system_type_type, system_type_type };
1160 MethodInfo set_corlib_type_builders = GetMethod (
1161 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1162 system_4_type_arg, true, false);
1164 if (set_corlib_type_builders != null) {
1165 object[] args = new object [4];
1166 args [0] = object_type;
1167 args [1] = value_type;
1168 args [2] = enum_type;
1169 args [3] = void_type;
1171 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1173 // Compatibility for an older version of the class libs.
1174 set_corlib_type_builders = GetMethod (
1175 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1176 system_3_type_arg, true, true);
1178 if (set_corlib_type_builders == null) {
1179 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1183 object[] args = new object [3];
1184 args [0] = object_type;
1185 args [1] = value_type;
1186 args [2] = enum_type;
1188 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1192 system_string_expr.Type = string_type;
1193 system_boolean_expr.Type = bool_type;
1194 system_decimal_expr.Type = decimal_type;
1195 system_single_expr.Type = float_type;
1196 system_double_expr.Type = double_type;
1197 system_sbyte_expr.Type = sbyte_type;
1198 system_byte_expr.Type = byte_type;
1199 system_int16_expr.Type = short_type;
1200 system_uint16_expr.Type = ushort_type;
1201 system_int32_expr.Type = int32_type;
1202 system_uint32_expr.Type = uint32_type;
1203 system_int64_expr.Type = int64_type;
1204 system_uint64_expr.Type = uint64_type;
1205 system_char_expr.Type = char_type;
1206 system_void_expr.Type = void_type;
1207 system_asynccallback_expr.Type = asynccallback_type;
1208 system_iasyncresult_expr.Type = iasyncresult_type;
1211 // These are only used for compare purposes
1213 anonymous_method_type = typeof (AnonymousMethod);
1214 null_type = typeof (NullType);
1218 // The helper methods that are used by the compiler
1220 public static void InitCodeHelpers ()
1223 // Now load the default methods that we use.
1225 Type [] string_string = { string_type, string_type };
1226 string_concat_string_string = GetMethod (
1227 string_type, "Concat", string_string);
1228 Type [] string_string_string = { string_type, string_type, string_type };
1229 string_concat_string_string_string = GetMethod (
1230 string_type, "Concat", string_string_string);
1231 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1232 string_concat_string_string_string_string = GetMethod (
1233 string_type, "Concat", string_string_string_string);
1234 Type[] params_string = { GetConstructedType (string_type, "[]") };
1235 string_concat_string_dot_dot_dot = GetMethod (
1236 string_type, "Concat", params_string);
1238 Type [] object_object = { object_type, object_type };
1239 string_concat_object_object = GetMethod (
1240 string_type, "Concat", object_object);
1241 Type [] object_object_object = { object_type, object_type, object_type };
1242 string_concat_object_object_object = GetMethod (
1243 string_type, "Concat", object_object_object);
1244 Type[] params_object = { GetConstructedType (object_type, "[]") };
1245 string_concat_object_dot_dot_dot = GetMethod (
1246 string_type, "Concat", params_object);
1248 Type [] string_ = { string_type };
1249 string_isinterned_string = GetMethod (
1250 string_type, "IsInterned", string_);
1252 Type [] runtime_type_handle = { runtime_handle_type };
1253 system_type_get_type_from_handle = GetMethod (
1254 type_type, "GetTypeFromHandle", runtime_type_handle);
1256 Type [] delegate_delegate = { delegate_type, delegate_type };
1257 delegate_combine_delegate_delegate = GetMethod (
1258 delegate_type, "Combine", delegate_delegate);
1260 delegate_remove_delegate_delegate = GetMethod (
1261 delegate_type, "Remove", delegate_delegate);
1266 ienumerator_getcurrent = GetProperty (
1267 ienumerator_type, "Current");
1268 bool_movenext_void = GetMethod (
1269 ienumerator_type, "MoveNext", Type.EmptyTypes);
1270 void_reset_void = GetMethod (
1271 ienumerator_type, "Reset", Type.EmptyTypes);
1272 void_dispose_void = GetMethod (
1273 idisposable_type, "Dispose", Type.EmptyTypes);
1274 int_get_offset_to_string_data = GetMethod (
1275 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1276 int_array_get_length = GetMethod (
1277 array_type, "get_Length", Type.EmptyTypes);
1278 int_array_get_rank = GetMethod (
1279 array_type, "get_Rank", Type.EmptyTypes);
1280 ienumerable_getenumerator_void = GetMethod (
1281 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1286 Type [] int_arg = { int32_type };
1287 int_array_get_length_int = GetMethod (
1288 array_type, "GetLength", int_arg);
1289 int_array_get_upper_bound_int = GetMethod (
1290 array_type, "GetUpperBound", int_arg);
1291 int_array_get_lower_bound_int = GetMethod (
1292 array_type, "GetLowerBound", int_arg);
1295 // System.Array methods
1297 object_array_clone = GetMethod (
1298 array_type, "Clone", Type.EmptyTypes);
1299 Type [] array_int_arg = { array_type, int32_type };
1300 void_array_copyto_array_int = GetMethod (
1301 array_type, "CopyTo", array_int_arg);
1306 Type [] object_arg = { object_type };
1307 void_monitor_enter_object = GetMethod (
1308 monitor_type, "Enter", object_arg);
1309 void_monitor_exit_object = GetMethod (
1310 monitor_type, "Exit", object_arg);
1312 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1314 void_initializearray_array_fieldhandle = GetMethod (
1315 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1320 int_getlength_int = GetMethod (
1321 array_type, "GetLength", int_arg);
1324 // Decimal constructors
1326 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1327 void_decimal_ctor_five_args = GetConstructor (
1328 decimal_type, dec_arg);
1330 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1335 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1336 default_member_ctor = GetConstructor (default_member_type, string_);
1337 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1339 Type[] short_arg = { short_type };
1340 // fails for .net 2.1
1341 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg, false);
1343 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1344 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1346 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1350 // System.Threading.CompareExchange
1352 Type[] compare_exchange_types = {
1353 GetReferenceType (int32_type), int32_type, int32_type };
1354 int_interlocked_compare_exchange = GetMethod (
1355 interlocked_type, "CompareExchange", compare_exchange_types);
1361 compiler_generated_attr = new CustomAttributeBuilder (
1362 GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1364 Type[] type_int_arg = { type_type, int32_type };
1365 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1372 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1375 InitGenericCodeHelpers ();
1380 static void InitSystemCore ()
1382 if (RootContext.Version != LanguageVersion.LINQ)
1385 if (extension_attribute_type != null)
1386 extension_attribute_attr = new CustomAttributeBuilder (
1387 GetConstructor (extension_attribute_type, Type.EmptyTypes), new object[0]);
1391 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1394 /// This is the "old", non-cache based FindMembers() function. We cannot use
1395 /// the cache here because there is no member name argument.
1397 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1398 MemberFilter filter, object criteria)
1400 #if MS_COMPATIBLE && GMCS_SOURCE
1401 if (t.IsGenericType)
1402 t = t.GetGenericTypeDefinition ();
1405 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1408 // `builder_to_declspace' contains all dynamic types.
1412 Timer.StartTimer (TimerType.FindMembers);
1413 list = decl.FindMembers (mt, bf, filter, criteria);
1414 Timer.StopTimer (TimerType.FindMembers);
1419 // We have to take care of arrays specially, because GetType on
1420 // a TypeBuilder array will return a Type, not a TypeBuilder,
1421 // and we can not call FindMembers on this type.
1424 #if MS_COMPATIBLE && GMCS_SOURCE
1427 t.IsSubclassOf (TypeManager.array_type))
1428 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1431 if (t is GenericTypeParameterBuilder) {
1432 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1434 Timer.StartTimer (TimerType.FindMembers);
1435 MemberList list = tparam.FindMembers (
1436 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1437 Timer.StopTimer (TimerType.FindMembers);
1443 // Since FindMembers will not lookup both static and instance
1444 // members, we emulate this behaviour here.
1446 if ((bf & instance_and_static) == instance_and_static){
1447 MemberInfo [] i_members = t.FindMembers (
1448 mt, bf & ~BindingFlags.Static, filter, criteria);
1450 int i_len = i_members.Length;
1452 MemberInfo one = i_members [0];
1455 // If any of these are present, we are done!
1457 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1458 return new MemberList (i_members);
1461 MemberInfo [] s_members = t.FindMembers (
1462 mt, bf & ~BindingFlags.Instance, filter, criteria);
1464 int s_len = s_members.Length;
1465 if (i_len > 0 || s_len > 0)
1466 return new MemberList (i_members, s_members);
1469 return new MemberList (i_members);
1471 return new MemberList (s_members);
1475 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1480 /// This method is only called from within MemberLookup. It tries to use the member
1481 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1482 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1483 /// our return value will already contain all inherited members and the caller don't need
1484 /// to check base classes and interfaces anymore.
1486 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1487 string name, out bool used_cache)
1492 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1493 // and we can ask the DeclSpace for the MemberCache.
1496 if (t.Assembly == CodeGen.Assembly.Builder) {
1497 if (t.IsGenericParameter) {
1498 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1501 if (tparam.MemberCache == null)
1502 return new MemberInfo[0];
1504 return tparam.MemberCache.FindMembers (
1505 mt, bf, name, FilterWithClosure_delegate, null);
1508 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1509 t = t.GetGenericTypeDefinition ();
1511 if (t is TypeBuilder) {
1513 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1514 cache = decl.MemberCache;
1517 // If this DeclSpace has a MemberCache, use it.
1520 if (cache != null) {
1522 return cache.FindMembers (
1523 mt, bf, name, FilterWithClosure_delegate, null);
1526 // If there is no MemberCache, we need to use the "normal" FindMembers.
1527 // Note, this is a VERY uncommon route!
1530 Timer.StartTimer (TimerType.FindMembers);
1531 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1532 FilterWithClosure_delegate, name);
1533 Timer.StopTimer (TimerType.FindMembers);
1535 return (MemberInfo []) list;
1539 // We have to take care of arrays specially, because GetType on
1540 // a TypeBuilder array will return a Type, not a TypeBuilder,
1541 // and we can not call FindMembers on this type.
1545 return TypeHandle.ArrayType.MemberCache.FindMembers (
1546 mt, bf, name, FilterWithClosure_delegate, null);
1550 if (t is GenericTypeParameterBuilder) {
1551 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1554 if (tparam.MemberCache == null)
1555 return new MemberInfo [0];
1557 return tparam.MemberCache.FindMembers (
1558 mt, bf, name, FilterWithClosure_delegate, null);
1562 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1564 // This happens if we're resolving a class'es base class and interfaces
1565 // in TypeContainer.DefineType(). At this time, the types aren't
1566 // populated yet, so we can't use the cache.
1568 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1569 FilterWithClosure_delegate, name);
1575 // This call will always succeed. There is exactly one TypeHandle instance per
1576 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1577 // the corresponding MemberCache.
1579 cache = TypeHandle.GetMemberCache (t);
1582 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1585 public static bool IsBuiltinType (Type t)
1587 t = TypeToCoreType (t);
1588 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1589 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1590 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1591 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1597 public static bool IsBuiltinType (TypeContainer tc)
1599 return IsBuiltinType (tc.TypeBuilder);
1603 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1604 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1606 public static bool IsPrimitiveType (Type t)
1608 return (t == int32_type || t == uint32_type ||
1609 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1610 t == char_type || t == short_type || t == bool_type ||
1611 t == sbyte_type || t == byte_type || t == ushort_type);
1614 public static bool IsDelegateType (Type t)
1617 if (t.IsGenericParameter)
1621 t = DropGenericTypeArguments (t);
1622 if (t.IsSubclassOf (TypeManager.delegate_type))
1628 public static bool IsEnumType (Type t)
1630 t = DropGenericTypeArguments (t);
1631 if (builder_to_declspace [t] is Enum)
1634 #if MS_COMPATIBLE && GMCS_SOURCE
1635 if (t.IsGenericParameter || t.IsGenericType)
1641 public static bool IsBuiltinOrEnum (Type t)
1643 if (IsBuiltinType (t))
1652 public static bool IsNullType (Type t)
1654 return t == null_type;
1657 public static bool IsAttributeType (Type t)
1659 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1662 static Stack unmanaged_enclosing_types = new Stack (4);
1665 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1667 public static bool IsUnmanagedType (Type t)
1669 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1670 if (unmanaged_enclosing_types.Contains (t))
1673 // builtins that are not unmanaged types
1674 if (t == TypeManager.object_type || t == TypeManager.string_type)
1677 if (IsGenericType (t) || IsGenericParameter (t))
1680 if (IsBuiltinOrEnum (t))
1683 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1687 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1691 if (!IsValueType (t))
1695 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1696 if (p.IsGenericTypeDefinition)
1701 unmanaged_enclosing_types.Push (t);
1705 if (t is TypeBuilder) {
1706 TypeContainer tc = LookupTypeContainer (t);
1707 if (tc.Fields != null){
1708 foreach (FieldBase f in tc.Fields){
1709 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1710 if ((f.ModFlags & Modifiers.STATIC) != 0)
1712 if (f.MemberType == null)
1714 if (!IsUnmanagedType (f.MemberType)){
1715 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1721 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1723 foreach (FieldInfo f in fields){
1724 if (!IsUnmanagedType (f.FieldType)){
1725 Report.SymbolRelatedToPreviousError (f);
1731 unmanaged_enclosing_types.Pop ();
1736 public static bool IsValueType (Type t)
1738 return t.IsValueType || IsGenericParameter (t);
1741 public static bool IsInterfaceType (Type t)
1743 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1747 return tc.Kind == Kind.Interface;
1750 public static bool IsSubclassOf (Type type, Type base_type)
1752 TypeParameter tparam = LookupTypeParameter (type);
1753 TypeParameter pparam = LookupTypeParameter (base_type);
1755 if ((tparam != null) && (pparam != null)) {
1756 if (tparam == pparam)
1759 return tparam.IsSubclassOf (base_type);
1762 #if MS_COMPATIBLE && GMCS_SOURCE
1763 if (type.IsGenericType)
1764 type = type.GetGenericTypeDefinition ();
1767 if (type.IsSubclassOf (base_type))
1771 if (IsEqual (type, base_type))
1774 type = type.BaseType;
1775 } while (type != null);
1780 public static bool IsPrivateAccessible (Type type, Type parent)
1785 if (type.Equals (parent))
1788 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1791 public static bool IsFamilyAccessible (Type type, Type parent)
1793 TypeParameter tparam = LookupTypeParameter (type);
1794 TypeParameter pparam = LookupTypeParameter (parent);
1796 if ((tparam != null) && (pparam != null)) {
1797 if (tparam == pparam)
1800 return tparam.IsSubclassOf (parent);
1804 if (IsInstantiationOfSameGenericType (type, parent))
1807 type = type.BaseType;
1808 } while (type != null);
1814 // Checks whether `type' is a subclass or nested child of `base_type'.
1816 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1819 if (IsFamilyAccessible (type, base_type))
1822 // Handle nested types.
1823 type = type.DeclaringType;
1824 } while (type != null);
1830 // Checks whether `type' is a nested child of `parent'.
1832 public static bool IsNestedChildOf (Type type, Type parent)
1837 type = DropGenericTypeArguments (type);
1838 parent = DropGenericTypeArguments (parent);
1840 if (IsEqual (type, parent))
1843 type = type.DeclaringType;
1844 while (type != null) {
1845 if (IsEqual (type, parent))
1848 type = type.DeclaringType;
1856 // Checks whether `extern_type' is friend of the output assembly
1858 public static bool IsFriendAssembly (Assembly assembly)
1860 // FIXME: This should not be reached
1861 if (assembly == CodeGen.Assembly.Builder)
1864 if (assembly_internals_vis_attrs.Contains (assembly))
1865 return (bool)(assembly_internals_vis_attrs [assembly]);
1867 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1868 if (attrs.Length == 0) {
1869 assembly_internals_vis_attrs.Add (assembly, false);
1873 AssemblyName this_name = CodeGen.Assembly.Name;
1874 byte [] this_token = this_name.GetPublicKeyToken ();
1875 bool is_friend = false;
1876 foreach (InternalsVisibleToAttribute attr in attrs) {
1877 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1880 AssemblyName aname = null;
1882 aname = new AssemblyName (attr.AssemblyName);
1883 } catch (FileLoadException) {
1884 } catch (ArgumentException) {
1887 if (aname == null || aname.Name != this_name.Name)
1890 byte [] key_token = aname.GetPublicKeyToken ();
1891 if (key_token != null) {
1892 if (this_token == null) {
1893 // Same name, but key token is null
1894 Error_FriendAccessNameNotMatching (aname.FullName);
1898 if (!CompareKeyTokens (this_token, key_token))
1906 assembly_internals_vis_attrs.Add (assembly, is_friend);
1910 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1912 for (int i = 0; i < token1.Length; i++)
1913 if (token1 [i] != token2 [i])
1919 static void Error_FriendAccessNameNotMatching (string other_name)
1921 Report.Error (281, "Friend access was granted to `" + other_name +
1922 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1923 "'. Try adding a reference to `" + other_name +
1924 "' or change the output assembly name to match it");
1927 public static bool IsFriendAssembly (Assembly assembly)
1934 // Do the right thing when returning the element type of an
1935 // array type based on whether we are compiling corlib or not
1937 public static Type GetElementType (Type t)
1939 if (RootContext.StdLib)
1940 return t.GetElementType ();
1942 return TypeToCoreType (t.GetElementType ());
1946 /// This method is not implemented by MS runtime for dynamic types
1948 public static bool HasElementType (Type t)
1950 return t.IsArray || t.IsPointer || t.IsByRef;
1954 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1958 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1959 /// for anything which is dynamic, and we need this in a number of places,
1960 /// we register this information here, and use it afterwards.
1962 static public void RegisterMethod (MethodBase mb, Parameters ip)
1964 method_params.Add (mb, ip);
1967 static public ParameterData GetParameterData (MethodBase mb)
1969 ParameterData pd = (ParameterData)method_params [mb];
1972 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1973 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1974 pd = GetParameterData (mi);
1975 if (mi.IsGenericMethod)
1976 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1978 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1979 method_params.Add (mb, pd);
1983 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1984 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1985 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1988 pd = new ReflectionParameters (mb);
1989 method_params.Add (mb, pd);
1994 public static ParameterData GetDelegateParameters (Type t)
1996 Delegate d = builder_to_declspace [t] as Delegate;
1998 return d.Parameters;
2000 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
2001 return GetParameterData (invoke_mb);
2004 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
2006 if (!method_overrides.Contains (override_method))
2007 method_overrides [override_method] = base_method;
2008 if (method_overrides [override_method] != base_method)
2009 throw new InternalErrorException ("Override mismatch: " + override_method);
2012 static public bool IsOverride (MethodBase m)
2014 m = DropGenericMethodArguments (m);
2016 return m.IsVirtual &&
2017 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
2018 (m is MethodBuilder || method_overrides.Contains (m));
2021 static public MethodBase TryGetBaseDefinition (MethodBase m)
2023 m = DropGenericMethodArguments (m);
2025 return (MethodBase) method_overrides [m];
2029 /// Returns the argument types for an indexer based on its PropertyInfo
2031 /// For dynamic indexers, we use the compiler provided types, for
2032 /// indexers from existing assemblies we load them from GetParameters,
2033 /// and insert them into the cache
2035 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2037 if (indexer_arguments.Contains (indexer))
2038 return (Type []) indexer_arguments [indexer];
2039 else if (indexer is PropertyBuilder)
2040 // If we're a PropertyBuilder and not in the
2041 // `indexer_arguments' hash, then we're a property and
2043 return Type.EmptyTypes;
2045 ParameterInfo [] pi = indexer.GetIndexParameters ();
2046 // Property, not an indexer.
2048 return Type.EmptyTypes;
2050 Type [] types = new Type [c];
2052 for (int i = 0; i < c; i++)
2053 types [i] = pi [i].ParameterType;
2055 indexer_arguments.Add (indexer, types);
2060 public static void RegisterConstant (FieldInfo fb, IConstant ic)
2062 fields.Add (fb, ic);
2065 public static IConstant GetConstant (FieldInfo fb)
2070 return (IConstant)fields [fb];
2073 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
2075 propertybuilder_to_property.Add (pi, pb);
2078 public static PropertyBase GetProperty (PropertyInfo pi)
2080 return (PropertyBase)propertybuilder_to_property [pi];
2083 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
2085 fieldbuilders_to_fields.Add (fb, f);
2089 // The return value can be null; This will be the case for
2090 // auxiliary FieldBuilders created by the compiler that have no
2091 // real field being declared on the source code
2093 static public FieldBase GetField (FieldInfo fb)
2096 fb = GetGenericFieldDefinition (fb);
2098 return (FieldBase) fieldbuilders_to_fields [fb];
2101 static public MethodInfo GetAddMethod (EventInfo ei)
2103 if (ei is MyEventBuilder) {
2104 return ((MyEventBuilder)ei).GetAddMethod (true);
2106 return ei.GetAddMethod (true);
2109 static public MethodInfo GetRemoveMethod (EventInfo ei)
2111 if (ei is MyEventBuilder) {
2112 return ((MyEventBuilder)ei).GetRemoveMethod (true);
2114 return ei.GetRemoveMethod (true);
2117 static public void RegisterEventField (EventInfo einfo, EventField e)
2120 events = new Hashtable ();
2122 events.Add (einfo, e);
2125 static public EventField GetEventField (EventInfo ei)
2130 return (EventField) events [ei];
2133 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2134 MethodBase set, Type[] args)
2136 indexer_arguments.Add (pb, args);
2141 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2143 Hashtable hash = new Hashtable ();
2144 return CheckStructCycles (tc, seen, hash);
2147 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2150 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2154 // `seen' contains all types we've already visited.
2156 if (seen.Contains (tc))
2158 seen.Add (tc, null);
2160 if (tc.Fields == null)
2163 foreach (FieldBase field in tc.Fields) {
2164 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2167 Type ftype = field.FieldBuilder.FieldType;
2168 TypeContainer ftc = LookupTypeContainer (ftype);
2172 if (hash.Contains (ftc)) {
2173 Report.Error (523, tc.Location,
2174 "Struct member `{0}.{1}' of type `{2}' " +
2175 "causes a cycle in the struct layout",
2176 tc.Name, field.Name, ftc.Name);
2181 // `hash' contains all types in the current path.
2183 hash.Add (tc, null);
2185 bool ok = CheckStructCycles (ftc, seen, hash);
2192 if (!seen.Contains (ftc))
2193 seen.Add (ftc, null);
2200 /// Given an array of interface types, expand and eliminate repeated ocurrences
2201 /// of an interface.
2205 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2208 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2210 ArrayList new_ifaces = new ArrayList ();
2212 foreach (TypeExpr iface in base_interfaces){
2213 Type itype = iface.Type;
2215 if (new_ifaces.Contains (itype))
2218 new_ifaces.Add (itype);
2220 Type [] implementing = GetInterfaces (itype);
2222 foreach (Type imp in implementing){
2223 if (!new_ifaces.Contains (imp))
2224 new_ifaces.Add (imp);
2227 Type [] ret = new Type [new_ifaces.Count];
2228 new_ifaces.CopyTo (ret, 0);
2232 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2234 ArrayList new_ifaces = new ArrayList ();
2236 foreach (Type itype in base_interfaces){
2237 if (new_ifaces.Contains (itype))
2240 new_ifaces.Add (itype);
2242 Type [] implementing = GetInterfaces (itype);
2244 foreach (Type imp in implementing){
2245 if (!new_ifaces.Contains (imp))
2246 new_ifaces.Add (imp);
2249 Type [] ret = new Type [new_ifaces.Count];
2250 new_ifaces.CopyTo (ret, 0);
2254 static PtrHashtable iface_cache = new PtrHashtable ();
2257 /// This function returns the interfaces in the type `t'. Works with
2258 /// both types and TypeBuilders.
2260 public static Type [] GetInterfaces (Type t)
2262 Type [] cached = iface_cache [t] as Type [];
2267 // The reason for catching the Array case is that Reflection.Emit
2268 // will not return a TypeBuilder for Array types of TypeBuilder types,
2269 // but will still throw an exception if we try to call GetInterfaces
2272 // Since the array interfaces are always constant, we return those for
2277 t = TypeManager.array_type;
2279 if ((t is TypeBuilder) || IsGenericType (t)) {
2280 Type [] base_ifaces;
2282 if (t.BaseType == null)
2283 base_ifaces = Type.EmptyTypes;
2285 base_ifaces = GetInterfaces (t.BaseType);
2287 if (IsGenericType (t))
2288 #if MS_COMPATIBLE && GMCS_SOURCE
2289 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2291 type_ifaces = t.GetInterfaces ();
2294 type_ifaces = (Type []) builder_to_ifaces [t];
2295 if (type_ifaces == null || type_ifaces.Length == 0)
2296 type_ifaces = Type.EmptyTypes;
2298 int base_count = base_ifaces.Length;
2299 Type [] result = new Type [base_count + type_ifaces.Length];
2300 base_ifaces.CopyTo (result, 0);
2301 type_ifaces.CopyTo (result, base_count);
2303 iface_cache [t] = result;
2306 } else if (t is GenericTypeParameterBuilder){
2307 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2308 if (type_ifaces == null || type_ifaces.Length == 0)
2309 type_ifaces = Type.EmptyTypes;
2311 iface_cache [t] = type_ifaces;
2315 Type[] ifaces = t.GetInterfaces ();
2316 iface_cache [t] = ifaces;
2322 // gets the interfaces that are declared explicitly on t
2324 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2326 return (Type []) builder_to_ifaces [t];
2330 /// The following is used to check if a given type implements an interface.
2331 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2333 public static bool ImplementsInterface (Type t, Type iface)
2338 // FIXME OPTIMIZATION:
2339 // as soon as we hit a non-TypeBuiler in the interface
2340 // chain, we could return, as the `Type.GetInterfaces'
2341 // will return all the interfaces implement by the type
2345 interfaces = GetInterfaces (t);
2347 if (interfaces != null){
2348 foreach (Type i in interfaces){
2355 } while (t != null);
2360 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2362 // This is a custom version of Convert.ChangeType() which works
2363 // with the TypeBuilder defined types when compiling corlib.
2364 public static object ChangeType (object value, Type conversionType, out bool error)
2366 IConvertible convert_value = value as IConvertible;
2368 if (convert_value == null){
2375 // We must use Type.Equals() here since `conversionType' is
2376 // the TypeBuilder created version of a system type and not
2377 // the system type itself. You cannot use Type.GetTypeCode()
2378 // on such a type - it'd always return TypeCode.Object.
2381 // We cannot rely on build-in type conversions as they are
2382 // more limited than what C# supports.
2383 // See char -> float/decimal/double conversion
2388 if (conversionType.Equals (typeof (Boolean)))
2389 return (object)(convert_value.ToBoolean (nf_provider));
2390 if (conversionType.Equals (typeof (Byte)))
2391 return (object)(convert_value.ToByte (nf_provider));
2392 if (conversionType.Equals (typeof (Char)))
2393 return (object)(convert_value.ToChar (nf_provider));
2394 if (conversionType.Equals (typeof (DateTime)))
2395 return (object)(convert_value.ToDateTime (nf_provider));
2397 if (conversionType.Equals (TypeManager.decimal_type)) {
2398 if (convert_value.GetType () == TypeManager.char_type)
2399 return (decimal)convert_value.ToInt32 (nf_provider);
2400 return convert_value.ToDecimal (nf_provider);
2403 if (conversionType.Equals (typeof (Double))) {
2404 if (convert_value.GetType () == TypeManager.char_type)
2405 return (double)convert_value.ToInt32 (nf_provider);
2406 return convert_value.ToDouble (nf_provider);
2409 if (conversionType.Equals (typeof (Int16)))
2410 return (object)(convert_value.ToInt16 (nf_provider));
2411 if (conversionType.Equals (typeof (Int32)))
2412 return (object)(convert_value.ToInt32 (nf_provider));
2413 if (conversionType.Equals (typeof (Int64)))
2414 return (object)(convert_value.ToInt64 (nf_provider));
2415 if (conversionType.Equals (typeof (SByte)))
2416 return (object)(convert_value.ToSByte (nf_provider));
2418 if (conversionType.Equals (typeof (Single))) {
2419 if (convert_value.GetType () == TypeManager.char_type)
2420 return (float)convert_value.ToInt32 (nf_provider);
2421 return convert_value.ToSingle (nf_provider);
2424 if (conversionType.Equals (typeof (String)))
2425 return (object)(convert_value.ToString (nf_provider));
2426 if (conversionType.Equals (typeof (UInt16)))
2427 return (object)(convert_value.ToUInt16 (nf_provider));
2428 if (conversionType.Equals (typeof (UInt32)))
2429 return (object)(convert_value.ToUInt32 (nf_provider));
2430 if (conversionType.Equals (typeof (UInt64)))
2431 return (object)(convert_value.ToUInt64 (nf_provider));
2432 if (conversionType.Equals (typeof (Object)))
2433 return (object)(value);
2443 // This is needed, because enumerations from assemblies
2444 // do not report their underlyingtype, but they report
2447 public static Type EnumToUnderlying (Type t)
2449 t = DropGenericTypeArguments (t);
2450 if (t == TypeManager.enum_type)
2453 t = t.UnderlyingSystemType;
2454 if (!TypeManager.IsEnumType (t))
2457 if (t is TypeBuilder) {
2458 // slow path needed to compile corlib
2459 if (t == TypeManager.bool_type ||
2460 t == TypeManager.byte_type ||
2461 t == TypeManager.sbyte_type ||
2462 t == TypeManager.char_type ||
2463 t == TypeManager.short_type ||
2464 t == TypeManager.ushort_type ||
2465 t == TypeManager.int32_type ||
2466 t == TypeManager.uint32_type ||
2467 t == TypeManager.int64_type ||
2468 t == TypeManager.uint64_type)
2471 TypeCode tc = Type.GetTypeCode (t);
2474 case TypeCode.Boolean:
2475 return TypeManager.bool_type;
2477 return TypeManager.byte_type;
2478 case TypeCode.SByte:
2479 return TypeManager.sbyte_type;
2481 return TypeManager.char_type;
2482 case TypeCode.Int16:
2483 return TypeManager.short_type;
2484 case TypeCode.UInt16:
2485 return TypeManager.ushort_type;
2486 case TypeCode.Int32:
2487 return TypeManager.int32_type;
2488 case TypeCode.UInt32:
2489 return TypeManager.uint32_type;
2490 case TypeCode.Int64:
2491 return TypeManager.int64_type;
2492 case TypeCode.UInt64:
2493 return TypeManager.uint64_type;
2495 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2499 // When compiling corlib and called with one of the core types, return
2500 // the corresponding typebuilder for that type.
2502 public static Type TypeToCoreType (Type t)
2504 if (RootContext.StdLib || (t is TypeBuilder))
2507 TypeCode tc = Type.GetTypeCode (t);
2510 case TypeCode.Boolean:
2511 return TypeManager.bool_type;
2513 return TypeManager.byte_type;
2514 case TypeCode.SByte:
2515 return TypeManager.sbyte_type;
2517 return TypeManager.char_type;
2518 case TypeCode.Int16:
2519 return TypeManager.short_type;
2520 case TypeCode.UInt16:
2521 return TypeManager.ushort_type;
2522 case TypeCode.Int32:
2523 return TypeManager.int32_type;
2524 case TypeCode.UInt32:
2525 return TypeManager.uint32_type;
2526 case TypeCode.Int64:
2527 return TypeManager.int64_type;
2528 case TypeCode.UInt64:
2529 return TypeManager.uint64_type;
2530 case TypeCode.Single:
2531 return TypeManager.float_type;
2532 case TypeCode.Double:
2533 return TypeManager.double_type;
2534 case TypeCode.String:
2535 return TypeManager.string_type;
2536 case TypeCode.Decimal:
2537 return TypeManager.decimal_type;
2539 if (t == typeof (void))
2540 return TypeManager.void_type;
2541 if (t == typeof (object))
2542 return TypeManager.object_type;
2543 if (t == typeof (System.Type))
2544 return TypeManager.type_type;
2545 if (t == typeof (System.IntPtr))
2546 return TypeManager.intptr_type;
2552 /// Utility function that can be used to probe whether a type
2553 /// is managed or not.
2555 public static bool VerifyUnManaged (Type t, Location loc)
2557 if (IsUnmanagedType (t))
2560 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2567 /// Returns the name of the indexer in a given type.
2570 /// The default is not always `Item'. The user can change this behaviour by
2571 /// using the IndexerNameAttribute in the container.
2572 /// For example, the String class indexer is named `Chars' not `Item'
2574 public static string IndexerPropertyName (Type t)
2576 t = DropGenericTypeArguments (t);
2577 if (t is TypeBuilder) {
2578 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2579 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2582 System.Attribute attr = System.Attribute.GetCustomAttribute (
2583 t, TypeManager.default_member_type);
2585 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2586 return dma.MemberName;
2589 return TypeContainer.DefaultIndexerName;
2592 static MethodInfo declare_local_method = null;
2594 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2596 if (declare_local_method == null){
2597 declare_local_method = typeof (ILGenerator).GetMethod (
2599 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2601 new Type [] { typeof (Type), typeof (bool)},
2603 if (declare_local_method == null){
2604 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2605 return ig.DeclareLocal (t);
2608 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2611 private static bool IsSignatureEqual (Type a, Type b)
2614 /// Consider the following example (bug #77674):
2616 /// public abstract class A
2618 /// public abstract T Foo<T> ();
2621 /// public abstract class B : A
2623 /// public override U Foo<T> ()
2624 /// { return default (U); }
2627 /// Here, `T' and `U' are method type parameters from different methods
2628 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2630 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2631 /// we need to do a signature based comparision and consider them equal.
2637 if (a.IsGenericParameter && b.IsGenericParameter &&
2638 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2639 return a.GenericParameterPosition == b.GenericParameterPosition;
2643 if (a.IsArray && b.IsArray) {
2644 if (a.GetArrayRank () != b.GetArrayRank ())
2647 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2650 if (a.IsByRef && b.IsByRef)
2651 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2654 if (a.IsGenericType && b.IsGenericType) {
2655 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2658 Type[] aargs = a.GetGenericArguments ();
2659 Type[] bargs = b.GetGenericArguments ();
2661 if (aargs.Length != bargs.Length)
2664 for (int i = 0; i < aargs.Length; i++) {
2665 if (!IsSignatureEqual (aargs [i], bargs [i]))
2677 // Returns whether the array of memberinfos contains the given method
2679 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2681 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2683 foreach (MethodBase method in array) {
2684 if (method.Name != new_method.Name)
2687 if (method is MethodInfo && new_method is MethodInfo)
2688 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2689 ((MethodInfo) new_method).ReturnType))
2693 Type [] old_args = TypeManager.GetParameterData (method).Types;
2694 int old_count = old_args.Length;
2697 if (new_args.Length != old_count)
2700 for (i = 0; i < old_count; i++){
2701 if (!IsSignatureEqual (old_args [i], new_args [i]))
2714 // We copy methods from `new_members' into `target_list' if the signature
2715 // for the method from in the new list does not exist in the target_list
2717 // The name is assumed to be the same.
2719 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2721 if (target_list == null){
2722 target_list = new ArrayList ();
2724 foreach (MemberInfo mi in new_members){
2725 if (mi is MethodBase)
2726 target_list.Add (mi);
2731 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2732 target_list.CopyTo (target_array, 0);
2734 foreach (MemberInfo mi in new_members){
2735 MethodBase new_method = (MethodBase) mi;
2737 if (!ArrayContainsMethod (target_array, new_method))
2738 target_list.Add (new_method);
2745 // Tracks the generic parameters.
2747 static PtrHashtable builder_to_type_param;
2749 public static void AddTypeParameter (Type t, TypeParameter tparam)
2751 if (!builder_to_type_param.Contains (t))
2752 builder_to_type_param.Add (t, tparam);
2755 public static TypeParameter LookupTypeParameter (Type t)
2757 return (TypeParameter) builder_to_type_param [t];
2760 // This method always return false for non-generic compiler,
2761 // while Type.IsGenericParameter is returned if it is supported.
2762 public static bool IsGenericParameter (Type type)
2765 return type.IsGenericParameter;
2771 public static int GenericParameterPosition (Type type)
2774 return type.GenericParameterPosition;
2776 throw new InternalErrorException ("should not be called");
2780 public static bool IsGenericType (Type type)
2783 return type.IsGenericType;
2789 public static bool IsGenericTypeDefinition (Type type)
2792 return type.IsGenericTypeDefinition;
2798 public static bool ContainsGenericParameters (Type type)
2801 return type.ContainsGenericParameters;
2807 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2810 if (fi.DeclaringType.IsGenericTypeDefinition ||
2811 !fi.DeclaringType.IsGenericType)
2814 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2815 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2816 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2818 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2819 foreach (FieldInfo f in t.GetFields (bf))
2820 if (f.MetadataToken == fi.MetadataToken)
2827 public static bool IsEqual (Type a, Type b)
2830 // MS BCL returns true even if enum types are different
2831 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2832 return a.FullName == b.FullName;
2838 if (a.IsGenericParameter && b.IsGenericParameter) {
2839 // TODO: needs more testing before cleaning up
2840 //if (a.DeclaringMethod != b.DeclaringMethod &&
2841 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2843 return a.GenericParameterPosition == b.GenericParameterPosition;
2846 if (a.IsArray && b.IsArray) {
2847 if (a.GetArrayRank () != b.GetArrayRank ())
2849 return IsEqual (a.GetElementType (), b.GetElementType ());
2852 if (a.IsByRef && b.IsByRef)
2853 return IsEqual (a.GetElementType (), b.GetElementType ());
2855 if (a.IsGenericType && b.IsGenericType) {
2856 Type adef = a.GetGenericTypeDefinition ();
2857 Type bdef = b.GetGenericTypeDefinition ();
2862 if (adef.IsEnum && bdef.IsEnum)
2865 Type[] aargs = a.GetGenericArguments ();
2866 Type[] bargs = b.GetGenericArguments ();
2868 if (aargs.Length != bargs.Length)
2871 for (int i = 0; i < aargs.Length; i++) {
2872 if (!IsEqual (aargs [i], bargs [i]))
2883 public static Type DropGenericTypeArguments (Type t)
2886 if (!t.IsGenericType)
2888 // Micro-optimization: a generic typebuilder is always a generic type definition
2889 if (t is TypeBuilder)
2891 return t.GetGenericTypeDefinition ();
2897 public static MethodBase DropGenericMethodArguments (MethodBase m)
2900 if (m.IsGenericMethodDefinition)
2902 if (m.IsGenericMethod)
2903 return ((MethodInfo) m).GetGenericMethodDefinition ();
2904 if (!m.DeclaringType.IsGenericType)
2907 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2908 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2909 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2912 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2916 if (m is ConstructorInfo) {
2917 foreach (ConstructorInfo c in t.GetConstructors (bf))
2918 if (c.MetadataToken == m.MetadataToken)
2921 foreach (MethodBase mb in t.GetMethods (bf))
2922 if (mb.MetadataToken == m.MetadataToken)
2930 public static Type[] GetGenericArguments (MethodBase mi)
2933 return mi.GetGenericArguments ();
2935 return Type.EmptyTypes;
2939 public static Type[] GetTypeArguments (Type t)
2942 DeclSpace tc = LookupDeclSpace (t);
2945 return Type.EmptyTypes;
2947 TypeParameter[] tparam = tc.TypeParameters;
2948 Type[] ret = new Type [tparam.Length];
2949 for (int i = 0; i < tparam.Length; i++) {
2950 ret [i] = tparam [i].Type;
2951 if (ret [i] == null)
2952 throw new InternalErrorException ();
2957 return t.GetGenericArguments ();
2959 throw new InternalErrorException ();
2963 public static GenericConstraints GetTypeParameterConstraints (Type t)
2966 if (!t.IsGenericParameter)
2967 throw new InvalidOperationException ();
2969 TypeParameter tparam = LookupTypeParameter (t);
2971 return tparam.GenericConstraints;
2973 return ReflectionConstraints.GetConstraints (t);
2975 throw new InternalErrorException ();
2979 public static bool HasGenericArguments (Type t)
2981 return GetNumberOfTypeArguments (t) > 0;
2984 public static int GetNumberOfTypeArguments (Type t)
2987 if (t.IsGenericParameter)
2989 DeclSpace tc = LookupDeclSpace (t);
2991 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2993 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
3000 /// Check whether `type' and `parent' are both instantiations of the same
3001 /// generic type. Note that we do not check the type parameters here.
3003 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
3005 int tcount = GetNumberOfTypeArguments (type);
3006 int pcount = GetNumberOfTypeArguments (parent);
3008 if (tcount != pcount)
3011 type = DropGenericTypeArguments (type);
3012 parent = DropGenericTypeArguments (parent);
3014 return type.Equals (parent);
3018 /// Whether `mb' is a generic method definition.
3020 public static bool IsGenericMethodDefinition (MethodBase mb)
3023 if (mb.DeclaringType is TypeBuilder) {
3024 IMethodData method = (IMethodData) builder_to_method [mb];
3028 return method.GenericMethod != null;
3031 return mb.IsGenericMethodDefinition;
3038 /// Whether `mb' is a generic method.
3040 public static bool IsGenericMethod (MethodBase mb)
3043 return mb.IsGenericMethod;
3049 public static bool IsNullableType (Type t)
3052 return generic_nullable_type == DropGenericTypeArguments (t);
3058 public static bool IsNullableTypeOf (Type t, Type nullable)
3061 if (!IsNullableType (t))
3064 return GetTypeArguments (t) [0] == nullable;
3070 public static bool IsNullableValueType (Type t)
3073 if (!IsNullableType (t))
3076 return GetTypeArguments (t) [0].IsValueType;
3083 #region MemberLookup implementation
3086 // Whether we allow private members in the result (since FindMembers
3087 // uses NonPublic for both protected and private), we need to distinguish.
3090 internal class Closure {
3091 internal bool private_ok;
3093 // Who is invoking us and which type is being queried currently.
3094 internal Type invocation_type;
3095 internal Type qualifier_type;
3097 // The assembly that defines the type is that is calling us
3098 internal Assembly invocation_assembly;
3099 internal IList almost_match;
3101 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3103 if (invocation_type == null)
3106 if (is_static && qualifier_type == null)
3107 // It resolved from a simple name, so it should be visible.
3110 if (IsNestedChildOf (invocation_type, m.DeclaringType))
3113 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
3114 if (!IsFamilyAccessible (t, m.DeclaringType))
3117 // Although a derived class can access protected members of its base class
3118 // it cannot do so through an instance of the base class (CS1540).
3119 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3120 if (is_static || qualifier_type == null ||
3121 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3122 IsFamilyAccessible (qualifier_type, t))
3126 if (almost_match != null)
3127 almost_match.Add (m);
3133 // This filter filters by name + whether it is ok to include private
3134 // members in the search
3136 internal bool Filter (MemberInfo m, object filter_criteria)
3139 // Hack: we know that the filter criteria will always be in the
3140 // `closure' // fields.
3143 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3146 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3147 (invocation_type != null) &&
3148 IsPrivateAccessible (m.DeclaringType, invocation_type))
3152 // Ugly: we need to find out the type of `m', and depending
3153 // on this, tell whether we accept or not
3155 if (m is MethodBase){
3156 MethodBase mb = (MethodBase) m;
3157 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3159 if (ma == MethodAttributes.Public)
3162 if (ma == MethodAttributes.PrivateScope)
3165 if (ma == MethodAttributes.Private)
3166 return private_ok ||
3167 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3168 IsNestedChildOf (invocation_type, m.DeclaringType);
3170 if (invocation_assembly == mb.DeclaringType.Assembly ||
3171 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3172 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3175 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3179 // Family, FamORAssem or FamANDAssem
3180 return CheckValidFamilyAccess (mb.IsStatic, m);
3183 if (m is FieldInfo){
3184 FieldInfo fi = (FieldInfo) m;
3185 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3187 if (fa == FieldAttributes.Public)
3190 if (fa == FieldAttributes.PrivateScope)
3193 if (fa == FieldAttributes.Private)
3194 return private_ok ||
3195 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3196 IsNestedChildOf (invocation_type, m.DeclaringType);
3198 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3199 (invocation_assembly == null) ||
3200 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3201 if ((fa == FieldAttributes.Assembly) ||
3202 (fa == FieldAttributes.FamORAssem))
3205 if ((fa == FieldAttributes.Assembly) ||
3206 (fa == FieldAttributes.FamANDAssem))
3210 // Family, FamORAssem or FamANDAssem
3211 return CheckValidFamilyAccess (fi.IsStatic, m);
3215 // EventInfos and PropertyInfos, return true because they lack
3216 // permission information, so we need to check later on the methods.
3222 static Closure closure = new Closure ();
3223 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3226 // Looks up a member called `name' in the `queried_type'. This lookup
3227 // is done by code that is contained in the definition for `invocation_type'
3228 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3230 // `invocation_type' is used to check whether we're allowed to access the requested
3231 // member wrt its protection level.
3233 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3234 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3235 // is B and qualifier_type is A). This is used to do the CS1540 check.
3237 // When resolving a SimpleName, `qualifier_type' is null.
3239 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3240 // the same than `queried_type' - except when we're being called from BaseAccess;
3241 // in this case, `invocation_type' is the current type and `queried_type' the base
3242 // type, so this'd normally trigger a CS1540.
3244 // The binding flags are `bf' and the kind of members being looked up are `mt'
3246 // The return value always includes private members which code in `invocation_type'
3247 // is allowed to access (using the specified `qualifier_type' if given); only use
3248 // BindingFlags.NonPublic to bypass the permission check.
3250 // The 'almost_match' argument is used for reporting error CS1540.
3252 // Returns an array of a single element for everything but Methods/Constructors
3253 // that might return multiple matches.
3255 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3256 Type queried_type, MemberTypes mt,
3257 BindingFlags original_bf, string name, IList almost_match)
3259 Timer.StartTimer (TimerType.MemberLookup);
3261 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3262 queried_type, mt, original_bf, name, almost_match);
3264 Timer.StopTimer (TimerType.MemberLookup);
3269 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3270 Type queried_type, MemberTypes mt,
3271 BindingFlags original_bf, string name, IList almost_match)
3273 BindingFlags bf = original_bf;
3275 ArrayList method_list = null;
3276 Type current_type = queried_type;
3277 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3278 bool skip_iface_check = true, used_cache = false;
3279 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3281 closure.invocation_type = invocation_type;
3282 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3283 closure.qualifier_type = qualifier_type;
3284 closure.almost_match = almost_match;
3286 // This is from the first time we find a method
3287 // in most cases, we do not actually find a method in the base class
3288 // so we can just ignore it, and save the arraylist allocation
3289 MemberInfo [] first_members_list = null;
3290 bool use_first_members_list = false;
3296 // `NonPublic' is lame, because it includes both protected and
3297 // private methods, so we need to control this behavior by
3298 // explicitly tracking if a private method is ok or not.
3300 // The possible cases are:
3301 // public, private and protected (internal does not come into the
3304 if ((invocation_type != null) &&
3305 ((invocation_type == current_type) ||
3306 IsNestedChildOf (invocation_type, current_type)) ||
3308 bf = original_bf | BindingFlags.NonPublic;
3312 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3314 Timer.StopTimer (TimerType.MemberLookup);
3316 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3318 Timer.StartTimer (TimerType.MemberLookup);
3321 // When queried for an interface type, the cache will automatically check all
3322 // inherited members, so we don't need to do this here. However, this only
3323 // works if we already used the cache in the first iteration of this loop.
3325 // If we used the cache in any further iteration, we can still terminate the
3326 // loop since the cache always looks in all base classes.
3332 skip_iface_check = false;
3334 if (current_type == TypeManager.object_type)
3337 current_type = current_type.BaseType;
3340 // This happens with interfaces, they have a null
3341 // basetype. Look members up in the Object class.
3343 if (current_type == null) {
3344 current_type = TypeManager.object_type;
3349 if (list.Length == 0)
3353 // Events and types are returned by both `static' and `instance'
3354 // searches, which means that our above FindMembers will
3355 // return two copies of the same.
3357 if (list.Length == 1 && !(list [0] is MethodBase)){
3362 // Multiple properties: we query those just to find out the indexer
3365 if (list [0] is PropertyInfo)
3369 // We found an event: the cache lookup returns both the event and
3370 // its private field.
3372 if (list [0] is EventInfo) {
3373 if ((list.Length == 2) && (list [1] is FieldInfo))
3374 return new MemberInfo [] { list [0] };
3380 // We found methods, turn the search into "method scan"
3384 if (first_members_list != null) {
3385 if (use_first_members_list) {
3386 method_list = CopyNewMethods (method_list, first_members_list);
3387 use_first_members_list = false;
3390 method_list = CopyNewMethods (method_list, list);
3392 first_members_list = list;
3393 use_first_members_list = true;
3394 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3396 } while (searching);
3398 if (use_first_members_list)
3399 return first_members_list;
3401 if (method_list != null && method_list.Count > 0) {
3402 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3405 // This happens if we already used the cache in the first iteration, in this case
3406 // the cache already looked in all interfaces.
3408 if (skip_iface_check)
3412 // Interfaces do not list members they inherit, so we have to
3415 if (!queried_type.IsInterface)
3418 if (queried_type.IsArray)
3419 queried_type = TypeManager.array_type;
3421 Type [] ifaces = GetInterfaces (queried_type);
3425 foreach (Type itype in ifaces){
3428 x = MemberLookup (null, null, itype, mt, bf, name, null);
3436 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3437 BindingFlags.Static | BindingFlags.Instance |
3438 BindingFlags.DeclaredOnly;
3440 // Currently is designed to work with external types only
3441 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3443 if (!mb.IsSpecialName)
3446 string name = mb.Name;
3447 if (name.Length < 5)
3450 if (name [3] != '_')
3453 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3454 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3455 Type.FilterName, name.Substring (4));
3460 // This can happen when property is indexer (it can have same name but different parameters)
3461 foreach (PropertyInfo p in pi) {
3462 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3463 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3472 // Currently is designed to work with external types only
3473 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3475 if (!mb.IsSpecialName)
3478 string name = mb.Name;
3479 if (name.Length < 5)
3482 if (name.StartsWith ("add_"))
3483 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3485 if (name.StartsWith ("remove_"))
3486 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3491 // Tests whether external method is really special
3492 public static bool IsSpecialMethod (MethodBase mb)
3494 if (!mb.IsSpecialName)
3497 IMethodData md = TypeManager.GetMethod (mb);
3499 return (md is AbstractPropertyEventMethod || md is Operator);
3501 PropertyInfo pi = GetPropertyFromAccessor (mb);
3503 return IsValidProperty (pi);
3505 if (GetEventFromAccessor (mb) != null)
3508 string name = mb.Name;
3509 if (name.StartsWith ("op_")){
3510 foreach (string oname in Unary.oper_names) {
3515 foreach (string oname in Binary.oper_names) {
3523 // Tests whether imported property is valid C# property.
3524 // TODO: It seems to me that we should do a lot of sanity tests before
3525 // we accept property as C# property
3526 static bool IsValidProperty (PropertyInfo pi)
3528 MethodInfo get_method = pi.GetGetMethod (true);
3529 MethodInfo set_method = pi.GetSetMethod (true);
3530 if (get_method != null && set_method != null) {
3531 int g_count = get_method.GetParameters ().Length;
3532 int s_count = set_method.GetParameters ().Length;
3533 if (g_count + 1 != s_count)
3544 /// There is exactly one instance of this class per type.
3546 public sealed class TypeHandle : IMemberContainer {
3547 public readonly IMemberContainer BaseType;
3549 readonly int id = ++next_id;
3550 static int next_id = 0;
3552 static TypeHandle ()
3558 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3559 /// a TypeHandle yet, a new instance of it is created. This static method
3560 /// ensures that we'll only have one TypeHandle instance per type.
3562 private static TypeHandle GetTypeHandle (Type t)
3564 TypeHandle handle = (TypeHandle) type_hash [t];
3568 handle = new TypeHandle (t);
3569 type_hash.Add (t, handle);
3573 public static MemberCache GetMemberCache (Type t)
3575 return GetTypeHandle (t).MemberCache;
3578 public static void CleanUp ()
3583 public static void Reset ()
3585 type_hash = new PtrHashtable ();
3589 /// Returns the TypeHandle for TypeManager.object_type.
3591 public static IMemberContainer ObjectType {
3593 if (object_type != null)
3596 object_type = GetTypeHandle (TypeManager.object_type);
3603 /// Returns the TypeHandle for TypeManager.array_type.
3605 public static TypeHandle ArrayType {
3607 if (array_type != null)
3610 array_type = GetTypeHandle (TypeManager.array_type);
3616 private static PtrHashtable type_hash;
3618 private static TypeHandle object_type = null;
3619 private static TypeHandle array_type = null;
3622 private string full_name;
3623 private bool is_interface;
3624 private MemberCache member_cache;
3625 private MemberCache base_cache;
3627 private TypeHandle (Type type)
3630 full_name = type.FullName != null ? type.FullName : type.Name;
3631 if (type.BaseType != null) {
3632 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3633 BaseType = base_cache.Container;
3634 } else if (type.IsInterface)
3635 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3636 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3637 this.member_cache = new MemberCache (this);
3640 // IMemberContainer methods
3642 public string Name {
3654 public MemberCache BaseCache {
3660 public bool IsInterface {
3662 return is_interface;
3666 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3668 MemberInfo [] members;
3671 if (type is GenericTypeParameterBuilder)
3672 return MemberList.Empty;
3675 if (mt == MemberTypes.Event)
3676 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3678 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3681 if (members.Length == 0)
3682 return MemberList.Empty;
3684 Array.Reverse (members);
3685 return new MemberList (members);
3688 // IMemberFinder methods
3690 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3691 MemberFilter filter, object criteria)
3693 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3696 public MemberCache MemberCache {
3698 return member_cache;
3702 public override string ToString ()
3704 if (BaseType != null)
3705 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3707 return "TypeHandle (" + id + "," + Name + ")";