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 {
34 public partial class TypeManager {
36 // A list of core types that the compiler requires or uses
38 static public Type object_type;
39 static public Type value_type;
40 static public Type string_type;
41 static public Type int32_type;
42 static public Type uint32_type;
43 static public Type int64_type;
44 static public Type uint64_type;
45 static public Type float_type;
46 static public Type double_type;
47 static public Type char_type;
48 static public Type char_ptr_type;
49 static public Type short_type;
50 static public Type decimal_type;
51 static public Type bool_type;
52 static public Type sbyte_type;
53 static public Type byte_type;
54 static public Type ushort_type;
55 static public Type enum_type;
56 static public Type delegate_type;
57 static public Type multicast_delegate_type;
58 static public Type void_type;
59 static public Type null_type;
60 static public Type enumeration_type;
61 static public Type array_type;
62 static public Type runtime_handle_type;
63 static public Type icloneable_type;
64 static public Type type_type;
65 static public Type ienumerator_type;
66 static public Type ienumerable_type;
67 static public Type idisposable_type;
68 static public Type iconvertible_type;
69 static public Type default_member_type;
70 static public Type iasyncresult_type;
71 static public Type asynccallback_type;
72 static public Type intptr_type;
73 static public Type uintptr_type;
74 static public Type monitor_type;
75 static public Type interlocked_type;
76 static public Type runtime_field_handle_type;
77 static public Type runtime_argument_handle_type;
78 static public Type attribute_type;
79 static public Type attribute_usage_type;
80 static public Type decimal_constant_attribute_type;
81 static public Type dllimport_type;
82 static public Type unverifiable_code_type;
83 static public Type methodimpl_attr_type;
84 static public Type marshal_as_attr_type;
85 static public Type param_array_type;
86 static public Type void_ptr_type;
87 static public Type indexer_name_type;
88 static public Type exception_type;
89 static public Type invalid_operation_exception_type;
90 static public Type not_supported_exception_type;
91 static public Type obsolete_attribute_type;
92 static public Type conditional_attribute_type;
93 static public Type in_attribute_type;
94 static public Type out_attribute_type;
95 static public Type default_parameter_value_attribute_type;
97 static public Type anonymous_method_type;
98 static public Type cls_compliant_attribute_type;
99 static public Type typed_reference_type;
100 static public Type arg_iterator_type;
101 static public Type mbr_type;
102 static public Type struct_layout_attribute_type;
103 static public Type field_offset_attribute_type;
104 static public Type security_attr_type;
105 static public Type required_attr_type;
106 static public Type guid_attr_type;
107 static public Type assembly_culture_attribute_type;
108 static public Type coclass_attr_type;
109 static public Type comimport_attr_type;
115 static internal Type runtime_compatibility_attr_type;
116 static internal Type compiler_generated_attr_type;
117 static internal Type fixed_buffer_attr_type;
118 static internal Type default_charset_type;
119 static internal Type internals_visible_attr_type;
120 static internal Type type_forwarder_attr_type;
124 // Expressions representing the internal types. Used during declaration
127 static public TypeExpr system_object_expr, system_string_expr;
128 static public TypeExpr system_boolean_expr, system_decimal_expr;
129 static public TypeExpr system_single_expr, system_double_expr;
130 static public TypeExpr system_sbyte_expr, system_byte_expr;
131 static public TypeExpr system_int16_expr, system_uint16_expr;
132 static public TypeExpr system_int32_expr, system_uint32_expr;
133 static public TypeExpr system_int64_expr, system_uint64_expr;
134 static public TypeExpr system_char_expr, system_void_expr;
135 static public TypeExpr system_asynccallback_expr;
136 static public TypeExpr system_iasyncresult_expr;
137 static public TypeExpr system_valuetype_expr;
138 static public TypeExpr system_intptr_expr;
141 // This is only used when compiling corlib
143 static public Type system_int32_type;
144 static public Type system_array_type;
145 static public Type system_type_type;
146 static public Type system_assemblybuilder_type;
147 static public MethodInfo system_int_array_get_length;
148 static public MethodInfo system_int_array_get_rank;
149 static public MethodInfo system_object_array_clone;
150 static public MethodInfo system_int_array_get_length_int;
151 static public MethodInfo system_int_array_get_lower_bound_int;
152 static public MethodInfo system_int_array_get_upper_bound_int;
153 static public MethodInfo system_void_array_copyto_array_int;
157 // Internal, not really used outside
159 static Type runtime_helpers_type;
162 // These methods are called by code generated by the compiler
164 static public MethodInfo string_concat_string_string;
165 static public MethodInfo string_concat_string_string_string;
166 static public MethodInfo string_concat_string_string_string_string;
167 static public MethodInfo string_concat_string_dot_dot_dot;
168 static public MethodInfo string_concat_object_object;
169 static public MethodInfo string_concat_object_object_object;
170 static public MethodInfo string_concat_object_dot_dot_dot;
171 static public MethodInfo string_isinterneted_string;
172 static public MethodInfo system_type_get_type_from_handle;
173 static public MethodInfo bool_movenext_void;
174 static public MethodInfo ienumerable_getenumerator_void;
175 static public MethodInfo void_reset_void;
176 static public MethodInfo void_dispose_void;
177 static public MethodInfo void_monitor_enter_object;
178 static public MethodInfo void_monitor_exit_object;
179 static public MethodInfo void_initializearray_array_fieldhandle;
180 static public MethodInfo int_getlength_int;
181 static public MethodInfo delegate_combine_delegate_delegate;
182 static public MethodInfo delegate_remove_delegate_delegate;
183 static public MethodInfo int_get_offset_to_string_data;
184 static public MethodInfo int_array_get_length;
185 static public MethodInfo int_array_get_rank;
186 static public MethodInfo object_array_clone;
187 static public MethodInfo int_array_get_length_int;
188 static public MethodInfo int_array_get_lower_bound_int;
189 static public MethodInfo int_array_get_upper_bound_int;
190 static public MethodInfo void_array_copyto_array_int;
191 static public MethodInfo int_interlocked_compare_exchange;
192 static public PropertyInfo ienumerator_getcurrent;
195 // The attribute constructors.
197 static public ConstructorInfo object_ctor;
198 static private ConstructorInfo cons_param_array_attribute;
199 static public ConstructorInfo void_decimal_ctor_five_args;
200 static public ConstructorInfo void_decimal_ctor_int_arg;
201 static public ConstructorInfo unverifiable_code_ctor;
202 static public ConstructorInfo default_member_ctor;
203 static public ConstructorInfo decimal_constant_attribute_ctor;
204 static internal ConstructorInfo struct_layout_attribute_ctor;
205 static public ConstructorInfo field_offset_attribute_ctor;
211 static internal CustomAttributeBuilder compiler_generated_attr;
212 static internal ConstructorInfo fixed_buffer_attr_ctor;
215 static PtrHashtable builder_to_declspace;
217 static PtrHashtable builder_to_member_cache;
220 // Tracks the interfaces implemented by typebuilders. We only
221 // enter those who do implement or or more interfaces
223 static PtrHashtable builder_to_ifaces;
226 // Maps PropertyBuilder to a Type array that contains
227 // the arguments to the indexer
229 static Hashtable indexer_arguments;
232 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
234 static Hashtable method_params;
237 // A hash table from override methods to their base virtual method.
239 static Hashtable method_overrides;
242 // Keeps track of methods
245 static Hashtable builder_to_method;
248 // Contains all public types from referenced assemblies.
249 // This member is used only if CLS Compliance verification is required.
251 public static Hashtable AllClsTopLevelTypes;
253 static Hashtable fieldbuilders_to_fields;
254 static Hashtable propertybuilder_to_property;
255 static Hashtable fields;
256 static Hashtable events;
259 static PtrHashtable assembly_internals_vis_attrs;
267 public static void CleanUp ()
269 // Lets get everything clean so that we can collect before generating code
270 builder_to_declspace = null;
271 builder_to_member_cache = null;
272 builder_to_ifaces = null;
273 builder_to_type_param = null;
274 indexer_arguments = null;
275 method_params = null;
276 builder_to_method = null;
279 fieldbuilders_to_fields = null;
281 priv_fields_events = null;
283 propertybuilder_to_property = null;
286 assembly_internals_vis_attrs = null;
289 TypeHandle.CleanUp ();
293 /// A filter for Findmembers that uses the Signature object to
296 static bool SignatureFilter (MemberInfo mi, object criteria)
298 Signature sig = (Signature) criteria;
300 if (!(mi is MethodBase))
303 if (mi.Name != sig.name)
306 int count = sig.args.Length;
308 if (mi is MethodBuilder || mi is ConstructorBuilder){
309 Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
311 if (candidate_args.Length != count)
314 for (int i = 0; i < count; i++)
315 if (candidate_args [i] != sig.args [i])
320 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
322 if (pars.Length != count)
325 for (int i = 0; i < count; i++)
326 if (pars [i].ParameterType != sig.args [i])
332 // A delegate that points to the filter above.
333 static MemberFilter signature_filter;
336 // These are expressions that represent some of the internal data types, used
339 static void InitExpressionTypes ()
341 system_object_expr = new TypeLookupExpression ("System.Object");
342 system_string_expr = new TypeLookupExpression ("System.String");
343 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
344 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
345 system_single_expr = new TypeLookupExpression ("System.Single");
346 system_double_expr = new TypeLookupExpression ("System.Double");
347 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
348 system_byte_expr = new TypeLookupExpression ("System.Byte");
349 system_int16_expr = new TypeLookupExpression ("System.Int16");
350 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
351 system_int32_expr = new TypeLookupExpression ("System.Int32");
352 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
353 system_int64_expr = new TypeLookupExpression ("System.Int64");
354 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
355 system_char_expr = new TypeLookupExpression ("System.Char");
356 system_void_expr = new TypeLookupExpression ("System.Void");
357 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
358 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
359 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
360 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
363 static TypeManager ()
367 signature_filter = new MemberFilter (SignatureFilter);
368 InitExpressionTypes ();
371 static public void Reset ()
373 builder_to_declspace = new PtrHashtable ();
374 builder_to_member_cache = new PtrHashtable ();
375 builder_to_method = new PtrHashtable ();
376 builder_to_type_param = new PtrHashtable ();
377 method_params = new PtrHashtable ();
378 method_overrides = new PtrHashtable ();
379 indexer_arguments = new PtrHashtable ();
380 builder_to_ifaces = new PtrHashtable ();
382 fieldbuilders_to_fields = new Hashtable ();
383 propertybuilder_to_property = new Hashtable ();
384 fields = new Hashtable ();
385 type_hash = new DoubleHash ();
388 assembly_internals_vis_attrs = new PtrHashtable ();
391 // to uncover regressions
392 cons_param_array_attribute = null;
395 public static void AddUserType (DeclSpace ds)
397 builder_to_declspace.Add (ds.TypeBuilder, ds);
401 // This entry point is used by types that we define under the covers
403 public static void RegisterBuilder (Type tb, Type [] ifaces)
406 builder_to_ifaces [tb] = ifaces;
409 public static void AddMethod (MethodBase builder, IMethodData method)
411 builder_to_method.Add (builder, method);
412 method_params.Add (builder, method.ParameterInfo);
415 public static IMethodData GetMethod (MethodBase builder)
417 return (IMethodData) builder_to_method [builder];
421 /// Returns the DeclSpace whose Type is `t' or null if there is no
422 /// DeclSpace for `t' (ie, the Type comes from a library)
424 public static DeclSpace LookupDeclSpace (Type t)
426 return builder_to_declspace [t] as DeclSpace;
430 /// Returns the TypeContainer whose Type is `t' or null if there is no
431 /// TypeContainer for `t' (ie, the Type comes from a library)
433 public static TypeContainer LookupTypeContainer (Type t)
435 return builder_to_declspace [t] as TypeContainer;
438 public static MemberCache LookupMemberCache (Type t)
440 #if GMCS_SOURCE && MS_COMPATIBLE
441 if (t.IsGenericType && !t.IsGenericTypeDefinition)
442 t = t.GetGenericTypeDefinition ();
445 if (t is TypeBuilder) {
446 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
447 if (container != null)
448 return container.MemberCache;
452 if (t is GenericTypeParameterBuilder) {
453 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
455 if (container != null)
456 return container.MemberCache;
460 return TypeHandle.GetMemberCache (t);
463 public static MemberCache LookupBaseInterfacesCache (Type t)
465 Type [] ifaces = GetInterfaces (t);
467 if (ifaces != null && ifaces.Length == 1)
468 return LookupMemberCache (ifaces [0]);
470 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
471 MemberCache cache = builder_to_member_cache [t] as MemberCache;
475 cache = new MemberCache (ifaces);
476 builder_to_member_cache.Add (t, cache);
480 public static TypeContainer LookupInterface (Type t)
482 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
483 if ((tc == null) || (tc.Kind != Kind.Interface))
489 public static Delegate LookupDelegate (Type t)
491 return builder_to_declspace [t] as Delegate;
494 public static Class LookupClass (Type t)
496 return (Class) builder_to_declspace [t];
500 // We use this hash for multiple kinds of constructed types:
502 // (T, "&") Given T, get T &
503 // (T, "*") Given T, get T *
504 // (T, "[]") Given T and a array dimension, get T []
505 // (T, X) Given a type T and a simple name X, get the type T+X
507 // Accessibility tests, if necessary, should be done by the user
509 static DoubleHash type_hash = new DoubleHash ();
512 // Gets the reference to T version of the Type (T&)
514 public static Type GetReferenceType (Type t)
517 return t.MakeByRefType ();
519 return GetConstructedType (t, "&");
524 // Gets the pointer to T version of the Type (T*)
526 public static Type GetPointerType (Type t)
528 return GetConstructedType (t, "*");
531 public static Type GetConstructedType (Type t, string dim)
534 if (type_hash.Lookup (t, dim, out ret))
537 ret = t.Module.GetType (t.ToString () + dim);
539 type_hash.Insert (t, dim, ret);
544 ret = GetReferenceType (t);
545 type_hash.Insert (t, dim, ret);
550 if (t.IsGenericParameter || t.IsGenericType) {
553 while ((pos < dim.Length) && (dim [pos] == '[')) {
556 if (dim [pos] == ']') {
557 result = result.MakeArrayType ();
560 if (pos < dim.Length)
563 type_hash.Insert (t, dim, result);
568 while (dim [pos] == ',') {
572 if ((dim [pos] != ']') || (pos != dim.Length-1))
575 result = result.MakeArrayType (rank + 1);
576 type_hash.Insert (t, dim, result);
582 type_hash.Insert (t, dim, null);
586 public static Type GetNestedType (Type t, string name)
589 if (!type_hash.Lookup (t, name, out ret)) {
590 ret = t.GetNestedType (name,
591 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
592 type_hash.Insert (t, name, ret);
598 /// Fills static table with exported types from all referenced assemblies.
599 /// This information is required for CLS Compliance tests.
601 public static void LoadAllImportedTypes ()
603 AllClsTopLevelTypes = new Hashtable (1500);
604 foreach (Assembly a in RootNamespace.Global.Assemblies) {
605 foreach (Type t in a.GetExportedTypes ()) {
606 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
611 public static bool NamespaceClash (string name, Location loc)
613 if (! RootNamespace.Global.IsNamespace (name))
616 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
621 /// Returns the C# name of a type if possible, or the full type name otherwise
623 static public string CSharpName (Type t)
625 if (t == typeof(NullType))
629 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
630 t = GetTypeArguments (t) [0];
631 return CSharpName (t) + "?";
635 string name = GetFullName (t);
637 return Regex.Replace (name,
639 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
640 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
641 @"Boolean|String|Void|Null)" +
643 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
646 static public string CSharpName (Type[] types)
648 StringBuilder sb = new StringBuilder ();
649 foreach (Type t in types) {
650 sb.Append (CSharpName (t));
653 sb.Remove (sb.Length - 1, 1);
654 return sb.ToString ();
657 static String CSharpNameMatch (Match match)
659 string s = match.Groups [1].Captures [0].Value;
661 Replace ("int32", "int").
662 Replace ("uint32", "uint").
663 Replace ("int16", "short").
664 Replace ("uint16", "ushort").
665 Replace ("int64", "long").
666 Replace ("uint64", "ulong").
667 Replace ("single", "float").
668 Replace ("boolean", "bool")
669 + match.Groups [2].Captures [0].Value;
673 /// Returns the signature of the method with full namespace classification
675 static public string GetFullNameSignature (MemberInfo mi)
677 PropertyInfo pi = mi as PropertyInfo;
679 MethodBase pmi = pi.GetGetMethod (true);
681 pmi = pi.GetSetMethod (true);
682 if (GetParameterData (pmi).Count > 0)
685 return (mi is MethodBase)
686 ? CSharpSignature (mi as MethodBase)
687 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
691 private static int GetFullName (Type t, StringBuilder sb)
695 if (!t.IsGenericType) {
696 sb.Append (t.FullName);
700 if (t.DeclaringType != null) {
701 pos = GetFullName (t.DeclaringType, sb);
703 sb.Append (RemoveGenericArity (t.Name));
705 sb.Append (RemoveGenericArity (t.FullName));
708 Type[] this_args = GetTypeArguments (t);
710 if (this_args.Length < pos)
711 throw new InternalErrorException (
712 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
713 if (this_args.Length == pos)
718 sb.Append (CSharpName (this_args [pos++]));
719 if (pos == this_args.Length)
727 public static string GetFullName (Type t)
729 if (t.IsGenericParameter)
731 if (!t.IsGenericType)
734 StringBuilder sb = new StringBuilder ();
735 int pos = GetFullName (t, sb);
737 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
738 return sb.ToString ();
741 public static string GetFullName (Type t)
747 public static string RemoveGenericArity (string from)
749 int i = from.IndexOf ('`');
751 return from.Substring (0, i);
756 /// When we need to report accessors as well
758 static public string CSharpSignature (MethodBase mb)
760 return CSharpSignature (mb, false);
764 /// Returns the signature of the method
766 static public string CSharpSignature (MethodBase mb, bool show_accessor)
768 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
771 ParameterData iparams = GetParameterData (mb);
772 string parameters = iparams.GetSignatureForError ();
773 string accessor = "";
776 if (mb.IsSpecialName) {
777 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
778 if (ot != Operator.OpType.TOP) {
779 sig.Append ("operator ");
780 sig.Append (Operator.GetName (ot));
781 sig.Append (parameters);
782 return sig.ToString ();
785 if (mb.Name.StartsWith ("get_") || mb.Name.StartsWith ("set_")) {
786 accessor = mb.Name.Substring (0, 3);
791 if (mb.IsSpecialName && !mb.IsConstructor) {
792 if (iparams.Count > (mb.Name.StartsWith ("get_") ? 0 : 1)) {
793 sig.Append ("this[");
795 sig.Append (parameters.Substring (1, parameters.Length - 2));
798 int before_ret_val = parameters.LastIndexOf (',');
799 if (before_ret_val < 0)
800 sig.Append (parameters.Substring (1, parameters.Length - 2));
802 sig.Append (parameters.Substring (1, before_ret_val - 1));
806 sig.Append (mb.Name.Substring (4));
809 if (mb.Name == ".ctor")
810 sig.Append (mb.DeclaringType.Name);
812 sig.Append (mb.Name);
815 if (TypeManager.IsGenericMethod (mb)) {
816 Type[] args = mb.GetGenericArguments ();
818 for (int i = 0; i < args.Length; i++) {
821 sig.Append (args [i].Name);
828 sig.Append (parameters);
831 if (show_accessor && accessor.Length > 0) {
833 sig.Append (accessor);
836 return sig.ToString ();
839 public static string GetMethodName (MethodInfo m)
842 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
845 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
851 static public string CSharpSignature (EventInfo ei)
853 return CSharpName (ei.DeclaringType) + '.' + ei.Name;
857 /// Looks up a type, and aborts if it is not found. This is used
858 /// by types required by the compiler
860 static Type CoreLookupType (string ns_name, string name)
862 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
863 FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
864 Type t = fne == null ? null : fne.Type;
866 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
871 /// Returns the MethodInfo for a method named `name' defined
872 /// in type `t' which takes arguments of types `args'
874 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
878 BindingFlags flags = instance_and_static | BindingFlags.Public;
884 flags |= BindingFlags.NonPublic;
886 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
887 if (list.Count == 0) {
889 Report.Error (-19, "Can not find the core function `" + name + "'");
893 MethodInfo mi = list [0] as MethodInfo;
896 Report.Error (-19, "Can not find the core function `" + name + "'");
903 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
905 return GetMethod (t, name, args, false, report_errors);
908 public static MethodInfo GetMethod (Type t, string name, Type [] args)
910 return GetMethod (t, name, args, true);
914 /// Returns the PropertyInfo for a property named `name' defined
917 public static PropertyInfo GetProperty (Type t, string name)
919 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
920 BindingFlags.Instance, Type.FilterName, name);
921 if (list.Count == 0) {
922 Report.Error (-19, "Can not find the core property `" + name + "'");
926 PropertyInfo pi = list [0] as PropertyInfo;
928 Report.Error (-19, "Can not find the core function `" + name + "'");
936 /// Returns the ConstructorInfo for "args"
938 public static ConstructorInfo GetConstructor (Type t, Type [] args)
947 throw new InternalErrorException ("Core types haven't been initialized yet?");
949 list = FindMembers (t, MemberTypes.Constructor,
950 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
951 signature_filter, sig);
952 if (list.Count == 0){
953 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
957 ConstructorInfo ci = list [0] as ConstructorInfo;
959 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
966 public static void InitEnumUnderlyingTypes ()
968 int32_type = CoreLookupType ("System", "Int32");
969 int64_type = CoreLookupType ("System", "Int64");
970 uint32_type = CoreLookupType ("System", "UInt32");
971 uint64_type = CoreLookupType ("System", "UInt64");
972 byte_type = CoreLookupType ("System", "Byte");
973 sbyte_type = CoreLookupType ("System", "SByte");
974 short_type = CoreLookupType ("System", "Int16");
975 ushort_type = CoreLookupType ("System", "UInt16");
977 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
978 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
980 idisposable_type = CoreLookupType ("System", "IDisposable");
983 InitGenericCoreTypes ();
988 /// The types have to be initialized after the initial
989 /// population of the type has happened (for example, to
990 /// bootstrap the corlib.dll
992 public static void InitCoreTypes ()
994 object_type = CoreLookupType ("System", "Object");
995 value_type = CoreLookupType ("System", "ValueType");
997 InitEnumUnderlyingTypes ();
999 char_type = CoreLookupType ("System", "Char");
1000 string_type = CoreLookupType ("System", "String");
1001 float_type = CoreLookupType ("System", "Single");
1002 double_type = CoreLookupType ("System", "Double");
1003 char_ptr_type = GetPointerType (char_type);
1004 decimal_type = CoreLookupType ("System", "Decimal");
1005 bool_type = CoreLookupType ("System", "Boolean");
1006 enum_type = CoreLookupType ("System", "Enum");
1008 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
1009 delegate_type = CoreLookupType ("System", "Delegate");
1011 array_type = CoreLookupType ("System", "Array");
1012 void_type = CoreLookupType ("System", "Void");
1013 type_type = CoreLookupType ("System", "Type");
1015 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
1016 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
1017 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
1018 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
1019 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
1020 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
1021 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
1022 icloneable_type = CoreLookupType ("System", "ICloneable");
1023 iconvertible_type = CoreLookupType ("System", "IConvertible");
1024 interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
1025 monitor_type = CoreLookupType ("System.Threading", "Monitor");
1026 intptr_type = CoreLookupType ("System", "IntPtr");
1027 uintptr_type = CoreLookupType ("System", "UIntPtr");
1029 attribute_type = CoreLookupType ("System", "Attribute");
1030 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
1031 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
1032 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
1033 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
1034 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
1035 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
1036 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
1038 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1040 typed_reference_type = CoreLookupType ("System", "TypedReference");
1041 arg_iterator_type = CoreLookupType ("System", "ArgIterator");
1042 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
1043 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1045 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
1047 void_ptr_type = GetPointerType (void_type);
1049 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1051 exception_type = CoreLookupType ("System", "Exception");
1052 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
1053 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
1058 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
1059 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
1060 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
1061 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
1062 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1063 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
1064 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1065 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
1066 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
1067 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
1068 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
1074 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1075 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1076 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1077 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1078 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1079 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1082 // When compiling corlib, store the "real" types here.
1084 if (!RootContext.StdLib) {
1085 system_int32_type = typeof (System.Int32);
1086 system_array_type = typeof (System.Array);
1087 system_type_type = typeof (System.Type);
1088 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1090 system_int_array_get_length = GetMethod (
1091 system_array_type, "get_Length", Type.EmptyTypes);
1092 system_int_array_get_rank = GetMethod (
1093 system_array_type, "get_Rank", Type.EmptyTypes);
1094 system_object_array_clone = GetMethod (
1095 system_array_type, "Clone", Type.EmptyTypes);
1097 Type [] system_int_arg = { system_int32_type };
1098 system_int_array_get_length_int = GetMethod (
1099 system_array_type, "GetLength", system_int_arg);
1100 system_int_array_get_upper_bound_int = GetMethod (
1101 system_array_type, "GetUpperBound", system_int_arg);
1102 system_int_array_get_lower_bound_int = GetMethod (
1103 system_array_type, "GetLowerBound", system_int_arg);
1105 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1106 system_void_array_copyto_array_int = GetMethod (
1107 system_array_type, "CopyTo", system_array_int_arg);
1109 Type [] system_3_type_arg = {
1110 system_type_type, system_type_type, system_type_type };
1111 Type [] system_4_type_arg = {
1112 system_type_type, system_type_type, system_type_type, system_type_type };
1114 MethodInfo set_corlib_type_builders = GetMethod (
1115 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1116 system_4_type_arg, true, false);
1118 if (set_corlib_type_builders != null) {
1119 object[] args = new object [4];
1120 args [0] = object_type;
1121 args [1] = value_type;
1122 args [2] = enum_type;
1123 args [3] = void_type;
1125 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1127 // Compatibility for an older version of the class libs.
1128 set_corlib_type_builders = GetMethod (
1129 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1130 system_3_type_arg, true, true);
1132 if (set_corlib_type_builders == null) {
1133 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1137 object[] args = new object [3];
1138 args [0] = object_type;
1139 args [1] = value_type;
1140 args [2] = enum_type;
1142 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1146 system_object_expr.Type = object_type;
1147 system_string_expr.Type = string_type;
1148 system_boolean_expr.Type = bool_type;
1149 system_decimal_expr.Type = decimal_type;
1150 system_single_expr.Type = float_type;
1151 system_double_expr.Type = double_type;
1152 system_sbyte_expr.Type = sbyte_type;
1153 system_byte_expr.Type = byte_type;
1154 system_int16_expr.Type = short_type;
1155 system_uint16_expr.Type = ushort_type;
1156 system_int32_expr.Type = int32_type;
1157 system_uint32_expr.Type = uint32_type;
1158 system_int64_expr.Type = int64_type;
1159 system_uint64_expr.Type = uint64_type;
1160 system_char_expr.Type = char_type;
1161 system_void_expr.Type = void_type;
1162 system_asynccallback_expr.Type = asynccallback_type;
1163 system_iasyncresult_expr.Type = iasyncresult_type;
1164 system_valuetype_expr.Type = value_type;
1167 // These are only used for compare purposes
1169 anonymous_method_type = typeof (AnonymousMethod);
1170 null_type = typeof (NullType);
1174 // The helper methods that are used by the compiler
1176 public static void InitCodeHelpers ()
1179 // Now load the default methods that we use.
1181 Type [] string_string = { string_type, string_type };
1182 string_concat_string_string = GetMethod (
1183 string_type, "Concat", string_string);
1184 Type [] string_string_string = { string_type, string_type, string_type };
1185 string_concat_string_string_string = GetMethod (
1186 string_type, "Concat", string_string_string);
1187 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1188 string_concat_string_string_string_string = GetMethod (
1189 string_type, "Concat", string_string_string_string);
1190 Type[] params_string = { GetConstructedType (string_type, "[]") };
1191 string_concat_string_dot_dot_dot = GetMethod (
1192 string_type, "Concat", params_string);
1194 Type [] object_object = { object_type, object_type };
1195 string_concat_object_object = GetMethod (
1196 string_type, "Concat", object_object);
1197 Type [] object_object_object = { object_type, object_type, object_type };
1198 string_concat_object_object_object = GetMethod (
1199 string_type, "Concat", object_object_object);
1200 Type[] params_object = { GetConstructedType (object_type, "[]") };
1201 string_concat_object_dot_dot_dot = GetMethod (
1202 string_type, "Concat", params_object);
1204 Type [] string_ = { string_type };
1205 string_isinterneted_string = GetMethod (
1206 string_type, "IsInterned", string_);
1208 Type [] runtime_type_handle = { runtime_handle_type };
1209 system_type_get_type_from_handle = GetMethod (
1210 type_type, "GetTypeFromHandle", runtime_type_handle);
1212 Type [] delegate_delegate = { delegate_type, delegate_type };
1213 delegate_combine_delegate_delegate = GetMethod (
1214 delegate_type, "Combine", delegate_delegate);
1216 delegate_remove_delegate_delegate = GetMethod (
1217 delegate_type, "Remove", delegate_delegate);
1222 ienumerator_getcurrent = GetProperty (
1223 ienumerator_type, "Current");
1224 bool_movenext_void = GetMethod (
1225 ienumerator_type, "MoveNext", Type.EmptyTypes);
1226 void_reset_void = GetMethod (
1227 ienumerator_type, "Reset", Type.EmptyTypes);
1228 void_dispose_void = GetMethod (
1229 idisposable_type, "Dispose", Type.EmptyTypes);
1230 int_get_offset_to_string_data = GetMethod (
1231 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1232 int_array_get_length = GetMethod (
1233 array_type, "get_Length", Type.EmptyTypes);
1234 int_array_get_rank = GetMethod (
1235 array_type, "get_Rank", Type.EmptyTypes);
1236 ienumerable_getenumerator_void = GetMethod (
1237 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1242 Type [] int_arg = { int32_type };
1243 int_array_get_length_int = GetMethod (
1244 array_type, "GetLength", int_arg);
1245 int_array_get_upper_bound_int = GetMethod (
1246 array_type, "GetUpperBound", int_arg);
1247 int_array_get_lower_bound_int = GetMethod (
1248 array_type, "GetLowerBound", int_arg);
1251 // System.Array methods
1253 object_array_clone = GetMethod (
1254 array_type, "Clone", Type.EmptyTypes);
1255 Type [] array_int_arg = { array_type, int32_type };
1256 void_array_copyto_array_int = GetMethod (
1257 array_type, "CopyTo", array_int_arg);
1262 Type [] object_arg = { object_type };
1263 void_monitor_enter_object = GetMethod (
1264 monitor_type, "Enter", object_arg);
1265 void_monitor_exit_object = GetMethod (
1266 monitor_type, "Exit", object_arg);
1268 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1270 void_initializearray_array_fieldhandle = GetMethod (
1271 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1276 int_getlength_int = GetMethod (
1277 array_type, "GetLength", int_arg);
1280 // Decimal constructors
1282 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1283 void_decimal_ctor_five_args = GetConstructor (
1284 decimal_type, dec_arg);
1286 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1291 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1292 default_member_ctor = GetConstructor (default_member_type, string_);
1294 Type[] short_arg = { short_type };
1295 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1297 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1298 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1300 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1304 // System.Threading.CompareExchange
1306 Type[] compare_exchange_types = {
1307 GetReferenceType (int32_type), int32_type, int32_type };
1308 int_interlocked_compare_exchange = GetMethod (
1309 interlocked_type, "CompareExchange", compare_exchange_types);
1315 compiler_generated_attr = new CustomAttributeBuilder (
1316 GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1318 Type[] type_int_arg = { type_type, int32_type };
1319 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1323 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1326 InitGenericCodeHelpers ();
1330 static public ConstructorInfo ConsParamArrayAttribute {
1332 if (cons_param_array_attribute == null)
1333 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1334 return cons_param_array_attribute;
1338 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1341 /// This is the "old", non-cache based FindMembers() function. We cannot use
1342 /// the cache here because there is no member name argument.
1344 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1345 MemberFilter filter, object criteria)
1347 #if MS_COMPATIBLE && GMCS_SOURCE
1348 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1349 t = t.GetGenericTypeDefinition ();
1352 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1355 // `builder_to_declspace' contains all dynamic types.
1359 Timer.StartTimer (TimerType.FindMembers);
1360 list = decl.FindMembers (mt, bf, filter, criteria);
1361 Timer.StopTimer (TimerType.FindMembers);
1366 // We have to take care of arrays specially, because GetType on
1367 // a TypeBuilder array will return a Type, not a TypeBuilder,
1368 // and we can not call FindMembers on this type.
1371 #if MS_COMPATIBLE && GMCS_SOURCE
1374 t.IsSubclassOf (TypeManager.array_type))
1375 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1378 if (t is GenericTypeParameterBuilder) {
1379 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1381 Timer.StartTimer (TimerType.FindMembers);
1382 MemberList list = tparam.FindMembers (
1383 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1384 Timer.StopTimer (TimerType.FindMembers);
1390 // Since FindMembers will not lookup both static and instance
1391 // members, we emulate this behaviour here.
1393 if ((bf & instance_and_static) == instance_and_static){
1394 MemberInfo [] i_members = t.FindMembers (
1395 mt, bf & ~BindingFlags.Static, filter, criteria);
1397 int i_len = i_members.Length;
1399 MemberInfo one = i_members [0];
1402 // If any of these are present, we are done!
1404 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1405 return new MemberList (i_members);
1408 MemberInfo [] s_members = t.FindMembers (
1409 mt, bf & ~BindingFlags.Instance, filter, criteria);
1411 int s_len = s_members.Length;
1412 if (i_len > 0 || s_len > 0)
1413 return new MemberList (i_members, s_members);
1416 return new MemberList (i_members);
1418 return new MemberList (s_members);
1422 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1427 /// This method is only called from within MemberLookup. It tries to use the member
1428 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1429 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1430 /// our return value will already contain all inherited members and the caller don't need
1431 /// to check base classes and interfaces anymore.
1433 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1434 string name, out bool used_cache)
1438 #if GMCS_SOURCE && MS_COMPATIBLE
1439 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1440 t = t.GetGenericTypeDefinition();
1444 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1445 // and we can ask the DeclSpace for the MemberCache.
1447 if (t is TypeBuilder) {
1448 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1449 cache = decl.MemberCache;
1452 // If this DeclSpace has a MemberCache, use it.
1455 if (cache != null) {
1457 return cache.FindMembers (
1458 mt, bf, name, FilterWithClosure_delegate, null);
1461 // If there is no MemberCache, we need to use the "normal" FindMembers.
1462 // Note, this is a VERY uncommon route!
1465 Timer.StartTimer (TimerType.FindMembers);
1466 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1467 FilterWithClosure_delegate, name);
1468 Timer.StopTimer (TimerType.FindMembers);
1470 return (MemberInfo []) list;
1474 // We have to take care of arrays specially, because GetType on
1475 // a TypeBuilder array will return a Type, not a TypeBuilder,
1476 // and we can not call FindMembers on this type.
1478 if (t.IsArray) { // == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1480 return TypeHandle.ArrayType.MemberCache.FindMembers (
1481 mt, bf, name, FilterWithClosure_delegate, null);
1485 if (t is GenericTypeParameterBuilder) {
1486 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1489 Timer.StartTimer (TimerType.FindMembers);
1490 list = tparam.FindMembers (mt, bf & ~BindingFlags.DeclaredOnly,
1491 FilterWithClosure_delegate, name);
1492 Timer.StopTimer (TimerType.FindMembers);
1494 return (MemberInfo []) list;
1498 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1500 // This happens if we're resolving a class'es base class and interfaces
1501 // in TypeContainer.DefineType(). At this time, the types aren't
1502 // populated yet, so we can't use the cache.
1504 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1505 FilterWithClosure_delegate, name);
1511 // This call will always succeed. There is exactly one TypeHandle instance per
1512 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1513 // the corresponding MemberCache.
1515 cache = TypeHandle.GetMemberCache (t);
1518 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1521 public static bool IsBuiltinType (Type t)
1523 t = TypeToCoreType (t);
1524 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1525 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1526 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1527 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1533 public static bool IsBuiltinType (TypeContainer tc)
1535 return IsBuiltinType (tc.TypeBuilder);
1539 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1540 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1542 public static bool IsPrimitiveType (Type t)
1544 return (t == int32_type || t == uint32_type ||
1545 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1546 t == char_type || t == short_type || t == bool_type ||
1547 t == sbyte_type || t == byte_type || t == ushort_type);
1550 public static bool IsDelegateType (Type t)
1552 t = DropGenericTypeArguments (t);
1553 if (t.IsSubclassOf (TypeManager.delegate_type))
1559 public static bool IsEnumType (Type t)
1561 if (builder_to_declspace [t] is Enum)
1564 #if MS_COMPATIBLE && GMCS_SOURCE
1565 if (t.IsGenericParameter || t.IsGenericType)
1571 public static bool IsBuiltinOrEnum (Type t)
1573 if (IsBuiltinType (t))
1582 public static bool IsNullType (Type t)
1584 return t == null_type;
1587 public static bool IsAttributeType (Type t)
1589 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1592 static Stack unmanaged_enclosing_types = new Stack (4);
1595 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1597 public static bool IsUnmanagedType (Type t)
1599 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1600 if (unmanaged_enclosing_types.Contains (t))
1603 // builtins that are not unmanaged types
1604 if (t == TypeManager.object_type || t == TypeManager.string_type)
1607 if (IsGenericType (t) || IsGenericParameter (t))
1610 if (IsBuiltinOrEnum (t))
1613 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1617 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1621 if (!IsValueType (t))
1625 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1626 if (p.IsGenericTypeDefinition)
1631 unmanaged_enclosing_types.Push (t);
1635 if (t is TypeBuilder) {
1636 TypeContainer tc = LookupTypeContainer (t);
1637 if (tc.Fields != null){
1638 foreach (FieldMember f in tc.Fields){
1639 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1640 if ((f.ModFlags & Modifiers.STATIC) != 0)
1642 if (f.MemberType == null)
1644 if (!IsUnmanagedType (f.MemberType)){
1645 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1651 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1653 foreach (FieldInfo f in fields){
1654 if (!IsUnmanagedType (f.FieldType)){
1655 Report.SymbolRelatedToPreviousError (f);
1661 unmanaged_enclosing_types.Pop ();
1666 public static bool IsValueType (Type t)
1668 return t.IsValueType || IsGenericParameter (t);
1671 public static bool IsInterfaceType (Type t)
1673 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1677 return tc.Kind == Kind.Interface;
1680 public static bool IsSubclassOf (Type type, Type base_type)
1682 TypeParameter tparam = LookupTypeParameter (type);
1683 TypeParameter pparam = LookupTypeParameter (base_type);
1685 if ((tparam != null) && (pparam != null)) {
1686 if (tparam == pparam)
1689 return tparam.IsSubclassOf (base_type);
1692 #if MS_COMPATIBLE && GMCS_SOURCE
1693 if (type.IsGenericType)
1694 type = type.GetGenericTypeDefinition ();
1697 if (type.IsSubclassOf (base_type))
1701 if (IsEqual (type, base_type))
1704 type = type.BaseType;
1705 } while (type != null);
1710 public static bool IsPrivateAccessible (Type type, Type parent)
1715 if (type.Equals (parent))
1718 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1721 public static bool IsFamilyAccessible (Type type, Type parent)
1723 TypeParameter tparam = LookupTypeParameter (type);
1724 TypeParameter pparam = LookupTypeParameter (parent);
1726 if ((tparam != null) && (pparam != null)) {
1727 if (tparam == pparam)
1730 return tparam.IsSubclassOf (parent);
1734 if (IsInstantiationOfSameGenericType (type, parent))
1737 type = type.BaseType;
1738 } while (type != null);
1744 // Checks whether `type' is a subclass or nested child of `base_type'.
1746 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1749 if (IsFamilyAccessible (type, base_type))
1752 // Handle nested types.
1753 type = type.DeclaringType;
1754 } while (type != null);
1760 // Checks whether `type' is a nested child of `parent'.
1762 public static bool IsNestedChildOf (Type type, Type parent)
1767 type = DropGenericTypeArguments (type);
1768 parent = DropGenericTypeArguments (parent);
1770 if (IsEqual (type, parent))
1773 type = type.DeclaringType;
1774 while (type != null) {
1775 if (IsEqual (type, parent))
1778 type = type.DeclaringType;
1786 // Checks whether `extern_type' is friend of the output assembly
1788 public static bool IsFriendAssembly (Assembly assembly)
1790 if (assembly_internals_vis_attrs.Contains (assembly))
1791 return (bool)(assembly_internals_vis_attrs [assembly]);
1793 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1794 if (attrs.Length == 0) {
1795 assembly_internals_vis_attrs.Add (assembly, false);
1799 AssemblyName this_name = CodeGen.Assembly.Name;
1800 byte [] this_token = this_name.GetPublicKeyToken ();
1801 bool is_friend = false;
1802 foreach (InternalsVisibleToAttribute attr in attrs) {
1803 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1806 AssemblyName aname = null;
1808 aname = new AssemblyName (attr.AssemblyName);
1809 } catch (FileLoadException) {
1810 } catch (ArgumentException) {
1813 if (aname == null || aname.Name != this_name.Name)
1816 byte [] key_token = aname.GetPublicKeyToken ();
1817 if (key_token != null) {
1818 if (this_token == null) {
1819 // Same name, but key token is null
1820 Error_FriendAccessNameNotMatching (aname.FullName);
1824 if (!CompareKeyTokens (this_token, key_token))
1832 assembly_internals_vis_attrs.Add (assembly, is_friend);
1836 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1838 for (int i = 0; i < token1.Length; i++)
1839 if (token1 [i] != token2 [i])
1845 static void Error_FriendAccessNameNotMatching (string other_name)
1847 Report.Error (281, "Friend access was granted to `" + other_name +
1848 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1849 "'. Try adding a reference to `" + other_name +
1850 "' or change the output assembly name to match it");
1853 public static bool IsFriendAssembly (Assembly assembly)
1860 // Do the right thing when returning the element type of an
1861 // array type based on whether we are compiling corlib or not
1863 public static Type GetElementType (Type t)
1865 if (RootContext.StdLib)
1866 return t.GetElementType ();
1868 return TypeToCoreType (t.GetElementType ());
1872 /// This method is not implemented by MS runtime for dynamic types
1874 public static bool HasElementType (Type t)
1876 return t.IsArray || t.IsPointer || t.IsByRef;
1880 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1884 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1885 /// for anything which is dynamic, and we need this in a number of places,
1886 /// we register this information here, and use it afterwards.
1888 static public void RegisterMethod (MethodBase mb, Parameters ip)
1890 method_params.Add (mb, ip);
1893 static public ParameterData GetParameterData (MethodBase mb)
1895 ParameterData pd = (ParameterData)method_params [mb];
1897 if (mb is MethodBuilder || mb is ConstructorBuilder)
1898 throw new InternalErrorException ("Argument for Method not registered" + mb);
1900 pd = new ReflectionParameters (mb);
1901 method_params.Add (mb, pd);
1906 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1908 if (!method_overrides.Contains (override_method))
1909 method_overrides [override_method] = base_method;
1910 if (method_overrides [override_method] != base_method)
1911 throw new InternalErrorException ("Override mismatch: " + override_method);
1914 static public bool IsOverride (MethodBase m)
1916 m = DropGenericMethodArguments (m);
1918 return m.IsVirtual &&
1919 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1920 (m is MethodBuilder || method_overrides.Contains (m));
1923 static public MethodBase TryGetBaseDefinition (MethodBase m)
1925 m = DropGenericMethodArguments (m);
1927 return (MethodBase) method_overrides [m];
1931 /// Returns the argument types for an indexer based on its PropertyInfo
1933 /// For dynamic indexers, we use the compiler provided types, for
1934 /// indexers from existing assemblies we load them from GetParameters,
1935 /// and insert them into the cache
1937 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1939 if (indexer_arguments.Contains (indexer))
1940 return (Type []) indexer_arguments [indexer];
1941 else if (indexer is PropertyBuilder)
1942 // If we're a PropertyBuilder and not in the
1943 // `indexer_arguments' hash, then we're a property and
1945 return Type.EmptyTypes;
1947 ParameterInfo [] pi = indexer.GetIndexParameters ();
1948 // Property, not an indexer.
1950 return Type.EmptyTypes;
1952 Type [] types = new Type [c];
1954 for (int i = 0; i < c; i++)
1955 types [i] = pi [i].ParameterType;
1957 indexer_arguments.Add (indexer, types);
1962 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1964 fields.Add (fb, ic);
1967 public static IConstant GetConstant (FieldInfo fb)
1972 return (IConstant)fields [fb];
1975 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1977 propertybuilder_to_property.Add (pi, pb);
1980 public static PropertyBase GetProperty (PropertyInfo pi)
1982 return (PropertyBase)propertybuilder_to_property [pi];
1985 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1987 if (fieldbuilders_to_fields.Contains (fb))
1990 fieldbuilders_to_fields.Add (fb, f);
1995 // The return value can be null; This will be the case for
1996 // auxiliary FieldBuilders created by the compiler that have no
1997 // real field being declared on the source code
1999 static public FieldBase GetField (FieldInfo fb)
2002 fb = GetGenericFieldDefinition (fb);
2004 return (FieldBase) fieldbuilders_to_fields [fb];
2007 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2010 events = new Hashtable ();
2012 if (!events.Contains (eb)) {
2013 events.Add (eb, new Pair (add, remove));
2017 static public MethodInfo GetAddMethod (EventInfo ei)
2019 if (ei is MyEventBuilder) {
2020 Pair pair = (Pair) events [ei];
2022 return (MethodInfo) pair.First;
2024 return ei.GetAddMethod (true);
2027 static public MethodInfo GetRemoveMethod (EventInfo ei)
2029 if (ei is MyEventBuilder) {
2030 Pair pair = (Pair) events [ei];
2032 return (MethodInfo) pair.Second;
2034 return ei.GetRemoveMethod (true);
2037 static Hashtable priv_fields_events;
2039 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2041 if (priv_fields_events == null)
2042 priv_fields_events = new Hashtable ();
2044 if (priv_fields_events.Contains (einfo))
2047 priv_fields_events.Add (einfo, builder);
2052 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2054 if (priv_fields_events == null)
2057 return (MemberInfo) priv_fields_events [ei];
2060 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2061 MethodBase set, Type[] args)
2063 indexer_arguments.Add (pb, args);
2068 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2070 Hashtable hash = new Hashtable ();
2071 return CheckStructCycles (tc, seen, hash);
2074 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2077 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2081 // `seen' contains all types we've already visited.
2083 if (seen.Contains (tc))
2085 seen.Add (tc, null);
2087 if (tc.Fields == null)
2090 foreach (FieldMember field in tc.Fields) {
2091 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2094 Type ftype = field.FieldBuilder.FieldType;
2095 TypeContainer ftc = LookupTypeContainer (ftype);
2099 if (hash.Contains (ftc)) {
2100 Report.Error (523, tc.Location,
2101 "Struct member `{0}.{1}' of type `{2}' " +
2102 "causes a cycle in the struct layout",
2103 tc.Name, field.Name, ftc.Name);
2108 // `hash' contains all types in the current path.
2110 hash.Add (tc, null);
2112 bool ok = CheckStructCycles (ftc, seen, hash);
2119 if (!seen.Contains (ftc))
2120 seen.Add (ftc, null);
2127 /// Given an array of interface types, expand and eliminate repeated ocurrences
2128 /// of an interface.
2132 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2135 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2137 ArrayList new_ifaces = new ArrayList ();
2139 foreach (TypeExpr iface in base_interfaces){
2140 Type itype = iface.Type;
2142 if (new_ifaces.Contains (itype))
2145 new_ifaces.Add (itype);
2147 Type [] implementing = GetInterfaces (itype);
2149 foreach (Type imp in implementing){
2150 if (!new_ifaces.Contains (imp))
2151 new_ifaces.Add (imp);
2154 Type [] ret = new Type [new_ifaces.Count];
2155 new_ifaces.CopyTo (ret, 0);
2159 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2161 ArrayList new_ifaces = new ArrayList ();
2163 foreach (Type itype in base_interfaces){
2164 if (new_ifaces.Contains (itype))
2167 new_ifaces.Add (itype);
2169 Type [] implementing = GetInterfaces (itype);
2171 foreach (Type imp in implementing){
2172 if (!new_ifaces.Contains (imp))
2173 new_ifaces.Add (imp);
2176 Type [] ret = new Type [new_ifaces.Count];
2177 new_ifaces.CopyTo (ret, 0);
2181 static PtrHashtable iface_cache = new PtrHashtable ();
2184 /// This function returns the interfaces in the type `t'. Works with
2185 /// both types and TypeBuilders.
2187 public static Type [] GetInterfaces (Type t)
2189 Type [] cached = iface_cache [t] as Type [];
2194 // The reason for catching the Array case is that Reflection.Emit
2195 // will not return a TypeBuilder for Array types of TypeBuilder types,
2196 // but will still throw an exception if we try to call GetInterfaces
2199 // Since the array interfaces are always constant, we return those for
2204 t = TypeManager.array_type;
2206 if ((t is TypeBuilder) || IsGenericType (t)) {
2207 Type [] base_ifaces;
2209 if (t.BaseType == null)
2210 base_ifaces = Type.EmptyTypes;
2212 base_ifaces = GetInterfaces (t.BaseType);
2214 if (IsGenericType (t))
2215 #if MS_COMPATIBLE && GMCS_SOURCE
2216 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2218 type_ifaces = t.GetInterfaces ();
2221 type_ifaces = (Type []) builder_to_ifaces [t];
2222 if (type_ifaces == null || type_ifaces.Length == 0)
2223 type_ifaces = Type.EmptyTypes;
2225 int base_count = base_ifaces.Length;
2226 Type [] result = new Type [base_count + type_ifaces.Length];
2227 base_ifaces.CopyTo (result, 0);
2228 type_ifaces.CopyTo (result, base_count);
2230 iface_cache [t] = result;
2233 } else if (t is GenericTypeParameterBuilder){
2234 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2235 if (type_ifaces == null || type_ifaces.Length == 0)
2236 type_ifaces = Type.EmptyTypes;
2238 iface_cache [t] = type_ifaces;
2242 Type[] ifaces = t.GetInterfaces ();
2243 iface_cache [t] = ifaces;
2249 // gets the interfaces that are declared explicitly on t
2251 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2253 return (Type []) builder_to_ifaces [t];
2257 /// The following is used to check if a given type implements an interface.
2258 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2260 public static bool ImplementsInterface (Type t, Type iface)
2265 // FIXME OPTIMIZATION:
2266 // as soon as we hit a non-TypeBuiler in the interface
2267 // chain, we could return, as the `Type.GetInterfaces'
2268 // will return all the interfaces implement by the type
2272 interfaces = GetInterfaces (t);
2274 if (interfaces != null){
2275 foreach (Type i in interfaces){
2282 } while (t != null);
2287 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2289 // This is a custom version of Convert.ChangeType() which works
2290 // with the TypeBuilder defined types when compiling corlib.
2291 public static object ChangeType (object value, Type conversionType, out bool error)
2293 IConvertible convert_value = value as IConvertible;
2295 if (convert_value == null){
2301 // We must use Type.Equals() here since `conversionType' is
2302 // the TypeBuilder created version of a system type and not
2303 // the system type itself. You cannot use Type.GetTypeCode()
2304 // on such a type - it'd always return TypeCode.Object.
2308 if (conversionType.Equals (typeof (Boolean)))
2309 return (object)(convert_value.ToBoolean (nf_provider));
2310 else if (conversionType.Equals (typeof (Byte)))
2311 return (object)(convert_value.ToByte (nf_provider));
2312 else if (conversionType.Equals (typeof (Char)))
2313 return (object)(convert_value.ToChar (nf_provider));
2314 else if (conversionType.Equals (typeof (DateTime)))
2315 return (object)(convert_value.ToDateTime (nf_provider));
2316 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2317 return (object)(convert_value.ToDecimal (nf_provider));
2318 else if (conversionType.Equals (typeof (Double)))
2319 return (object)(convert_value.ToDouble (nf_provider));
2320 else if (conversionType.Equals (typeof (Int16)))
2321 return (object)(convert_value.ToInt16 (nf_provider));
2322 else if (conversionType.Equals (typeof (Int32)))
2323 return (object)(convert_value.ToInt32 (nf_provider));
2324 else if (conversionType.Equals (typeof (Int64)))
2325 return (object)(convert_value.ToInt64 (nf_provider));
2326 else if (conversionType.Equals (typeof (SByte)))
2327 return (object)(convert_value.ToSByte (nf_provider));
2328 else if (conversionType.Equals (typeof (Single)))
2329 return (object)(convert_value.ToSingle (nf_provider));
2330 else if (conversionType.Equals (typeof (String)))
2331 return (object)(convert_value.ToString (nf_provider));
2332 else if (conversionType.Equals (typeof (UInt16)))
2333 return (object)(convert_value.ToUInt16 (nf_provider));
2334 else if (conversionType.Equals (typeof (UInt32)))
2335 return (object)(convert_value.ToUInt32 (nf_provider));
2336 else if (conversionType.Equals (typeof (UInt64)))
2337 return (object)(convert_value.ToUInt64 (nf_provider));
2338 else if (conversionType.Equals (typeof (Object)))
2339 return (object)(value);
2349 // This is needed, because enumerations from assemblies
2350 // do not report their underlyingtype, but they report
2353 public static Type EnumToUnderlying (Type t)
2355 if (t == TypeManager.enum_type)
2358 t = t.UnderlyingSystemType;
2359 if (!TypeManager.IsEnumType (t))
2362 if (t is TypeBuilder) {
2363 // slow path needed to compile corlib
2364 if (t == TypeManager.bool_type ||
2365 t == TypeManager.byte_type ||
2366 t == TypeManager.sbyte_type ||
2367 t == TypeManager.char_type ||
2368 t == TypeManager.short_type ||
2369 t == TypeManager.ushort_type ||
2370 t == TypeManager.int32_type ||
2371 t == TypeManager.uint32_type ||
2372 t == TypeManager.int64_type ||
2373 t == TypeManager.uint64_type)
2376 TypeCode tc = Type.GetTypeCode (t);
2379 case TypeCode.Boolean:
2380 return TypeManager.bool_type;
2382 return TypeManager.byte_type;
2383 case TypeCode.SByte:
2384 return TypeManager.sbyte_type;
2386 return TypeManager.char_type;
2387 case TypeCode.Int16:
2388 return TypeManager.short_type;
2389 case TypeCode.UInt16:
2390 return TypeManager.ushort_type;
2391 case TypeCode.Int32:
2392 return TypeManager.int32_type;
2393 case TypeCode.UInt32:
2394 return TypeManager.uint32_type;
2395 case TypeCode.Int64:
2396 return TypeManager.int64_type;
2397 case TypeCode.UInt64:
2398 return TypeManager.uint64_type;
2400 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2404 // When compiling corlib and called with one of the core types, return
2405 // the corresponding typebuilder for that type.
2407 public static Type TypeToCoreType (Type t)
2409 if (RootContext.StdLib || (t is TypeBuilder))
2412 TypeCode tc = Type.GetTypeCode (t);
2415 case TypeCode.Boolean:
2416 return TypeManager.bool_type;
2418 return TypeManager.byte_type;
2419 case TypeCode.SByte:
2420 return TypeManager.sbyte_type;
2422 return TypeManager.char_type;
2423 case TypeCode.Int16:
2424 return TypeManager.short_type;
2425 case TypeCode.UInt16:
2426 return TypeManager.ushort_type;
2427 case TypeCode.Int32:
2428 return TypeManager.int32_type;
2429 case TypeCode.UInt32:
2430 return TypeManager.uint32_type;
2431 case TypeCode.Int64:
2432 return TypeManager.int64_type;
2433 case TypeCode.UInt64:
2434 return TypeManager.uint64_type;
2435 case TypeCode.Single:
2436 return TypeManager.float_type;
2437 case TypeCode.Double:
2438 return TypeManager.double_type;
2439 case TypeCode.String:
2440 return TypeManager.string_type;
2441 case TypeCode.Decimal:
2442 return TypeManager.decimal_type;
2444 if (t == typeof (void))
2445 return TypeManager.void_type;
2446 if (t == typeof (object))
2447 return TypeManager.object_type;
2448 if (t == typeof (System.Type))
2449 return TypeManager.type_type;
2450 if (t == typeof (System.IntPtr))
2451 return TypeManager.intptr_type;
2457 /// Utility function that can be used to probe whether a type
2458 /// is managed or not.
2460 public static bool VerifyUnManaged (Type t, Location loc)
2462 if (IsUnmanagedType (t))
2465 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2472 /// Returns the name of the indexer in a given type.
2475 /// The default is not always `Item'. The user can change this behaviour by
2476 /// using the IndexerNameAttribute in the container.
2477 /// For example, the String class indexer is named `Chars' not `Item'
2479 public static string IndexerPropertyName (Type t)
2481 t = DropGenericTypeArguments (t);
2482 if (t is TypeBuilder) {
2483 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2484 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2487 System.Attribute attr = System.Attribute.GetCustomAttribute (
2488 t, TypeManager.default_member_type);
2490 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2491 return dma.MemberName;
2494 return TypeContainer.DefaultIndexerName;
2497 static MethodInfo declare_local_method = null;
2499 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2501 if (declare_local_method == null){
2502 declare_local_method = typeof (ILGenerator).GetMethod (
2504 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2506 new Type [] { typeof (Type), typeof (bool)},
2508 if (declare_local_method == null){
2509 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2510 return ig.DeclareLocal (t);
2513 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2516 private static bool IsSignatureEqual (Type a, Type b)
2519 /// Consider the following example (bug #77674):
2521 /// public abstract class A
2523 /// public abstract T Foo<T> ();
2526 /// public abstract class B : A
2528 /// public override U Foo<T> ()
2529 /// { return default (U); }
2532 /// Here, `T' and `U' are method type parameters from different methods
2533 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2535 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2536 /// we need to do a signature based comparision and consider them equal.
2542 if (a.IsGenericParameter && b.IsGenericParameter &&
2543 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2544 return a.GenericParameterPosition == b.GenericParameterPosition;
2548 if (a.IsArray && b.IsArray) {
2549 if (a.GetArrayRank () != b.GetArrayRank ())
2552 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2555 if (a.IsByRef && b.IsByRef)
2556 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2559 if (a.IsGenericType && b.IsGenericType) {
2560 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2563 Type[] aargs = a.GetGenericArguments ();
2564 Type[] bargs = b.GetGenericArguments ();
2566 if (aargs.Length != bargs.Length)
2569 for (int i = 0; i < aargs.Length; i++) {
2570 if (!IsSignatureEqual (aargs [i], bargs [i]))
2582 // Returns whether the array of memberinfos contains the given method
2584 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2586 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2588 foreach (MethodBase method in array) {
2589 if (method.Name != new_method.Name)
2592 if (method is MethodInfo && new_method is MethodInfo)
2593 if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
2594 ((MethodInfo) new_method).ReturnType))
2598 Type [] old_args = TypeManager.GetParameterData (method).Types;
2599 int old_count = old_args.Length;
2602 if (new_args.Length != old_count)
2605 for (i = 0; i < old_count; i++){
2606 if (!IsSignatureEqual (old_args [i], new_args [i]))
2619 // We copy methods from `new_members' into `target_list' if the signature
2620 // for the method from in the new list does not exist in the target_list
2622 // The name is assumed to be the same.
2624 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2626 if (target_list == null){
2627 target_list = new ArrayList ();
2629 foreach (MemberInfo mi in new_members){
2630 if (mi is MethodBase)
2631 target_list.Add (mi);
2636 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2637 target_list.CopyTo (target_array, 0);
2639 foreach (MemberInfo mi in new_members){
2640 MethodBase new_method = (MethodBase) mi;
2642 if (!ArrayContainsMethod (target_array, new_method))
2643 target_list.Add (new_method);
2650 // Tracks the generic parameters.
2652 static PtrHashtable builder_to_type_param;
2654 public static void AddTypeParameter (Type t, TypeParameter tparam)
2656 if (!builder_to_type_param.Contains (t))
2657 builder_to_type_param.Add (t, tparam);
2660 public static TypeParameter LookupTypeParameter (Type t)
2662 return (TypeParameter) builder_to_type_param [t];
2665 // This method always return false for non-generic compiler,
2666 // while Type.IsGenericParameter is returned if it is supported.
2667 public static bool IsGenericParameter (Type type)
2670 return type.IsGenericParameter;
2676 public static int GenericParameterPosition (Type type)
2679 return type.GenericParameterPosition;
2681 throw new InternalErrorException ("should not be called");
2685 public static bool IsGenericType (Type type)
2688 return type.IsGenericType;
2694 public static bool IsGenericTypeDefinition (Type type)
2697 return type.IsGenericTypeDefinition;
2703 public static bool ContainsGenericParameters (Type type)
2706 return type.ContainsGenericParameters;
2712 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2715 if (fi.DeclaringType.IsGenericTypeDefinition ||
2716 !fi.DeclaringType.IsGenericType)
2719 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2720 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2721 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2723 foreach (FieldInfo f in t.GetFields (bf))
2724 if (f.MetadataToken == fi.MetadataToken)
2731 public static bool IsEqual (Type a, Type b)
2737 if (a.IsGenericParameter && b.IsGenericParameter) {
2738 if (a.DeclaringMethod != b.DeclaringMethod &&
2739 (a.DeclaringMethod == null || b.DeclaringMethod == null))
2741 return a.GenericParameterPosition == b.GenericParameterPosition;
2744 if (a.IsArray && b.IsArray) {
2745 if (a.GetArrayRank () != b.GetArrayRank ())
2747 return IsEqual (a.GetElementType (), b.GetElementType ());
2750 if (a.IsByRef && b.IsByRef)
2751 return IsEqual (a.GetElementType (), b.GetElementType ());
2753 if (a.IsGenericType && b.IsGenericType) {
2754 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2757 Type[] aargs = a.GetGenericArguments ();
2758 Type[] bargs = b.GetGenericArguments ();
2760 if (aargs.Length != bargs.Length)
2763 for (int i = 0; i < aargs.Length; i++) {
2764 if (!IsEqual (aargs [i], bargs [i]))
2775 public static Type DropGenericTypeArguments (Type t)
2778 if (!t.IsGenericType)
2780 // Micro-optimization: a generic typebuilder is always a generic type definition
2781 if (t is TypeBuilder)
2783 return t.GetGenericTypeDefinition ();
2789 public static MethodBase DropGenericMethodArguments (MethodBase m)
2792 if (m.IsGenericMethodDefinition)
2794 if (m.IsGenericMethod)
2795 return ((MethodInfo) m).GetGenericMethodDefinition ();
2796 if (!m.DeclaringType.IsGenericType)
2799 Type t = m.DeclaringType.GetGenericTypeDefinition ();
2800 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2801 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2807 if (m is ConstructorInfo) {
2808 foreach (ConstructorInfo c in t.GetConstructors (bf))
2809 if (c.MetadataToken == m.MetadataToken)
2812 foreach (MethodBase mb in t.GetMethods (bf))
2813 if (mb.MetadataToken == m.MetadataToken)
2821 public static Type[] GetGenericArguments (MethodInfo mi)
2824 return mi.GetGenericArguments ();
2826 return Type.EmptyTypes;
2830 public static Type[] GetTypeArguments (Type t)
2833 DeclSpace tc = LookupDeclSpace (t);
2836 return Type.EmptyTypes;
2838 TypeParameter[] tparam = tc.TypeParameters;
2839 Type[] ret = new Type [tparam.Length];
2840 for (int i = 0; i < tparam.Length; i++) {
2841 ret [i] = tparam [i].Type;
2842 if (ret [i] == null)
2843 throw new InternalErrorException ();
2848 return t.GetGenericArguments ();
2850 throw new InternalErrorException ();
2854 public static bool HasGenericArguments (Type t)
2856 return GetNumberOfTypeArguments (t) > 0;
2859 public static int GetNumberOfTypeArguments (Type t)
2862 if (t.IsGenericParameter)
2864 DeclSpace tc = LookupDeclSpace (t);
2866 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2868 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2875 /// Check whether `type' and `parent' are both instantiations of the same
2876 /// generic type. Note that we do not check the type parameters here.
2878 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2880 int tcount = GetNumberOfTypeArguments (type);
2881 int pcount = GetNumberOfTypeArguments (parent);
2883 if (tcount != pcount)
2886 type = DropGenericTypeArguments (type);
2887 parent = DropGenericTypeArguments (parent);
2889 return type.Equals (parent);
2893 /// Whether `mb' is a generic method definition.
2895 public static bool IsGenericMethodDefinition (MethodBase mb)
2898 if (mb.DeclaringType is TypeBuilder) {
2899 IMethodData method = (IMethodData) builder_to_method [mb];
2903 return method.GenericMethod != null;
2906 return mb.IsGenericMethodDefinition;
2913 /// Whether `mb' is a generic method.
2915 public static bool IsGenericMethod (MethodBase mb)
2918 if (mb.DeclaringType is TypeBuilder) {
2919 IMethodData method = (IMethodData) builder_to_method [mb];
2923 return method.GenericMethod != null;
2926 return mb.IsGenericMethod;
2932 public static bool IsNullableType (Type t)
2935 return generic_nullable_type == DropGenericTypeArguments (t);
2941 public static bool IsNullableTypeOf (Type t, Type nullable)
2944 if (!IsNullableType (t))
2947 return GetTypeArguments (t) [0] == nullable;
2953 public static bool IsNullableValueType (Type t)
2956 if (!IsNullableType (t))
2959 return GetTypeArguments (t) [0].IsValueType;
2966 #region MemberLookup implementation
2969 // Whether we allow private members in the result (since FindMembers
2970 // uses NonPublic for both protected and private), we need to distinguish.
2973 internal class Closure {
2974 internal bool private_ok;
2976 // Who is invoking us and which type is being queried currently.
2977 internal Type invocation_type;
2978 internal Type qualifier_type;
2980 // The assembly that defines the type is that is calling us
2981 internal Assembly invocation_assembly;
2982 internal IList almost_match;
2984 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2986 if (invocation_type == null)
2989 if (is_static && qualifier_type == null)
2990 // It resolved from a simple name, so it should be visible.
2993 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2996 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2997 if (!IsFamilyAccessible (t, m.DeclaringType))
3000 // Although a derived class can access protected members of its base class
3001 // it cannot do so through an instance of the base class (CS1540).
3002 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
3003 if (is_static || qualifier_type == null ||
3004 IsInstantiationOfSameGenericType (t, qualifier_type) ||
3005 IsFamilyAccessible (qualifier_type, t))
3009 if (almost_match != null)
3010 almost_match.Add (m);
3016 // This filter filters by name + whether it is ok to include private
3017 // members in the search
3019 internal bool Filter (MemberInfo m, object filter_criteria)
3022 // Hack: we know that the filter criteria will always be in the
3023 // `closure' // fields.
3026 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3029 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3030 (invocation_type != null) &&
3031 IsPrivateAccessible (m.DeclaringType, invocation_type))
3035 // Ugly: we need to find out the type of `m', and depending
3036 // on this, tell whether we accept or not
3038 if (m is MethodBase){
3039 MethodBase mb = (MethodBase) m;
3040 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3042 if (ma == MethodAttributes.Public)
3045 if (ma == MethodAttributes.PrivateScope)
3048 if (ma == MethodAttributes.Private)
3049 return private_ok ||
3050 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3051 IsNestedChildOf (invocation_type, m.DeclaringType);
3053 if (invocation_assembly == mb.DeclaringType.Assembly ||
3054 TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
3055 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
3058 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
3062 // Family, FamORAssem or FamANDAssem
3063 return CheckValidFamilyAccess (mb.IsStatic, m);
3066 if (m is FieldInfo){
3067 FieldInfo fi = (FieldInfo) m;
3068 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3070 if (fa == FieldAttributes.Public)
3073 if (fa == FieldAttributes.PrivateScope)
3076 if (fa == FieldAttributes.Private)
3077 return private_ok ||
3078 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
3079 IsNestedChildOf (invocation_type, m.DeclaringType);
3081 if ((invocation_assembly == fi.DeclaringType.Assembly) ||
3082 (invocation_assembly == null) ||
3083 TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
3084 if ((fa == FieldAttributes.Assembly) ||
3085 (fa == FieldAttributes.FamORAssem))
3088 if ((fa == FieldAttributes.Assembly) ||
3089 (fa == FieldAttributes.FamANDAssem))
3093 // Family, FamORAssem or FamANDAssem
3094 return CheckValidFamilyAccess (fi.IsStatic, m);
3098 // EventInfos and PropertyInfos, return true because they lack
3099 // permission information, so we need to check later on the methods.
3105 static Closure closure = new Closure ();
3106 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3109 // Looks up a member called `name' in the `queried_type'. This lookup
3110 // is done by code that is contained in the definition for `invocation_type'
3111 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3113 // `invocation_type' is used to check whether we're allowed to access the requested
3114 // member wrt its protection level.
3116 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3117 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3118 // is B and qualifier_type is A). This is used to do the CS1540 check.
3120 // When resolving a SimpleName, `qualifier_type' is null.
3122 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3123 // the same than `queried_type' - except when we're being called from BaseAccess;
3124 // in this case, `invocation_type' is the current type and `queried_type' the base
3125 // type, so this'd normally trigger a CS1540.
3127 // The binding flags are `bf' and the kind of members being looked up are `mt'
3129 // The return value always includes private members which code in `invocation_type'
3130 // is allowed to access (using the specified `qualifier_type' if given); only use
3131 // BindingFlags.NonPublic to bypass the permission check.
3133 // The 'almost_match' argument is used for reporting error CS1540.
3135 // Returns an array of a single element for everything but Methods/Constructors
3136 // that might return multiple matches.
3138 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3139 Type queried_type, MemberTypes mt,
3140 BindingFlags original_bf, string name, IList almost_match)
3142 Timer.StartTimer (TimerType.MemberLookup);
3144 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3145 queried_type, mt, original_bf, name, almost_match);
3147 Timer.StopTimer (TimerType.MemberLookup);
3152 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3153 Type queried_type, MemberTypes mt,
3154 BindingFlags original_bf, string name, IList almost_match)
3156 BindingFlags bf = original_bf;
3158 ArrayList method_list = null;
3159 Type current_type = queried_type;
3160 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3161 bool skip_iface_check = true, used_cache = false;
3162 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3164 closure.invocation_type = invocation_type;
3165 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3166 closure.qualifier_type = qualifier_type;
3167 closure.almost_match = almost_match;
3169 // This is from the first time we find a method
3170 // in most cases, we do not actually find a method in the base class
3171 // so we can just ignore it, and save the arraylist allocation
3172 MemberInfo [] first_members_list = null;
3173 bool use_first_members_list = false;
3179 // `NonPublic' is lame, because it includes both protected and
3180 // private methods, so we need to control this behavior by
3181 // explicitly tracking if a private method is ok or not.
3183 // The possible cases are:
3184 // public, private and protected (internal does not come into the
3187 if ((invocation_type != null) &&
3188 ((invocation_type == current_type) ||
3189 IsNestedChildOf (invocation_type, current_type)) ||
3191 bf = original_bf | BindingFlags.NonPublic;
3195 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3197 Timer.StopTimer (TimerType.MemberLookup);
3199 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3201 Timer.StartTimer (TimerType.MemberLookup);
3204 // When queried for an interface type, the cache will automatically check all
3205 // inherited members, so we don't need to do this here. However, this only
3206 // works if we already used the cache in the first iteration of this loop.
3208 // If we used the cache in any further iteration, we can still terminate the
3209 // loop since the cache always looks in all base classes.
3215 skip_iface_check = false;
3217 if (current_type == TypeManager.object_type)
3220 current_type = current_type.BaseType;
3223 // This happens with interfaces, they have a null
3224 // basetype. Look members up in the Object class.
3226 if (current_type == null) {
3227 current_type = TypeManager.object_type;
3232 if (list.Length == 0)
3236 // Events and types are returned by both `static' and `instance'
3237 // searches, which means that our above FindMembers will
3238 // return two copies of the same.
3240 if (list.Length == 1 && !(list [0] is MethodBase)){
3245 // Multiple properties: we query those just to find out the indexer
3248 if (list [0] is PropertyInfo)
3252 // We found an event: the cache lookup returns both the event and
3253 // its private field.
3255 if (list [0] is EventInfo) {
3256 if ((list.Length == 2) && (list [1] is FieldInfo))
3257 return new MemberInfo [] { list [0] };
3263 // We found methods, turn the search into "method scan"
3267 if (first_members_list != null) {
3268 if (use_first_members_list) {
3269 method_list = CopyNewMethods (method_list, first_members_list);
3270 use_first_members_list = false;
3273 method_list = CopyNewMethods (method_list, list);
3275 first_members_list = list;
3276 use_first_members_list = true;
3277 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3279 } while (searching);
3281 if (use_first_members_list)
3282 return first_members_list;
3284 if (method_list != null && method_list.Count > 0) {
3285 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3288 // This happens if we already used the cache in the first iteration, in this case
3289 // the cache already looked in all interfaces.
3291 if (skip_iface_check)
3295 // Interfaces do not list members they inherit, so we have to
3298 if (!queried_type.IsInterface)
3301 if (queried_type.IsArray)
3302 queried_type = TypeManager.array_type;
3304 Type [] ifaces = GetInterfaces (queried_type);
3308 foreach (Type itype in ifaces){
3311 x = MemberLookup (null, null, itype, mt, bf, name, null);
3319 // Tests whether external method is really special
3320 public static bool IsSpecialMethod (MethodBase mb)
3322 string name = mb.Name;
3323 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3324 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3326 if (name.StartsWith ("add_"))
3327 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3329 if (name.StartsWith ("remove_"))
3330 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3332 if (name.StartsWith ("op_")){
3333 foreach (string oname in Unary.oper_names) {
3338 foreach (string oname in Binary.oper_names) {
3351 /// There is exactly one instance of this class per type.
3353 public sealed class TypeHandle : IMemberContainer {
3354 public readonly IMemberContainer BaseType;
3356 readonly int id = ++next_id;
3357 static int next_id = 0;
3359 static TypeHandle ()
3365 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3366 /// a TypeHandle yet, a new instance of it is created. This static method
3367 /// ensures that we'll only have one TypeHandle instance per type.
3369 private static TypeHandle GetTypeHandle (Type t)
3371 TypeHandle handle = (TypeHandle) type_hash [t];
3375 handle = new TypeHandle (t);
3376 type_hash.Add (t, handle);
3380 public static MemberCache GetMemberCache (Type t)
3382 return GetTypeHandle (t).MemberCache;
3385 public static void CleanUp ()
3390 public static void Reset ()
3392 type_hash = new PtrHashtable ();
3396 /// Returns the TypeHandle for TypeManager.object_type.
3398 public static IMemberContainer ObjectType {
3400 if (object_type != null)
3403 object_type = GetTypeHandle (TypeManager.object_type);
3410 /// Returns the TypeHandle for TypeManager.array_type.
3412 public static IMemberContainer ArrayType {
3414 if (array_type != null)
3417 array_type = GetTypeHandle (TypeManager.array_type);
3423 private static PtrHashtable type_hash;
3425 private static TypeHandle object_type = null;
3426 private static TypeHandle array_type = null;
3429 private string full_name;
3430 private bool is_interface;
3431 private MemberCache member_cache;
3432 private MemberCache base_cache;
3434 private TypeHandle (Type type)
3437 #if MS_COMPATIBLE && GMCS_SOURCE
3438 if (type.IsGenericType)
3439 this.type = this.type.GetGenericTypeDefinition ();
3441 full_name = type.FullName != null ? type.FullName : type.Name;
3442 if (type.BaseType != null) {
3443 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3444 BaseType = base_cache.Container;
3445 } else if (type.IsInterface)
3446 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3447 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3448 this.member_cache = new MemberCache (this);
3451 // IMemberContainer methods
3453 public string Name {
3465 public MemberCache BaseCache {
3471 public bool IsInterface {
3473 return is_interface;
3477 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3479 MemberInfo [] members;
3482 if (type is GenericTypeParameterBuilder)
3483 return MemberList.Empty;
3486 if (mt == MemberTypes.Event)
3487 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3489 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3491 Array.Reverse (members);
3493 return new MemberList (members);
3496 // IMemberFinder methods
3498 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3499 MemberFilter filter, object criteria)
3501 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3504 public MemberCache MemberCache {
3506 return member_cache;
3510 public override string ToString ()
3512 if (BaseType != null)
3513 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3515 return "TypeHandle (" + id + "," + Name + ")";