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_method_handle_type;
80 static public Type runtime_argument_handle_type;
81 static public Type attribute_type;
82 static public Type attribute_usage_type;
83 static public Type decimal_constant_attribute_type;
84 static public Type dllimport_type;
85 static public Type unverifiable_code_type;
86 static public Type methodimpl_attr_type;
87 static public Type marshal_as_attr_type;
88 static public Type param_array_type;
89 static public Type void_ptr_type;
90 static public Type indexer_name_type;
91 static public Type exception_type;
92 static public Type invalid_operation_exception_type;
93 static public Type not_supported_exception_type;
94 static public Type obsolete_attribute_type;
95 static public Type conditional_attribute_type;
96 static public Type in_attribute_type;
97 static public Type out_attribute_type;
98 static public Type extension_attribute_type;
99 static public Type default_parameter_value_attribute_type;
101 static public Type anonymous_method_type;
102 static public Type cls_compliant_attribute_type;
103 static public Type typed_reference_type;
104 static public Type arg_iterator_type;
105 static public Type mbr_type;
106 static public Type struct_layout_attribute_type;
107 static public Type field_offset_attribute_type;
108 static public Type security_attr_type;
109 static public Type required_attr_type;
110 static public Type guid_attr_type;
111 static public Type assembly_culture_attribute_type;
112 static public Type assembly_version_attribute_type;
113 static public Type coclass_attr_type;
114 static public Type comimport_attr_type;
120 static internal Type runtime_compatibility_attr_type;
121 static internal Type compiler_generated_attr_type;
122 static internal Type fixed_buffer_attr_type;
123 static internal Type default_charset_type;
124 static internal Type internals_visible_attr_type;
125 static internal Type type_forwarder_attr_type;
130 static internal Type expression_type;
134 // Expressions representing the internal types. Used during declaration
137 static public TypeExpr system_object_expr, system_string_expr;
138 static public TypeExpr system_boolean_expr, system_decimal_expr;
139 static public TypeExpr system_single_expr, system_double_expr;
140 static public TypeExpr system_sbyte_expr, system_byte_expr;
141 static public TypeExpr system_int16_expr, system_uint16_expr;
142 static public TypeExpr system_int32_expr, system_uint32_expr;
143 static public TypeExpr system_int64_expr, system_uint64_expr;
144 static public TypeExpr system_char_expr, system_void_expr;
145 static public TypeExpr system_asynccallback_expr;
146 static public TypeExpr system_iasyncresult_expr;
147 static public TypeExpr system_valuetype_expr;
148 static public TypeExpr system_intptr_expr;
151 // This is only used when compiling corlib
153 static public Type system_int32_type;
154 static public Type system_array_type;
155 static public Type system_type_type;
156 static public Type system_assemblybuilder_type;
157 static public MethodInfo system_int_array_get_length;
158 static public MethodInfo system_int_array_get_rank;
159 static public MethodInfo system_object_array_clone;
160 static public MethodInfo system_int_array_get_length_int;
161 static public MethodInfo system_int_array_get_lower_bound_int;
162 static public MethodInfo system_int_array_get_upper_bound_int;
163 static public MethodInfo system_void_array_copyto_array_int;
167 // Internal, not really used outside
169 static Type runtime_helpers_type;
172 // These methods are called by code generated by the compiler
174 static public MethodInfo string_isinterned_string;
175 static public MethodInfo system_type_get_type_from_handle;
176 static public MethodInfo bool_movenext_void;
177 static public MethodInfo ienumerable_getenumerator_void;
178 static public MethodInfo void_reset_void;
179 static public MethodInfo void_dispose_void;
180 static public MethodInfo void_monitor_enter_object;
181 static public MethodInfo void_monitor_exit_object;
182 static public MethodInfo void_initializearray_array_fieldhandle;
183 static public MethodInfo int_getlength_int;
184 static public MethodInfo delegate_combine_delegate_delegate;
185 static public MethodInfo delegate_remove_delegate_delegate;
186 static public MethodInfo int_get_offset_to_string_data;
187 static public MethodInfo int_array_get_length;
188 static public MethodInfo int_array_get_rank;
189 static public MethodInfo object_array_clone;
190 static public MethodInfo int_array_get_length_int;
191 static public MethodInfo int_array_get_lower_bound_int;
192 static public MethodInfo int_array_get_upper_bound_int;
193 static public MethodInfo void_array_copyto_array_int;
194 static public MethodInfo int_interlocked_compare_exchange;
195 static public PropertyInfo ienumerator_getcurrent;
198 // The attribute constructors.
200 static public ConstructorInfo object_ctor;
201 static public ConstructorInfo cons_param_array_attribute;
202 static public ConstructorInfo void_decimal_ctor_five_args;
203 static public ConstructorInfo void_decimal_ctor_int_arg;
204 static public ConstructorInfo unverifiable_code_ctor;
205 static public ConstructorInfo default_member_ctor;
206 static public ConstructorInfo decimal_constant_attribute_ctor;
207 static internal ConstructorInfo struct_layout_attribute_ctor;
208 static public ConstructorInfo field_offset_attribute_ctor;
212 static internal CustomAttributeBuilder compiler_generated_attr;
213 static internal ConstructorInfo fixed_buffer_attr_ctor;
216 static internal CustomAttributeBuilder extension_attribute_attr;
219 static PtrHashtable builder_to_declspace;
221 static PtrHashtable builder_to_member_cache;
224 // Tracks the interfaces implemented by typebuilders. We only
225 // enter those who do implement or or more interfaces
227 static PtrHashtable builder_to_ifaces;
230 // Maps PropertyBuilder to a Type array that contains
231 // the arguments to the indexer
233 static Hashtable indexer_arguments;
236 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
238 static Hashtable method_params;
241 // A hash table from override methods to their base virtual method.
243 static Hashtable method_overrides;
246 // Keeps track of methods
249 static Hashtable builder_to_method;
252 // Contains all public types from referenced assemblies.
253 // This member is used only if CLS Compliance verification is required.
255 public static Hashtable AllClsTopLevelTypes;
257 static Hashtable fieldbuilders_to_fields;
258 static Hashtable propertybuilder_to_property;
259 static Hashtable fields;
260 static Hashtable events;
263 static PtrHashtable assembly_internals_vis_attrs;
271 public static void CleanUp ()
273 // Lets get everything clean so that we can collect before generating code
274 builder_to_declspace = null;
275 builder_to_member_cache = null;
276 builder_to_ifaces = null;
277 builder_to_type_param = null;
278 indexer_arguments = null;
279 method_params = null;
280 builder_to_method = null;
285 propertybuilder_to_property = null;
288 assembly_internals_vis_attrs = null;
291 TypeHandle.CleanUp ();
295 /// A filter for Findmembers that uses the Signature object to
298 static bool SignatureFilter (MemberInfo mi, object criteria)
300 Signature sig = (Signature) criteria;
302 if (!(mi is MethodBase))
305 if (mi.Name != sig.name)
308 int count = sig.args.Length;
310 if (mi is MethodBuilder || mi is ConstructorBuilder){
311 Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
313 if (candidate_args.Length != count)
316 for (int i = 0; i < count; i++)
317 if (candidate_args [i] != sig.args [i])
322 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
324 if (pars.Length != count)
327 for (int i = 0; i < count; i++)
328 if (pars [i].ParameterType != sig.args [i])
334 // A delegate that points to the filter above.
335 static MemberFilter signature_filter;
338 // These are expressions that represent some of the internal data types, used
341 static void InitExpressionTypes ()
343 system_object_expr = new TypeLookupExpression ("System.Object");
344 system_string_expr = new TypeLookupExpression ("System.String");
345 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
346 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
347 system_single_expr = new TypeLookupExpression ("System.Single");
348 system_double_expr = new TypeLookupExpression ("System.Double");
349 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
350 system_byte_expr = new TypeLookupExpression ("System.Byte");
351 system_int16_expr = new TypeLookupExpression ("System.Int16");
352 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
353 system_int32_expr = new TypeLookupExpression ("System.Int32");
354 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
355 system_int64_expr = new TypeLookupExpression ("System.Int64");
356 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
357 system_char_expr = new TypeLookupExpression ("System.Char");
358 system_void_expr = new TypeLookupExpression ("System.Void");
359 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
360 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
361 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
362 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
365 static TypeManager ()
369 signature_filter = new MemberFilter (SignatureFilter);
370 InitExpressionTypes ();
373 static public void Reset ()
375 builder_to_declspace = new PtrHashtable ();
376 builder_to_member_cache = new PtrHashtable ();
377 builder_to_method = new PtrHashtable ();
378 builder_to_type_param = new PtrHashtable ();
379 method_params = new PtrHashtable ();
380 method_overrides = new PtrHashtable ();
381 indexer_arguments = new PtrHashtable ();
382 builder_to_ifaces = new PtrHashtable ();
384 fieldbuilders_to_fields = new Hashtable ();
385 propertybuilder_to_property = new Hashtable ();
386 fields = new Hashtable ();
387 type_hash = new DoubleHash ();
390 assembly_internals_vis_attrs = new PtrHashtable ();
393 // to uncover regressions
394 AllClsTopLevelTypes = null;
397 public static void AddUserType (DeclSpace ds)
399 builder_to_declspace.Add (ds.TypeBuilder, ds);
403 // This entry point is used by types that we define under the covers
405 public static void RegisterBuilder (Type tb, Type [] ifaces)
408 builder_to_ifaces [tb] = ifaces;
411 public static void AddMethod (MethodBase builder, IMethodData method)
413 builder_to_method.Add (builder, method);
414 method_params.Add (builder, method.ParameterInfo);
417 public static IMethodData GetMethod (MethodBase builder)
419 return (IMethodData) builder_to_method [builder];
423 /// Returns the DeclSpace whose Type is `t' or null if there is no
424 /// DeclSpace for `t' (ie, the Type comes from a library)
426 public static DeclSpace LookupDeclSpace (Type t)
428 return builder_to_declspace [t] as DeclSpace;
432 /// Returns the TypeContainer whose Type is `t' or null if there is no
433 /// TypeContainer for `t' (ie, the Type comes from a library)
435 public static TypeContainer LookupTypeContainer (Type t)
437 return builder_to_declspace [t] as TypeContainer;
440 public static MemberCache LookupMemberCache (Type t)
442 if (t.Module == CodeGen.Module.Builder) {
443 DeclSpace container = (DeclSpace)builder_to_declspace [t];
444 if (container != null)
445 return container.MemberCache;
449 if (t is GenericTypeParameterBuilder) {
450 TypeParameter container = builder_to_type_param [t] as TypeParameter;
452 if (container != null)
453 return container.MemberCache;
457 return TypeHandle.GetMemberCache (t);
460 public static MemberCache LookupBaseInterfacesCache (Type t)
462 Type [] ifaces = GetInterfaces (t);
464 if (ifaces != null && ifaces.Length == 1)
465 return LookupMemberCache (ifaces [0]);
467 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
468 MemberCache cache = builder_to_member_cache [t] as MemberCache;
472 cache = new MemberCache (ifaces);
473 builder_to_member_cache.Add (t, cache);
477 public static TypeContainer LookupInterface (Type t)
479 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
480 if ((tc == null) || (tc.Kind != Kind.Interface))
486 public static Delegate LookupDelegate (Type t)
488 return builder_to_declspace [t] as Delegate;
491 public static Class LookupClass (Type t)
493 return (Class) builder_to_declspace [t];
497 // We use this hash for multiple kinds of constructed types:
499 // (T, "&") Given T, get T &
500 // (T, "*") Given T, get T *
501 // (T, "[]") Given T and a array dimension, get T []
502 // (T, X) Given a type T and a simple name X, get the type T+X
504 // Accessibility tests, if necessary, should be done by the user
506 static DoubleHash type_hash = new DoubleHash ();
509 // Gets the reference to T version of the Type (T&)
511 public static Type GetReferenceType (Type t)
514 return t.MakeByRefType ();
516 return GetConstructedType (t, "&");
521 // Gets the pointer to T version of the Type (T*)
523 public static Type GetPointerType (Type t)
525 return GetConstructedType (t, "*");
528 public static Type GetConstructedType (Type t, string dim)
531 if (type_hash.Lookup (t, dim, out ret))
534 ret = t.Module.GetType (t.ToString () + dim);
536 type_hash.Insert (t, dim, ret);
541 ret = GetReferenceType (t);
542 type_hash.Insert (t, dim, ret);
547 if (t.IsGenericParameter || t.IsGenericType) {
550 while ((pos < dim.Length) && (dim [pos] == '[')) {
553 if (dim [pos] == ']') {
554 result = result.MakeArrayType ();
557 if (pos < dim.Length)
560 type_hash.Insert (t, dim, result);
565 while (dim [pos] == ',') {
569 if ((dim [pos] != ']') || (pos != dim.Length-1))
572 result = result.MakeArrayType (rank + 1);
573 type_hash.Insert (t, dim, result);
579 type_hash.Insert (t, dim, null);
583 public static Type GetNestedType (Type t, string name)
586 if (!type_hash.Lookup (t, name, out ret)) {
587 ret = t.GetNestedType (name,
588 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
589 type_hash.Insert (t, name, ret);
595 /// Fills static table with exported types from all referenced assemblies.
596 /// This information is required for CLS Compliance tests.
598 public static void LoadAllImportedTypes ()
600 AllClsTopLevelTypes = new Hashtable (1500);
601 foreach (Assembly a in RootNamespace.Global.Assemblies) {
602 foreach (Type t in a.GetExportedTypes ()) {
603 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
608 public static bool NamespaceClash (string name, Location loc)
610 if (! RootNamespace.Global.IsNamespace (name))
613 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
618 /// Returns the C# name of a type if possible, or the full type name otherwise
620 static public string CSharpName (Type t)
622 if (t == typeof(NullType))
625 if (t == typeof (ArglistParameter))
628 if (t == typeof (AnonymousMethod))
629 return "anonymous method";
631 return CSharpName (GetFullName (t));
634 public static string CSharpName (string name)
636 if (name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
637 return AnonymousTypeClass.SignatureForError;
639 return Regex.Replace (name,
641 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
642 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
643 @"Boolean|String|Void|Null)" +
645 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
648 static public string CSharpName (Type[] types)
650 StringBuilder sb = new StringBuilder ();
651 foreach (Type t in types) {
652 sb.Append (CSharpName (t));
655 sb.Remove (sb.Length - 1, 1);
656 return sb.ToString ();
659 static String CSharpNameMatch (Match match)
661 string s = match.Groups [1].Captures [0].Value;
663 Replace ("int32", "int").
664 Replace ("uint32", "uint").
665 Replace ("int16", "short").
666 Replace ("uint16", "ushort").
667 Replace ("int64", "long").
668 Replace ("uint64", "ulong").
669 Replace ("single", "float").
670 Replace ("boolean", "bool")
671 + match.Groups [2].Captures [0].Value;
674 // Used for error reporting to show symbolic name instead of underlying value
675 public static string CSharpEnumValue (Type t, object value)
677 t = DropGenericTypeArguments (t);
678 Enum e = LookupDeclSpace (t) as Enum;
680 return System.Enum.GetName (t, value);
682 return e.GetDefinition (value).GetSignatureForError ();
686 /// Returns the signature of the method with full namespace classification
688 static public string GetFullNameSignature (MemberInfo mi)
690 PropertyInfo pi = mi as PropertyInfo;
692 MethodBase pmi = pi.GetGetMethod (true);
694 pmi = pi.GetSetMethod (true);
695 if (GetParameterData (pmi).Count > 0)
698 return (mi is MethodBase)
699 ? CSharpSignature (mi as MethodBase)
700 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
704 private static int GetFullName (Type t, StringBuilder sb)
708 if (!t.IsGenericType) {
709 sb.Append (t.FullName);
713 if (t.DeclaringType != null) {
714 pos = GetFullName (t.DeclaringType, sb);
716 } else if (t.Namespace != null && t.Namespace.Length != 0) {
717 sb.Append (t.Namespace);
720 sb.Append (RemoveGenericArity (t.Name));
722 Type[] this_args = GetTypeArguments (t);
724 if (this_args.Length < pos)
725 throw new InternalErrorException (
726 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
727 if (this_args.Length == pos)
732 sb.Append (CSharpName (this_args [pos++]));
733 if (pos == this_args.Length)
741 static string GetFullName (Type t)
744 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
745 return GetFullName (t.GetElementType ()) + dimension;
748 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
749 t = GetTypeArguments (t)[0];
750 return CSharpName (t) + "?";
753 if (t.IsGenericParameter)
755 if (!t.IsGenericType)
758 StringBuilder sb = new StringBuilder ();
759 int pos = GetFullName (t, sb);
761 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
762 return sb.ToString ();
765 public static string GetFullName (Type t)
771 public static string RemoveGenericArity (string from)
773 int i = from.IndexOf ('`');
775 return from.Substring (0, i);
780 /// When we need to report accessors as well
782 static public string CSharpSignature (MethodBase mb)
784 return CSharpSignature (mb, false);
788 /// Returns the signature of the method
790 static public string CSharpSignature (MethodBase mb, bool show_accessor)
792 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
795 ParameterData iparams = GetParameterData (mb);
796 string parameters = iparams.GetSignatureForError ();
797 int accessor_end = 0;
799 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
800 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
801 if (ot != Operator.OpType.TOP) {
802 sig.Append ("operator ");
803 sig.Append (Operator.GetName (ot));
804 sig.Append (parameters);
805 return sig.ToString ();
808 bool is_getter = mb.Name.StartsWith ("get_");
809 bool is_setter = mb.Name.StartsWith ("set_");
810 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
812 } else if (mb.Name.StartsWith ("remove_")) {
817 if (iparams.Count > (is_getter ? 0 : 1)) {
818 sig.Append ("this[");
820 sig.Append (parameters.Substring (1, parameters.Length - 2));
822 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
825 sig.Append (mb.Name.Substring (accessor_end + 1));
828 if (mb.Name == ".ctor")
829 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
831 sig.Append (mb.Name);
834 if (TypeManager.IsGenericMethod (mb)) {
835 Type[] args = mb.GetGenericArguments ();
837 for (int i = 0; i < args.Length; i++) {
840 sig.Append (CSharpName (args [i]));
847 sig.Append (parameters);
850 if (show_accessor && accessor_end > 0) {
852 sig.Append (mb.Name.Substring (0, accessor_end));
855 return sig.ToString ();
858 public static string GetMethodName (MethodInfo m)
861 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
864 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
870 static public string CSharpSignature (EventInfo ei)
872 return CSharpName (ei.DeclaringType) + "." + ei.Name;
876 /// Looks up a type, and aborts if it is not found. This is used
877 /// by types required by the compiler
879 public static Type CoreLookupType (string namespaceName, string name)
881 return CoreLookupType (namespaceName, name, false);
884 static Type CoreLookupType (string ns_name, string name, bool mayFail)
886 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
887 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
888 Type t = fne == null ? null : fne.Type;
891 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
895 AttributeTester.RegisterNonObsoleteType (t);
900 /// Returns the MethodInfo for a method named `name' defined
901 /// in type `t' which takes arguments of types `args'
903 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
907 BindingFlags flags = instance_and_static | BindingFlags.Public;
913 flags |= BindingFlags.NonPublic;
915 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
916 if (list.Count == 0) {
918 Report.Error (-19, "Can not find the core function `" + name + "'");
922 MethodInfo mi = list [0] as MethodInfo;
925 Report.Error (-19, "Can not find the core function `" + name + "'");
932 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
934 return GetMethod (t, name, args, false, report_errors);
937 public static MethodInfo GetMethod (Type t, string name, Type [] args)
939 return GetMethod (t, name, args, true);
943 /// Returns the PropertyInfo for a property named `name' defined
946 public static PropertyInfo GetProperty (Type t, string name)
948 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
949 BindingFlags.Instance, Type.FilterName, name);
950 if (list.Count == 0) {
951 Report.Error (-19, "Can not find the core property `" + name + "'");
955 PropertyInfo pi = list [0] as PropertyInfo;
957 Report.Error (-19, "Can not find the core function `" + name + "'");
965 /// Returns the ConstructorInfo for "args"
967 public static ConstructorInfo GetConstructor (Type t, Type [] args)
969 return GetConstructor (t, args, true);
972 public static ConstructorInfo GetConstructor (Type t, Type [] args, bool report_errors)
981 throw new InternalErrorException ("Core types haven't been initialized yet?");
983 list = FindMembers (t, MemberTypes.Constructor,
984 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
985 signature_filter, sig);
986 if (list.Count == 0){
988 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
992 ConstructorInfo ci = list [0] as ConstructorInfo;
995 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1002 public static void InitEnumUnderlyingTypes ()
1004 int32_type = CoreLookupType ("System", "Int32");
1005 int64_type = CoreLookupType ("System", "Int64");
1006 uint32_type = CoreLookupType ("System", "UInt32");
1007 uint64_type = CoreLookupType ("System", "UInt64");
1008 byte_type = CoreLookupType ("System", "Byte");
1009 sbyte_type = CoreLookupType ("System", "SByte");
1010 short_type = CoreLookupType ("System", "Int16");
1011 ushort_type = CoreLookupType ("System", "UInt16");
1013 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
1014 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
1016 idisposable_type = CoreLookupType ("System", "IDisposable");
1019 InitGenericCoreTypes ();
1024 /// The types have to be initialized after the initial
1025 /// population of the type has happened (for example, to
1026 /// bootstrap the corlib.dll
1028 public static void InitCoreTypes ()
1030 object_type = CoreLookupType ("System", "Object");
1031 system_object_expr.Type = object_type;
1032 value_type = CoreLookupType ("System", "ValueType");
1033 system_valuetype_expr.Type = value_type;
1035 InitEnumUnderlyingTypes ();
1037 char_type = CoreLookupType ("System", "Char");
1038 string_type = CoreLookupType ("System", "String");
1039 float_type = CoreLookupType ("System", "Single");
1040 double_type = CoreLookupType ("System", "Double");
1041 char_ptr_type = GetPointerType (char_type);
1042 decimal_type = CoreLookupType ("System", "Decimal");
1043 bool_type = CoreLookupType ("System", "Boolean");
1044 enum_type = CoreLookupType ("System", "Enum");
1046 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1047 delegate_type = CoreLookupType ("System", "Delegate");
1049 array_type = CoreLookupType ("System", "Array");
1050 void_type = CoreLookupType ("System", "Void");
1051 type_type = CoreLookupType ("System", "Type");
1053 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1054 runtime_method_handle_type = CoreLookupType ("System", "RuntimeMethodHandle");
1055 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1056 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1057 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1058 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1059 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1060 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1061 icloneable_type = CoreLookupType ("System", "ICloneable");
1062 iconvertible_type = CoreLookupType ("System", "IConvertible");
1063 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1064 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1065 intptr_type = CoreLookupType ("System", "IntPtr");
1066 uintptr_type = CoreLookupType ("System", "UIntPtr");
1068 attribute_type = CoreLookupType ("System", "Attribute");
1069 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1070 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1071 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1072 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1073 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1074 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1075 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1077 // needed before any call susceptible to fail, as it is used during resolution
1078 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1080 // this can fail if the user doesn't have an -r:System.dll
1081 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", true);
1083 typed_reference_type = CoreLookupType ("System", "TypedReference");
1084 arg_iterator_type = CoreLookupType ("System", "ArgIterator", true);
1085 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1086 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1088 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1090 void_ptr_type = GetPointerType (void_type);
1092 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1094 exception_type = CoreLookupType ("System", "Exception");
1095 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1096 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1101 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1102 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1103 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1104 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1105 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1106 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1107 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", true);
1108 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1109 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1110 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute");
1111 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1112 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1118 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1119 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1120 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1121 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1122 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", true);
1127 extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
1128 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", true);
1132 // When compiling corlib, store the "real" types here.
1134 if (!RootContext.StdLib) {
1135 system_int32_type = typeof (System.Int32);
1136 system_array_type = typeof (System.Array);
1137 system_type_type = typeof (System.Type);
1138 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1140 system_int_array_get_length = GetMethod (
1141 system_array_type, "get_Length", Type.EmptyTypes);
1142 system_int_array_get_rank = GetMethod (
1143 system_array_type, "get_Rank", Type.EmptyTypes);
1144 system_object_array_clone = GetMethod (
1145 system_array_type, "Clone", Type.EmptyTypes);
1147 Type [] system_int_arg = { system_int32_type };
1148 system_int_array_get_length_int = GetMethod (
1149 system_array_type, "GetLength", system_int_arg);
1150 system_int_array_get_upper_bound_int = GetMethod (
1151 system_array_type, "GetUpperBound", system_int_arg);
1152 system_int_array_get_lower_bound_int = GetMethod (
1153 system_array_type, "GetLowerBound", system_int_arg);
1155 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1156 system_void_array_copyto_array_int = GetMethod (
1157 system_array_type, "CopyTo", system_array_int_arg);
1159 Type [] system_3_type_arg = {
1160 system_type_type, system_type_type, system_type_type };
1161 Type [] system_4_type_arg = {
1162 system_type_type, system_type_type, system_type_type, system_type_type };
1164 MethodInfo set_corlib_type_builders = GetMethod (
1165 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1166 system_4_type_arg, true, false);
1168 if (set_corlib_type_builders != null) {
1169 object[] args = new object [4];
1170 args [0] = object_type;
1171 args [1] = value_type;
1172 args [2] = enum_type;
1173 args [3] = void_type;
1175 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1177 // Compatibility for an older version of the class libs.
1178 set_corlib_type_builders = GetMethod (
1179 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1180 system_3_type_arg, true, true);
1182 if (set_corlib_type_builders == null) {
1183 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1187 object[] args = new object [3];
1188 args [0] = object_type;
1189 args [1] = value_type;
1190 args [2] = enum_type;
1192 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1196 system_string_expr.Type = string_type;
1197 system_boolean_expr.Type = bool_type;
1198 system_decimal_expr.Type = decimal_type;
1199 system_single_expr.Type = float_type;
1200 system_double_expr.Type = double_type;
1201 system_sbyte_expr.Type = sbyte_type;
1202 system_byte_expr.Type = byte_type;
1203 system_int16_expr.Type = short_type;
1204 system_uint16_expr.Type = ushort_type;
1205 system_int32_expr.Type = int32_type;
1206 system_uint32_expr.Type = uint32_type;
1207 system_int64_expr.Type = int64_type;
1208 system_uint64_expr.Type = uint64_type;
1209 system_char_expr.Type = char_type;
1210 system_void_expr.Type = void_type;
1211 system_asynccallback_expr.Type = asynccallback_type;
1212 system_iasyncresult_expr.Type = iasyncresult_type;
1215 // These are only used for compare purposes
1217 anonymous_method_type = typeof (AnonymousMethod);
1218 null_type = typeof (NullType);
1222 // The helper methods that are used by the compiler
1224 public static void InitCodeHelpers ()
1227 // Now load the default methods that we use.
1229 Type [] string_ = { string_type };
1230 string_isinterned_string = GetMethod (
1231 string_type, "IsInterned", string_);
1233 Type [] runtime_type_handle = { runtime_handle_type };
1234 system_type_get_type_from_handle = GetMethod (
1235 type_type, "GetTypeFromHandle", runtime_type_handle);
1237 Type [] delegate_delegate = { delegate_type, delegate_type };
1238 delegate_combine_delegate_delegate = GetMethod (
1239 delegate_type, "Combine", delegate_delegate);
1241 delegate_remove_delegate_delegate = GetMethod (
1242 delegate_type, "Remove", delegate_delegate);
1247 ienumerator_getcurrent = GetProperty (
1248 ienumerator_type, "Current");
1249 bool_movenext_void = GetMethod (
1250 ienumerator_type, "MoveNext", Type.EmptyTypes);
1251 void_reset_void = GetMethod (
1252 ienumerator_type, "Reset", Type.EmptyTypes);
1253 void_dispose_void = GetMethod (
1254 idisposable_type, "Dispose", Type.EmptyTypes);
1255 int_get_offset_to_string_data = GetMethod (
1256 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1257 int_array_get_length = GetMethod (
1258 array_type, "get_Length", Type.EmptyTypes);
1259 int_array_get_rank = GetMethod (
1260 array_type, "get_Rank", Type.EmptyTypes);
1261 ienumerable_getenumerator_void = GetMethod (
1262 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1267 Type [] int_arg = { int32_type };
1268 int_array_get_length_int = GetMethod (
1269 array_type, "GetLength", int_arg);
1270 int_array_get_upper_bound_int = GetMethod (
1271 array_type, "GetUpperBound", int_arg);
1272 int_array_get_lower_bound_int = GetMethod (
1273 array_type, "GetLowerBound", int_arg);
1276 // System.Array methods
1278 object_array_clone = GetMethod (
1279 array_type, "Clone", Type.EmptyTypes);
1280 Type [] array_int_arg = { array_type, int32_type };
1281 void_array_copyto_array_int = GetMethod (
1282 array_type, "CopyTo", array_int_arg);
1287 Type [] object_arg = { object_type };
1288 void_monitor_enter_object = GetMethod (
1289 monitor_type, "Enter", object_arg);
1290 void_monitor_exit_object = GetMethod (
1291 monitor_type, "Exit", object_arg);
1293 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1295 void_initializearray_array_fieldhandle = GetMethod (
1296 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1301 int_getlength_int = GetMethod (
1302 array_type, "GetLength", int_arg);
1305 // Decimal constructors
1307 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1308 void_decimal_ctor_five_args = GetConstructor (
1309 decimal_type, dec_arg);
1311 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1316 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1317 default_member_ctor = GetConstructor (default_member_type, string_);
1318 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1320 Type[] short_arg = { short_type };
1321 // fails for .net 2.1
1322 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg, false);
1324 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1325 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1327 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1331 // System.Threading.CompareExchange
1333 Type[] compare_exchange_types = {
1334 GetReferenceType (int32_type), int32_type, int32_type };
1335 int_interlocked_compare_exchange = GetMethod (
1336 interlocked_type, "CompareExchange", compare_exchange_types);
1342 compiler_generated_attr = new CustomAttributeBuilder (
1343 GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1345 Type[] type_int_arg = { type_type, int32_type };
1346 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1353 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1356 InitGenericCodeHelpers ();
1361 static void InitSystemCore ()
1363 if (RootContext.Version != LanguageVersion.LINQ)
1366 if (extension_attribute_type != null)
1367 extension_attribute_attr = new CustomAttributeBuilder (
1368 GetConstructor (extension_attribute_type, Type.EmptyTypes), new object[0]);
1372 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1375 /// This is the "old", non-cache based FindMembers() function. We cannot use
1376 /// the cache here because there is no member name argument.
1378 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1379 MemberFilter filter, object criteria)
1381 #if MS_COMPATIBLE && GMCS_SOURCE
1382 if (t.IsGenericType)
1383 t = t.GetGenericTypeDefinition ();
1386 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1389 // `builder_to_declspace' contains all dynamic types.
1393 Timer.StartTimer (TimerType.FindMembers);
1394 list = decl.FindMembers (mt, bf, filter, criteria);
1395 Timer.StopTimer (TimerType.FindMembers);
1400 // We have to take care of arrays specially, because GetType on
1401 // a TypeBuilder array will return a Type, not a TypeBuilder,
1402 // and we can not call FindMembers on this type.
1405 #if MS_COMPATIBLE && GMCS_SOURCE
1408 t.IsSubclassOf (TypeManager.array_type))
1409 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1412 if (t is GenericTypeParameterBuilder) {
1413 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1415 Timer.StartTimer (TimerType.FindMembers);
1416 MemberList list = tparam.FindMembers (
1417 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1418 Timer.StopTimer (TimerType.FindMembers);
1424 // Since FindMembers will not lookup both static and instance
1425 // members, we emulate this behaviour here.
1427 if ((bf & instance_and_static) == instance_and_static){
1428 MemberInfo [] i_members = t.FindMembers (
1429 mt, bf & ~BindingFlags.Static, filter, criteria);
1431 int i_len = i_members.Length;
1433 MemberInfo one = i_members [0];
1436 // If any of these are present, we are done!
1438 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1439 return new MemberList (i_members);
1442 MemberInfo [] s_members = t.FindMembers (
1443 mt, bf & ~BindingFlags.Instance, filter, criteria);
1445 int s_len = s_members.Length;
1446 if (i_len > 0 || s_len > 0)
1447 return new MemberList (i_members, s_members);
1450 return new MemberList (i_members);
1452 return new MemberList (s_members);
1456 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1461 /// This method is only called from within MemberLookup. It tries to use the member
1462 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1463 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1464 /// our return value will already contain all inherited members and the caller don't need
1465 /// to check base classes and interfaces anymore.
1467 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1468 string name, out bool used_cache)
1473 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1474 // and we can ask the DeclSpace for the MemberCache.
1477 if (t.Assembly == CodeGen.Assembly.Builder) {
1478 if (t.IsGenericParameter) {
1479 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1482 if (tparam.MemberCache == null)
1483 return new MemberInfo[0];
1485 return tparam.MemberCache.FindMembers (
1486 mt, bf, name, FilterWithClosure_delegate, null);
1489 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1490 t = t.GetGenericTypeDefinition ();
1492 if (t is TypeBuilder) {
1494 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1495 cache = decl.MemberCache;
1498 // If this DeclSpace has a MemberCache, use it.
1501 if (cache != null) {
1503 return cache.FindMembers (
1504 mt, bf, name, FilterWithClosure_delegate, null);
1507 // If there is no MemberCache, we need to use the "normal" FindMembers.
1508 // Note, this is a VERY uncommon route!
1511 Timer.StartTimer (TimerType.FindMembers);
1512 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1513 FilterWithClosure_delegate, name);
1514 Timer.StopTimer (TimerType.FindMembers);
1516 return (MemberInfo []) list;
1520 // We have to take care of arrays specially, because GetType on
1521 // a TypeBuilder array will return a Type, not a TypeBuilder,
1522 // and we can not call FindMembers on this type.
1526 return TypeHandle.ArrayType.MemberCache.FindMembers (
1527 mt, bf, name, FilterWithClosure_delegate, null);
1531 if (t is GenericTypeParameterBuilder) {
1532 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1535 if (tparam.MemberCache == null)
1536 return new MemberInfo [0];
1538 return tparam.MemberCache.FindMembers (
1539 mt, bf, name, FilterWithClosure_delegate, null);
1543 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1545 // This happens if we're resolving a class'es base class and interfaces
1546 // in TypeContainer.DefineType(). At this time, the types aren't
1547 // populated yet, so we can't use the cache.
1549 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1550 FilterWithClosure_delegate, name);
1556 // This call will always succeed. There is exactly one TypeHandle instance per
1557 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1558 // the corresponding MemberCache.
1560 cache = TypeHandle.GetMemberCache (t);
1563 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1566 public static bool IsBuiltinType (Type t)
1568 t = TypeToCoreType (t);
1569 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1570 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1571 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1572 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1578 public static bool IsBuiltinType (TypeContainer tc)
1580 return IsBuiltinType (tc.TypeBuilder);
1584 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1585 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1587 public static bool IsPrimitiveType (Type t)
1589 return (t == int32_type || t == uint32_type ||
1590 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1591 t == char_type || t == short_type || t == bool_type ||
1592 t == sbyte_type || t == byte_type || t == ushort_type);
1595 public static bool IsDelegateType (Type t)
1598 if (t.IsGenericParameter)
1602 t = DropGenericTypeArguments (t);
1603 if (t.IsSubclassOf (TypeManager.delegate_type))
1609 public static bool IsEnumType (Type t)
1611 t = DropGenericTypeArguments (t);
1612 if (builder_to_declspace [t] is Enum)
1615 #if MS_COMPATIBLE && GMCS_SOURCE
1616 if (t.IsGenericParameter || t.IsGenericType)
1622 public static bool IsBuiltinOrEnum (Type t)
1624 if (IsBuiltinType (t))
1633 public static bool IsNullType (Type t)
1635 return t == null_type;
1638 public static bool IsAttributeType (Type t)
1640 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1643 static Stack unmanaged_enclosing_types = new Stack (4);
1646 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1648 public static bool IsUnmanagedType (Type t)
1650 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1651 if (unmanaged_enclosing_types.Contains (t))
1654 // builtins that are not unmanaged types
1655 if (t == TypeManager.object_type || t == TypeManager.string_type)
1658 if (IsGenericType (t) || IsGenericParameter (t))
1661 if (IsBuiltinOrEnum (t))
1664 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1668 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1672 if (!IsValueType (t))
1676 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1677 if (p.IsGenericTypeDefinition)
1682 unmanaged_enclosing_types.Push (t);
1686 if (t is TypeBuilder) {
1687 TypeContainer tc = LookupTypeContainer (t);
1688 if (tc.Fields != null){
1689 foreach (FieldBase f in tc.Fields){
1690 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1691 if ((f.ModFlags & Modifiers.STATIC) != 0)
1693 if (f.MemberType == null)
1695 if (!IsUnmanagedType (f.MemberType)){
1696 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1702 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1704 foreach (FieldInfo f in fields){
1705 if (!IsUnmanagedType (f.FieldType)){
1706 Report.SymbolRelatedToPreviousError (f);
1712 unmanaged_enclosing_types.Pop ();
1717 public static bool IsReferenceType (Type t)
1719 if (TypeManager.IsGenericParameter (t)) {
1720 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1721 if (constraints == null)
1724 return constraints.IsReferenceType;
1727 if (t == TypeManager.null_type)
1730 return !t.IsValueType;
1733 public static bool IsValueType (Type t)
1735 return t.IsValueType || IsGenericParameter (t);
1738 public static bool IsInterfaceType (Type t)
1740 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1744 return tc.Kind == Kind.Interface;
1747 public static bool IsSubclassOf (Type type, Type base_type)
1749 TypeParameter tparam = LookupTypeParameter (type);
1750 TypeParameter pparam = LookupTypeParameter (base_type);
1752 if ((tparam != null) && (pparam != null)) {
1753 if (tparam == pparam)
1756 return tparam.IsSubclassOf (base_type);
1759 #if MS_COMPATIBLE && GMCS_SOURCE
1760 if (type.IsGenericType)
1761 type = type.GetGenericTypeDefinition ();
1764 if (type.IsSubclassOf (base_type))
1768 if (IsEqual (type, base_type))
1771 type = type.BaseType;
1772 } while (type != null);
1777 public static bool IsPrivateAccessible (Type type, Type parent)
1782 if (type.Equals (parent))
1785 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1788 public static bool IsFamilyAccessible (Type type, Type parent)
1790 TypeParameter tparam = LookupTypeParameter (type);
1791 TypeParameter pparam = LookupTypeParameter (parent);
1793 if ((tparam != null) && (pparam != null)) {
1794 if (tparam == pparam)
1797 return tparam.IsSubclassOf (parent);
1801 if (IsInstantiationOfSameGenericType (type, parent))
1804 type = type.BaseType;
1805 } while (type != null);
1811 // Checks whether `type' is a subclass or nested child of `base_type'.
1813 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1816 if (IsFamilyAccessible (type, base_type))
1819 // Handle nested types.
1820 type = type.DeclaringType;
1821 } while (type != null);
1827 // Checks whether `type' is a nested child of `parent'.
1829 public static bool IsNestedChildOf (Type type, Type parent)
1834 type = DropGenericTypeArguments (type);
1835 parent = DropGenericTypeArguments (parent);
1837 if (IsEqual (type, parent))
1840 type = type.DeclaringType;
1841 while (type != null) {
1842 if (IsEqual (type, parent))
1845 type = type.DeclaringType;
1853 // Checks whether `extern_type' is friend of the output assembly
1855 public static bool IsFriendAssembly (Assembly assembly)
1857 // FIXME: This should not be reached
1858 if (assembly == CodeGen.Assembly.Builder)
1861 if (assembly_internals_vis_attrs.Contains (assembly))
1862 return (bool)(assembly_internals_vis_attrs [assembly]);
1864 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1865 if (attrs.Length == 0) {
1866 assembly_internals_vis_attrs.Add (assembly, false);
1870 AssemblyName this_name = CodeGen.Assembly.Name;
1871 byte [] this_token = this_name.GetPublicKeyToken ();
1872 bool is_friend = false;
1873 foreach (InternalsVisibleToAttribute attr in attrs) {
1874 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1877 AssemblyName aname = null;
1879 aname = new AssemblyName (attr.AssemblyName);
1880 } catch (FileLoadException) {
1881 } catch (ArgumentException) {
1884 if (aname == null || aname.Name != this_name.Name)
1887 byte [] key_token = aname.GetPublicKeyToken ();
1888 if (key_token != null) {
1889 if (this_token.Length == 0) {
1890 // Same name, but assembly is not strongnamed
1891 Error_FriendAccessNameNotMatching (aname.FullName);
1895 if (!CompareKeyTokens (this_token, key_token))
1903 assembly_internals_vis_attrs.Add (assembly, is_friend);
1907 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1909 for (int i = 0; i < token1.Length; i++)
1910 if (token1 [i] != token2 [i])
1916 static void Error_FriendAccessNameNotMatching (string other_name)
1918 Report.Error (281, "Friend access was granted to `" + other_name +
1919 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1920 "'. Try adding a reference to `" + other_name +
1921 "' or change the output assembly name to match it");
1924 public static bool IsFriendAssembly (Assembly assembly)
1931 // Do the right thing when returning the element type of an
1932 // array type based on whether we are compiling corlib or not
1934 public static Type GetElementType (Type t)
1936 if (RootContext.StdLib)
1937 return t.GetElementType ();
1939 return TypeToCoreType (t.GetElementType ());
1943 /// This method is not implemented by MS runtime for dynamic types
1945 public static bool HasElementType (Type t)
1947 return t.IsArray || t.IsPointer || t.IsByRef;
1951 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1955 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1956 /// for anything which is dynamic, and we need this in a number of places,
1957 /// we register this information here, and use it afterwards.
1959 static public void RegisterMethod (MethodBase mb, Parameters ip)
1961 method_params.Add (mb, ip);
1964 static public ParameterData GetParameterData (MethodBase mb)
1966 ParameterData pd = (ParameterData)method_params [mb];
1969 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1970 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1971 pd = GetParameterData (mi);
1972 if (mi.IsGenericMethod)
1973 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1975 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1976 method_params.Add (mb, pd);
1980 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1981 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1982 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1985 pd = new ReflectionParameters (mb);
1986 method_params.Add (mb, pd);
1991 public static ParameterData GetDelegateParameters (Type t)
1993 Delegate d = builder_to_declspace [t] as Delegate;
1995 return d.Parameters;
1997 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1998 return GetParameterData (invoke_mb);
2001 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
2003 if (!method_overrides.Contains (override_method))
2004 method_overrides [override_method] = base_method;
2005 if (method_overrides [override_method] != base_method)
2006 throw new InternalErrorException ("Override mismatch: " + override_method);
2009 static public bool IsOverride (MethodBase m)
2011 m = DropGenericMethodArguments (m);
2013 return m.IsVirtual &&
2014 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
2015 (m is MethodBuilder || method_overrides.Contains (m));
2018 static public MethodBase TryGetBaseDefinition (MethodBase m)
2020 m = DropGenericMethodArguments (m);
2022 return (MethodBase) method_overrides [m];
2026 /// Returns the argument types for an indexer based on its PropertyInfo
2028 /// For dynamic indexers, we use the compiler provided types, for
2029 /// indexers from existing assemblies we load them from GetParameters,
2030 /// and insert them into the cache
2032 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2034 if (indexer_arguments.Contains (indexer))
2035 return (Type []) indexer_arguments [indexer];
2036 else if (indexer is PropertyBuilder)
2037 // If we're a PropertyBuilder and not in the
2038 // `indexer_arguments' hash, then we're a property and
2040 return Type.EmptyTypes;
2042 ParameterInfo [] pi = indexer.GetIndexParameters ();
2043 // Property, not an indexer.
2045 return Type.EmptyTypes;
2047 Type [] types = new Type [c];
2049 for (int i = 0; i < c; i++)
2050 types [i] = pi [i].ParameterType;
2052 indexer_arguments.Add (indexer, types);
2057 public static void RegisterConstant (FieldInfo fb, IConstant ic)
2059 fields.Add (fb, ic);
2062 public static IConstant GetConstant (FieldInfo fb)
2067 return (IConstant)fields [fb];
2070 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
2072 propertybuilder_to_property.Add (pi, pb);
2075 public static PropertyBase GetProperty (PropertyInfo pi)
2077 return (PropertyBase)propertybuilder_to_property [pi];
2080 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
2082 fieldbuilders_to_fields.Add (fb, f);
2086 // The return value can be null; This will be the case for
2087 // auxiliary FieldBuilders created by the compiler that have no
2088 // real field being declared on the source code
2090 static public FieldBase GetField (FieldInfo fb)
2093 fb = GetGenericFieldDefinition (fb);
2095 return (FieldBase) fieldbuilders_to_fields [fb];
2098 static public MethodInfo GetAddMethod (EventInfo ei)
2100 if (ei is MyEventBuilder) {
2101 return ((MyEventBuilder)ei).GetAddMethod (true);
2103 return ei.GetAddMethod (true);
2106 static public MethodInfo GetRemoveMethod (EventInfo ei)
2108 if (ei is MyEventBuilder) {
2109 return ((MyEventBuilder)ei).GetRemoveMethod (true);
2111 return ei.GetRemoveMethod (true);
2114 static public void RegisterEventField (EventInfo einfo, EventField e)
2117 events = new Hashtable ();
2119 events.Add (einfo, e);
2122 static public EventField GetEventField (EventInfo ei)
2127 return (EventField) events [ei];
2130 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2131 MethodBase set, Type[] args)
2133 indexer_arguments.Add (pb, args);
2138 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2140 Hashtable hash = new Hashtable ();
2141 return CheckStructCycles (tc, seen, hash);
2144 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2147 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2151 // `seen' contains all types we've already visited.
2153 if (seen.Contains (tc))
2155 seen.Add (tc, null);
2157 if (tc.Fields == null)
2160 foreach (FieldBase field in tc.Fields) {
2161 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2164 Type ftype = field.FieldBuilder.FieldType;
2165 TypeContainer ftc = LookupTypeContainer (ftype);
2169 if (hash.Contains (ftc)) {
2170 Report.Error (523, tc.Location,
2171 "Struct member `{0}.{1}' of type `{2}' " +
2172 "causes a cycle in the struct layout",
2173 tc.Name, field.Name, ftc.Name);
2178 // `hash' contains all types in the current path.
2180 hash.Add (tc, null);
2182 bool ok = CheckStructCycles (ftc, seen, hash);
2189 if (!seen.Contains (ftc))
2190 seen.Add (ftc, null);
2197 /// Given an array of interface types, expand and eliminate repeated ocurrences
2198 /// of an interface.
2202 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2205 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2207 ArrayList new_ifaces = new ArrayList ();
2209 foreach (TypeExpr iface in base_interfaces){
2210 Type itype = iface.Type;
2212 if (new_ifaces.Contains (itype))
2215 new_ifaces.Add (itype);
2217 Type [] implementing = GetInterfaces (itype);
2219 foreach (Type imp in implementing){
2220 if (!new_ifaces.Contains (imp))
2221 new_ifaces.Add (imp);
2224 Type [] ret = new Type [new_ifaces.Count];
2225 new_ifaces.CopyTo (ret, 0);
2229 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2231 ArrayList new_ifaces = new ArrayList ();
2233 foreach (Type itype in base_interfaces){
2234 if (new_ifaces.Contains (itype))
2237 new_ifaces.Add (itype);
2239 Type [] implementing = GetInterfaces (itype);
2241 foreach (Type imp in implementing){
2242 if (!new_ifaces.Contains (imp))
2243 new_ifaces.Add (imp);
2246 Type [] ret = new Type [new_ifaces.Count];
2247 new_ifaces.CopyTo (ret, 0);
2251 static PtrHashtable iface_cache = new PtrHashtable ();
2254 /// This function returns the interfaces in the type `t'. Works with
2255 /// both types and TypeBuilders.
2257 public static Type [] GetInterfaces (Type t)
2259 Type [] cached = iface_cache [t] as Type [];
2264 // The reason for catching the Array case is that Reflection.Emit
2265 // will not return a TypeBuilder for Array types of TypeBuilder types,
2266 // but will still throw an exception if we try to call GetInterfaces
2269 // Since the array interfaces are always constant, we return those for
2274 t = TypeManager.array_type;
2276 if ((t is TypeBuilder) || IsGenericType (t)) {
2277 Type [] base_ifaces;
2279 if (t.BaseType == null)
2280 base_ifaces = Type.EmptyTypes;
2282 base_ifaces = GetInterfaces (t.BaseType);
2284 if (IsGenericType (t))
2285 #if MS_COMPATIBLE && GMCS_SOURCE
2286 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2288 type_ifaces = t.GetInterfaces ();
2291 type_ifaces = (Type []) builder_to_ifaces [t];
2292 if (type_ifaces == null || type_ifaces.Length == 0)
2293 type_ifaces = Type.EmptyTypes;
2295 int base_count = base_ifaces.Length;
2296 Type [] result = new Type [base_count + type_ifaces.Length];
2297 base_ifaces.CopyTo (result, 0);
2298 type_ifaces.CopyTo (result, base_count);
2300 iface_cache [t] = result;
2303 } else if (t is GenericTypeParameterBuilder){
2304 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2305 if (type_ifaces == null || type_ifaces.Length == 0)
2306 type_ifaces = Type.EmptyTypes;
2308 iface_cache [t] = type_ifaces;
2312 Type[] ifaces = t.GetInterfaces ();
2313 iface_cache [t] = ifaces;
2319 // gets the interfaces that are declared explicitly on t
2321 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2323 return (Type []) builder_to_ifaces [t];
2327 /// The following is used to check if a given type implements an interface.
2328 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2330 public static bool ImplementsInterface (Type t, Type iface)
2335 // FIXME OPTIMIZATION:
2336 // as soon as we hit a non-TypeBuiler in the interface
2337 // chain, we could return, as the `Type.GetInterfaces'
2338 // will return all the interfaces implement by the type
2342 interfaces = GetInterfaces (t);
2344 if (interfaces != null){
2345 foreach (Type i in interfaces){
2352 } while (t != null);
2357 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2359 // This is a custom version of Convert.ChangeType() which works
2360 // with the TypeBuilder defined types when compiling corlib.
2361 public static object ChangeType (object value, Type conversionType, out bool error)
2363 IConvertible convert_value = value as IConvertible;
2365 if (convert_value == null){
2372 // We must use Type.Equals() here since `conversionType' is
2373 // the TypeBuilder created version of a system type and not
2374 // the system type itself. You cannot use Type.GetTypeCode()
2375 // on such a type - it'd always return TypeCode.Object.
2378 // We cannot rely on build-in type conversions as they are
2379 // more limited than what C# supports.
2380 // See char -> float/decimal/double conversion
2385 if (conversionType.Equals (typeof (Boolean)))
2386 return (object)(convert_value.ToBoolean (nf_provider));
2387 if (conversionType.Equals (typeof (Byte)))
2388 return (object)(convert_value.ToByte (nf_provider));
2389 if (conversionType.Equals (typeof (Char)))
2390 return (object)(convert_value.ToChar (nf_provider));
2391 if (conversionType.Equals (typeof (DateTime)))
2392 return (object)(convert_value.ToDateTime (nf_provider));
2394 if (conversionType.Equals (TypeManager.decimal_type)) {
2395 if (convert_value.GetType () == TypeManager.char_type)
2396 return (decimal)convert_value.ToInt32 (nf_provider);
2397 return convert_value.ToDecimal (nf_provider);
2400 if (conversionType.Equals (typeof (Double))) {
2401 if (convert_value.GetType () == TypeManager.char_type)
2402 return (double)convert_value.ToInt32 (nf_provider);
2403 return convert_value.ToDouble (nf_provider);
2406 if (conversionType.Equals (typeof (Int16)))
2407 return (object)(convert_value.ToInt16 (nf_provider));
2408 if (conversionType.Equals (typeof (Int32)))
2409 return (object)(convert_value.ToInt32 (nf_provider));
2410 if (conversionType.Equals (typeof (Int64)))
2411 return (object)(convert_value.ToInt64 (nf_provider));
2412 if (conversionType.Equals (typeof (SByte)))
2413 return (object)(convert_value.ToSByte (nf_provider));
2415 if (conversionType.Equals (typeof (Single))) {
2416 if (convert_value.GetType () == TypeManager.char_type)
2417 return (float)convert_value.ToInt32 (nf_provider);
2418 return convert_value.ToSingle (nf_provider);
2421 if (conversionType.Equals (typeof (String)))
2422 return (object)(convert_value.ToString (nf_provider));
2423 if (conversionType.Equals (typeof (UInt16)))
2424 return (object)(convert_value.ToUInt16 (nf_provider));
2425 if (conversionType.Equals (typeof (UInt32)))
2426 return (object)(convert_value.ToUInt32 (nf_provider));
2427 if (conversionType.Equals (typeof (UInt64)))
2428 return (object)(convert_value.ToUInt64 (nf_provider));
2429 if (conversionType.Equals (typeof (Object)))
2430 return (object)(value);
2440 // This is needed, because enumerations from assemblies
2441 // do not report their underlyingtype, but they report
2444 public static Type EnumToUnderlying (Type t)
2446 t = DropGenericTypeArguments (t);
2447 if (t == TypeManager.enum_type)
2450 t = t.UnderlyingSystemType;
2451 if (!TypeManager.IsEnumType (t))
2454 if (t is TypeBuilder) {
2455 // slow path needed to compile corlib
2456 if (t == TypeManager.bool_type ||
2457 t == TypeManager.byte_type ||
2458 t == TypeManager.sbyte_type ||
2459 t == TypeManager.char_type ||
2460 t == TypeManager.short_type ||
2461 t == TypeManager.ushort_type ||
2462 t == TypeManager.int32_type ||
2463 t == TypeManager.uint32_type ||
2464 t == TypeManager.int64_type ||
2465 t == TypeManager.uint64_type)
2468 TypeCode tc = Type.GetTypeCode (t);
2471 case TypeCode.Boolean:
2472 return TypeManager.bool_type;
2474 return TypeManager.byte_type;
2475 case TypeCode.SByte:
2476 return TypeManager.sbyte_type;
2478 return TypeManager.char_type;
2479 case TypeCode.Int16:
2480 return TypeManager.short_type;
2481 case TypeCode.UInt16:
2482 return TypeManager.ushort_type;
2483 case TypeCode.Int32:
2484 return TypeManager.int32_type;
2485 case TypeCode.UInt32:
2486 return TypeManager.uint32_type;
2487 case TypeCode.Int64:
2488 return TypeManager.int64_type;
2489 case TypeCode.UInt64:
2490 return TypeManager.uint64_type;
2492 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2496 // When compiling corlib and called with one of the core types, return
2497 // the corresponding typebuilder for that type.
2499 public static Type TypeToCoreType (Type t)
2501 if (RootContext.StdLib || (t is TypeBuilder))
2504 TypeCode tc = Type.GetTypeCode (t);
2507 case TypeCode.Boolean:
2508 return TypeManager.bool_type;
2510 return TypeManager.byte_type;
2511 case TypeCode.SByte:
2512 return TypeManager.sbyte_type;
2514 return TypeManager.char_type;
2515 case TypeCode.Int16:
2516 return TypeManager.short_type;
2517 case TypeCode.UInt16:
2518 return TypeManager.ushort_type;
2519 case TypeCode.Int32:
2520 return TypeManager.int32_type;
2521 case TypeCode.UInt32:
2522 return TypeManager.uint32_type;
2523 case TypeCode.Int64:
2524 return TypeManager.int64_type;
2525 case TypeCode.UInt64:
2526 return TypeManager.uint64_type;
2527 case TypeCode.Single:
2528 return TypeManager.float_type;
2529 case TypeCode.Double:
2530 return TypeManager.double_type;
2531 case TypeCode.String:
2532 return TypeManager.string_type;
2533 case TypeCode.Decimal:
2534 return TypeManager.decimal_type;
2536 if (t == typeof (void))
2537 return TypeManager.void_type;
2538 if (t == typeof (object))
2539 return TypeManager.object_type;
2540 if (t == typeof (System.Type))
2541 return TypeManager.type_type;
2542 if (t == typeof (System.IntPtr))
2543 return TypeManager.intptr_type;
2549 /// Utility function that can be used to probe whether a type
2550 /// is managed or not.
2552 public static bool VerifyUnManaged (Type t, Location loc)
2554 if (IsUnmanagedType (t))
2557 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2564 /// Returns the name of the indexer in a given type.
2567 /// The default is not always `Item'. The user can change this behaviour by
2568 /// using the IndexerNameAttribute in the container.
2569 /// For example, the String class indexer is named `Chars' not `Item'
2571 public static string IndexerPropertyName (Type t)
2573 t = DropGenericTypeArguments (t);
2574 if (t is TypeBuilder) {
2575 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2576 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2579 System.Attribute attr = System.Attribute.GetCustomAttribute (
2580 t, TypeManager.default_member_type);
2582 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2583 return dma.MemberName;
2586 return TypeContainer.DefaultIndexerName;
2589 static MethodInfo declare_local_method = null;
2591 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2593 if (declare_local_method == null){
2594 declare_local_method = typeof (ILGenerator).GetMethod (
2596 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2598 new Type [] { typeof (Type), typeof (bool)},
2600 if (declare_local_method == null){
2601 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2602 return ig.DeclareLocal (t);
2605 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2608 private static bool IsSignatureEqual (Type a, Type b)
2611 /// Consider the following example (bug #77674):
2613 /// public abstract class A
2615 /// public abstract T Foo<T> ();
2618 /// public abstract class B : A
2620 /// public override U Foo<T> ()
2621 /// { return default (U); }
2624 /// Here, `T' and `U' are method type parameters from different methods
2625 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2627 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2628 /// we need to do a signature based comparision and consider them equal.
2634 if (a.IsGenericParameter && b.IsGenericParameter &&
2635 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2636 return a.GenericParameterPosition == b.GenericParameterPosition;
2640 if (a.IsArray && b.IsArray) {
2641 if (a.GetArrayRank () != b.GetArrayRank ())
2644 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2647 if (a.IsByRef && b.IsByRef)
2648 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2651 if (a.IsGenericType && b.IsGenericType) {
2652 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2655 Type[] aargs = a.GetGenericArguments ();
2656 Type[] bargs = b.GetGenericArguments ();
2658 if (aargs.Length != bargs.Length)
2661 for (int i = 0; i < aargs.Length; i++) {
2662 if (!IsSignatureEqual (aargs [i], bargs [i]))
2674 // Returns whether the array of memberinfos contains the given method
2676 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2678 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2680 foreach (MethodBase method in array) {
2681 if (method.Name != new_method.Name)
2684 if (method is MethodInfo && new_method is MethodInfo)
2685 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2686 ((MethodInfo) new_method).ReturnType))
2690 Type [] old_args = TypeManager.GetParameterData (method).Types;
2691 int old_count = old_args.Length;
2694 if (new_args.Length != old_count)
2697 for (i = 0; i < old_count; i++){
2698 if (!IsSignatureEqual (old_args [i], new_args [i]))
2711 // We copy methods from `new_members' into `target_list' if the signature
2712 // for the method from in the new list does not exist in the target_list
2714 // The name is assumed to be the same.
2716 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2718 if (target_list == null){
2719 target_list = new ArrayList ();
2721 foreach (MemberInfo mi in new_members){
2722 if (mi is MethodBase)
2723 target_list.Add (mi);
2728 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2729 target_list.CopyTo (target_array, 0);
2731 foreach (MemberInfo mi in new_members){
2732 MethodBase new_method = (MethodBase) mi;
2734 if (!ArrayContainsMethod (target_array, new_method))
2735 target_list.Add (new_method);
2742 // Tracks the generic parameters.
2744 static PtrHashtable builder_to_type_param;
2746 public static void AddTypeParameter (Type t, TypeParameter tparam)
2748 if (!builder_to_type_param.Contains (t))
2749 builder_to_type_param.Add (t, tparam);
2752 public static TypeParameter LookupTypeParameter (Type t)
2754 return (TypeParameter) builder_to_type_param [t];
2757 // This method always return false for non-generic compiler,
2758 // while Type.IsGenericParameter is returned if it is supported.
2759 public static bool IsGenericParameter (Type type)
2762 return type.IsGenericParameter;
2768 public static int GenericParameterPosition (Type type)
2771 return type.GenericParameterPosition;
2773 throw new InternalErrorException ("should not be called");
2777 public static bool IsGenericType (Type type)
2780 return type.IsGenericType;
2786 public static bool IsGenericTypeDefinition (Type type)
2789 return type.IsGenericTypeDefinition;
2795 public static bool ContainsGenericParameters (Type type)
2798 return type.ContainsGenericParameters;
2804 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2807 if (fi.DeclaringType.IsGenericTypeDefinition ||
2808 !fi.DeclaringType.IsGenericType)
2811 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2812 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2813 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2815 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2816 foreach (FieldInfo f in t.GetFields (bf))
2817 if (f.MetadataToken == fi.MetadataToken)
2824 public static bool IsEqual (Type a, Type b)
2827 // MS BCL returns true even if enum types are different
2828 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2829 return a.FullName == b.FullName;
2835 if (a.IsGenericParameter && b.IsGenericParameter) {
2836 // TODO: needs more testing before cleaning up
2837 //if (a.DeclaringMethod != b.DeclaringMethod &&
2838 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2840 return a.GenericParameterPosition == b.GenericParameterPosition;
2843 if (a.IsArray && b.IsArray) {
2844 if (a.GetArrayRank () != b.GetArrayRank ())
2846 return IsEqual (a.GetElementType (), b.GetElementType ());
2849 if (a.IsByRef && b.IsByRef)
2850 return IsEqual (a.GetElementType (), b.GetElementType ());
2852 if (a.IsGenericType && b.IsGenericType) {
2853 Type adef = a.GetGenericTypeDefinition ();
2854 Type bdef = b.GetGenericTypeDefinition ();
2859 if (adef.IsEnum && bdef.IsEnum)
2862 Type[] aargs = a.GetGenericArguments ();
2863 Type[] bargs = b.GetGenericArguments ();
2865 if (aargs.Length != bargs.Length)
2868 for (int i = 0; i < aargs.Length; i++) {
2869 if (!IsEqual (aargs [i], bargs [i]))
2880 public static Type DropGenericTypeArguments (Type t)
2883 if (!t.IsGenericType)
2885 // Micro-optimization: a generic typebuilder is always a generic type definition
2886 if (t is TypeBuilder)
2888 return t.GetGenericTypeDefinition ();
2894 public static MethodBase DropGenericMethodArguments (MethodBase m)
2897 if (m.IsGenericMethodDefinition)
2899 if (m.IsGenericMethod)
2900 return ((MethodInfo) m).GetGenericMethodDefinition ();
2901 if (!m.DeclaringType.IsGenericType)
2904 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2905 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2906 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2909 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2913 if (m is ConstructorInfo) {
2914 foreach (ConstructorInfo c in t.GetConstructors (bf))
2915 if (c.MetadataToken == m.MetadataToken)
2918 foreach (MethodBase mb in t.GetMethods (bf))
2919 if (mb.MetadataToken == m.MetadataToken)
2927 public static Type[] GetGenericArguments (MethodBase mi)
2930 return mi.GetGenericArguments ();
2932 return Type.EmptyTypes;
2936 public static Type[] GetTypeArguments (Type t)
2939 DeclSpace tc = LookupDeclSpace (t);
2942 return Type.EmptyTypes;
2944 TypeParameter[] tparam = tc.TypeParameters;
2945 Type[] ret = new Type [tparam.Length];
2946 for (int i = 0; i < tparam.Length; i++) {
2947 ret [i] = tparam [i].Type;
2948 if (ret [i] == null)
2949 throw new InternalErrorException ();
2954 return t.GetGenericArguments ();
2956 throw new InternalErrorException ();
2960 public static GenericConstraints GetTypeParameterConstraints (Type t)
2963 if (!t.IsGenericParameter)
2964 throw new InvalidOperationException ();
2966 TypeParameter tparam = LookupTypeParameter (t);
2968 return tparam.GenericConstraints;
2970 return ReflectionConstraints.GetConstraints (t);
2972 throw new InternalErrorException ();
2976 public static bool HasGenericArguments (Type t)
2978 return GetNumberOfTypeArguments (t) > 0;
2981 public static int GetNumberOfTypeArguments (Type t)
2984 if (t.IsGenericParameter)
2986 DeclSpace tc = LookupDeclSpace (t);
2988 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2990 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2997 /// Check whether `type' and `parent' are both instantiations of the same
2998 /// generic type. Note that we do not check the type parameters here.
3000 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
3002 int tcount = GetNumberOfTypeArguments (type);
3003 int pcount = GetNumberOfTypeArguments (parent);
3005 if (tcount != pcount)
3008 type = DropGenericTypeArguments (type);
3009 parent = DropGenericTypeArguments (parent);
3011 return type.Equals (parent);
3015 /// Whether `mb' is a generic method definition.
3017 public static bool IsGenericMethodDefinition (MethodBase mb)
3020 if (mb.DeclaringType is TypeBuilder) {
3021 IMethodData method = (IMethodData) builder_to_method [mb];
3025 return method.GenericMethod != null;
3028 return mb.IsGenericMethodDefinition;
3035 /// Whether `mb' is a generic method.
3037 public static bool IsGenericMethod (MethodBase mb)
3040 return mb.IsGenericMethod;
3046 public static bool IsNullableType (Type t)
3049 return generic_nullable_type == DropGenericTypeArguments (t);
3055 public static bool IsNullableTypeOf (Type t, Type nullable)
3058 if (!IsNullableType (t))
3061 return GetTypeArguments (t) [0] == nullable;
3067 public static bool IsNullableValueType (Type t)
3070 if (!IsNullableType (t))
3073 return GetTypeArguments (t) [0].IsValueType;
3080 #region MemberLookup implementation
3083 // Whether we allow private members in the result (since FindMembers
3084 // uses NonPublic for both protected and private), we need to distinguish.
3087 internal class Closure {
3088 internal bool private_ok;
3090 // Who is invoking us and which type is being queried currently.
3091 internal Type invocation_type;
3092 internal Type qualifier_type;
3094 // The assembly that defines the type is that is calling us
3095 internal Assembly invocation_assembly;
3096 internal IList almost_match;
3098 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3100 if (invocation_type == null)
3103 if (is_static && qualifier_type == null)
3104 // It resolved from a simple name, so it should be visible.
3107 if (IsNestedChildOf (invocation_type, m.DeclaringType))
3110 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
3111 if (!IsFamilyAccessible (t, m.DeclaringType))
3114 // Although a derived class can access protected members of its base class
3115 // it cannot do so through an instance of the base class (CS1540).
3116 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3117 if (is_static || qualifier_type == null ||
3118 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3119 IsFamilyAccessible (qualifier_type, t))
3123 if (almost_match != null)
3124 almost_match.Add (m);
3130 // This filter filters by name + whether it is ok to include private
3131 // members in the search
3133 internal bool Filter (MemberInfo m, object filter_criteria)
3136 // Hack: we know that the filter criteria will always be in the
3137 // `closure' // fields.
3140 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3143 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3144 (invocation_type != null) &&
3145 IsPrivateAccessible (m.DeclaringType, invocation_type))
3149 // Ugly: we need to find out the type of `m', and depending
3150 // on this, tell whether we accept or not
3152 if (m is MethodBase){
3153 MethodBase mb = (MethodBase) m;
3154 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3156 if (ma == MethodAttributes.Public)
3159 if (ma == MethodAttributes.PrivateScope)
3162 if (ma == MethodAttributes.Private)
3163 return private_ok ||
3164 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3165 IsNestedChildOf (invocation_type, m.DeclaringType);
3167 if (invocation_assembly == mb.DeclaringType.Assembly ||
3168 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3169 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3172 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3176 // Family, FamORAssem or FamANDAssem
3177 return CheckValidFamilyAccess (mb.IsStatic, m);
3180 if (m is FieldInfo){
3181 FieldInfo fi = (FieldInfo) m;
3182 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3184 if (fa == FieldAttributes.Public)
3187 if (fa == FieldAttributes.PrivateScope)
3190 if (fa == FieldAttributes.Private)
3191 return private_ok ||
3192 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3193 IsNestedChildOf (invocation_type, m.DeclaringType);
3195 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3196 (invocation_assembly == null) ||
3197 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3198 if ((fa == FieldAttributes.Assembly) ||
3199 (fa == FieldAttributes.FamORAssem))
3202 if ((fa == FieldAttributes.Assembly) ||
3203 (fa == FieldAttributes.FamANDAssem))
3207 // Family, FamORAssem or FamANDAssem
3208 return CheckValidFamilyAccess (fi.IsStatic, m);
3212 // EventInfos and PropertyInfos, return true because they lack
3213 // permission information, so we need to check later on the methods.
3219 static Closure closure = new Closure ();
3220 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3223 // Looks up a member called `name' in the `queried_type'. This lookup
3224 // is done by code that is contained in the definition for `invocation_type'
3225 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3227 // `invocation_type' is used to check whether we're allowed to access the requested
3228 // member wrt its protection level.
3230 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3231 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3232 // is B and qualifier_type is A). This is used to do the CS1540 check.
3234 // When resolving a SimpleName, `qualifier_type' is null.
3236 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3237 // the same than `queried_type' - except when we're being called from BaseAccess;
3238 // in this case, `invocation_type' is the current type and `queried_type' the base
3239 // type, so this'd normally trigger a CS1540.
3241 // The binding flags are `bf' and the kind of members being looked up are `mt'
3243 // The return value always includes private members which code in `invocation_type'
3244 // is allowed to access (using the specified `qualifier_type' if given); only use
3245 // BindingFlags.NonPublic to bypass the permission check.
3247 // The 'almost_match' argument is used for reporting error CS1540.
3249 // Returns an array of a single element for everything but Methods/Constructors
3250 // that might return multiple matches.
3252 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3253 Type queried_type, MemberTypes mt,
3254 BindingFlags original_bf, string name, IList almost_match)
3256 Timer.StartTimer (TimerType.MemberLookup);
3258 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3259 queried_type, mt, original_bf, name, almost_match);
3261 Timer.StopTimer (TimerType.MemberLookup);
3266 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3267 Type queried_type, MemberTypes mt,
3268 BindingFlags original_bf, string name, IList almost_match)
3270 BindingFlags bf = original_bf;
3272 ArrayList method_list = null;
3273 Type current_type = queried_type;
3274 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3275 bool skip_iface_check = true, used_cache = false;
3276 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3278 closure.invocation_type = invocation_type;
3279 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3280 closure.qualifier_type = qualifier_type;
3281 closure.almost_match = almost_match;
3283 // This is from the first time we find a method
3284 // in most cases, we do not actually find a method in the base class
3285 // so we can just ignore it, and save the arraylist allocation
3286 MemberInfo [] first_members_list = null;
3287 bool use_first_members_list = false;
3293 // `NonPublic' is lame, because it includes both protected and
3294 // private methods, so we need to control this behavior by
3295 // explicitly tracking if a private method is ok or not.
3297 // The possible cases are:
3298 // public, private and protected (internal does not come into the
3301 if ((invocation_type != null) &&
3302 ((invocation_type == current_type) ||
3303 IsNestedChildOf (invocation_type, current_type)) ||
3305 bf = original_bf | BindingFlags.NonPublic;
3309 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3311 Timer.StopTimer (TimerType.MemberLookup);
3313 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3315 Timer.StartTimer (TimerType.MemberLookup);
3318 // When queried for an interface type, the cache will automatically check all
3319 // inherited members, so we don't need to do this here. However, this only
3320 // works if we already used the cache in the first iteration of this loop.
3322 // If we used the cache in any further iteration, we can still terminate the
3323 // loop since the cache always looks in all base classes.
3329 skip_iface_check = false;
3331 if (current_type == TypeManager.object_type)
3334 current_type = current_type.BaseType;
3337 // This happens with interfaces, they have a null
3338 // basetype. Look members up in the Object class.
3340 if (current_type == null) {
3341 current_type = TypeManager.object_type;
3346 if (list.Length == 0)
3350 // Events and types are returned by both `static' and `instance'
3351 // searches, which means that our above FindMembers will
3352 // return two copies of the same.
3354 if (list.Length == 1 && !(list [0] is MethodBase)){
3359 // Multiple properties: we query those just to find out the indexer
3362 if (list [0] is PropertyInfo)
3366 // We found an event: the cache lookup returns both the event and
3367 // its private field.
3369 if (list [0] is EventInfo) {
3370 if ((list.Length == 2) && (list [1] is FieldInfo))
3371 return new MemberInfo [] { list [0] };
3377 // We found methods, turn the search into "method scan"
3381 if (first_members_list != null) {
3382 if (use_first_members_list) {
3383 method_list = CopyNewMethods (method_list, first_members_list);
3384 use_first_members_list = false;
3387 method_list = CopyNewMethods (method_list, list);
3389 first_members_list = list;
3390 use_first_members_list = true;
3391 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3393 } while (searching);
3395 if (use_first_members_list)
3396 return first_members_list;
3398 if (method_list != null && method_list.Count > 0) {
3399 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3402 // This happens if we already used the cache in the first iteration, in this case
3403 // the cache already looked in all interfaces.
3405 if (skip_iface_check)
3409 // Interfaces do not list members they inherit, so we have to
3412 if (!queried_type.IsInterface)
3415 if (queried_type.IsArray)
3416 queried_type = TypeManager.array_type;
3418 Type [] ifaces = GetInterfaces (queried_type);
3422 foreach (Type itype in ifaces){
3425 x = MemberLookup (null, null, itype, mt, bf, name, null);
3433 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3434 BindingFlags.Static | BindingFlags.Instance |
3435 BindingFlags.DeclaredOnly;
3437 // Currently is designed to work with external types only
3438 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3440 if (!mb.IsSpecialName)
3443 string name = mb.Name;
3444 if (name.Length < 5)
3447 if (name [3] != '_')
3450 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3451 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3452 Type.FilterName, name.Substring (4));
3457 // This can happen when property is indexer (it can have same name but different parameters)
3458 foreach (PropertyInfo p in pi) {
3459 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3460 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3469 // Currently is designed to work with external types only
3470 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3472 if (!mb.IsSpecialName)
3475 string name = mb.Name;
3476 if (name.Length < 5)
3479 if (name.StartsWith ("add_"))
3480 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3482 if (name.StartsWith ("remove_"))
3483 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3488 // Tests whether external method is really special
3489 public static bool IsSpecialMethod (MethodBase mb)
3491 if (!mb.IsSpecialName)
3494 IMethodData md = TypeManager.GetMethod (mb);
3496 return (md is AbstractPropertyEventMethod || md is Operator);
3498 PropertyInfo pi = GetPropertyFromAccessor (mb);
3500 return IsValidProperty (pi);
3502 if (GetEventFromAccessor (mb) != null)
3505 string name = mb.Name;
3506 if (name.StartsWith ("op_")){
3507 foreach (string oname in Unary.oper_names) {
3512 foreach (string oname in Binary.oper_names) {
3520 // Tests whether imported property is valid C# property.
3521 // TODO: It seems to me that we should do a lot of sanity tests before
3522 // we accept property as C# property
3523 static bool IsValidProperty (PropertyInfo pi)
3525 MethodInfo get_method = pi.GetGetMethod (true);
3526 MethodInfo set_method = pi.GetSetMethod (true);
3527 if (get_method != null && set_method != null) {
3528 int g_count = get_method.GetParameters ().Length;
3529 int s_count = set_method.GetParameters ().Length;
3530 if (g_count + 1 != s_count)
3541 /// There is exactly one instance of this class per type.
3543 public sealed class TypeHandle : IMemberContainer {
3544 public readonly IMemberContainer BaseType;
3546 readonly int id = ++next_id;
3547 static int next_id = 0;
3549 static TypeHandle ()
3555 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3556 /// a TypeHandle yet, a new instance of it is created. This static method
3557 /// ensures that we'll only have one TypeHandle instance per type.
3559 private static TypeHandle GetTypeHandle (Type t)
3561 TypeHandle handle = (TypeHandle) type_hash [t];
3565 handle = new TypeHandle (t);
3566 type_hash.Add (t, handle);
3570 public static MemberCache GetMemberCache (Type t)
3572 return GetTypeHandle (t).MemberCache;
3575 public static void CleanUp ()
3580 public static void Reset ()
3582 type_hash = new PtrHashtable ();
3586 /// Returns the TypeHandle for TypeManager.object_type.
3588 public static IMemberContainer ObjectType {
3590 if (object_type != null)
3593 object_type = GetTypeHandle (TypeManager.object_type);
3600 /// Returns the TypeHandle for TypeManager.array_type.
3602 public static TypeHandle ArrayType {
3604 if (array_type != null)
3607 array_type = GetTypeHandle (TypeManager.array_type);
3613 private static PtrHashtable type_hash;
3615 private static TypeHandle object_type = null;
3616 private static TypeHandle array_type = null;
3619 private string full_name;
3620 private bool is_interface;
3621 private MemberCache member_cache;
3622 private MemberCache base_cache;
3624 private TypeHandle (Type type)
3627 full_name = type.FullName != null ? type.FullName : type.Name;
3628 if (type.BaseType != null) {
3629 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3630 BaseType = base_cache.Container;
3631 } else if (type.IsInterface)
3632 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3633 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3634 this.member_cache = new MemberCache (this);
3637 // IMemberContainer methods
3639 public string Name {
3651 public MemberCache BaseCache {
3657 public bool IsInterface {
3659 return is_interface;
3663 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3665 MemberInfo [] members;
3668 if (type is GenericTypeParameterBuilder)
3669 return MemberList.Empty;
3672 if (mt == MemberTypes.Event)
3673 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3675 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3678 if (members.Length == 0)
3679 return MemberList.Empty;
3681 Array.Reverse (members);
3682 return new MemberList (members);
3685 // IMemberFinder methods
3687 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3688 MemberFilter filter, object criteria)
3690 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3693 public MemberCache MemberCache {
3695 return member_cache;
3699 public override string ToString ()
3701 if (BaseType != null)
3702 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3704 return "TypeHandle (" + id + "," + Name + ")";
3709 // Common expressions used by expression trees
3711 static class LinqExpression
3714 // These represent types thare are loaded from System.Core, similar
3715 // in spirit to the TypeManger _type variables.
3717 public static Type expression_type;
3718 public static Type parameter_expression_type;
3721 // The expressions represeing the internal types, if used
3723 public static TypeExpr expression_type_expr;
3725 static LinqExpression ()
3727 expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression");
3728 parameter_expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression");
3730 expression_type_expr = new TypeExpression (expression_type, Location.Null);