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;
131 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 MethodInfo system_int_array_get_length;
157 static public MethodInfo system_int_array_get_rank;
158 static public MethodInfo system_object_array_clone;
159 static public MethodInfo system_int_array_get_length_int;
160 static public MethodInfo system_int_array_get_lower_bound_int;
161 static public MethodInfo system_int_array_get_upper_bound_int;
162 static public MethodInfo system_void_array_copyto_array_int;
166 // Internal, not really used outside
168 static Type runtime_helpers_type;
171 // These methods are called by code generated by the compiler
173 static public MethodInfo string_isinterned_string;
174 static public MethodInfo system_type_get_type_from_handle;
175 static public MethodInfo bool_movenext_void;
176 static public MethodInfo ienumerable_getenumerator_void;
177 static public MethodInfo void_reset_void;
178 static public MethodInfo void_dispose_void;
179 static public MethodInfo void_monitor_enter_object;
180 static public MethodInfo void_monitor_exit_object;
181 static public MethodInfo void_initializearray_array_fieldhandle;
182 static public MethodInfo int_getlength_int;
183 static public MethodInfo delegate_combine_delegate_delegate;
184 static public MethodInfo delegate_remove_delegate_delegate;
185 static public MethodInfo int_get_offset_to_string_data;
186 static public MethodInfo int_array_get_length;
187 static public MethodInfo int_array_get_rank;
188 static public MethodInfo object_array_clone;
189 static public MethodInfo int_array_get_length_int;
190 static public MethodInfo int_array_get_lower_bound_int;
191 static public MethodInfo int_array_get_upper_bound_int;
192 static public MethodInfo void_array_copyto_array_int;
193 static public MethodInfo int_interlocked_compare_exchange;
194 static public PropertyInfo ienumerator_getcurrent;
197 // The attribute constructors.
199 static public ConstructorInfo object_ctor;
200 static public ConstructorInfo cons_param_array_attribute;
201 static public ConstructorInfo void_decimal_ctor_five_args;
202 static public ConstructorInfo void_decimal_ctor_int_arg;
203 static public ConstructorInfo unverifiable_code_ctor;
204 static public ConstructorInfo default_member_ctor;
205 static public ConstructorInfo decimal_constant_attribute_ctor;
206 static internal ConstructorInfo struct_layout_attribute_ctor;
207 static public ConstructorInfo field_offset_attribute_ctor;
211 static internal CustomAttributeBuilder compiler_generated_attr;
212 static internal ConstructorInfo fixed_buffer_attr_ctor;
215 static internal CustomAttributeBuilder extension_attribute_attr;
218 static PtrHashtable builder_to_declspace;
220 static PtrHashtable builder_to_member_cache;
223 // Tracks the interfaces implemented by typebuilders. We only
224 // enter those who do implement or or more interfaces
226 static PtrHashtable builder_to_ifaces;
229 // Maps PropertyBuilder to a Type array that contains
230 // the arguments to the indexer
232 static Hashtable indexer_arguments;
235 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
237 static Hashtable method_params;
240 // A hash table from override methods to their base virtual method.
242 static Hashtable method_overrides;
245 // Keeps track of methods
248 static Hashtable builder_to_method;
251 // Contains all public types from referenced assemblies.
252 // This member is used only if CLS Compliance verification is required.
254 public static Hashtable AllClsTopLevelTypes;
256 static Hashtable fieldbuilders_to_fields;
257 static Hashtable propertybuilder_to_property;
258 static Hashtable fields;
259 static Hashtable events;
262 static PtrHashtable assembly_internals_vis_attrs;
265 public static void CleanUp ()
267 // Lets get everything clean so that we can collect before generating code
268 builder_to_declspace = null;
269 builder_to_member_cache = null;
270 builder_to_ifaces = null;
271 builder_to_type_param = null;
272 indexer_arguments = null;
273 method_params = null;
274 builder_to_method = null;
279 propertybuilder_to_property = null;
282 assembly_internals_vis_attrs = null;
285 TypeHandle.CleanUp ();
289 // These are expressions that represent some of the internal data types, used
292 static void InitExpressionTypes ()
294 system_object_expr = new TypeLookupExpression ("System.Object");
295 system_string_expr = new TypeLookupExpression ("System.String");
296 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
297 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
298 system_single_expr = new TypeLookupExpression ("System.Single");
299 system_double_expr = new TypeLookupExpression ("System.Double");
300 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
301 system_byte_expr = new TypeLookupExpression ("System.Byte");
302 system_int16_expr = new TypeLookupExpression ("System.Int16");
303 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
304 system_int32_expr = new TypeLookupExpression ("System.Int32");
305 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
306 system_int64_expr = new TypeLookupExpression ("System.Int64");
307 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
308 system_char_expr = new TypeLookupExpression ("System.Char");
309 system_void_expr = new TypeLookupExpression ("System.Void");
310 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
311 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
312 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
313 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
316 static TypeManager ()
320 InitExpressionTypes ();
323 static public void Reset ()
325 builder_to_declspace = new PtrHashtable ();
326 builder_to_member_cache = new PtrHashtable ();
327 builder_to_method = new PtrHashtable ();
328 builder_to_type_param = new PtrHashtable ();
329 method_params = new PtrHashtable ();
330 method_overrides = new PtrHashtable ();
331 indexer_arguments = new PtrHashtable ();
332 builder_to_ifaces = new PtrHashtable ();
334 fieldbuilders_to_fields = new Hashtable ();
335 propertybuilder_to_property = new Hashtable ();
336 fields = new Hashtable ();
337 type_hash = new DoubleHash ();
340 assembly_internals_vis_attrs = new PtrHashtable ();
343 // to uncover regressions
344 AllClsTopLevelTypes = null;
347 public static void AddUserType (DeclSpace ds)
349 builder_to_declspace.Add (ds.TypeBuilder, ds);
353 // This entry point is used by types that we define under the covers
355 public static void RegisterBuilder (Type tb, Type [] ifaces)
358 builder_to_ifaces [tb] = ifaces;
361 public static void AddMethod (MethodBase builder, IMethodData method)
363 builder_to_method.Add (builder, method);
364 method_params.Add (builder, method.ParameterInfo);
367 public static IMethodData GetMethod (MethodBase builder)
369 return (IMethodData) builder_to_method [builder];
373 /// Returns the DeclSpace whose Type is `t' or null if there is no
374 /// DeclSpace for `t' (ie, the Type comes from a library)
376 public static DeclSpace LookupDeclSpace (Type t)
378 return builder_to_declspace [t] as DeclSpace;
382 /// Returns the TypeContainer whose Type is `t' or null if there is no
383 /// TypeContainer for `t' (ie, the Type comes from a library)
385 public static TypeContainer LookupTypeContainer (Type t)
387 return builder_to_declspace [t] as TypeContainer;
390 public static MemberCache LookupMemberCache (Type t)
392 if (t.Module == CodeGen.Module.Builder) {
393 DeclSpace container = (DeclSpace)builder_to_declspace [t];
394 if (container != null)
395 return container.MemberCache;
399 if (t is GenericTypeParameterBuilder) {
400 TypeParameter container = builder_to_type_param [t] as TypeParameter;
402 if (container != null)
403 return container.MemberCache;
407 return TypeHandle.GetMemberCache (t);
410 public static MemberCache LookupBaseInterfacesCache (Type t)
412 Type [] ifaces = GetInterfaces (t);
414 if (ifaces != null && ifaces.Length == 1)
415 return LookupMemberCache (ifaces [0]);
417 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
418 MemberCache cache = builder_to_member_cache [t] as MemberCache;
422 cache = new MemberCache (ifaces);
423 builder_to_member_cache.Add (t, cache);
427 public static TypeContainer LookupInterface (Type t)
429 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
430 if ((tc == null) || (tc.Kind != Kind.Interface))
436 public static Delegate LookupDelegate (Type t)
438 return builder_to_declspace [t] as Delegate;
441 public static Class LookupClass (Type t)
443 return (Class) builder_to_declspace [t];
447 // We use this hash for multiple kinds of constructed types:
449 // (T, "&") Given T, get T &
450 // (T, "*") Given T, get T *
451 // (T, "[]") Given T and a array dimension, get T []
452 // (T, X) Given a type T and a simple name X, get the type T+X
454 // Accessibility tests, if necessary, should be done by the user
456 static DoubleHash type_hash = new DoubleHash ();
459 // Gets the reference to T version of the Type (T&)
461 public static Type GetReferenceType (Type t)
464 return t.MakeByRefType ();
466 return GetConstructedType (t, "&");
471 // Gets the pointer to T version of the Type (T*)
473 public static Type GetPointerType (Type t)
475 return GetConstructedType (t, "*");
478 public static Type GetConstructedType (Type t, string dim)
481 if (type_hash.Lookup (t, dim, out ret))
484 ret = t.Module.GetType (t.ToString () + dim);
486 type_hash.Insert (t, dim, ret);
491 ret = GetReferenceType (t);
492 type_hash.Insert (t, dim, ret);
497 if (t.IsGenericParameter || t.IsGenericType) {
500 while ((pos < dim.Length) && (dim [pos] == '[')) {
503 if (dim [pos] == ']') {
504 result = result.MakeArrayType ();
507 if (pos < dim.Length)
510 type_hash.Insert (t, dim, result);
515 while (dim [pos] == ',') {
519 if ((dim [pos] != ']') || (pos != dim.Length-1))
522 result = result.MakeArrayType (rank + 1);
523 type_hash.Insert (t, dim, result);
529 type_hash.Insert (t, dim, null);
533 public static Type GetNestedType (Type t, string name)
536 if (!type_hash.Lookup (t, name, out ret)) {
537 ret = t.GetNestedType (name,
538 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
539 type_hash.Insert (t, name, ret);
545 /// Fills static table with exported types from all referenced assemblies.
546 /// This information is required for CLS Compliance tests.
548 public static void LoadAllImportedTypes ()
550 AllClsTopLevelTypes = new Hashtable (1500);
551 foreach (Assembly a in RootNamespace.Global.Assemblies) {
552 foreach (Type t in a.GetExportedTypes ()) {
553 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
558 public static bool NamespaceClash (string name, Location loc)
560 if (! RootNamespace.Global.IsNamespace (name))
563 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
568 /// Returns the C# name of a type if possible, or the full type name otherwise
570 static public string CSharpName (Type t)
572 if (t == typeof(NullType))
575 if (t == typeof (ArglistParameter))
578 if (t == typeof (AnonymousMethod))
579 return "anonymous method";
581 return CSharpName (GetFullName (t));
584 public static string CSharpName (string name)
586 if (name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
587 return AnonymousTypeClass.SignatureForError;
589 return Regex.Replace (name,
591 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
592 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
593 @"Boolean|String|Void|Null)" +
595 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
598 static public string CSharpName (Type[] types)
600 StringBuilder sb = new StringBuilder ();
601 foreach (Type t in types) {
602 sb.Append (CSharpName (t));
605 sb.Remove (sb.Length - 1, 1);
606 return sb.ToString ();
609 static String CSharpNameMatch (Match match)
611 string s = match.Groups [1].Captures [0].Value;
613 Replace ("int32", "int").
614 Replace ("uint32", "uint").
615 Replace ("int16", "short").
616 Replace ("uint16", "ushort").
617 Replace ("int64", "long").
618 Replace ("uint64", "ulong").
619 Replace ("single", "float").
620 Replace ("boolean", "bool")
621 + match.Groups [2].Captures [0].Value;
624 // Used for error reporting to show symbolic name instead of underlying value
625 public static string CSharpEnumValue (Type t, object value)
627 t = DropGenericTypeArguments (t);
628 Enum e = LookupDeclSpace (t) as Enum;
630 return System.Enum.GetName (t, value);
632 return e.GetDefinition (value).GetSignatureForError ();
636 /// Returns the signature of the method with full namespace classification
638 static public string GetFullNameSignature (MemberInfo mi)
640 PropertyInfo pi = mi as PropertyInfo;
642 MethodBase pmi = pi.GetGetMethod (true);
644 pmi = pi.GetSetMethod (true);
645 if (GetParameterData (pmi).Count > 0)
648 return (mi is MethodBase)
649 ? CSharpSignature (mi as MethodBase)
650 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
654 private static int GetFullName (Type t, StringBuilder sb)
658 if (!t.IsGenericType) {
659 sb.Append (t.FullName);
663 if (t.DeclaringType != null) {
664 pos = GetFullName (t.DeclaringType, sb);
666 } else if (t.Namespace != null && t.Namespace.Length != 0) {
667 sb.Append (t.Namespace);
670 sb.Append (RemoveGenericArity (t.Name));
672 Type[] this_args = GetTypeArguments (t);
674 if (this_args.Length < pos)
675 throw new InternalErrorException (
676 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
677 if (this_args.Length == pos)
682 sb.Append (CSharpName (this_args [pos++]));
683 if (pos == this_args.Length)
691 static string GetFullName (Type t)
694 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
695 return GetFullName (t.GetElementType ()) + dimension;
698 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
699 t = GetTypeArguments (t)[0];
700 return CSharpName (t) + "?";
703 if (t.IsGenericParameter)
705 if (!t.IsGenericType)
708 StringBuilder sb = new StringBuilder ();
709 int pos = GetFullName (t, sb);
711 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
712 return sb.ToString ();
715 public static string GetFullName (Type t)
721 public static string RemoveGenericArity (string from)
723 int i = from.IndexOf ('`');
725 return from.Substring (0, i);
730 /// When we need to report accessors as well
732 static public string CSharpSignature (MethodBase mb)
734 return CSharpSignature (mb, false);
738 /// Returns the signature of the method
740 static public string CSharpSignature (MethodBase mb, bool show_accessor)
742 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
745 ParameterData iparams = GetParameterData (mb);
746 string parameters = iparams.GetSignatureForError ();
747 int accessor_end = 0;
749 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
750 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
751 if (ot != Operator.OpType.TOP) {
752 sig.Append ("operator ");
753 sig.Append (Operator.GetName (ot));
754 sig.Append (parameters);
755 return sig.ToString ();
758 bool is_getter = mb.Name.StartsWith ("get_");
759 bool is_setter = mb.Name.StartsWith ("set_");
760 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
762 } else if (mb.Name.StartsWith ("remove_")) {
767 if (iparams.Count > (is_getter ? 0 : 1)) {
768 sig.Append ("this[");
770 sig.Append (parameters.Substring (1, parameters.Length - 2));
772 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
775 sig.Append (mb.Name.Substring (accessor_end + 1));
778 if (mb.Name == ".ctor")
779 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
781 sig.Append (mb.Name);
784 if (TypeManager.IsGenericMethod (mb)) {
785 Type[] args = mb.GetGenericArguments ();
787 for (int i = 0; i < args.Length; i++) {
790 sig.Append (CSharpName (args [i]));
797 sig.Append (parameters);
800 if (show_accessor && accessor_end > 0) {
802 sig.Append (mb.Name.Substring (0, accessor_end));
805 return sig.ToString ();
808 public static string GetMethodName (MethodInfo m)
811 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
814 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
820 static public string CSharpSignature (EventInfo ei)
822 return CSharpName (ei.DeclaringType) + "." + ei.Name;
826 /// Looks up a type, and aborts if it is not found. This is used
827 /// by types required by the compiler
829 public static Type CoreLookupType (string namespaceName, string name)
831 return CoreLookupType (namespaceName, name, false);
834 static Type CoreLookupType (string ns_name, string name, bool mayFail)
836 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
837 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
838 Type t = fne == null ? null : fne.Type;
841 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
845 AttributeTester.RegisterNonObsoleteType (t);
850 /// Returns the MethodInfo for a method named `name' defined
851 /// in type `t' which takes arguments of types `args'
853 static MethodInfo GetCoreMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
855 BindingFlags flags = instance_and_static;
857 flags |= BindingFlags.NonPublic;
859 flags |= BindingFlags.Public;
861 MemberInfo[] methods = MemberLookup (null, null, t, MemberTypes.Method, flags, name, null);
862 if (methods != null) {
863 for (int i = 0; i < methods.Length; ++i) {
864 MethodBase method = (MethodBase) methods [i];
865 ParameterData pd = TypeManager.GetParameterData (method);
866 if (pd.Count != args.Length)
869 for (int ii = 0; ii < args.Length; ++ii) {
870 if (!IsEqual (pd.Types [ii], args [ii])) {
877 return (MethodInfo) method;
882 Report.Error (-19, "The predefined method `{0}.{1}({2})' could not be found",
883 TypeManager.CSharpName (t), name, TypeManager.CSharpName (args));
888 static MethodInfo GetCoreMethod (Type t, string name, Type [] args, bool report_errors)
890 return GetCoreMethod (t, name, args, false, report_errors);
893 public static MethodInfo GetCoreMethod (Type t, string name, Type [] args)
895 return GetCoreMethod (t, name, args, true);
899 /// Returns the ConstructorInfo for "args"
901 public static ConstructorInfo GetCoreConstructor (Type t, Type [] args)
903 return GetCoreConstructor (t, args, true);
906 public static ConstructorInfo GetCoreConstructor (Type t, Type [] args, bool report_errors)
908 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
910 MemberInfo [] methods = MemberLookup (null, null, t, MemberTypes.Constructor,
911 flags, ConstructorInfo.ConstructorName, null);
913 for (int i = 0; i < methods.Length; ++i) {
914 MethodBase method = (MethodBase) methods [i];
915 ParameterData pd = TypeManager.GetParameterData (method);
916 if (pd.Count != args.Length)
919 for (int ii = 0; ii < args.Length; ++ii) {
920 if (!IsEqual (pd.Types [ii], args [ii])) {
927 return (ConstructorInfo) method;
931 Report.Error (-19, "Can not find the core constructor of type `{0}'",
932 TypeManager.CSharpName (t));
938 /// Returns the PropertyInfo for a property named `name' defined
941 public static PropertyInfo GetCoreProperty (Type t, string name)
943 MemberInfo [] properties = MemberLookup (null, null, t, MemberTypes.Property,
944 BindingFlags.Public | BindingFlags.Instance, name, null);
946 if (properties == null || properties.Length != 1) {
947 Report.Error (-19, "Can not find the core property `" + name + "'");
951 return (PropertyInfo) properties [0];
954 public static void InitEnumUnderlyingTypes ()
956 int32_type = CoreLookupType ("System", "Int32");
957 int64_type = CoreLookupType ("System", "Int64");
958 uint32_type = CoreLookupType ("System", "UInt32");
959 uint64_type = CoreLookupType ("System", "UInt64");
960 byte_type = CoreLookupType ("System", "Byte");
961 sbyte_type = CoreLookupType ("System", "SByte");
962 short_type = CoreLookupType ("System", "Int16");
963 ushort_type = CoreLookupType ("System", "UInt16");
965 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
966 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
968 idisposable_type = CoreLookupType ("System", "IDisposable");
971 InitGenericCoreTypes ();
976 /// The types have to be initialized after the initial
977 /// population of the type has happened (for example, to
978 /// bootstrap the corlib.dll
980 public static void InitCoreTypes ()
982 object_type = CoreLookupType ("System", "Object");
983 system_object_expr.Type = object_type;
984 value_type = CoreLookupType ("System", "ValueType");
985 system_valuetype_expr.Type = value_type;
987 InitEnumUnderlyingTypes ();
989 char_type = CoreLookupType ("System", "Char");
990 string_type = CoreLookupType ("System", "String");
991 float_type = CoreLookupType ("System", "Single");
992 double_type = CoreLookupType ("System", "Double");
993 char_ptr_type = GetPointerType (char_type);
994 decimal_type = CoreLookupType ("System", "Decimal");
995 bool_type = CoreLookupType ("System", "Boolean");
996 enum_type = CoreLookupType ("System", "Enum");
998 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
999 delegate_type = CoreLookupType ("System", "Delegate");
1001 array_type = CoreLookupType ("System", "Array");
1002 void_type = CoreLookupType ("System", "Void");
1003 type_type = CoreLookupType ("System", "Type");
1005 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1006 runtime_method_handle_type = CoreLookupType ("System", "RuntimeMethodHandle");
1007 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1008 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1009 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1010 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1011 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1012 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1013 icloneable_type = CoreLookupType ("System", "ICloneable");
1014 iconvertible_type = CoreLookupType ("System", "IConvertible");
1015 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1016 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1017 intptr_type = CoreLookupType ("System", "IntPtr");
1018 uintptr_type = CoreLookupType ("System", "UIntPtr");
1020 attribute_type = CoreLookupType ("System", "Attribute");
1021 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1022 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1023 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1024 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1025 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1026 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1027 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1029 // needed before any call susceptible to fail, as it is used during resolution
1030 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1032 // this can fail if the user doesn't have an -r:System.dll
1033 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", true);
1035 typed_reference_type = CoreLookupType ("System", "TypedReference");
1036 arg_iterator_type = CoreLookupType ("System", "ArgIterator", true);
1037 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1038 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1040 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1042 void_ptr_type = GetPointerType (void_type);
1044 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1046 exception_type = CoreLookupType ("System", "Exception");
1047 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1048 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1053 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1054 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1055 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1056 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1057 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1058 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1059 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", true);
1060 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1061 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1062 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute");
1063 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1064 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1070 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1071 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1072 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1073 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1074 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", true);
1079 extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
1080 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", true);
1084 // When compiling corlib, store the "real" types here.
1086 if (!RootContext.StdLib) {
1087 system_int32_type = typeof (System.Int32);
1088 system_array_type = typeof (System.Array);
1089 system_type_type = typeof (System.Type);
1091 system_int_array_get_length = GetCoreMethod (
1092 system_array_type, "get_Length", Type.EmptyTypes);
1093 system_int_array_get_rank = GetCoreMethod (
1094 system_array_type, "get_Rank", Type.EmptyTypes);
1095 system_object_array_clone = GetCoreMethod (
1096 system_array_type, "Clone", Type.EmptyTypes);
1098 Type [] system_int_arg = { system_int32_type };
1099 system_int_array_get_length_int = GetCoreMethod (
1100 system_array_type, "GetLength", system_int_arg);
1101 system_int_array_get_upper_bound_int = GetCoreMethod (
1102 system_array_type, "GetUpperBound", system_int_arg);
1103 system_int_array_get_lower_bound_int = GetCoreMethod (
1104 system_array_type, "GetLowerBound", system_int_arg);
1106 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1107 system_void_array_copyto_array_int = GetCoreMethod (
1108 system_array_type, "CopyTo", system_array_int_arg);
1111 // HACK: When building corlib replace corlib internal core types
1112 // with mcs core types to handle type comparisons inside corlib
1114 Type [] system_4_type_arg = {
1115 system_type_type, system_type_type, system_type_type, system_type_type };
1117 MethodInfo set_corlib_type_builders =
1118 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1119 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1120 system_4_type_arg, null);
1122 if (set_corlib_type_builders != null) {
1123 object[] args = new object [4];
1124 args [0] = object_type;
1125 args [1] = value_type;
1126 args [2] = enum_type;
1127 args [3] = void_type;
1129 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1131 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1136 system_string_expr.Type = string_type;
1137 system_boolean_expr.Type = bool_type;
1138 system_decimal_expr.Type = decimal_type;
1139 system_single_expr.Type = float_type;
1140 system_double_expr.Type = double_type;
1141 system_sbyte_expr.Type = sbyte_type;
1142 system_byte_expr.Type = byte_type;
1143 system_int16_expr.Type = short_type;
1144 system_uint16_expr.Type = ushort_type;
1145 system_int32_expr.Type = int32_type;
1146 system_uint32_expr.Type = uint32_type;
1147 system_int64_expr.Type = int64_type;
1148 system_uint64_expr.Type = uint64_type;
1149 system_char_expr.Type = char_type;
1150 system_void_expr.Type = void_type;
1151 system_asynccallback_expr.Type = asynccallback_type;
1152 system_iasyncresult_expr.Type = iasyncresult_type;
1155 // These are only used for compare purposes
1157 anonymous_method_type = typeof (AnonymousMethod);
1158 null_type = typeof (NullType);
1162 // The helper methods that are used by the compiler
1164 public static void InitCodeHelpers ()
1167 // Now load the default methods that we use.
1169 Type [] string_ = { string_type };
1170 string_isinterned_string = GetCoreMethod (
1171 string_type, "IsInterned", string_);
1173 Type [] runtime_type_handle = { runtime_handle_type };
1174 system_type_get_type_from_handle = GetCoreMethod (
1175 type_type, "GetTypeFromHandle", runtime_type_handle);
1177 Type [] delegate_delegate = { delegate_type, delegate_type };
1178 delegate_combine_delegate_delegate = GetCoreMethod (
1179 delegate_type, "Combine", delegate_delegate);
1181 delegate_remove_delegate_delegate = GetCoreMethod (
1182 delegate_type, "Remove", delegate_delegate);
1187 ienumerator_getcurrent = GetCoreProperty (
1188 ienumerator_type, "Current");
1189 bool_movenext_void = GetCoreMethod (
1190 ienumerator_type, "MoveNext", Type.EmptyTypes);
1191 void_reset_void = GetCoreMethod (
1192 ienumerator_type, "Reset", Type.EmptyTypes);
1193 void_dispose_void = GetCoreMethod (
1194 idisposable_type, "Dispose", Type.EmptyTypes);
1195 int_get_offset_to_string_data = GetCoreMethod (
1196 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1197 int_array_get_length = GetCoreMethod (
1198 array_type, "get_Length", Type.EmptyTypes);
1199 int_array_get_rank = GetCoreMethod (
1200 array_type, "get_Rank", Type.EmptyTypes);
1201 ienumerable_getenumerator_void = GetCoreMethod (
1202 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1207 Type [] int_arg = { int32_type };
1208 int_array_get_length_int = GetCoreMethod (
1209 array_type, "GetLength", int_arg);
1210 int_array_get_upper_bound_int = GetCoreMethod (
1211 array_type, "GetUpperBound", int_arg);
1212 int_array_get_lower_bound_int = GetCoreMethod (
1213 array_type, "GetLowerBound", int_arg);
1216 // System.Array methods
1218 object_array_clone = GetCoreMethod (
1219 array_type, "Clone", Type.EmptyTypes);
1220 Type [] array_int_arg = { array_type, int32_type };
1221 void_array_copyto_array_int = GetCoreMethod (
1222 array_type, "CopyTo", array_int_arg);
1227 Type [] object_arg = { object_type };
1228 void_monitor_enter_object = GetCoreMethod (
1229 monitor_type, "Enter", object_arg);
1230 void_monitor_exit_object = GetCoreMethod (
1231 monitor_type, "Exit", object_arg);
1233 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1235 void_initializearray_array_fieldhandle = GetCoreMethod (
1236 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1241 int_getlength_int = GetCoreMethod (
1242 array_type, "GetLength", int_arg);
1245 // Decimal constructors
1247 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1248 void_decimal_ctor_five_args = GetCoreConstructor (
1249 decimal_type, dec_arg);
1251 void_decimal_ctor_int_arg = GetCoreConstructor (decimal_type, int_arg);
1256 unverifiable_code_ctor = GetCoreConstructor (unverifiable_code_type, Type.EmptyTypes);
1257 default_member_ctor = GetCoreConstructor (default_member_type, string_);
1258 cons_param_array_attribute = GetCoreConstructor (param_array_type, Type.EmptyTypes);
1260 Type[] short_arg = { short_type };
1261 // fails for .net 2.1
1262 struct_layout_attribute_ctor = GetCoreConstructor (struct_layout_attribute_type, short_arg, false);
1264 decimal_constant_attribute_ctor = GetCoreConstructor (decimal_constant_attribute_type, new Type []
1265 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1267 field_offset_attribute_ctor = GetCoreConstructor (field_offset_attribute_type, new Type []
1271 // System.Threading.CompareExchange
1273 Type[] compare_exchange_types = {
1274 GetReferenceType (int32_type), int32_type, int32_type };
1275 int_interlocked_compare_exchange = GetCoreMethod (
1276 interlocked_type, "CompareExchange", compare_exchange_types);
1282 compiler_generated_attr = new CustomAttributeBuilder (
1283 GetCoreConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1285 Type[] type_int_arg = { type_type, int32_type };
1286 fixed_buffer_attr_ctor = GetCoreConstructor (fixed_buffer_attr_type, type_int_arg);
1293 object_ctor = GetCoreConstructor (object_type, Type.EmptyTypes);
1296 InitGenericCodeHelpers ();
1301 static void InitSystemCore ()
1303 if (RootContext.Version != LanguageVersion.LINQ)
1306 if (extension_attribute_type != null)
1307 extension_attribute_attr = new CustomAttributeBuilder (
1308 GetCoreConstructor (extension_attribute_type, Type.EmptyTypes), new object[0]);
1312 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1315 /// This is the "old", non-cache based FindMembers() function. We cannot use
1316 /// the cache here because there is no member name argument.
1318 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1319 MemberFilter filter, object criteria)
1321 #if MS_COMPATIBLE && GMCS_SOURCE
1322 if (t.IsGenericType)
1323 t = t.GetGenericTypeDefinition ();
1326 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1329 // `builder_to_declspace' contains all dynamic types.
1333 Timer.StartTimer (TimerType.FindMembers);
1334 list = decl.FindMembers (mt, bf, filter, criteria);
1335 Timer.StopTimer (TimerType.FindMembers);
1340 // We have to take care of arrays specially, because GetType on
1341 // a TypeBuilder array will return a Type, not a TypeBuilder,
1342 // and we can not call FindMembers on this type.
1345 #if MS_COMPATIBLE && GMCS_SOURCE
1348 t.IsSubclassOf (TypeManager.array_type))
1349 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1352 if (t is GenericTypeParameterBuilder) {
1353 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1355 Timer.StartTimer (TimerType.FindMembers);
1356 MemberList list = tparam.FindMembers (
1357 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1358 Timer.StopTimer (TimerType.FindMembers);
1364 // Since FindMembers will not lookup both static and instance
1365 // members, we emulate this behaviour here.
1367 if ((bf & instance_and_static) == instance_and_static){
1368 MemberInfo [] i_members = t.FindMembers (
1369 mt, bf & ~BindingFlags.Static, filter, criteria);
1371 int i_len = i_members.Length;
1373 MemberInfo one = i_members [0];
1376 // If any of these are present, we are done!
1378 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1379 return new MemberList (i_members);
1382 MemberInfo [] s_members = t.FindMembers (
1383 mt, bf & ~BindingFlags.Instance, filter, criteria);
1385 int s_len = s_members.Length;
1386 if (i_len > 0 || s_len > 0)
1387 return new MemberList (i_members, s_members);
1390 return new MemberList (i_members);
1392 return new MemberList (s_members);
1396 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1401 /// This method is only called from within MemberLookup. It tries to use the member
1402 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1403 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1404 /// our return value will already contain all inherited members and the caller don't need
1405 /// to check base classes and interfaces anymore.
1407 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1408 string name, out bool used_cache)
1413 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1414 // and we can ask the DeclSpace for the MemberCache.
1417 if (t.Assembly == CodeGen.Assembly.Builder) {
1418 if (t.IsGenericParameter) {
1419 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1422 if (tparam.MemberCache == null)
1423 return new MemberInfo[0];
1425 return tparam.MemberCache.FindMembers (
1426 mt, bf, name, FilterWithClosure_delegate, null);
1429 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1430 t = t.GetGenericTypeDefinition ();
1432 if (t is TypeBuilder) {
1434 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1435 cache = decl.MemberCache;
1438 // If this DeclSpace has a MemberCache, use it.
1441 if (cache != null) {
1443 return cache.FindMembers (
1444 mt, bf, name, FilterWithClosure_delegate, null);
1447 // If there is no MemberCache, we need to use the "normal" FindMembers.
1448 // Note, this is a VERY uncommon route!
1451 Timer.StartTimer (TimerType.FindMembers);
1452 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1453 FilterWithClosure_delegate, name);
1454 Timer.StopTimer (TimerType.FindMembers);
1456 return (MemberInfo []) list;
1460 // We have to take care of arrays specially, because GetType on
1461 // a TypeBuilder array will return a Type, not a TypeBuilder,
1462 // and we can not call FindMembers on this type.
1466 return TypeHandle.ArrayType.MemberCache.FindMembers (
1467 mt, bf, name, FilterWithClosure_delegate, null);
1471 if (t is GenericTypeParameterBuilder) {
1472 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1475 if (tparam.MemberCache == null)
1476 return new MemberInfo [0];
1478 return tparam.MemberCache.FindMembers (
1479 mt, bf, name, FilterWithClosure_delegate, null);
1483 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1485 // This happens if we're resolving a class'es base class and interfaces
1486 // in TypeContainer.DefineType(). At this time, the types aren't
1487 // populated yet, so we can't use the cache.
1489 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1490 FilterWithClosure_delegate, name);
1496 // This call will always succeed. There is exactly one TypeHandle instance per
1497 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1498 // the corresponding MemberCache.
1500 cache = TypeHandle.GetMemberCache (t);
1503 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1506 public static bool IsBuiltinType (Type t)
1508 t = TypeToCoreType (t);
1509 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1510 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1511 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1512 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1518 public static bool IsBuiltinType (TypeContainer tc)
1520 return IsBuiltinType (tc.TypeBuilder);
1524 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1525 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1527 public static bool IsPrimitiveType (Type t)
1529 return (t == int32_type || t == uint32_type ||
1530 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1531 t == char_type || t == short_type || t == bool_type ||
1532 t == sbyte_type || t == byte_type || t == ushort_type);
1535 public static bool IsDelegateType (Type t)
1538 if (t.IsGenericParameter)
1542 if (t == TypeManager.delegate_type)
1545 t = DropGenericTypeArguments (t);
1546 return IsSubclassOf (t, TypeManager.delegate_type);
1549 public static bool IsEnumType (Type t)
1551 t = DropGenericTypeArguments (t);
1552 if (builder_to_declspace [t] is Enum)
1555 #if MS_COMPATIBLE && GMCS_SOURCE
1556 if (t.IsGenericParameter || t.IsGenericType)
1562 public static bool IsBuiltinOrEnum (Type t)
1564 if (IsBuiltinType (t))
1573 public static bool IsNullType (Type t)
1575 return t == null_type;
1578 public static bool IsAttributeType (Type t)
1580 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1583 static Stack unmanaged_enclosing_types = new Stack (4);
1586 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1588 public static bool IsUnmanagedType (Type t)
1590 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1591 if (unmanaged_enclosing_types.Contains (t))
1594 // builtins that are not unmanaged types
1595 if (t == TypeManager.object_type || t == TypeManager.string_type)
1598 if (IsGenericType (t) || IsGenericParameter (t))
1601 if (IsBuiltinOrEnum (t))
1604 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1608 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1612 if (!IsValueType (t))
1616 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1617 if (p.IsGenericTypeDefinition)
1622 unmanaged_enclosing_types.Push (t);
1626 if (t is TypeBuilder) {
1627 TypeContainer tc = LookupTypeContainer (t);
1628 if (tc.Fields != null){
1629 foreach (FieldBase f in tc.Fields){
1630 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1631 if ((f.ModFlags & Modifiers.STATIC) != 0)
1633 if (f.MemberType == null)
1635 if (!IsUnmanagedType (f.MemberType)){
1636 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1642 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1644 foreach (FieldInfo f in fields){
1645 if (!IsUnmanagedType (f.FieldType)){
1646 Report.SymbolRelatedToPreviousError (f);
1652 unmanaged_enclosing_types.Pop ();
1657 public static bool IsReferenceType (Type t)
1659 if (TypeManager.IsGenericParameter (t)) {
1660 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1661 if (constraints == null)
1664 return constraints.IsReferenceType;
1667 if (t == TypeManager.null_type)
1670 return !t.IsValueType;
1673 public static bool IsValueType (Type t)
1675 return t.IsValueType || IsGenericParameter (t);
1678 public static bool IsInterfaceType (Type t)
1680 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1684 return tc.Kind == Kind.Interface;
1687 public static bool IsSubclassOf (Type type, Type base_type)
1689 TypeParameter tparam = LookupTypeParameter (type);
1690 TypeParameter pparam = LookupTypeParameter (base_type);
1692 if ((tparam != null) && (pparam != null)) {
1693 if (tparam == pparam)
1696 return tparam.IsSubclassOf (base_type);
1699 #if MS_COMPATIBLE && GMCS_SOURCE
1700 if (type.IsGenericType)
1701 type = type.GetGenericTypeDefinition ();
1704 if (type.IsSubclassOf (base_type))
1708 if (IsEqual (type, base_type))
1711 type = type.BaseType;
1712 } while (type != null);
1717 public static bool IsPrivateAccessible (Type type, Type parent)
1722 if (type.Equals (parent))
1725 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1728 public static bool IsFamilyAccessible (Type type, Type parent)
1730 TypeParameter tparam = LookupTypeParameter (type);
1731 TypeParameter pparam = LookupTypeParameter (parent);
1733 if ((tparam != null) && (pparam != null)) {
1734 if (tparam == pparam)
1737 return tparam.IsSubclassOf (parent);
1741 if (IsInstantiationOfSameGenericType (type, parent))
1744 type = type.BaseType;
1745 } while (type != null);
1751 // Checks whether `type' is a subclass or nested child of `base_type'.
1753 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1756 if (IsFamilyAccessible (type, base_type))
1759 // Handle nested types.
1760 type = type.DeclaringType;
1761 } while (type != null);
1767 // Checks whether `type' is a nested child of `parent'.
1769 public static bool IsNestedChildOf (Type type, Type parent)
1774 type = DropGenericTypeArguments (type);
1775 parent = DropGenericTypeArguments (parent);
1777 if (IsEqual (type, parent))
1780 type = type.DeclaringType;
1781 while (type != null) {
1782 if (IsEqual (type, parent))
1785 type = type.DeclaringType;
1793 // Checks whether `extern_type' is friend of the output assembly
1795 public static bool IsFriendAssembly (Assembly assembly)
1797 // FIXME: This should not be reached
1798 if (assembly == CodeGen.Assembly.Builder)
1801 if (assembly_internals_vis_attrs.Contains (assembly))
1802 return (bool)(assembly_internals_vis_attrs [assembly]);
1804 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1805 if (attrs.Length == 0) {
1806 assembly_internals_vis_attrs.Add (assembly, false);
1810 AssemblyName this_name = CodeGen.Assembly.Name;
1811 byte [] this_token = this_name.GetPublicKeyToken ();
1812 bool is_friend = false;
1813 foreach (InternalsVisibleToAttribute attr in attrs) {
1814 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1817 AssemblyName aname = null;
1819 aname = new AssemblyName (attr.AssemblyName);
1820 } catch (FileLoadException) {
1821 } catch (ArgumentException) {
1824 if (aname == null || aname.Name != this_name.Name)
1827 byte [] key_token = aname.GetPublicKeyToken ();
1828 if (key_token != null) {
1829 if (this_token.Length == 0) {
1830 // Same name, but assembly is not strongnamed
1831 Error_FriendAccessNameNotMatching (aname.FullName);
1835 if (!CompareKeyTokens (this_token, key_token))
1843 assembly_internals_vis_attrs.Add (assembly, is_friend);
1847 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1849 for (int i = 0; i < token1.Length; i++)
1850 if (token1 [i] != token2 [i])
1856 static void Error_FriendAccessNameNotMatching (string other_name)
1858 Report.Error (281, "Friend access was granted to `" + other_name +
1859 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1860 "'. Try adding a reference to `" + other_name +
1861 "' or change the output assembly name to match it");
1864 public static bool IsFriendAssembly (Assembly assembly)
1871 // Do the right thing when returning the element type of an
1872 // array type based on whether we are compiling corlib or not
1874 public static Type GetElementType (Type t)
1876 if (RootContext.StdLib)
1877 return t.GetElementType ();
1879 return TypeToCoreType (t.GetElementType ());
1883 /// This method is not implemented by MS runtime for dynamic types
1885 public static bool HasElementType (Type t)
1887 return t.IsArray || t.IsPointer || t.IsByRef;
1891 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1895 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1896 /// for anything which is dynamic, and we need this in a number of places,
1897 /// we register this information here, and use it afterwards.
1899 static public void RegisterMethod (MethodBase mb, Parameters ip)
1901 method_params.Add (mb, ip);
1904 static public ParameterData GetParameterData (MethodBase mb)
1906 ParameterData pd = (ParameterData)method_params [mb];
1909 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1910 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1911 pd = GetParameterData (mi);
1912 if (mi.IsGenericMethod)
1913 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1915 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1916 method_params.Add (mb, pd);
1920 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1921 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1922 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1925 pd = new ReflectionParameters (mb);
1926 method_params.Add (mb, pd);
1931 public static ParameterData GetDelegateParameters (Type t)
1933 Delegate d = builder_to_declspace [t] as Delegate;
1935 return d.Parameters;
1937 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1938 return GetParameterData (invoke_mb);
1941 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1943 if (!method_overrides.Contains (override_method))
1944 method_overrides [override_method] = base_method;
1945 if (method_overrides [override_method] != base_method)
1946 throw new InternalErrorException ("Override mismatch: " + override_method);
1949 static public bool IsOverride (MethodBase m)
1951 m = DropGenericMethodArguments (m);
1953 return m.IsVirtual &&
1954 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1955 (m is MethodBuilder || method_overrides.Contains (m));
1958 static public MethodBase TryGetBaseDefinition (MethodBase m)
1960 m = DropGenericMethodArguments (m);
1962 return (MethodBase) method_overrides [m];
1966 /// Returns the argument types for an indexer based on its PropertyInfo
1968 /// For dynamic indexers, we use the compiler provided types, for
1969 /// indexers from existing assemblies we load them from GetParameters,
1970 /// and insert them into the cache
1972 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1974 if (indexer_arguments.Contains (indexer))
1975 return (Type []) indexer_arguments [indexer];
1976 else if (indexer is PropertyBuilder)
1977 // If we're a PropertyBuilder and not in the
1978 // `indexer_arguments' hash, then we're a property and
1980 return Type.EmptyTypes;
1982 ParameterInfo [] pi = indexer.GetIndexParameters ();
1983 // Property, not an indexer.
1985 return Type.EmptyTypes;
1987 Type [] types = new Type [c];
1989 for (int i = 0; i < c; i++)
1990 types [i] = pi [i].ParameterType;
1992 indexer_arguments.Add (indexer, types);
1997 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1999 fields.Add (fb, ic);
2002 public static IConstant GetConstant (FieldInfo fb)
2007 return (IConstant)fields [fb];
2010 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
2012 propertybuilder_to_property.Add (pi, pb);
2015 public static PropertyBase GetProperty (PropertyInfo pi)
2017 return (PropertyBase)propertybuilder_to_property [pi];
2020 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
2022 fieldbuilders_to_fields.Add (fb, f);
2026 // The return value can be null; This will be the case for
2027 // auxiliary FieldBuilders created by the compiler that have no
2028 // real field being declared on the source code
2030 static public FieldBase GetField (FieldInfo fb)
2033 fb = GetGenericFieldDefinition (fb);
2035 return (FieldBase) fieldbuilders_to_fields [fb];
2038 static public MethodInfo GetAddMethod (EventInfo ei)
2040 if (ei is MyEventBuilder) {
2041 return ((MyEventBuilder)ei).GetAddMethod (true);
2043 return ei.GetAddMethod (true);
2046 static public MethodInfo GetRemoveMethod (EventInfo ei)
2048 if (ei is MyEventBuilder) {
2049 return ((MyEventBuilder)ei).GetRemoveMethod (true);
2051 return ei.GetRemoveMethod (true);
2054 static public void RegisterEventField (EventInfo einfo, EventField e)
2057 events = new Hashtable ();
2059 events.Add (einfo, e);
2062 static public EventField GetEventField (EventInfo ei)
2067 return (EventField) events [ei];
2070 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2071 MethodBase set, Type[] args)
2073 indexer_arguments.Add (pb, args);
2078 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2080 Hashtable hash = new Hashtable ();
2081 return CheckStructCycles (tc, seen, hash);
2084 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2087 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2091 // `seen' contains all types we've already visited.
2093 if (seen.Contains (tc))
2095 seen.Add (tc, null);
2097 if (tc.Fields == null)
2100 foreach (FieldBase field in tc.Fields) {
2101 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2104 Type ftype = field.FieldBuilder.FieldType;
2105 TypeContainer ftc = LookupTypeContainer (ftype);
2109 if (hash.Contains (ftc)) {
2110 Report.Error (523, tc.Location,
2111 "Struct member `{0}.{1}' of type `{2}' " +
2112 "causes a cycle in the struct layout",
2113 tc.Name, field.Name, ftc.Name);
2118 // `hash' contains all types in the current path.
2120 hash.Add (tc, null);
2122 bool ok = CheckStructCycles (ftc, seen, hash);
2129 if (!seen.Contains (ftc))
2130 seen.Add (ftc, null);
2137 /// Given an array of interface types, expand and eliminate repeated ocurrences
2138 /// of an interface.
2142 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2145 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2147 ArrayList new_ifaces = new ArrayList ();
2149 foreach (TypeExpr iface in base_interfaces){
2150 Type itype = iface.Type;
2152 if (new_ifaces.Contains (itype))
2155 new_ifaces.Add (itype);
2157 Type [] implementing = GetInterfaces (itype);
2159 foreach (Type imp in implementing){
2160 if (!new_ifaces.Contains (imp))
2161 new_ifaces.Add (imp);
2164 Type [] ret = new Type [new_ifaces.Count];
2165 new_ifaces.CopyTo (ret, 0);
2169 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2171 ArrayList new_ifaces = new ArrayList ();
2173 foreach (Type itype in base_interfaces){
2174 if (new_ifaces.Contains (itype))
2177 new_ifaces.Add (itype);
2179 Type [] implementing = GetInterfaces (itype);
2181 foreach (Type imp in implementing){
2182 if (!new_ifaces.Contains (imp))
2183 new_ifaces.Add (imp);
2186 Type [] ret = new Type [new_ifaces.Count];
2187 new_ifaces.CopyTo (ret, 0);
2191 static PtrHashtable iface_cache = new PtrHashtable ();
2194 /// This function returns the interfaces in the type `t'. Works with
2195 /// both types and TypeBuilders.
2197 public static Type [] GetInterfaces (Type t)
2199 Type [] cached = iface_cache [t] as Type [];
2204 // The reason for catching the Array case is that Reflection.Emit
2205 // will not return a TypeBuilder for Array types of TypeBuilder types,
2206 // but will still throw an exception if we try to call GetInterfaces
2209 // Since the array interfaces are always constant, we return those for
2214 t = TypeManager.array_type;
2216 if ((t is TypeBuilder) || IsGenericType (t)) {
2217 Type [] base_ifaces;
2219 if (t.BaseType == null)
2220 base_ifaces = Type.EmptyTypes;
2222 base_ifaces = GetInterfaces (t.BaseType);
2224 if (IsGenericType (t))
2225 #if MS_COMPATIBLE && GMCS_SOURCE
2226 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2228 type_ifaces = t.GetInterfaces ();
2231 type_ifaces = (Type []) builder_to_ifaces [t];
2232 if (type_ifaces == null || type_ifaces.Length == 0)
2233 type_ifaces = Type.EmptyTypes;
2235 int base_count = base_ifaces.Length;
2236 Type [] result = new Type [base_count + type_ifaces.Length];
2237 base_ifaces.CopyTo (result, 0);
2238 type_ifaces.CopyTo (result, base_count);
2240 iface_cache [t] = result;
2243 } else if (t is GenericTypeParameterBuilder){
2244 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2245 if (type_ifaces == null || type_ifaces.Length == 0)
2246 type_ifaces = Type.EmptyTypes;
2248 iface_cache [t] = type_ifaces;
2252 Type[] ifaces = t.GetInterfaces ();
2253 iface_cache [t] = ifaces;
2259 // gets the interfaces that are declared explicitly on t
2261 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2263 return (Type []) builder_to_ifaces [t];
2267 /// The following is used to check if a given type implements an interface.
2268 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2270 public static bool ImplementsInterface (Type t, Type iface)
2275 // FIXME OPTIMIZATION:
2276 // as soon as we hit a non-TypeBuiler in the interface
2277 // chain, we could return, as the `Type.GetInterfaces'
2278 // will return all the interfaces implement by the type
2282 interfaces = GetInterfaces (t);
2284 if (interfaces != null){
2285 foreach (Type i in interfaces){
2292 } while (t != null);
2297 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2299 // This is a custom version of Convert.ChangeType() which works
2300 // with the TypeBuilder defined types when compiling corlib.
2301 public static object ChangeType (object value, Type conversionType, out bool error)
2303 IConvertible convert_value = value as IConvertible;
2305 if (convert_value == null){
2312 // We must use Type.Equals() here since `conversionType' is
2313 // the TypeBuilder created version of a system type and not
2314 // the system type itself. You cannot use Type.GetTypeCode()
2315 // on such a type - it'd always return TypeCode.Object.
2318 // We cannot rely on build-in type conversions as they are
2319 // more limited than what C# supports.
2320 // See char -> float/decimal/double conversion
2325 if (conversionType.Equals (typeof (Boolean)))
2326 return (object)(convert_value.ToBoolean (nf_provider));
2327 if (conversionType.Equals (typeof (Byte)))
2328 return (object)(convert_value.ToByte (nf_provider));
2329 if (conversionType.Equals (typeof (Char)))
2330 return (object)(convert_value.ToChar (nf_provider));
2331 if (conversionType.Equals (typeof (DateTime)))
2332 return (object)(convert_value.ToDateTime (nf_provider));
2334 if (conversionType.Equals (TypeManager.decimal_type)) {
2335 if (convert_value.GetType () == TypeManager.char_type)
2336 return (decimal)convert_value.ToInt32 (nf_provider);
2337 return convert_value.ToDecimal (nf_provider);
2340 if (conversionType.Equals (typeof (Double))) {
2341 if (convert_value.GetType () == TypeManager.char_type)
2342 return (double)convert_value.ToInt32 (nf_provider);
2343 return convert_value.ToDouble (nf_provider);
2346 if (conversionType.Equals (typeof (Int16)))
2347 return (object)(convert_value.ToInt16 (nf_provider));
2348 if (conversionType.Equals (typeof (Int32)))
2349 return (object)(convert_value.ToInt32 (nf_provider));
2350 if (conversionType.Equals (typeof (Int64)))
2351 return (object)(convert_value.ToInt64 (nf_provider));
2352 if (conversionType.Equals (typeof (SByte)))
2353 return (object)(convert_value.ToSByte (nf_provider));
2355 if (conversionType.Equals (typeof (Single))) {
2356 if (convert_value.GetType () == TypeManager.char_type)
2357 return (float)convert_value.ToInt32 (nf_provider);
2358 return convert_value.ToSingle (nf_provider);
2361 if (conversionType.Equals (typeof (String)))
2362 return (object)(convert_value.ToString (nf_provider));
2363 if (conversionType.Equals (typeof (UInt16)))
2364 return (object)(convert_value.ToUInt16 (nf_provider));
2365 if (conversionType.Equals (typeof (UInt32)))
2366 return (object)(convert_value.ToUInt32 (nf_provider));
2367 if (conversionType.Equals (typeof (UInt64)))
2368 return (object)(convert_value.ToUInt64 (nf_provider));
2369 if (conversionType.Equals (typeof (Object)))
2370 return (object)(value);
2380 // This is needed, because enumerations from assemblies
2381 // do not report their underlyingtype, but they report
2384 public static Type EnumToUnderlying (Type t)
2386 t = DropGenericTypeArguments (t);
2387 if (t == TypeManager.enum_type)
2390 t = t.UnderlyingSystemType;
2391 if (!TypeManager.IsEnumType (t))
2394 if (t is TypeBuilder) {
2395 // slow path needed to compile corlib
2396 if (t == TypeManager.bool_type ||
2397 t == TypeManager.byte_type ||
2398 t == TypeManager.sbyte_type ||
2399 t == TypeManager.char_type ||
2400 t == TypeManager.short_type ||
2401 t == TypeManager.ushort_type ||
2402 t == TypeManager.int32_type ||
2403 t == TypeManager.uint32_type ||
2404 t == TypeManager.int64_type ||
2405 t == TypeManager.uint64_type)
2408 TypeCode tc = Type.GetTypeCode (t);
2411 case TypeCode.Boolean:
2412 return TypeManager.bool_type;
2414 return TypeManager.byte_type;
2415 case TypeCode.SByte:
2416 return TypeManager.sbyte_type;
2418 return TypeManager.char_type;
2419 case TypeCode.Int16:
2420 return TypeManager.short_type;
2421 case TypeCode.UInt16:
2422 return TypeManager.ushort_type;
2423 case TypeCode.Int32:
2424 return TypeManager.int32_type;
2425 case TypeCode.UInt32:
2426 return TypeManager.uint32_type;
2427 case TypeCode.Int64:
2428 return TypeManager.int64_type;
2429 case TypeCode.UInt64:
2430 return TypeManager.uint64_type;
2432 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2436 // When compiling corlib and called with one of the core types, return
2437 // the corresponding typebuilder for that type.
2439 public static Type TypeToCoreType (Type t)
2441 if (RootContext.StdLib || (t is TypeBuilder))
2444 TypeCode tc = Type.GetTypeCode (t);
2447 case TypeCode.Boolean:
2448 return TypeManager.bool_type;
2450 return TypeManager.byte_type;
2451 case TypeCode.SByte:
2452 return TypeManager.sbyte_type;
2454 return TypeManager.char_type;
2455 case TypeCode.Int16:
2456 return TypeManager.short_type;
2457 case TypeCode.UInt16:
2458 return TypeManager.ushort_type;
2459 case TypeCode.Int32:
2460 return TypeManager.int32_type;
2461 case TypeCode.UInt32:
2462 return TypeManager.uint32_type;
2463 case TypeCode.Int64:
2464 return TypeManager.int64_type;
2465 case TypeCode.UInt64:
2466 return TypeManager.uint64_type;
2467 case TypeCode.Single:
2468 return TypeManager.float_type;
2469 case TypeCode.Double:
2470 return TypeManager.double_type;
2471 case TypeCode.String:
2472 return TypeManager.string_type;
2473 case TypeCode.Decimal:
2474 return TypeManager.decimal_type;
2476 if (t == typeof (void))
2477 return TypeManager.void_type;
2478 if (t == typeof (object))
2479 return TypeManager.object_type;
2480 if (t == typeof (System.Type))
2481 return TypeManager.type_type;
2482 if (t == typeof (System.IntPtr))
2483 return TypeManager.intptr_type;
2489 /// Utility function that can be used to probe whether a type
2490 /// is managed or not.
2492 public static bool VerifyUnManaged (Type t, Location loc)
2494 if (IsUnmanagedType (t))
2497 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2504 /// Returns the name of the indexer in a given type.
2507 /// The default is not always `Item'. The user can change this behaviour by
2508 /// using the IndexerNameAttribute in the container.
2509 /// For example, the String class indexer is named `Chars' not `Item'
2511 public static string IndexerPropertyName (Type t)
2513 t = DropGenericTypeArguments (t);
2514 if (t is TypeBuilder) {
2515 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2516 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2519 System.Attribute attr = System.Attribute.GetCustomAttribute (
2520 t, TypeManager.default_member_type);
2522 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2523 return dma.MemberName;
2526 return TypeContainer.DefaultIndexerName;
2529 static MethodInfo declare_local_method = null;
2531 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2533 if (declare_local_method == null){
2534 declare_local_method = typeof (ILGenerator).GetMethod (
2536 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2538 new Type [] { typeof (Type), typeof (bool)},
2540 if (declare_local_method == null){
2541 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2542 return ig.DeclareLocal (t);
2545 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2548 private static bool IsSignatureEqual (Type a, Type b)
2551 /// Consider the following example (bug #77674):
2553 /// public abstract class A
2555 /// public abstract T Foo<T> ();
2558 /// public abstract class B : A
2560 /// public override U Foo<T> ()
2561 /// { return default (U); }
2564 /// Here, `T' and `U' are method type parameters from different methods
2565 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2567 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2568 /// we need to do a signature based comparision and consider them equal.
2574 if (a.IsGenericParameter && b.IsGenericParameter &&
2575 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2576 return a.GenericParameterPosition == b.GenericParameterPosition;
2580 if (a.IsArray && b.IsArray) {
2581 if (a.GetArrayRank () != b.GetArrayRank ())
2584 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2587 if (a.IsByRef && b.IsByRef)
2588 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2591 if (a.IsGenericType && b.IsGenericType) {
2592 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2595 Type[] aargs = a.GetGenericArguments ();
2596 Type[] bargs = b.GetGenericArguments ();
2598 if (aargs.Length != bargs.Length)
2601 for (int i = 0; i < aargs.Length; i++) {
2602 if (!IsSignatureEqual (aargs [i], bargs [i]))
2614 // Returns whether the array of memberinfos contains the given method
2616 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2618 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2620 foreach (MethodBase method in array) {
2621 if (method.Name != new_method.Name)
2624 if (method is MethodInfo && new_method is MethodInfo)
2625 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2626 ((MethodInfo) new_method).ReturnType))
2630 Type [] old_args = TypeManager.GetParameterData (method).Types;
2631 int old_count = old_args.Length;
2634 if (new_args.Length != old_count)
2637 for (i = 0; i < old_count; i++){
2638 if (!IsSignatureEqual (old_args [i], new_args [i]))
2651 // We copy methods from `new_members' into `target_list' if the signature
2652 // for the method from in the new list does not exist in the target_list
2654 // The name is assumed to be the same.
2656 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2658 if (target_list == null){
2659 target_list = new ArrayList ();
2661 foreach (MemberInfo mi in new_members){
2662 if (mi is MethodBase)
2663 target_list.Add (mi);
2668 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2669 target_list.CopyTo (target_array, 0);
2671 foreach (MemberInfo mi in new_members){
2672 MethodBase new_method = (MethodBase) mi;
2674 if (!ArrayContainsMethod (target_array, new_method))
2675 target_list.Add (new_method);
2682 // Tracks the generic parameters.
2684 static PtrHashtable builder_to_type_param;
2686 public static void AddTypeParameter (Type t, TypeParameter tparam)
2688 if (!builder_to_type_param.Contains (t))
2689 builder_to_type_param.Add (t, tparam);
2692 public static TypeParameter LookupTypeParameter (Type t)
2694 return (TypeParameter) builder_to_type_param [t];
2697 // This method always return false for non-generic compiler,
2698 // while Type.IsGenericParameter is returned if it is supported.
2699 public static bool IsGenericParameter (Type type)
2702 return type.IsGenericParameter;
2708 public static int GenericParameterPosition (Type type)
2711 return type.GenericParameterPosition;
2713 throw new InternalErrorException ("should not be called");
2717 public static bool IsGenericType (Type type)
2720 return type.IsGenericType;
2726 public static bool IsGenericTypeDefinition (Type type)
2729 return type.IsGenericTypeDefinition;
2735 public static bool ContainsGenericParameters (Type type)
2738 return type.ContainsGenericParameters;
2744 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2747 if (fi.DeclaringType.IsGenericTypeDefinition ||
2748 !fi.DeclaringType.IsGenericType)
2751 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2752 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2753 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2755 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2756 foreach (FieldInfo f in t.GetFields (bf))
2757 if (f.MetadataToken == fi.MetadataToken)
2764 public static bool IsEqual (Type a, Type b)
2767 // MS BCL returns true even if enum types are different
2768 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2769 return a.FullName == b.FullName;
2775 if (a.IsGenericParameter && b.IsGenericParameter) {
2776 // TODO: needs more testing before cleaning up
2777 //if (a.DeclaringMethod != b.DeclaringMethod &&
2778 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2780 return a.GenericParameterPosition == b.GenericParameterPosition;
2783 if (a.IsArray && b.IsArray) {
2784 if (a.GetArrayRank () != b.GetArrayRank ())
2786 return IsEqual (a.GetElementType (), b.GetElementType ());
2789 if (a.IsByRef && b.IsByRef)
2790 return IsEqual (a.GetElementType (), b.GetElementType ());
2792 if (a.IsGenericType && b.IsGenericType) {
2793 Type adef = a.GetGenericTypeDefinition ();
2794 Type bdef = b.GetGenericTypeDefinition ();
2799 if (adef.IsEnum && bdef.IsEnum)
2802 Type[] aargs = a.GetGenericArguments ();
2803 Type[] bargs = b.GetGenericArguments ();
2805 if (aargs.Length != bargs.Length)
2808 for (int i = 0; i < aargs.Length; i++) {
2809 if (!IsEqual (aargs [i], bargs [i]))
2820 public static Type DropGenericTypeArguments (Type t)
2823 if (!t.IsGenericType)
2825 // Micro-optimization: a generic typebuilder is always a generic type definition
2826 if (t is TypeBuilder)
2828 return t.GetGenericTypeDefinition ();
2834 public static MethodBase DropGenericMethodArguments (MethodBase m)
2837 if (m.IsGenericMethodDefinition)
2839 if (m.IsGenericMethod)
2840 return ((MethodInfo) m).GetGenericMethodDefinition ();
2841 if (!m.DeclaringType.IsGenericType)
2844 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2845 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2846 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2849 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2853 if (m is ConstructorInfo) {
2854 foreach (ConstructorInfo c in t.GetConstructors (bf))
2855 if (c.MetadataToken == m.MetadataToken)
2858 foreach (MethodBase mb in t.GetMethods (bf))
2859 if (mb.MetadataToken == m.MetadataToken)
2867 public static Type[] GetGenericArguments (MethodBase mi)
2870 return mi.GetGenericArguments ();
2872 return Type.EmptyTypes;
2876 public static Type[] GetTypeArguments (Type t)
2879 DeclSpace tc = LookupDeclSpace (t);
2882 return Type.EmptyTypes;
2884 TypeParameter[] tparam = tc.TypeParameters;
2885 Type[] ret = new Type [tparam.Length];
2886 for (int i = 0; i < tparam.Length; i++) {
2887 ret [i] = tparam [i].Type;
2888 if (ret [i] == null)
2889 throw new InternalErrorException ();
2894 return t.GetGenericArguments ();
2896 throw new InternalErrorException ();
2900 public static GenericConstraints GetTypeParameterConstraints (Type t)
2903 if (!t.IsGenericParameter)
2904 throw new InvalidOperationException ();
2906 TypeParameter tparam = LookupTypeParameter (t);
2908 return tparam.GenericConstraints;
2910 return ReflectionConstraints.GetConstraints (t);
2912 throw new InternalErrorException ();
2916 public static bool HasGenericArguments (Type t)
2918 return GetNumberOfTypeArguments (t) > 0;
2921 public static int GetNumberOfTypeArguments (Type t)
2924 if (t.IsGenericParameter)
2926 DeclSpace tc = LookupDeclSpace (t);
2928 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2930 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2937 /// Check whether `type' and `parent' are both instantiations of the same
2938 /// generic type. Note that we do not check the type parameters here.
2940 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2942 int tcount = GetNumberOfTypeArguments (type);
2943 int pcount = GetNumberOfTypeArguments (parent);
2945 if (tcount != pcount)
2948 type = DropGenericTypeArguments (type);
2949 parent = DropGenericTypeArguments (parent);
2951 return type.Equals (parent);
2955 /// Whether `mb' is a generic method definition.
2957 public static bool IsGenericMethodDefinition (MethodBase mb)
2960 if (mb.DeclaringType is TypeBuilder) {
2961 IMethodData method = (IMethodData) builder_to_method [mb];
2965 return method.GenericMethod != null;
2968 return mb.IsGenericMethodDefinition;
2975 /// Whether `mb' is a generic method.
2977 public static bool IsGenericMethod (MethodBase mb)
2980 return mb.IsGenericMethod;
2986 public static bool IsNullableType (Type t)
2989 return generic_nullable_type == DropGenericTypeArguments (t);
2995 public static bool IsNullableTypeOf (Type t, Type nullable)
2998 if (!IsNullableType (t))
3001 return GetTypeArguments (t) [0] == nullable;
3007 public static bool IsNullableValueType (Type t)
3010 if (!IsNullableType (t))
3013 return GetTypeArguments (t) [0].IsValueType;
3020 #region MemberLookup implementation
3023 // Whether we allow private members in the result (since FindMembers
3024 // uses NonPublic for both protected and private), we need to distinguish.
3027 internal class Closure {
3028 internal bool private_ok;
3030 // Who is invoking us and which type is being queried currently.
3031 internal Type invocation_type;
3032 internal Type qualifier_type;
3034 // The assembly that defines the type is that is calling us
3035 internal Assembly invocation_assembly;
3036 internal IList almost_match;
3038 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3040 if (invocation_type == null)
3043 if (is_static && qualifier_type == null)
3044 // It resolved from a simple name, so it should be visible.
3047 if (IsNestedChildOf (invocation_type, m.DeclaringType))
3050 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
3051 if (!IsFamilyAccessible (t, m.DeclaringType))
3054 // Although a derived class can access protected members of its base class
3055 // it cannot do so through an instance of the base class (CS1540).
3056 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3057 if (is_static || qualifier_type == null ||
3058 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3059 IsFamilyAccessible (qualifier_type, t))
3063 if (almost_match != null)
3064 almost_match.Add (m);
3070 // This filter filters by name + whether it is ok to include private
3071 // members in the search
3073 internal bool Filter (MemberInfo m, object filter_criteria)
3076 // Hack: we know that the filter criteria will always be in the
3077 // `closure' // fields.
3080 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3083 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3084 (invocation_type != null) &&
3085 IsPrivateAccessible (m.DeclaringType, invocation_type))
3089 // Ugly: we need to find out the type of `m', and depending
3090 // on this, tell whether we accept or not
3092 if (m is MethodBase){
3093 MethodBase mb = (MethodBase) m;
3094 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3096 if (ma == MethodAttributes.Public)
3099 if (ma == MethodAttributes.PrivateScope)
3102 if (ma == MethodAttributes.Private)
3103 return private_ok ||
3104 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3105 IsNestedChildOf (invocation_type, m.DeclaringType);
3107 if (invocation_assembly == mb.DeclaringType.Assembly ||
3108 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3109 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3112 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3116 // Family, FamORAssem or FamANDAssem
3117 return CheckValidFamilyAccess (mb.IsStatic, m);
3120 if (m is FieldInfo){
3121 FieldInfo fi = (FieldInfo) m;
3122 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3124 if (fa == FieldAttributes.Public)
3127 if (fa == FieldAttributes.PrivateScope)
3130 if (fa == FieldAttributes.Private)
3131 return private_ok ||
3132 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3133 IsNestedChildOf (invocation_type, m.DeclaringType);
3135 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3136 (invocation_assembly == null) ||
3137 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3138 if ((fa == FieldAttributes.Assembly) ||
3139 (fa == FieldAttributes.FamORAssem))
3142 if ((fa == FieldAttributes.Assembly) ||
3143 (fa == FieldAttributes.FamANDAssem))
3147 // Family, FamORAssem or FamANDAssem
3148 return CheckValidFamilyAccess (fi.IsStatic, m);
3152 // EventInfos and PropertyInfos, return true because they lack
3153 // permission information, so we need to check later on the methods.
3159 static Closure closure = new Closure ();
3160 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3163 // Looks up a member called `name' in the `queried_type'. This lookup
3164 // is done by code that is contained in the definition for `invocation_type'
3165 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3167 // `invocation_type' is used to check whether we're allowed to access the requested
3168 // member wrt its protection level.
3170 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3171 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3172 // is B and qualifier_type is A). This is used to do the CS1540 check.
3174 // When resolving a SimpleName, `qualifier_type' is null.
3176 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3177 // the same than `queried_type' - except when we're being called from BaseAccess;
3178 // in this case, `invocation_type' is the current type and `queried_type' the base
3179 // type, so this'd normally trigger a CS1540.
3181 // The binding flags are `bf' and the kind of members being looked up are `mt'
3183 // The return value always includes private members which code in `invocation_type'
3184 // is allowed to access (using the specified `qualifier_type' if given); only use
3185 // BindingFlags.NonPublic to bypass the permission check.
3187 // The 'almost_match' argument is used for reporting error CS1540.
3189 // Returns an array of a single element for everything but Methods/Constructors
3190 // that might return multiple matches.
3192 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3193 Type queried_type, MemberTypes mt,
3194 BindingFlags original_bf, string name, IList almost_match)
3196 Timer.StartTimer (TimerType.MemberLookup);
3198 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3199 queried_type, mt, original_bf, name, almost_match);
3201 Timer.StopTimer (TimerType.MemberLookup);
3206 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3207 Type queried_type, MemberTypes mt,
3208 BindingFlags original_bf, string name, IList almost_match)
3210 BindingFlags bf = original_bf;
3212 ArrayList method_list = null;
3213 Type current_type = queried_type;
3214 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3215 bool skip_iface_check = true, used_cache = false;
3216 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3218 closure.invocation_type = invocation_type;
3219 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3220 closure.qualifier_type = qualifier_type;
3221 closure.almost_match = almost_match;
3223 // This is from the first time we find a method
3224 // in most cases, we do not actually find a method in the base class
3225 // so we can just ignore it, and save the arraylist allocation
3226 MemberInfo [] first_members_list = null;
3227 bool use_first_members_list = false;
3233 // `NonPublic' is lame, because it includes both protected and
3234 // private methods, so we need to control this behavior by
3235 // explicitly tracking if a private method is ok or not.
3237 // The possible cases are:
3238 // public, private and protected (internal does not come into the
3241 if ((invocation_type != null) &&
3242 ((invocation_type == current_type) ||
3243 IsNestedChildOf (invocation_type, current_type)) ||
3245 bf = original_bf | BindingFlags.NonPublic;
3249 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3251 Timer.StopTimer (TimerType.MemberLookup);
3253 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3255 Timer.StartTimer (TimerType.MemberLookup);
3258 // When queried for an interface type, the cache will automatically check all
3259 // inherited members, so we don't need to do this here. However, this only
3260 // works if we already used the cache in the first iteration of this loop.
3262 // If we used the cache in any further iteration, we can still terminate the
3263 // loop since the cache always looks in all base classes.
3269 skip_iface_check = false;
3271 if (current_type == TypeManager.object_type)
3274 current_type = current_type.BaseType;
3277 // This happens with interfaces, they have a null
3278 // basetype. Look members up in the Object class.
3280 if (current_type == null) {
3281 current_type = TypeManager.object_type;
3286 if (list.Length == 0)
3290 // Events and types are returned by both `static' and `instance'
3291 // searches, which means that our above FindMembers will
3292 // return two copies of the same.
3294 if (list.Length == 1 && !(list [0] is MethodBase)){
3299 // Multiple properties: we query those just to find out the indexer
3302 if (list [0] is PropertyInfo)
3306 // We found an event: the cache lookup returns both the event and
3307 // its private field.
3309 if (list [0] is EventInfo) {
3310 if ((list.Length == 2) && (list [1] is FieldInfo))
3311 return new MemberInfo [] { list [0] };
3317 // We found methods, turn the search into "method scan"
3321 if (first_members_list != null) {
3322 if (use_first_members_list) {
3323 method_list = CopyNewMethods (method_list, first_members_list);
3324 use_first_members_list = false;
3327 method_list = CopyNewMethods (method_list, list);
3329 first_members_list = list;
3330 use_first_members_list = true;
3331 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3333 } while (searching);
3335 if (use_first_members_list)
3336 return first_members_list;
3338 if (method_list != null && method_list.Count > 0) {
3339 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3342 // This happens if we already used the cache in the first iteration, in this case
3343 // the cache already looked in all interfaces.
3345 if (skip_iface_check)
3349 // Interfaces do not list members they inherit, so we have to
3352 if (!queried_type.IsInterface)
3355 if (queried_type.IsArray)
3356 queried_type = TypeManager.array_type;
3358 Type [] ifaces = GetInterfaces (queried_type);
3362 foreach (Type itype in ifaces){
3365 x = MemberLookup (null, null, itype, mt, bf, name, null);
3373 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3374 BindingFlags.Static | BindingFlags.Instance |
3375 BindingFlags.DeclaredOnly;
3377 // Currently is designed to work with external types only
3378 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3380 if (!mb.IsSpecialName)
3383 string name = mb.Name;
3384 if (name.Length < 5)
3387 if (name [3] != '_')
3390 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3391 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3392 Type.FilterName, name.Substring (4));
3397 // This can happen when property is indexer (it can have same name but different parameters)
3398 foreach (PropertyInfo p in pi) {
3399 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3400 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3409 // Currently is designed to work with external types only
3410 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3412 if (!mb.IsSpecialName)
3415 string name = mb.Name;
3416 if (name.Length < 5)
3419 if (name.StartsWith ("add_"))
3420 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3422 if (name.StartsWith ("remove_"))
3423 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3428 // Tests whether external method is really special
3429 public static bool IsSpecialMethod (MethodBase mb)
3431 if (!mb.IsSpecialName)
3434 IMethodData md = TypeManager.GetMethod (mb);
3436 return (md is AbstractPropertyEventMethod || md is Operator);
3438 PropertyInfo pi = GetPropertyFromAccessor (mb);
3440 return IsValidProperty (pi);
3442 if (GetEventFromAccessor (mb) != null)
3445 string name = mb.Name;
3446 if (name.StartsWith ("op_")){
3447 foreach (string oname in Unary.oper_names) {
3452 foreach (string oname in Binary.oper_names) {
3460 // Tests whether imported property is valid C# property.
3461 // TODO: It seems to me that we should do a lot of sanity tests before
3462 // we accept property as C# property
3463 static bool IsValidProperty (PropertyInfo pi)
3465 MethodInfo get_method = pi.GetGetMethod (true);
3466 MethodInfo set_method = pi.GetSetMethod (true);
3467 if (get_method != null && set_method != null) {
3468 int g_count = get_method.GetParameters ().Length;
3469 int s_count = set_method.GetParameters ().Length;
3470 if (g_count + 1 != s_count)
3481 /// There is exactly one instance of this class per type.
3483 public sealed class TypeHandle : IMemberContainer {
3484 public readonly IMemberContainer BaseType;
3486 readonly int id = ++next_id;
3487 static int next_id = 0;
3489 static TypeHandle ()
3495 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3496 /// a TypeHandle yet, a new instance of it is created. This static method
3497 /// ensures that we'll only have one TypeHandle instance per type.
3499 private static TypeHandle GetTypeHandle (Type t)
3501 TypeHandle handle = (TypeHandle) type_hash [t];
3505 handle = new TypeHandle (t);
3506 type_hash.Add (t, handle);
3510 public static MemberCache GetMemberCache (Type t)
3512 return GetTypeHandle (t).MemberCache;
3515 public static void CleanUp ()
3520 public static void Reset ()
3522 type_hash = new PtrHashtable ();
3526 /// Returns the TypeHandle for TypeManager.object_type.
3528 public static IMemberContainer ObjectType {
3530 if (object_type != null)
3533 object_type = GetTypeHandle (TypeManager.object_type);
3540 /// Returns the TypeHandle for TypeManager.array_type.
3542 public static TypeHandle ArrayType {
3544 if (array_type != null)
3547 array_type = GetTypeHandle (TypeManager.array_type);
3553 private static PtrHashtable type_hash;
3555 private static TypeHandle object_type = null;
3556 private static TypeHandle array_type = null;
3559 private string full_name;
3560 private bool is_interface;
3561 private MemberCache member_cache;
3562 private MemberCache base_cache;
3564 private TypeHandle (Type type)
3567 full_name = type.FullName != null ? type.FullName : type.Name;
3568 if (type.BaseType != null) {
3569 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3570 BaseType = base_cache.Container;
3571 } else if (type.IsInterface)
3572 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3573 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3574 this.member_cache = new MemberCache (this);
3577 // IMemberContainer methods
3579 public string Name {
3591 public MemberCache BaseCache {
3597 public bool IsInterface {
3599 return is_interface;
3603 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3605 MemberInfo [] members;
3608 if (type is GenericTypeParameterBuilder)
3609 return MemberList.Empty;
3612 if (mt == MemberTypes.Event)
3613 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3615 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3618 if (members.Length == 0)
3619 return MemberList.Empty;
3621 Array.Reverse (members);
3622 return new MemberList (members);
3625 // IMemberFinder methods
3627 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3628 MemberFilter filter, object criteria)
3630 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3633 public MemberCache MemberCache {
3635 return member_cache;
3639 public override string ToString ()
3641 if (BaseType != null)
3642 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3644 return "TypeHandle (" + id + "," + Name + ")";
3649 // Common expressions used by expression trees
3651 static class LinqExpression
3654 // These represent types thare are loaded from System.Core, similar
3655 // in spirit to the TypeManger _type variables.
3657 public static Type expression_type;
3658 public static Type parameter_expression_type;
3661 // The expressions represeing the internal types, if used
3663 public static TypeExpr expression_type_expr;
3665 static LinqExpression ()
3667 expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression");
3668 parameter_expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression");
3670 expression_type_expr = new TypeExpression (expression_type, Location.Null);