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) {
867 if (name == "SetCorlibTypeBuilders")
868 Console.WriteLine ("XX");
872 for (int ii = 0; ii < args.Length; ++ii) {
873 if (!IsEqual (pd.Types [ii], args [ii])) {
874 if (name == "SetCorlibTypeBuilders")
875 Console.WriteLine (pd.Types [ii].FullName);
883 return (MethodInfo) method;
888 Report.Error (-19, "The predefined method `{0}.{1}({2})' could not be found",
889 TypeManager.CSharpName (t), name, TypeManager.CSharpName (args));
894 static MethodInfo GetCoreMethod (Type t, string name, Type [] args, bool report_errors)
896 return GetCoreMethod (t, name, args, false, report_errors);
899 public static MethodInfo GetCoreMethod (Type t, string name, Type [] args)
901 return GetCoreMethod (t, name, args, true);
905 /// Returns the ConstructorInfo for "args"
907 public static ConstructorInfo GetCoreConstructor (Type t, Type [] args)
909 return GetCoreConstructor (t, args, true);
912 public static ConstructorInfo GetCoreConstructor (Type t, Type [] args, bool report_errors)
914 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
916 MemberInfo [] methods = MemberLookup (null, null, t, MemberTypes.Constructor,
917 flags, ConstructorInfo.ConstructorName, null);
919 for (int i = 0; i < methods.Length; ++i) {
920 MethodBase method = (MethodBase) methods [i];
921 ParameterData pd = TypeManager.GetParameterData (method);
922 if (pd.Count != args.Length)
925 for (int ii = 0; ii < args.Length; ++ii) {
926 if (!IsEqual (pd.Types [ii], args [ii])) {
933 return (ConstructorInfo) method;
937 Report.Error (-19, "Can not find the core constructor of type `{0}'",
938 TypeManager.CSharpName (t));
944 /// Returns the PropertyInfo for a property named `name' defined
947 public static PropertyInfo GetCoreProperty (Type t, string name)
949 MemberInfo [] properties = MemberLookup (null, null, t, MemberTypes.Property,
950 BindingFlags.Public | BindingFlags.Instance, name, null);
952 if (properties == null || properties.Length != 1) {
953 Report.Error (-19, "Can not find the core property `" + name + "'");
957 return (PropertyInfo) properties [0];
960 public static void InitEnumUnderlyingTypes ()
962 int32_type = CoreLookupType ("System", "Int32");
963 int64_type = CoreLookupType ("System", "Int64");
964 uint32_type = CoreLookupType ("System", "UInt32");
965 uint64_type = CoreLookupType ("System", "UInt64");
966 byte_type = CoreLookupType ("System", "Byte");
967 sbyte_type = CoreLookupType ("System", "SByte");
968 short_type = CoreLookupType ("System", "Int16");
969 ushort_type = CoreLookupType ("System", "UInt16");
971 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
972 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
974 idisposable_type = CoreLookupType ("System", "IDisposable");
977 InitGenericCoreTypes ();
982 /// The types have to be initialized after the initial
983 /// population of the type has happened (for example, to
984 /// bootstrap the corlib.dll
986 public static void InitCoreTypes ()
988 object_type = CoreLookupType ("System", "Object");
989 system_object_expr.Type = object_type;
990 value_type = CoreLookupType ("System", "ValueType");
991 system_valuetype_expr.Type = value_type;
993 InitEnumUnderlyingTypes ();
995 char_type = CoreLookupType ("System", "Char");
996 string_type = CoreLookupType ("System", "String");
997 float_type = CoreLookupType ("System", "Single");
998 double_type = CoreLookupType ("System", "Double");
999 char_ptr_type = GetPointerType (char_type);
1000 decimal_type = CoreLookupType ("System", "Decimal");
1001 bool_type = CoreLookupType ("System", "Boolean");
1002 enum_type = CoreLookupType ("System", "Enum");
1004 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1005 delegate_type = CoreLookupType ("System", "Delegate");
1007 array_type = CoreLookupType ("System", "Array");
1008 void_type = CoreLookupType ("System", "Void");
1009 type_type = CoreLookupType ("System", "Type");
1011 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1012 runtime_method_handle_type = CoreLookupType ("System", "RuntimeMethodHandle");
1013 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1014 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1015 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1016 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1017 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1018 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1019 icloneable_type = CoreLookupType ("System", "ICloneable");
1020 iconvertible_type = CoreLookupType ("System", "IConvertible");
1021 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1022 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1023 intptr_type = CoreLookupType ("System", "IntPtr");
1024 uintptr_type = CoreLookupType ("System", "UIntPtr");
1026 attribute_type = CoreLookupType ("System", "Attribute");
1027 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1028 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1029 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1030 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1031 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1032 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1033 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1035 // needed before any call susceptible to fail, as it is used during resolution
1036 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1038 // this can fail if the user doesn't have an -r:System.dll
1039 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", true);
1041 typed_reference_type = CoreLookupType ("System", "TypedReference");
1042 arg_iterator_type = CoreLookupType ("System", "ArgIterator", true);
1043 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1044 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1046 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1048 void_ptr_type = GetPointerType (void_type);
1050 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1052 exception_type = CoreLookupType ("System", "Exception");
1053 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1054 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1059 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1060 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1061 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1062 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1063 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1064 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1065 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", true);
1066 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1067 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1068 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute");
1069 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1070 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1076 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1077 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1078 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1079 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1080 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", true);
1085 extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
1086 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", true);
1090 // When compiling corlib, store the "real" types here.
1092 if (!RootContext.StdLib) {
1093 system_int32_type = typeof (System.Int32);
1094 system_array_type = typeof (System.Array);
1095 system_type_type = typeof (System.Type);
1097 system_int_array_get_length = GetCoreMethod (
1098 system_array_type, "get_Length", Type.EmptyTypes);
1099 system_int_array_get_rank = GetCoreMethod (
1100 system_array_type, "get_Rank", Type.EmptyTypes);
1101 system_object_array_clone = GetCoreMethod (
1102 system_array_type, "Clone", Type.EmptyTypes);
1104 Type [] system_int_arg = { system_int32_type };
1105 system_int_array_get_length_int = GetCoreMethod (
1106 system_array_type, "GetLength", system_int_arg);
1107 system_int_array_get_upper_bound_int = GetCoreMethod (
1108 system_array_type, "GetUpperBound", system_int_arg);
1109 system_int_array_get_lower_bound_int = GetCoreMethod (
1110 system_array_type, "GetLowerBound", system_int_arg);
1112 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1113 system_void_array_copyto_array_int = GetCoreMethod (
1114 system_array_type, "CopyTo", system_array_int_arg);
1117 // HACK: When building corlib replace corlib internal core types
1118 // with mcs core types to handle type comparisons inside corlib
1120 Type [] system_4_type_arg = {
1121 system_type_type, system_type_type, system_type_type, system_type_type };
1123 MethodInfo set_corlib_type_builders =
1124 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1125 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1126 system_4_type_arg, null);
1128 if (set_corlib_type_builders != null) {
1129 object[] args = new object [4];
1130 args [0] = object_type;
1131 args [1] = value_type;
1132 args [2] = enum_type;
1133 args [3] = void_type;
1135 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1137 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1142 system_string_expr.Type = string_type;
1143 system_boolean_expr.Type = bool_type;
1144 system_decimal_expr.Type = decimal_type;
1145 system_single_expr.Type = float_type;
1146 system_double_expr.Type = double_type;
1147 system_sbyte_expr.Type = sbyte_type;
1148 system_byte_expr.Type = byte_type;
1149 system_int16_expr.Type = short_type;
1150 system_uint16_expr.Type = ushort_type;
1151 system_int32_expr.Type = int32_type;
1152 system_uint32_expr.Type = uint32_type;
1153 system_int64_expr.Type = int64_type;
1154 system_uint64_expr.Type = uint64_type;
1155 system_char_expr.Type = char_type;
1156 system_void_expr.Type = void_type;
1157 system_asynccallback_expr.Type = asynccallback_type;
1158 system_iasyncresult_expr.Type = iasyncresult_type;
1161 // These are only used for compare purposes
1163 anonymous_method_type = typeof (AnonymousMethod);
1164 null_type = typeof (NullType);
1168 // The helper methods that are used by the compiler
1170 public static void InitCodeHelpers ()
1173 // Now load the default methods that we use.
1175 Type [] string_ = { string_type };
1176 string_isinterned_string = GetCoreMethod (
1177 string_type, "IsInterned", string_);
1179 Type [] runtime_type_handle = { runtime_handle_type };
1180 system_type_get_type_from_handle = GetCoreMethod (
1181 type_type, "GetTypeFromHandle", runtime_type_handle);
1183 Type [] delegate_delegate = { delegate_type, delegate_type };
1184 delegate_combine_delegate_delegate = GetCoreMethod (
1185 delegate_type, "Combine", delegate_delegate);
1187 delegate_remove_delegate_delegate = GetCoreMethod (
1188 delegate_type, "Remove", delegate_delegate);
1193 ienumerator_getcurrent = GetCoreProperty (
1194 ienumerator_type, "Current");
1195 bool_movenext_void = GetCoreMethod (
1196 ienumerator_type, "MoveNext", Type.EmptyTypes);
1197 void_reset_void = GetCoreMethod (
1198 ienumerator_type, "Reset", Type.EmptyTypes);
1199 void_dispose_void = GetCoreMethod (
1200 idisposable_type, "Dispose", Type.EmptyTypes);
1201 int_get_offset_to_string_data = GetCoreMethod (
1202 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1203 int_array_get_length = GetCoreMethod (
1204 array_type, "get_Length", Type.EmptyTypes);
1205 int_array_get_rank = GetCoreMethod (
1206 array_type, "get_Rank", Type.EmptyTypes);
1207 ienumerable_getenumerator_void = GetCoreMethod (
1208 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1213 Type [] int_arg = { int32_type };
1214 int_array_get_length_int = GetCoreMethod (
1215 array_type, "GetLength", int_arg);
1216 int_array_get_upper_bound_int = GetCoreMethod (
1217 array_type, "GetUpperBound", int_arg);
1218 int_array_get_lower_bound_int = GetCoreMethod (
1219 array_type, "GetLowerBound", int_arg);
1222 // System.Array methods
1224 object_array_clone = GetCoreMethod (
1225 array_type, "Clone", Type.EmptyTypes);
1226 Type [] array_int_arg = { array_type, int32_type };
1227 void_array_copyto_array_int = GetCoreMethod (
1228 array_type, "CopyTo", array_int_arg);
1233 Type [] object_arg = { object_type };
1234 void_monitor_enter_object = GetCoreMethod (
1235 monitor_type, "Enter", object_arg);
1236 void_monitor_exit_object = GetCoreMethod (
1237 monitor_type, "Exit", object_arg);
1239 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1241 void_initializearray_array_fieldhandle = GetCoreMethod (
1242 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1247 int_getlength_int = GetCoreMethod (
1248 array_type, "GetLength", int_arg);
1251 // Decimal constructors
1253 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1254 void_decimal_ctor_five_args = GetCoreConstructor (
1255 decimal_type, dec_arg);
1257 void_decimal_ctor_int_arg = GetCoreConstructor (decimal_type, int_arg);
1262 unverifiable_code_ctor = GetCoreConstructor (unverifiable_code_type, Type.EmptyTypes);
1263 default_member_ctor = GetCoreConstructor (default_member_type, string_);
1264 cons_param_array_attribute = GetCoreConstructor (param_array_type, Type.EmptyTypes);
1266 Type[] short_arg = { short_type };
1267 // fails for .net 2.1
1268 struct_layout_attribute_ctor = GetCoreConstructor (struct_layout_attribute_type, short_arg, false);
1270 decimal_constant_attribute_ctor = GetCoreConstructor (decimal_constant_attribute_type, new Type []
1271 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1273 field_offset_attribute_ctor = GetCoreConstructor (field_offset_attribute_type, new Type []
1277 // System.Threading.CompareExchange
1279 Type[] compare_exchange_types = {
1280 GetReferenceType (int32_type), int32_type, int32_type };
1281 int_interlocked_compare_exchange = GetCoreMethod (
1282 interlocked_type, "CompareExchange", compare_exchange_types);
1288 compiler_generated_attr = new CustomAttributeBuilder (
1289 GetCoreConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1291 Type[] type_int_arg = { type_type, int32_type };
1292 fixed_buffer_attr_ctor = GetCoreConstructor (fixed_buffer_attr_type, type_int_arg);
1299 object_ctor = GetCoreConstructor (object_type, Type.EmptyTypes);
1302 InitGenericCodeHelpers ();
1307 static void InitSystemCore ()
1309 if (RootContext.Version != LanguageVersion.LINQ)
1312 if (extension_attribute_type != null)
1313 extension_attribute_attr = new CustomAttributeBuilder (
1314 GetCoreConstructor (extension_attribute_type, Type.EmptyTypes), new object[0]);
1318 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1321 /// This is the "old", non-cache based FindMembers() function. We cannot use
1322 /// the cache here because there is no member name argument.
1324 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1325 MemberFilter filter, object criteria)
1327 #if MS_COMPATIBLE && GMCS_SOURCE
1328 if (t.IsGenericType)
1329 t = t.GetGenericTypeDefinition ();
1332 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1335 // `builder_to_declspace' contains all dynamic types.
1339 Timer.StartTimer (TimerType.FindMembers);
1340 list = decl.FindMembers (mt, bf, filter, criteria);
1341 Timer.StopTimer (TimerType.FindMembers);
1346 // We have to take care of arrays specially, because GetType on
1347 // a TypeBuilder array will return a Type, not a TypeBuilder,
1348 // and we can not call FindMembers on this type.
1351 #if MS_COMPATIBLE && GMCS_SOURCE
1354 t.IsSubclassOf (TypeManager.array_type))
1355 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1358 if (t is GenericTypeParameterBuilder) {
1359 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1361 Timer.StartTimer (TimerType.FindMembers);
1362 MemberList list = tparam.FindMembers (
1363 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1364 Timer.StopTimer (TimerType.FindMembers);
1370 // Since FindMembers will not lookup both static and instance
1371 // members, we emulate this behaviour here.
1373 if ((bf & instance_and_static) == instance_and_static){
1374 MemberInfo [] i_members = t.FindMembers (
1375 mt, bf & ~BindingFlags.Static, filter, criteria);
1377 int i_len = i_members.Length;
1379 MemberInfo one = i_members [0];
1382 // If any of these are present, we are done!
1384 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1385 return new MemberList (i_members);
1388 MemberInfo [] s_members = t.FindMembers (
1389 mt, bf & ~BindingFlags.Instance, filter, criteria);
1391 int s_len = s_members.Length;
1392 if (i_len > 0 || s_len > 0)
1393 return new MemberList (i_members, s_members);
1396 return new MemberList (i_members);
1398 return new MemberList (s_members);
1402 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1407 /// This method is only called from within MemberLookup. It tries to use the member
1408 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1409 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1410 /// our return value will already contain all inherited members and the caller don't need
1411 /// to check base classes and interfaces anymore.
1413 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1414 string name, out bool used_cache)
1419 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1420 // and we can ask the DeclSpace for the MemberCache.
1423 if (t.Assembly == CodeGen.Assembly.Builder) {
1424 if (t.IsGenericParameter) {
1425 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1428 if (tparam.MemberCache == null)
1429 return new MemberInfo[0];
1431 return tparam.MemberCache.FindMembers (
1432 mt, bf, name, FilterWithClosure_delegate, null);
1435 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1436 t = t.GetGenericTypeDefinition ();
1438 if (t is TypeBuilder) {
1440 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1441 cache = decl.MemberCache;
1444 // If this DeclSpace has a MemberCache, use it.
1447 if (cache != null) {
1449 return cache.FindMembers (
1450 mt, bf, name, FilterWithClosure_delegate, null);
1453 // If there is no MemberCache, we need to use the "normal" FindMembers.
1454 // Note, this is a VERY uncommon route!
1457 Timer.StartTimer (TimerType.FindMembers);
1458 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1459 FilterWithClosure_delegate, name);
1460 Timer.StopTimer (TimerType.FindMembers);
1462 return (MemberInfo []) list;
1466 // We have to take care of arrays specially, because GetType on
1467 // a TypeBuilder array will return a Type, not a TypeBuilder,
1468 // and we can not call FindMembers on this type.
1472 return TypeHandle.ArrayType.MemberCache.FindMembers (
1473 mt, bf, name, FilterWithClosure_delegate, null);
1477 if (t is GenericTypeParameterBuilder) {
1478 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1481 if (tparam.MemberCache == null)
1482 return new MemberInfo [0];
1484 return tparam.MemberCache.FindMembers (
1485 mt, bf, name, FilterWithClosure_delegate, null);
1489 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1491 // This happens if we're resolving a class'es base class and interfaces
1492 // in TypeContainer.DefineType(). At this time, the types aren't
1493 // populated yet, so we can't use the cache.
1495 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1496 FilterWithClosure_delegate, name);
1502 // This call will always succeed. There is exactly one TypeHandle instance per
1503 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1504 // the corresponding MemberCache.
1506 cache = TypeHandle.GetMemberCache (t);
1509 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1512 public static bool IsBuiltinType (Type t)
1514 t = TypeToCoreType (t);
1515 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1516 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1517 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1518 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1524 public static bool IsBuiltinType (TypeContainer tc)
1526 return IsBuiltinType (tc.TypeBuilder);
1530 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1531 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1533 public static bool IsPrimitiveType (Type t)
1535 return (t == int32_type || t == uint32_type ||
1536 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1537 t == char_type || t == short_type || t == bool_type ||
1538 t == sbyte_type || t == byte_type || t == ushort_type);
1541 public static bool IsDelegateType (Type t)
1544 if (t.IsGenericParameter)
1548 if (t == TypeManager.delegate_type)
1551 t = DropGenericTypeArguments (t);
1552 return IsSubclassOf (t, TypeManager.delegate_type);
1555 public static bool IsEnumType (Type t)
1557 t = DropGenericTypeArguments (t);
1558 if (builder_to_declspace [t] is Enum)
1561 #if MS_COMPATIBLE && GMCS_SOURCE
1562 if (t.IsGenericParameter || t.IsGenericType)
1568 public static bool IsBuiltinOrEnum (Type t)
1570 if (IsBuiltinType (t))
1579 public static bool IsNullType (Type t)
1581 return t == null_type;
1584 public static bool IsAttributeType (Type t)
1586 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1589 static Stack unmanaged_enclosing_types = new Stack (4);
1592 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1594 public static bool IsUnmanagedType (Type t)
1596 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1597 if (unmanaged_enclosing_types.Contains (t))
1600 // builtins that are not unmanaged types
1601 if (t == TypeManager.object_type || t == TypeManager.string_type)
1604 if (IsGenericType (t) || IsGenericParameter (t))
1607 if (IsBuiltinOrEnum (t))
1610 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1614 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1618 if (!IsValueType (t))
1622 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1623 if (p.IsGenericTypeDefinition)
1628 unmanaged_enclosing_types.Push (t);
1632 if (t is TypeBuilder) {
1633 TypeContainer tc = LookupTypeContainer (t);
1634 if (tc.Fields != null){
1635 foreach (FieldBase f in tc.Fields){
1636 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1637 if ((f.ModFlags & Modifiers.STATIC) != 0)
1639 if (f.MemberType == null)
1641 if (!IsUnmanagedType (f.MemberType)){
1642 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1648 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1650 foreach (FieldInfo f in fields){
1651 if (!IsUnmanagedType (f.FieldType)){
1652 Report.SymbolRelatedToPreviousError (f);
1658 unmanaged_enclosing_types.Pop ();
1663 public static bool IsReferenceType (Type t)
1665 if (TypeManager.IsGenericParameter (t)) {
1666 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1667 if (constraints == null)
1670 return constraints.IsReferenceType;
1673 if (t == TypeManager.null_type)
1676 return !t.IsValueType;
1679 public static bool IsValueType (Type t)
1681 return t.IsValueType || IsGenericParameter (t);
1684 public static bool IsInterfaceType (Type t)
1686 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1690 return tc.Kind == Kind.Interface;
1693 public static bool IsSubclassOf (Type type, Type base_type)
1695 TypeParameter tparam = LookupTypeParameter (type);
1696 TypeParameter pparam = LookupTypeParameter (base_type);
1698 if ((tparam != null) && (pparam != null)) {
1699 if (tparam == pparam)
1702 return tparam.IsSubclassOf (base_type);
1705 #if MS_COMPATIBLE && GMCS_SOURCE
1706 if (type.IsGenericType)
1707 type = type.GetGenericTypeDefinition ();
1710 if (type.IsSubclassOf (base_type))
1714 if (IsEqual (type, base_type))
1717 type = type.BaseType;
1718 } while (type != null);
1723 public static bool IsPrivateAccessible (Type type, Type parent)
1728 if (type.Equals (parent))
1731 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1734 public static bool IsFamilyAccessible (Type type, Type parent)
1736 TypeParameter tparam = LookupTypeParameter (type);
1737 TypeParameter pparam = LookupTypeParameter (parent);
1739 if ((tparam != null) && (pparam != null)) {
1740 if (tparam == pparam)
1743 return tparam.IsSubclassOf (parent);
1747 if (IsInstantiationOfSameGenericType (type, parent))
1750 type = type.BaseType;
1751 } while (type != null);
1757 // Checks whether `type' is a subclass or nested child of `base_type'.
1759 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1762 if (IsFamilyAccessible (type, base_type))
1765 // Handle nested types.
1766 type = type.DeclaringType;
1767 } while (type != null);
1773 // Checks whether `type' is a nested child of `parent'.
1775 public static bool IsNestedChildOf (Type type, Type parent)
1780 type = DropGenericTypeArguments (type);
1781 parent = DropGenericTypeArguments (parent);
1783 if (IsEqual (type, parent))
1786 type = type.DeclaringType;
1787 while (type != null) {
1788 if (IsEqual (type, parent))
1791 type = type.DeclaringType;
1799 // Checks whether `extern_type' is friend of the output assembly
1801 public static bool IsFriendAssembly (Assembly assembly)
1803 // FIXME: This should not be reached
1804 if (assembly == CodeGen.Assembly.Builder)
1807 if (assembly_internals_vis_attrs.Contains (assembly))
1808 return (bool)(assembly_internals_vis_attrs [assembly]);
1810 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1811 if (attrs.Length == 0) {
1812 assembly_internals_vis_attrs.Add (assembly, false);
1816 AssemblyName this_name = CodeGen.Assembly.Name;
1817 byte [] this_token = this_name.GetPublicKeyToken ();
1818 bool is_friend = false;
1819 foreach (InternalsVisibleToAttribute attr in attrs) {
1820 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1823 AssemblyName aname = null;
1825 aname = new AssemblyName (attr.AssemblyName);
1826 } catch (FileLoadException) {
1827 } catch (ArgumentException) {
1830 if (aname == null || aname.Name != this_name.Name)
1833 byte [] key_token = aname.GetPublicKeyToken ();
1834 if (key_token != null) {
1835 if (this_token.Length == 0) {
1836 // Same name, but assembly is not strongnamed
1837 Error_FriendAccessNameNotMatching (aname.FullName);
1841 if (!CompareKeyTokens (this_token, key_token))
1849 assembly_internals_vis_attrs.Add (assembly, is_friend);
1853 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1855 for (int i = 0; i < token1.Length; i++)
1856 if (token1 [i] != token2 [i])
1862 static void Error_FriendAccessNameNotMatching (string other_name)
1864 Report.Error (281, "Friend access was granted to `" + other_name +
1865 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1866 "'. Try adding a reference to `" + other_name +
1867 "' or change the output assembly name to match it");
1870 public static bool IsFriendAssembly (Assembly assembly)
1877 // Do the right thing when returning the element type of an
1878 // array type based on whether we are compiling corlib or not
1880 public static Type GetElementType (Type t)
1882 if (RootContext.StdLib)
1883 return t.GetElementType ();
1885 return TypeToCoreType (t.GetElementType ());
1889 /// This method is not implemented by MS runtime for dynamic types
1891 public static bool HasElementType (Type t)
1893 return t.IsArray || t.IsPointer || t.IsByRef;
1897 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1901 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1902 /// for anything which is dynamic, and we need this in a number of places,
1903 /// we register this information here, and use it afterwards.
1905 static public void RegisterMethod (MethodBase mb, Parameters ip)
1907 method_params.Add (mb, ip);
1910 static public ParameterData GetParameterData (MethodBase mb)
1912 ParameterData pd = (ParameterData)method_params [mb];
1915 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1916 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1917 pd = GetParameterData (mi);
1918 if (mi.IsGenericMethod)
1919 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1921 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1922 method_params.Add (mb, pd);
1926 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1927 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1928 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1931 pd = new ReflectionParameters (mb);
1932 method_params.Add (mb, pd);
1937 public static ParameterData GetDelegateParameters (Type t)
1939 Delegate d = builder_to_declspace [t] as Delegate;
1941 return d.Parameters;
1943 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1944 return GetParameterData (invoke_mb);
1947 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1949 if (!method_overrides.Contains (override_method))
1950 method_overrides [override_method] = base_method;
1951 if (method_overrides [override_method] != base_method)
1952 throw new InternalErrorException ("Override mismatch: " + override_method);
1955 static public bool IsOverride (MethodBase m)
1957 m = DropGenericMethodArguments (m);
1959 return m.IsVirtual &&
1960 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1961 (m is MethodBuilder || method_overrides.Contains (m));
1964 static public MethodBase TryGetBaseDefinition (MethodBase m)
1966 m = DropGenericMethodArguments (m);
1968 return (MethodBase) method_overrides [m];
1972 /// Returns the argument types for an indexer based on its PropertyInfo
1974 /// For dynamic indexers, we use the compiler provided types, for
1975 /// indexers from existing assemblies we load them from GetParameters,
1976 /// and insert them into the cache
1978 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1980 if (indexer_arguments.Contains (indexer))
1981 return (Type []) indexer_arguments [indexer];
1982 else if (indexer is PropertyBuilder)
1983 // If we're a PropertyBuilder and not in the
1984 // `indexer_arguments' hash, then we're a property and
1986 return Type.EmptyTypes;
1988 ParameterInfo [] pi = indexer.GetIndexParameters ();
1989 // Property, not an indexer.
1991 return Type.EmptyTypes;
1993 Type [] types = new Type [c];
1995 for (int i = 0; i < c; i++)
1996 types [i] = pi [i].ParameterType;
1998 indexer_arguments.Add (indexer, types);
2003 public static void RegisterConstant (FieldInfo fb, IConstant ic)
2005 fields.Add (fb, ic);
2008 public static IConstant GetConstant (FieldInfo fb)
2013 return (IConstant)fields [fb];
2016 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
2018 propertybuilder_to_property.Add (pi, pb);
2021 public static PropertyBase GetProperty (PropertyInfo pi)
2023 return (PropertyBase)propertybuilder_to_property [pi];
2026 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
2028 fieldbuilders_to_fields.Add (fb, f);
2032 // The return value can be null; This will be the case for
2033 // auxiliary FieldBuilders created by the compiler that have no
2034 // real field being declared on the source code
2036 static public FieldBase GetField (FieldInfo fb)
2039 fb = GetGenericFieldDefinition (fb);
2041 return (FieldBase) fieldbuilders_to_fields [fb];
2044 static public MethodInfo GetAddMethod (EventInfo ei)
2046 if (ei is MyEventBuilder) {
2047 return ((MyEventBuilder)ei).GetAddMethod (true);
2049 return ei.GetAddMethod (true);
2052 static public MethodInfo GetRemoveMethod (EventInfo ei)
2054 if (ei is MyEventBuilder) {
2055 return ((MyEventBuilder)ei).GetRemoveMethod (true);
2057 return ei.GetRemoveMethod (true);
2060 static public void RegisterEventField (EventInfo einfo, EventField e)
2063 events = new Hashtable ();
2065 events.Add (einfo, e);
2068 static public EventField GetEventField (EventInfo ei)
2073 return (EventField) events [ei];
2076 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2077 MethodBase set, Type[] args)
2079 indexer_arguments.Add (pb, args);
2084 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2086 Hashtable hash = new Hashtable ();
2087 return CheckStructCycles (tc, seen, hash);
2090 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2093 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2097 // `seen' contains all types we've already visited.
2099 if (seen.Contains (tc))
2101 seen.Add (tc, null);
2103 if (tc.Fields == null)
2106 foreach (FieldBase field in tc.Fields) {
2107 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2110 Type ftype = field.FieldBuilder.FieldType;
2111 TypeContainer ftc = LookupTypeContainer (ftype);
2115 if (hash.Contains (ftc)) {
2116 Report.Error (523, tc.Location,
2117 "Struct member `{0}.{1}' of type `{2}' " +
2118 "causes a cycle in the struct layout",
2119 tc.Name, field.Name, ftc.Name);
2124 // `hash' contains all types in the current path.
2126 hash.Add (tc, null);
2128 bool ok = CheckStructCycles (ftc, seen, hash);
2135 if (!seen.Contains (ftc))
2136 seen.Add (ftc, null);
2143 /// Given an array of interface types, expand and eliminate repeated ocurrences
2144 /// of an interface.
2148 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2151 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2153 ArrayList new_ifaces = new ArrayList ();
2155 foreach (TypeExpr iface in base_interfaces){
2156 Type itype = iface.Type;
2158 if (new_ifaces.Contains (itype))
2161 new_ifaces.Add (itype);
2163 Type [] implementing = GetInterfaces (itype);
2165 foreach (Type imp in implementing){
2166 if (!new_ifaces.Contains (imp))
2167 new_ifaces.Add (imp);
2170 Type [] ret = new Type [new_ifaces.Count];
2171 new_ifaces.CopyTo (ret, 0);
2175 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2177 ArrayList new_ifaces = new ArrayList ();
2179 foreach (Type itype in base_interfaces){
2180 if (new_ifaces.Contains (itype))
2183 new_ifaces.Add (itype);
2185 Type [] implementing = GetInterfaces (itype);
2187 foreach (Type imp in implementing){
2188 if (!new_ifaces.Contains (imp))
2189 new_ifaces.Add (imp);
2192 Type [] ret = new Type [new_ifaces.Count];
2193 new_ifaces.CopyTo (ret, 0);
2197 static PtrHashtable iface_cache = new PtrHashtable ();
2200 /// This function returns the interfaces in the type `t'. Works with
2201 /// both types and TypeBuilders.
2203 public static Type [] GetInterfaces (Type t)
2205 Type [] cached = iface_cache [t] as Type [];
2210 // The reason for catching the Array case is that Reflection.Emit
2211 // will not return a TypeBuilder for Array types of TypeBuilder types,
2212 // but will still throw an exception if we try to call GetInterfaces
2215 // Since the array interfaces are always constant, we return those for
2220 t = TypeManager.array_type;
2222 if ((t is TypeBuilder) || IsGenericType (t)) {
2223 Type [] base_ifaces;
2225 if (t.BaseType == null)
2226 base_ifaces = Type.EmptyTypes;
2228 base_ifaces = GetInterfaces (t.BaseType);
2230 if (IsGenericType (t))
2231 #if MS_COMPATIBLE && GMCS_SOURCE
2232 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2234 type_ifaces = t.GetInterfaces ();
2237 type_ifaces = (Type []) builder_to_ifaces [t];
2238 if (type_ifaces == null || type_ifaces.Length == 0)
2239 type_ifaces = Type.EmptyTypes;
2241 int base_count = base_ifaces.Length;
2242 Type [] result = new Type [base_count + type_ifaces.Length];
2243 base_ifaces.CopyTo (result, 0);
2244 type_ifaces.CopyTo (result, base_count);
2246 iface_cache [t] = result;
2249 } else if (t is GenericTypeParameterBuilder){
2250 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2251 if (type_ifaces == null || type_ifaces.Length == 0)
2252 type_ifaces = Type.EmptyTypes;
2254 iface_cache [t] = type_ifaces;
2258 Type[] ifaces = t.GetInterfaces ();
2259 iface_cache [t] = ifaces;
2265 // gets the interfaces that are declared explicitly on t
2267 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2269 return (Type []) builder_to_ifaces [t];
2273 /// The following is used to check if a given type implements an interface.
2274 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2276 public static bool ImplementsInterface (Type t, Type iface)
2281 // FIXME OPTIMIZATION:
2282 // as soon as we hit a non-TypeBuiler in the interface
2283 // chain, we could return, as the `Type.GetInterfaces'
2284 // will return all the interfaces implement by the type
2288 interfaces = GetInterfaces (t);
2290 if (interfaces != null){
2291 foreach (Type i in interfaces){
2298 } while (t != null);
2303 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2305 // This is a custom version of Convert.ChangeType() which works
2306 // with the TypeBuilder defined types when compiling corlib.
2307 public static object ChangeType (object value, Type conversionType, out bool error)
2309 IConvertible convert_value = value as IConvertible;
2311 if (convert_value == null){
2318 // We must use Type.Equals() here since `conversionType' is
2319 // the TypeBuilder created version of a system type and not
2320 // the system type itself. You cannot use Type.GetTypeCode()
2321 // on such a type - it'd always return TypeCode.Object.
2324 // We cannot rely on build-in type conversions as they are
2325 // more limited than what C# supports.
2326 // See char -> float/decimal/double conversion
2331 if (conversionType.Equals (typeof (Boolean)))
2332 return (object)(convert_value.ToBoolean (nf_provider));
2333 if (conversionType.Equals (typeof (Byte)))
2334 return (object)(convert_value.ToByte (nf_provider));
2335 if (conversionType.Equals (typeof (Char)))
2336 return (object)(convert_value.ToChar (nf_provider));
2337 if (conversionType.Equals (typeof (DateTime)))
2338 return (object)(convert_value.ToDateTime (nf_provider));
2340 if (conversionType.Equals (TypeManager.decimal_type)) {
2341 if (convert_value.GetType () == TypeManager.char_type)
2342 return (decimal)convert_value.ToInt32 (nf_provider);
2343 return convert_value.ToDecimal (nf_provider);
2346 if (conversionType.Equals (typeof (Double))) {
2347 if (convert_value.GetType () == TypeManager.char_type)
2348 return (double)convert_value.ToInt32 (nf_provider);
2349 return convert_value.ToDouble (nf_provider);
2352 if (conversionType.Equals (typeof (Int16)))
2353 return (object)(convert_value.ToInt16 (nf_provider));
2354 if (conversionType.Equals (typeof (Int32)))
2355 return (object)(convert_value.ToInt32 (nf_provider));
2356 if (conversionType.Equals (typeof (Int64)))
2357 return (object)(convert_value.ToInt64 (nf_provider));
2358 if (conversionType.Equals (typeof (SByte)))
2359 return (object)(convert_value.ToSByte (nf_provider));
2361 if (conversionType.Equals (typeof (Single))) {
2362 if (convert_value.GetType () == TypeManager.char_type)
2363 return (float)convert_value.ToInt32 (nf_provider);
2364 return convert_value.ToSingle (nf_provider);
2367 if (conversionType.Equals (typeof (String)))
2368 return (object)(convert_value.ToString (nf_provider));
2369 if (conversionType.Equals (typeof (UInt16)))
2370 return (object)(convert_value.ToUInt16 (nf_provider));
2371 if (conversionType.Equals (typeof (UInt32)))
2372 return (object)(convert_value.ToUInt32 (nf_provider));
2373 if (conversionType.Equals (typeof (UInt64)))
2374 return (object)(convert_value.ToUInt64 (nf_provider));
2375 if (conversionType.Equals (typeof (Object)))
2376 return (object)(value);
2386 // This is needed, because enumerations from assemblies
2387 // do not report their underlyingtype, but they report
2390 public static Type EnumToUnderlying (Type t)
2392 t = DropGenericTypeArguments (t);
2393 if (t == TypeManager.enum_type)
2396 t = t.UnderlyingSystemType;
2397 if (!TypeManager.IsEnumType (t))
2400 if (t is TypeBuilder) {
2401 // slow path needed to compile corlib
2402 if (t == TypeManager.bool_type ||
2403 t == TypeManager.byte_type ||
2404 t == TypeManager.sbyte_type ||
2405 t == TypeManager.char_type ||
2406 t == TypeManager.short_type ||
2407 t == TypeManager.ushort_type ||
2408 t == TypeManager.int32_type ||
2409 t == TypeManager.uint32_type ||
2410 t == TypeManager.int64_type ||
2411 t == TypeManager.uint64_type)
2414 TypeCode tc = Type.GetTypeCode (t);
2417 case TypeCode.Boolean:
2418 return TypeManager.bool_type;
2420 return TypeManager.byte_type;
2421 case TypeCode.SByte:
2422 return TypeManager.sbyte_type;
2424 return TypeManager.char_type;
2425 case TypeCode.Int16:
2426 return TypeManager.short_type;
2427 case TypeCode.UInt16:
2428 return TypeManager.ushort_type;
2429 case TypeCode.Int32:
2430 return TypeManager.int32_type;
2431 case TypeCode.UInt32:
2432 return TypeManager.uint32_type;
2433 case TypeCode.Int64:
2434 return TypeManager.int64_type;
2435 case TypeCode.UInt64:
2436 return TypeManager.uint64_type;
2438 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2442 // When compiling corlib and called with one of the core types, return
2443 // the corresponding typebuilder for that type.
2445 public static Type TypeToCoreType (Type t)
2447 if (RootContext.StdLib || (t is TypeBuilder))
2450 TypeCode tc = Type.GetTypeCode (t);
2453 case TypeCode.Boolean:
2454 return TypeManager.bool_type;
2456 return TypeManager.byte_type;
2457 case TypeCode.SByte:
2458 return TypeManager.sbyte_type;
2460 return TypeManager.char_type;
2461 case TypeCode.Int16:
2462 return TypeManager.short_type;
2463 case TypeCode.UInt16:
2464 return TypeManager.ushort_type;
2465 case TypeCode.Int32:
2466 return TypeManager.int32_type;
2467 case TypeCode.UInt32:
2468 return TypeManager.uint32_type;
2469 case TypeCode.Int64:
2470 return TypeManager.int64_type;
2471 case TypeCode.UInt64:
2472 return TypeManager.uint64_type;
2473 case TypeCode.Single:
2474 return TypeManager.float_type;
2475 case TypeCode.Double:
2476 return TypeManager.double_type;
2477 case TypeCode.String:
2478 return TypeManager.string_type;
2479 case TypeCode.Decimal:
2480 return TypeManager.decimal_type;
2482 if (t == typeof (void))
2483 return TypeManager.void_type;
2484 if (t == typeof (object))
2485 return TypeManager.object_type;
2486 if (t == typeof (System.Type))
2487 return TypeManager.type_type;
2488 if (t == typeof (System.IntPtr))
2489 return TypeManager.intptr_type;
2495 /// Utility function that can be used to probe whether a type
2496 /// is managed or not.
2498 public static bool VerifyUnManaged (Type t, Location loc)
2500 if (IsUnmanagedType (t))
2503 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2510 /// Returns the name of the indexer in a given type.
2513 /// The default is not always `Item'. The user can change this behaviour by
2514 /// using the IndexerNameAttribute in the container.
2515 /// For example, the String class indexer is named `Chars' not `Item'
2517 public static string IndexerPropertyName (Type t)
2519 t = DropGenericTypeArguments (t);
2520 if (t is TypeBuilder) {
2521 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2522 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2525 System.Attribute attr = System.Attribute.GetCustomAttribute (
2526 t, TypeManager.default_member_type);
2528 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2529 return dma.MemberName;
2532 return TypeContainer.DefaultIndexerName;
2535 static MethodInfo declare_local_method = null;
2537 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2539 if (declare_local_method == null){
2540 declare_local_method = typeof (ILGenerator).GetMethod (
2542 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2544 new Type [] { typeof (Type), typeof (bool)},
2546 if (declare_local_method == null){
2547 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2548 return ig.DeclareLocal (t);
2551 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2554 private static bool IsSignatureEqual (Type a, Type b)
2557 /// Consider the following example (bug #77674):
2559 /// public abstract class A
2561 /// public abstract T Foo<T> ();
2564 /// public abstract class B : A
2566 /// public override U Foo<T> ()
2567 /// { return default (U); }
2570 /// Here, `T' and `U' are method type parameters from different methods
2571 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2573 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2574 /// we need to do a signature based comparision and consider them equal.
2580 if (a.IsGenericParameter && b.IsGenericParameter &&
2581 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2582 return a.GenericParameterPosition == b.GenericParameterPosition;
2586 if (a.IsArray && b.IsArray) {
2587 if (a.GetArrayRank () != b.GetArrayRank ())
2590 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2593 if (a.IsByRef && b.IsByRef)
2594 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2597 if (a.IsGenericType && b.IsGenericType) {
2598 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2601 Type[] aargs = a.GetGenericArguments ();
2602 Type[] bargs = b.GetGenericArguments ();
2604 if (aargs.Length != bargs.Length)
2607 for (int i = 0; i < aargs.Length; i++) {
2608 if (!IsSignatureEqual (aargs [i], bargs [i]))
2620 // Returns whether the array of memberinfos contains the given method
2622 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2624 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2626 foreach (MethodBase method in array) {
2627 if (method.Name != new_method.Name)
2630 if (method is MethodInfo && new_method is MethodInfo)
2631 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2632 ((MethodInfo) new_method).ReturnType))
2636 Type [] old_args = TypeManager.GetParameterData (method).Types;
2637 int old_count = old_args.Length;
2640 if (new_args.Length != old_count)
2643 for (i = 0; i < old_count; i++){
2644 if (!IsSignatureEqual (old_args [i], new_args [i]))
2657 // We copy methods from `new_members' into `target_list' if the signature
2658 // for the method from in the new list does not exist in the target_list
2660 // The name is assumed to be the same.
2662 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2664 if (target_list == null){
2665 target_list = new ArrayList ();
2667 foreach (MemberInfo mi in new_members){
2668 if (mi is MethodBase)
2669 target_list.Add (mi);
2674 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2675 target_list.CopyTo (target_array, 0);
2677 foreach (MemberInfo mi in new_members){
2678 MethodBase new_method = (MethodBase) mi;
2680 if (!ArrayContainsMethod (target_array, new_method))
2681 target_list.Add (new_method);
2688 // Tracks the generic parameters.
2690 static PtrHashtable builder_to_type_param;
2692 public static void AddTypeParameter (Type t, TypeParameter tparam)
2694 if (!builder_to_type_param.Contains (t))
2695 builder_to_type_param.Add (t, tparam);
2698 public static TypeParameter LookupTypeParameter (Type t)
2700 return (TypeParameter) builder_to_type_param [t];
2703 // This method always return false for non-generic compiler,
2704 // while Type.IsGenericParameter is returned if it is supported.
2705 public static bool IsGenericParameter (Type type)
2708 return type.IsGenericParameter;
2714 public static int GenericParameterPosition (Type type)
2717 return type.GenericParameterPosition;
2719 throw new InternalErrorException ("should not be called");
2723 public static bool IsGenericType (Type type)
2726 return type.IsGenericType;
2732 public static bool IsGenericTypeDefinition (Type type)
2735 return type.IsGenericTypeDefinition;
2741 public static bool ContainsGenericParameters (Type type)
2744 return type.ContainsGenericParameters;
2750 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2753 if (fi.DeclaringType.IsGenericTypeDefinition ||
2754 !fi.DeclaringType.IsGenericType)
2757 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2758 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2759 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2761 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2762 foreach (FieldInfo f in t.GetFields (bf))
2763 if (f.MetadataToken == fi.MetadataToken)
2770 public static bool IsEqual (Type a, Type b)
2773 // MS BCL returns true even if enum types are different
2774 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2775 return a.FullName == b.FullName;
2781 if (a.IsGenericParameter && b.IsGenericParameter) {
2782 // TODO: needs more testing before cleaning up
2783 //if (a.DeclaringMethod != b.DeclaringMethod &&
2784 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2786 return a.GenericParameterPosition == b.GenericParameterPosition;
2789 if (a.IsArray && b.IsArray) {
2790 if (a.GetArrayRank () != b.GetArrayRank ())
2792 return IsEqual (a.GetElementType (), b.GetElementType ());
2795 if (a.IsByRef && b.IsByRef)
2796 return IsEqual (a.GetElementType (), b.GetElementType ());
2798 if (a.IsGenericType && b.IsGenericType) {
2799 Type adef = a.GetGenericTypeDefinition ();
2800 Type bdef = b.GetGenericTypeDefinition ();
2805 if (adef.IsEnum && bdef.IsEnum)
2808 Type[] aargs = a.GetGenericArguments ();
2809 Type[] bargs = b.GetGenericArguments ();
2811 if (aargs.Length != bargs.Length)
2814 for (int i = 0; i < aargs.Length; i++) {
2815 if (!IsEqual (aargs [i], bargs [i]))
2826 public static Type DropGenericTypeArguments (Type t)
2829 if (!t.IsGenericType)
2831 // Micro-optimization: a generic typebuilder is always a generic type definition
2832 if (t is TypeBuilder)
2834 return t.GetGenericTypeDefinition ();
2840 public static MethodBase DropGenericMethodArguments (MethodBase m)
2843 if (m.IsGenericMethodDefinition)
2845 if (m.IsGenericMethod)
2846 return ((MethodInfo) m).GetGenericMethodDefinition ();
2847 if (!m.DeclaringType.IsGenericType)
2850 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2851 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2852 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2855 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2859 if (m is ConstructorInfo) {
2860 foreach (ConstructorInfo c in t.GetConstructors (bf))
2861 if (c.MetadataToken == m.MetadataToken)
2864 foreach (MethodBase mb in t.GetMethods (bf))
2865 if (mb.MetadataToken == m.MetadataToken)
2873 public static Type[] GetGenericArguments (MethodBase mi)
2876 return mi.GetGenericArguments ();
2878 return Type.EmptyTypes;
2882 public static Type[] GetTypeArguments (Type t)
2885 DeclSpace tc = LookupDeclSpace (t);
2888 return Type.EmptyTypes;
2890 TypeParameter[] tparam = tc.TypeParameters;
2891 Type[] ret = new Type [tparam.Length];
2892 for (int i = 0; i < tparam.Length; i++) {
2893 ret [i] = tparam [i].Type;
2894 if (ret [i] == null)
2895 throw new InternalErrorException ();
2900 return t.GetGenericArguments ();
2902 throw new InternalErrorException ();
2906 public static GenericConstraints GetTypeParameterConstraints (Type t)
2909 if (!t.IsGenericParameter)
2910 throw new InvalidOperationException ();
2912 TypeParameter tparam = LookupTypeParameter (t);
2914 return tparam.GenericConstraints;
2916 return ReflectionConstraints.GetConstraints (t);
2918 throw new InternalErrorException ();
2922 public static bool HasGenericArguments (Type t)
2924 return GetNumberOfTypeArguments (t) > 0;
2927 public static int GetNumberOfTypeArguments (Type t)
2930 if (t.IsGenericParameter)
2932 DeclSpace tc = LookupDeclSpace (t);
2934 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2936 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2943 /// Check whether `type' and `parent' are both instantiations of the same
2944 /// generic type. Note that we do not check the type parameters here.
2946 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2948 int tcount = GetNumberOfTypeArguments (type);
2949 int pcount = GetNumberOfTypeArguments (parent);
2951 if (tcount != pcount)
2954 type = DropGenericTypeArguments (type);
2955 parent = DropGenericTypeArguments (parent);
2957 return type.Equals (parent);
2961 /// Whether `mb' is a generic method definition.
2963 public static bool IsGenericMethodDefinition (MethodBase mb)
2966 if (mb.DeclaringType is TypeBuilder) {
2967 IMethodData method = (IMethodData) builder_to_method [mb];
2971 return method.GenericMethod != null;
2974 return mb.IsGenericMethodDefinition;
2981 /// Whether `mb' is a generic method.
2983 public static bool IsGenericMethod (MethodBase mb)
2986 return mb.IsGenericMethod;
2992 public static bool IsNullableType (Type t)
2995 return generic_nullable_type == DropGenericTypeArguments (t);
3001 public static bool IsNullableTypeOf (Type t, Type nullable)
3004 if (!IsNullableType (t))
3007 return GetTypeArguments (t) [0] == nullable;
3013 public static bool IsNullableValueType (Type t)
3016 if (!IsNullableType (t))
3019 return GetTypeArguments (t) [0].IsValueType;
3026 #region MemberLookup implementation
3029 // Whether we allow private members in the result (since FindMembers
3030 // uses NonPublic for both protected and private), we need to distinguish.
3033 internal class Closure {
3034 internal bool private_ok;
3036 // Who is invoking us and which type is being queried currently.
3037 internal Type invocation_type;
3038 internal Type qualifier_type;
3040 // The assembly that defines the type is that is calling us
3041 internal Assembly invocation_assembly;
3042 internal IList almost_match;
3044 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3046 if (invocation_type == null)
3049 if (is_static && qualifier_type == null)
3050 // It resolved from a simple name, so it should be visible.
3053 if (IsNestedChildOf (invocation_type, m.DeclaringType))
3056 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
3057 if (!IsFamilyAccessible (t, m.DeclaringType))
3060 // Although a derived class can access protected members of its base class
3061 // it cannot do so through an instance of the base class (CS1540).
3062 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3063 if (is_static || qualifier_type == null ||
3064 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3065 IsFamilyAccessible (qualifier_type, t))
3069 if (almost_match != null)
3070 almost_match.Add (m);
3076 // This filter filters by name + whether it is ok to include private
3077 // members in the search
3079 internal bool Filter (MemberInfo m, object filter_criteria)
3082 // Hack: we know that the filter criteria will always be in the
3083 // `closure' // fields.
3086 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3089 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3090 (invocation_type != null) &&
3091 IsPrivateAccessible (m.DeclaringType, invocation_type))
3095 // Ugly: we need to find out the type of `m', and depending
3096 // on this, tell whether we accept or not
3098 if (m is MethodBase){
3099 MethodBase mb = (MethodBase) m;
3100 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3102 if (ma == MethodAttributes.Public)
3105 if (ma == MethodAttributes.PrivateScope)
3108 if (ma == MethodAttributes.Private)
3109 return private_ok ||
3110 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3111 IsNestedChildOf (invocation_type, m.DeclaringType);
3113 if (invocation_assembly == mb.DeclaringType.Assembly ||
3114 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3115 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3118 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3122 // Family, FamORAssem or FamANDAssem
3123 return CheckValidFamilyAccess (mb.IsStatic, m);
3126 if (m is FieldInfo){
3127 FieldInfo fi = (FieldInfo) m;
3128 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3130 if (fa == FieldAttributes.Public)
3133 if (fa == FieldAttributes.PrivateScope)
3136 if (fa == FieldAttributes.Private)
3137 return private_ok ||
3138 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3139 IsNestedChildOf (invocation_type, m.DeclaringType);
3141 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3142 (invocation_assembly == null) ||
3143 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3144 if ((fa == FieldAttributes.Assembly) ||
3145 (fa == FieldAttributes.FamORAssem))
3148 if ((fa == FieldAttributes.Assembly) ||
3149 (fa == FieldAttributes.FamANDAssem))
3153 // Family, FamORAssem or FamANDAssem
3154 return CheckValidFamilyAccess (fi.IsStatic, m);
3158 // EventInfos and PropertyInfos, return true because they lack
3159 // permission information, so we need to check later on the methods.
3165 static Closure closure = new Closure ();
3166 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3169 // Looks up a member called `name' in the `queried_type'. This lookup
3170 // is done by code that is contained in the definition for `invocation_type'
3171 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3173 // `invocation_type' is used to check whether we're allowed to access the requested
3174 // member wrt its protection level.
3176 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3177 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3178 // is B and qualifier_type is A). This is used to do the CS1540 check.
3180 // When resolving a SimpleName, `qualifier_type' is null.
3182 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3183 // the same than `queried_type' - except when we're being called from BaseAccess;
3184 // in this case, `invocation_type' is the current type and `queried_type' the base
3185 // type, so this'd normally trigger a CS1540.
3187 // The binding flags are `bf' and the kind of members being looked up are `mt'
3189 // The return value always includes private members which code in `invocation_type'
3190 // is allowed to access (using the specified `qualifier_type' if given); only use
3191 // BindingFlags.NonPublic to bypass the permission check.
3193 // The 'almost_match' argument is used for reporting error CS1540.
3195 // Returns an array of a single element for everything but Methods/Constructors
3196 // that might return multiple matches.
3198 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3199 Type queried_type, MemberTypes mt,
3200 BindingFlags original_bf, string name, IList almost_match)
3202 Timer.StartTimer (TimerType.MemberLookup);
3204 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3205 queried_type, mt, original_bf, name, almost_match);
3207 Timer.StopTimer (TimerType.MemberLookup);
3212 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3213 Type queried_type, MemberTypes mt,
3214 BindingFlags original_bf, string name, IList almost_match)
3216 BindingFlags bf = original_bf;
3218 ArrayList method_list = null;
3219 Type current_type = queried_type;
3220 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3221 bool skip_iface_check = true, used_cache = false;
3222 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3224 closure.invocation_type = invocation_type;
3225 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3226 closure.qualifier_type = qualifier_type;
3227 closure.almost_match = almost_match;
3229 // This is from the first time we find a method
3230 // in most cases, we do not actually find a method in the base class
3231 // so we can just ignore it, and save the arraylist allocation
3232 MemberInfo [] first_members_list = null;
3233 bool use_first_members_list = false;
3239 // `NonPublic' is lame, because it includes both protected and
3240 // private methods, so we need to control this behavior by
3241 // explicitly tracking if a private method is ok or not.
3243 // The possible cases are:
3244 // public, private and protected (internal does not come into the
3247 if ((invocation_type != null) &&
3248 ((invocation_type == current_type) ||
3249 IsNestedChildOf (invocation_type, current_type)) ||
3251 bf = original_bf | BindingFlags.NonPublic;
3255 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3257 Timer.StopTimer (TimerType.MemberLookup);
3259 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3261 Timer.StartTimer (TimerType.MemberLookup);
3264 // When queried for an interface type, the cache will automatically check all
3265 // inherited members, so we don't need to do this here. However, this only
3266 // works if we already used the cache in the first iteration of this loop.
3268 // If we used the cache in any further iteration, we can still terminate the
3269 // loop since the cache always looks in all base classes.
3275 skip_iface_check = false;
3277 if (current_type == TypeManager.object_type)
3280 current_type = current_type.BaseType;
3283 // This happens with interfaces, they have a null
3284 // basetype. Look members up in the Object class.
3286 if (current_type == null) {
3287 current_type = TypeManager.object_type;
3292 if (list.Length == 0)
3296 // Events and types are returned by both `static' and `instance'
3297 // searches, which means that our above FindMembers will
3298 // return two copies of the same.
3300 if (list.Length == 1 && !(list [0] is MethodBase)){
3305 // Multiple properties: we query those just to find out the indexer
3308 if (list [0] is PropertyInfo)
3312 // We found an event: the cache lookup returns both the event and
3313 // its private field.
3315 if (list [0] is EventInfo) {
3316 if ((list.Length == 2) && (list [1] is FieldInfo))
3317 return new MemberInfo [] { list [0] };
3323 // We found methods, turn the search into "method scan"
3327 if (first_members_list != null) {
3328 if (use_first_members_list) {
3329 method_list = CopyNewMethods (method_list, first_members_list);
3330 use_first_members_list = false;
3333 method_list = CopyNewMethods (method_list, list);
3335 first_members_list = list;
3336 use_first_members_list = true;
3337 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3339 } while (searching);
3341 if (use_first_members_list)
3342 return first_members_list;
3344 if (method_list != null && method_list.Count > 0) {
3345 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3348 // This happens if we already used the cache in the first iteration, in this case
3349 // the cache already looked in all interfaces.
3351 if (skip_iface_check)
3355 // Interfaces do not list members they inherit, so we have to
3358 if (!queried_type.IsInterface)
3361 if (queried_type.IsArray)
3362 queried_type = TypeManager.array_type;
3364 Type [] ifaces = GetInterfaces (queried_type);
3368 foreach (Type itype in ifaces){
3371 x = MemberLookup (null, null, itype, mt, bf, name, null);
3379 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3380 BindingFlags.Static | BindingFlags.Instance |
3381 BindingFlags.DeclaredOnly;
3383 // Currently is designed to work with external types only
3384 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3386 if (!mb.IsSpecialName)
3389 string name = mb.Name;
3390 if (name.Length < 5)
3393 if (name [3] != '_')
3396 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3397 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3398 Type.FilterName, name.Substring (4));
3403 // This can happen when property is indexer (it can have same name but different parameters)
3404 foreach (PropertyInfo p in pi) {
3405 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3406 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3415 // Currently is designed to work with external types only
3416 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3418 if (!mb.IsSpecialName)
3421 string name = mb.Name;
3422 if (name.Length < 5)
3425 if (name.StartsWith ("add_"))
3426 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3428 if (name.StartsWith ("remove_"))
3429 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3434 // Tests whether external method is really special
3435 public static bool IsSpecialMethod (MethodBase mb)
3437 if (!mb.IsSpecialName)
3440 IMethodData md = TypeManager.GetMethod (mb);
3442 return (md is AbstractPropertyEventMethod || md is Operator);
3444 PropertyInfo pi = GetPropertyFromAccessor (mb);
3446 return IsValidProperty (pi);
3448 if (GetEventFromAccessor (mb) != null)
3451 string name = mb.Name;
3452 if (name.StartsWith ("op_")){
3453 foreach (string oname in Unary.oper_names) {
3458 foreach (string oname in Binary.oper_names) {
3466 // Tests whether imported property is valid C# property.
3467 // TODO: It seems to me that we should do a lot of sanity tests before
3468 // we accept property as C# property
3469 static bool IsValidProperty (PropertyInfo pi)
3471 MethodInfo get_method = pi.GetGetMethod (true);
3472 MethodInfo set_method = pi.GetSetMethod (true);
3473 if (get_method != null && set_method != null) {
3474 int g_count = get_method.GetParameters ().Length;
3475 int s_count = set_method.GetParameters ().Length;
3476 if (g_count + 1 != s_count)
3487 /// There is exactly one instance of this class per type.
3489 public sealed class TypeHandle : IMemberContainer {
3490 public readonly IMemberContainer BaseType;
3492 readonly int id = ++next_id;
3493 static int next_id = 0;
3495 static TypeHandle ()
3501 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3502 /// a TypeHandle yet, a new instance of it is created. This static method
3503 /// ensures that we'll only have one TypeHandle instance per type.
3505 private static TypeHandle GetTypeHandle (Type t)
3507 TypeHandle handle = (TypeHandle) type_hash [t];
3511 handle = new TypeHandle (t);
3512 type_hash.Add (t, handle);
3516 public static MemberCache GetMemberCache (Type t)
3518 return GetTypeHandle (t).MemberCache;
3521 public static void CleanUp ()
3526 public static void Reset ()
3528 type_hash = new PtrHashtable ();
3532 /// Returns the TypeHandle for TypeManager.object_type.
3534 public static IMemberContainer ObjectType {
3536 if (object_type != null)
3539 object_type = GetTypeHandle (TypeManager.object_type);
3546 /// Returns the TypeHandle for TypeManager.array_type.
3548 public static TypeHandle ArrayType {
3550 if (array_type != null)
3553 array_type = GetTypeHandle (TypeManager.array_type);
3559 private static PtrHashtable type_hash;
3561 private static TypeHandle object_type = null;
3562 private static TypeHandle array_type = null;
3565 private string full_name;
3566 private bool is_interface;
3567 private MemberCache member_cache;
3568 private MemberCache base_cache;
3570 private TypeHandle (Type type)
3573 full_name = type.FullName != null ? type.FullName : type.Name;
3574 if (type.BaseType != null) {
3575 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3576 BaseType = base_cache.Container;
3577 } else if (type.IsInterface)
3578 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3579 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3580 this.member_cache = new MemberCache (this);
3583 // IMemberContainer methods
3585 public string Name {
3597 public MemberCache BaseCache {
3603 public bool IsInterface {
3605 return is_interface;
3609 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3611 MemberInfo [] members;
3614 if (type is GenericTypeParameterBuilder)
3615 return MemberList.Empty;
3618 if (mt == MemberTypes.Event)
3619 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3621 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3624 if (members.Length == 0)
3625 return MemberList.Empty;
3627 Array.Reverse (members);
3628 return new MemberList (members);
3631 // IMemberFinder methods
3633 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3634 MemberFilter filter, object criteria)
3636 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3639 public MemberCache MemberCache {
3641 return member_cache;
3645 public override string ToString ()
3647 if (BaseType != null)
3648 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3650 return "TypeHandle (" + id + "," + Name + ")";
3655 // Common expressions used by expression trees
3657 static class LinqExpression
3660 // These represent types thare are loaded from System.Core, similar
3661 // in spirit to the TypeManger _type variables.
3663 public static Type expression_type;
3664 public static Type parameter_expression_type;
3667 // The expressions represeing the internal types, if used
3669 public static TypeExpr expression_type_expr;
3671 static LinqExpression ()
3673 expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression");
3674 parameter_expression_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression");
3676 expression_type_expr = new TypeExpression (expression_type, Location.Null);