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 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2008 Novell, Inc.
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.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
38 // A list of core types that the compiler requires or uses
40 static public Type object_type;
41 static public Type value_type;
42 static public Type string_type;
43 static public Type int32_type;
44 static public Type uint32_type;
45 static public Type int64_type;
46 static public Type uint64_type;
47 static public Type float_type;
48 static public Type double_type;
49 static public Type char_type;
50 static public Type char_ptr_type;
51 static public Type short_type;
52 static public Type decimal_type;
53 static public Type bool_type;
54 static public Type sbyte_type;
55 static public Type byte_type;
56 static public Type ushort_type;
57 static public Type enum_type;
58 static public Type delegate_type;
59 static public Type multicast_delegate_type;
60 static public Type void_type;
61 static public Type null_type;
62 static public Type array_type;
63 static public Type runtime_handle_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 default_member_type;
69 static public Type iasyncresult_type;
70 static public Type asynccallback_type;
71 static public Type intptr_type;
72 static public Type uintptr_type;
73 static public Type runtime_field_handle_type;
74 static public Type runtime_argument_handle_type;
75 static public Type attribute_type;
76 static public Type attribute_usage_type;
77 static public Type decimal_constant_attribute_type;
78 static public Type dllimport_type;
79 static public Type methodimpl_attr_type;
81 static public Type marshal_as_attr_type;
83 static public Type param_array_type;
84 static public Type void_ptr_type;
85 static public Type indexer_name_type;
86 static public Type exception_type;
87 static public Type obsolete_attribute_type;
88 static public Type conditional_attribute_type;
89 static public Type in_attribute_type;
90 static public Type out_attribute_type;
91 static public Type extension_attribute_type;
92 static public Type default_parameter_value_attribute_type;
94 static public Type anonymous_method_type;
95 static public Type cls_compliant_attribute_type;
96 static public Type typed_reference_type;
97 static public Type arg_iterator_type;
98 static public Type mbr_type;
99 static public Type struct_layout_attribute_type;
100 static public Type field_offset_attribute_type;
101 static public Type security_attr_type;
102 static public Type required_attr_type;
103 static public Type guid_attr_type;
104 static public Type assembly_culture_attribute_type;
105 static public Type assembly_version_attribute_type;
106 static public Type coclass_attr_type;
107 static public Type comimport_attr_type;
108 public static Type runtime_helpers_type;
109 public static Type internals_visible_attr_type;
114 static internal Type fixed_buffer_attr_type;
115 static internal Type default_charset_type;
116 static internal Type type_forwarder_attr_type;
117 static internal Type isvolatile_type;
118 static public Type generic_ilist_type;
119 static public Type generic_icollection_type;
120 static public Type generic_ienumerator_type;
121 static public Type generic_ienumerable_type;
122 static public Type generic_nullable_type;
127 static internal Type expression_type;
128 public static Type parameter_expression_type;
131 // Expressions representing the internal types. Used during declaration
134 static public TypeExpr system_object_expr, system_string_expr;
135 static public TypeExpr system_boolean_expr, system_decimal_expr;
136 static public TypeExpr system_single_expr, system_double_expr;
137 static public TypeExpr system_sbyte_expr, system_byte_expr;
138 static public TypeExpr system_int16_expr, system_uint16_expr;
139 static public TypeExpr system_int32_expr, system_uint32_expr;
140 static public TypeExpr system_int64_expr, system_uint64_expr;
141 static public TypeExpr system_char_expr, system_void_expr;
142 static public TypeExpr system_valuetype_expr;
143 static public TypeExpr system_intptr_expr;
144 public static TypeExpr expression_type_expr;
148 // These methods are called by code generated by the compiler
150 static public FieldInfo string_empty;
151 static public MethodInfo system_type_get_type_from_handle;
152 static public MethodInfo bool_movenext_void;
153 static public MethodInfo void_dispose_void;
154 static public MethodInfo void_monitor_enter_object;
155 static public MethodInfo void_monitor_exit_object;
156 static public MethodInfo void_initializearray_array_fieldhandle;
157 static public MethodInfo delegate_combine_delegate_delegate;
158 static public MethodInfo delegate_remove_delegate_delegate;
159 static public MethodInfo int_get_offset_to_string_data;
160 static public MethodInfo int_interlocked_compare_exchange;
161 static public PropertyInfo ienumerator_getcurrent;
162 public static MethodInfo methodbase_get_type_from_handle;
163 public static MethodInfo methodbase_get_type_from_handle_generic;
164 public static MethodInfo fieldinfo_get_field_from_handle;
165 static public MethodInfo activator_create_instance;
168 // The attribute constructors.
170 static public ConstructorInfo void_decimal_ctor_five_args;
171 static public ConstructorInfo void_decimal_ctor_int_arg;
172 static public ConstructorInfo default_member_ctor;
173 static public ConstructorInfo decimal_constant_attribute_ctor;
174 static internal ConstructorInfo struct_layout_attribute_ctor;
175 static public ConstructorInfo field_offset_attribute_ctor;
176 public static ConstructorInfo invalid_operation_exception_ctor;
178 static public CustomAttributeBuilder param_array_attr;
179 static CustomAttributeBuilder compiler_generated_attr;
180 static CustomAttributeBuilder debugger_hidden_attr;
183 static internal ConstructorInfo fixed_buffer_attr_ctor;
184 static internal CustomAttributeBuilder unsafe_value_type_attr;
187 static internal CustomAttributeBuilder extension_attribute_attr;
189 static PtrHashtable builder_to_declspace;
191 static PtrHashtable builder_to_member_cache;
194 // Tracks the interfaces implemented by typebuilders. We only
195 // enter those who do implement or or more interfaces
197 static PtrHashtable builder_to_ifaces;
200 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
202 static Hashtable method_params;
205 // A hash table from override methods to their base virtual method.
207 static Hashtable method_overrides;
210 // Keeps track of methods
213 static Hashtable builder_to_method;
216 // Contains all public types from referenced assemblies.
217 // This member is used only if CLS Compliance verification is required.
219 public static Hashtable AllClsTopLevelTypes;
221 static Hashtable fieldbuilders_to_fields;
222 static Hashtable propertybuilder_to_property;
223 static Hashtable fields;
224 static Hashtable events;
225 static PtrHashtable assembly_internals_vis_attrs;
227 public static void CleanUp ()
229 // Lets get everything clean so that we can collect before generating code
230 builder_to_declspace = null;
231 builder_to_member_cache = null;
232 builder_to_ifaces = null;
233 builder_to_type_param = null;
234 method_params = null;
235 builder_to_method = null;
240 propertybuilder_to_property = null;
241 assembly_internals_vis_attrs = null;
243 TypeHandle.CleanUp ();
247 // These are expressions that represent some of the internal data types, used
250 static void InitExpressionTypes ()
252 system_object_expr = new TypeLookupExpression ("System.Object");
253 system_string_expr = new TypeLookupExpression ("System.String");
254 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
255 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
256 system_single_expr = new TypeLookupExpression ("System.Single");
257 system_double_expr = new TypeLookupExpression ("System.Double");
258 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
259 system_byte_expr = new TypeLookupExpression ("System.Byte");
260 system_int16_expr = new TypeLookupExpression ("System.Int16");
261 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
262 system_int32_expr = new TypeLookupExpression ("System.Int32");
263 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
264 system_int64_expr = new TypeLookupExpression ("System.Int64");
265 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
266 system_char_expr = new TypeLookupExpression ("System.Char");
267 system_void_expr = new TypeLookupExpression ("System.Void");
268 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
269 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
272 static TypeManager ()
276 InitExpressionTypes ();
279 static public void Reset ()
281 builder_to_declspace = new PtrHashtable ();
282 builder_to_member_cache = new PtrHashtable ();
283 builder_to_method = new PtrHashtable ();
284 builder_to_type_param = new PtrHashtable ();
285 method_params = new PtrHashtable ();
286 method_overrides = new PtrHashtable ();
287 builder_to_ifaces = new PtrHashtable ();
289 fieldbuilders_to_fields = new Hashtable ();
290 propertybuilder_to_property = new Hashtable ();
291 fields = new Hashtable ();
292 type_hash = new DoubleHash ();
293 assembly_internals_vis_attrs = new PtrHashtable ();
295 // TODO: I am really bored by all this static stuff
296 system_type_get_type_from_handle =
299 void_monitor_enter_object =
300 void_monitor_exit_object =
301 void_initializearray_array_fieldhandle =
302 delegate_combine_delegate_delegate =
303 delegate_remove_delegate_delegate =
304 int_get_offset_to_string_data =
305 int_interlocked_compare_exchange =
306 methodbase_get_type_from_handle =
307 methodbase_get_type_from_handle_generic =
308 fieldinfo_get_field_from_handle =
309 activator_create_instance = null;
311 ienumerator_getcurrent = null;
313 void_decimal_ctor_five_args =
314 void_decimal_ctor_int_arg =
315 default_member_ctor =
316 decimal_constant_attribute_ctor =
317 struct_layout_attribute_ctor =
318 field_offset_attribute_ctor =
319 invalid_operation_exception_ctor =
320 fixed_buffer_attr_ctor = null;
323 compiler_generated_attr =
324 unsafe_value_type_attr =
325 extension_attribute_attr = null;
327 isvolatile_type = null;
329 // to uncover regressions
330 AllClsTopLevelTypes = null;
333 public static void AddUserType (DeclSpace ds)
335 builder_to_declspace.Add (ds.TypeBuilder, ds);
339 // This entry point is used by types that we define under the covers
341 public static void RegisterBuilder (Type tb, Type [] ifaces)
344 builder_to_ifaces [tb] = ifaces;
347 public static void AddMethod (MethodBase builder, IMethodData method)
349 builder_to_method.Add (builder, method);
350 method_params.Add (builder, method.ParameterInfo);
353 public static IMethodData GetMethod (MethodBase builder)
355 return (IMethodData) builder_to_method [builder];
359 /// Returns the DeclSpace whose Type is `t' or null if there is no
360 /// DeclSpace for `t' (ie, the Type comes from a library)
362 public static DeclSpace LookupDeclSpace (Type t)
364 return builder_to_declspace [t] as DeclSpace;
368 /// Returns the TypeContainer whose Type is `t' or null if there is no
369 /// TypeContainer for `t' (ie, the Type comes from a library)
371 public static TypeContainer LookupTypeContainer (Type t)
373 return builder_to_declspace [t] as TypeContainer;
376 public static MemberCache LookupMemberCache (Type t)
378 if (t.Module == CodeGen.Module.Builder) {
379 DeclSpace container = (DeclSpace)builder_to_declspace [t];
380 if (container != null)
381 return container.MemberCache;
385 if (t is GenericTypeParameterBuilder) {
386 TypeParameter container = builder_to_type_param [t] as TypeParameter;
388 if (container != null)
389 return container.MemberCache;
393 return TypeHandle.GetMemberCache (t);
396 public static MemberCache LookupBaseInterfacesCache (Type t)
398 Type [] ifaces = GetInterfaces (t);
400 if (ifaces != null && ifaces.Length == 1)
401 return LookupMemberCache (ifaces [0]);
403 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
404 MemberCache cache = builder_to_member_cache [t] as MemberCache;
408 cache = new MemberCache (ifaces);
409 builder_to_member_cache.Add (t, cache);
413 public static TypeContainer LookupInterface (Type t)
415 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
416 if ((tc == null) || (tc.Kind != Kind.Interface))
422 public static Delegate LookupDelegate (Type t)
424 return builder_to_declspace [t] as Delegate;
427 public static Class LookupClass (Type t)
429 return (Class) builder_to_declspace [t];
433 // We use this hash for multiple kinds of constructed types:
435 // (T, "&") Given T, get T &
436 // (T, "*") Given T, get T *
437 // (T, "[]") Given T and a array dimension, get T []
438 // (T, X) Given a type T and a simple name X, get the type T+X
440 // Accessibility tests, if necessary, should be done by the user
442 static DoubleHash type_hash = new DoubleHash ();
445 // Gets the reference to T version of the Type (T&)
447 public static Type GetReferenceType (Type t)
450 return t.MakeByRefType ();
452 return GetConstructedType (t, "&");
457 // Gets the pointer to T version of the Type (T*)
459 public static Type GetPointerType (Type t)
461 return GetConstructedType (t, "*");
464 public static Type GetConstructedType (Type t, string dim)
467 if (type_hash.Lookup (t, dim, out ret))
470 ret = t.Module.GetType (t.ToString () + dim);
472 type_hash.Insert (t, dim, ret);
477 ret = GetReferenceType (t);
478 type_hash.Insert (t, dim, ret);
483 if (t.IsGenericParameter || t.IsGenericType) {
486 while ((pos < dim.Length) && (dim [pos] == '[')) {
489 if (dim [pos] == ']') {
490 result = result.MakeArrayType ();
493 if (pos < dim.Length)
496 type_hash.Insert (t, dim, result);
501 while (dim [pos] == ',') {
505 if ((dim [pos] != ']') || (pos != dim.Length-1))
508 result = result.MakeArrayType (rank + 1);
509 type_hash.Insert (t, dim, result);
515 type_hash.Insert (t, dim, null);
519 public static CustomAttributeBuilder GetCompilerGeneratedAttribute (Location loc)
521 if (compiler_generated_attr != null)
522 return compiler_generated_attr;
524 Type t = TypeManager.CoreLookupType (
525 "System.Runtime.CompilerServices", "CompilerGeneratedAttribute", Kind.Class, true);
527 // TODO: it cannot be null
531 compiler_generated_attr = new CustomAttributeBuilder (
532 GetPredefinedConstructor (t, loc, Type.EmptyTypes), new object[0]);
534 return compiler_generated_attr;
537 public static CustomAttributeBuilder GetDebuggerHiddenAttribute (Location loc)
539 if (debugger_hidden_attr != null)
540 return debugger_hidden_attr;
542 Type t = TypeManager.CoreLookupType (
543 "System.Diagnostics", "DebuggerHiddenAttribute", Kind.Class, true);
545 // TODO: it cannot be null
549 debugger_hidden_attr = new CustomAttributeBuilder (
550 GetPredefinedConstructor (t, loc, Type.EmptyTypes), new object[0]);
552 return debugger_hidden_attr;
555 public static Type GetNestedType (Type t, string name)
558 if (!type_hash.Lookup (t, name, out ret)) {
559 ret = t.GetNestedType (name,
560 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
561 type_hash.Insert (t, name, ret);
567 /// Fills static table with exported types from all referenced assemblies.
568 /// This information is required for CLS Compliance tests.
570 public static void LoadAllImportedTypes ()
572 AllClsTopLevelTypes = new Hashtable (1500);
573 foreach (Assembly a in RootNamespace.Global.Assemblies) {
574 foreach (Type t in a.GetExportedTypes ()) {
575 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
580 public static bool NamespaceClash (string name, Location loc)
582 if (! RootNamespace.Global.IsNamespace (name))
585 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
590 /// Returns the C# name of a type if possible, or the full type name otherwise
592 static public string CSharpName (Type t)
597 if (t == typeof (ArglistParameter))
600 if (t == typeof (AnonymousMethodBody))
601 return "anonymous method";
604 return "internal error";
606 return CSharpName (GetFullName (t), t);
609 static readonly char [] elements = new char [] { '*', '[' };
611 public static string CSharpName (string name, Type type)
613 if (name.Length > 10) {
616 case "System.Int32": s = "int"; break;
617 case "System.Int64": s = "long"; break;
618 case "System.String": s = "string"; break;
619 case "System.Boolean": s = "bool"; break;
620 case "System.Void": s = "void"; break;
621 case "System.Object": s = "object"; break;
622 case "System.UInt32": s = "uint"; break;
623 case "System.Int16": s = "short"; break;
624 case "System.UInt16": s = "ushort"; break;
625 case "System.UInt64": s = "ulong"; break;
626 case "System.Single": s = "float"; break;
627 case "System.Double": s = "double"; break;
628 case "System.Decimal": s = "decimal"; break;
629 case "System.Char": s = "char"; break;
630 case "System.Byte": s = "byte"; break;
631 case "System.SByte": s = "sbyte"; break;
632 default: s = null; break;
637 // Predefined names can come from mscorlib only
639 if (type == null || type.Module.Name == "mscorlib.dll" || !RootContext.StdLib)
645 int idx = name.IndexOfAny (elements, 10);
647 return CSharpName (name.Substring (0, idx), type) + name.Substring (idx);
650 if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
651 return AnonymousTypeClass.SignatureForError;
653 return name.Replace ('+', '.');
656 static public string CSharpName (Type[] types)
658 if (types.Length == 0)
661 StringBuilder sb = new StringBuilder ();
662 for (int i = 0; i < types.Length; ++i) {
666 sb.Append (CSharpName (types [i]));
668 return sb.ToString ();
672 /// Returns the signature of the method with full namespace classification
674 static public string GetFullNameSignature (MemberInfo mi)
676 PropertyInfo pi = mi as PropertyInfo;
678 MethodBase pmi = pi.GetGetMethod (true);
680 pmi = pi.GetSetMethod (true);
681 if (GetParameterData (pmi).Count > 0)
684 return (mi is MethodBase)
685 ? CSharpSignature (mi as MethodBase)
686 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
690 private static int GetFullName (Type t, StringBuilder sb)
694 if (!t.IsGenericType) {
695 sb.Append (t.FullName);
699 if (t.DeclaringType != null) {
700 pos = GetFullName (t.DeclaringType, sb);
702 } else if (t.Namespace != null && t.Namespace.Length != 0) {
703 sb.Append (t.Namespace);
706 sb.Append (RemoveGenericArity (t.Name));
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 static string GetFullName (Type t)
730 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
731 return GetFullName (t.GetElementType ()) + dimension;
734 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
735 t = GetTypeArguments (t)[0];
736 return CSharpName (t) + "?";
739 if (t.IsGenericParameter)
741 if (!t.IsGenericType)
744 StringBuilder sb = new StringBuilder ();
745 int pos = GetFullName (t, sb);
747 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
748 return sb.ToString ();
751 public static string GetFullName (Type t)
757 public static string RemoveGenericArity (string from)
759 int i = from.IndexOf ('`');
761 return from.Substring (0, i);
766 /// When we need to report accessors as well
768 static public string CSharpSignature (MethodBase mb)
770 return CSharpSignature (mb, false);
774 /// Returns the signature of the method
776 static public string CSharpSignature (MethodBase mb, bool show_accessor)
778 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
781 AParametersCollection iparams = GetParameterData (mb);
782 string parameters = iparams.GetSignatureForError ();
783 int accessor_end = 0;
785 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
786 string op_name = Operator.GetName (mb.Name);
787 if (op_name != null) {
788 if (op_name == "explicit" || op_name == "implicit") {
789 sig.Append (op_name);
790 sig.Append (" operator ");
791 sig.Append (CSharpName (((MethodInfo)mb).ReturnType));
793 sig.Append ("operator ");
794 sig.Append (op_name);
796 sig.Append (parameters);
797 return sig.ToString ();
800 bool is_getter = mb.Name.StartsWith ("get_");
801 bool is_setter = mb.Name.StartsWith ("set_");
802 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
804 } else if (mb.Name.StartsWith ("remove_")) {
809 if (iparams.Count > (is_getter ? 0 : 1)) {
810 sig.Append ("this[");
812 sig.Append (parameters.Substring (1, parameters.Length - 2));
814 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
817 sig.Append (mb.Name.Substring (accessor_end + 1));
820 if (mb.Name == ".ctor")
821 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
823 sig.Append (mb.Name);
826 if (TypeManager.IsGenericMethod (mb)) {
827 Type[] args = mb.GetGenericArguments ();
829 for (int i = 0; i < args.Length; i++) {
832 sig.Append (CSharpName (args [i]));
839 sig.Append (parameters);
842 if (show_accessor && accessor_end > 0) {
844 sig.Append (mb.Name.Substring (0, accessor_end));
847 return sig.ToString ();
850 public static string GetMethodName (MethodInfo m)
853 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
856 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
862 static public string CSharpSignature (EventInfo ei)
864 return CSharpName (ei.DeclaringType) + "." + ei.Name;
868 // Looks up a type, and aborts if it is not found. This is used
869 // by predefined types required by the compiler
871 public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required)
874 if (RootContext.StdLib) {
875 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
876 expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
879 Report.DisableReporting ();
881 TypeLookupExpression tle = new TypeLookupExpression (ns_name + "." + name);
882 expr = tle.ResolveAsTypeTerminal (RootContext.ToplevelTypes, false);
885 Report.EnableReporting ();
890 Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
897 if (RootContext.StdLib || t == null || !required)
900 // TODO: All predefined imported types have to have correct signature
901 if (t.Module != CodeGen.Module.Builder)
904 DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
905 if (ds is Delegate) {
906 if (type_kind == Kind.Delegate)
909 TypeContainer tc = (TypeContainer)ds;
910 if (tc.Kind == type_kind)
914 Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
919 static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
921 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
923 MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
924 if (members != null) {
925 for (int i = 0; i < members.Length; ++i) {
926 MemberInfo member = members [i];
927 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
928 MethodBase mb = member as MethodBase;
932 AParametersCollection pd = TypeManager.GetParameterData (mb);
933 if (IsEqual (pd.Types, args))
936 if (mt == MemberTypes.Field) {
937 FieldInfo fi = member as FieldInfo;
941 if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
947 if (mt == MemberTypes.Property) {
948 PropertyInfo pi = member as PropertyInfo;
952 if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
960 string method_args = null;
961 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
962 method_args = "(" + TypeManager.CSharpName (args) + ")";
964 Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
965 TypeManager.CSharpName (t), name, method_args);
971 // Returns the ConstructorInfo for "args"
973 public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
975 return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
979 // Returns the MethodInfo for a method named `name' defined
980 // in type `t' which takes arguments of types `args'
982 public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
984 return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
987 public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
989 return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
992 public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
994 return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
998 /// The types have to be initialized after the initial
999 /// population of the type has happened (for example, to
1000 /// bootstrap the corlib.dll
1002 public static bool InitCoreTypes ()
1004 object_type = CoreLookupType ("System", "Object", Kind.Class, true);
1005 system_object_expr.Type = object_type;
1006 value_type = CoreLookupType ("System", "ValueType", Kind.Class, true);
1007 system_valuetype_expr.Type = value_type;
1008 attribute_type = CoreLookupType ("System", "Attribute", Kind.Class, true);
1010 int32_type = CoreLookupType ("System", "Int32", Kind.Struct, true);
1011 int64_type = CoreLookupType ("System", "Int64", Kind.Struct, true);
1012 uint32_type = CoreLookupType ("System", "UInt32", Kind.Struct, true);
1013 uint64_type = CoreLookupType ("System", "UInt64", Kind.Struct, true);
1014 byte_type = CoreLookupType ("System", "Byte", Kind.Struct, true);
1015 sbyte_type = CoreLookupType ("System", "SByte", Kind.Struct, true);
1016 short_type = CoreLookupType ("System", "Int16", Kind.Struct, true);
1017 ushort_type = CoreLookupType ("System", "UInt16", Kind.Struct, true);
1019 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator", Kind.Interface, true);
1020 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable", Kind.Interface, true);
1021 idisposable_type = CoreLookupType ("System", "IDisposable", Kind.Interface, true);
1023 // HACK: DefineType immediately resolves iterators (very wrong)
1024 generic_ienumerator_type = CoreLookupType ("System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
1026 char_type = CoreLookupType ("System", "Char", Kind.Struct, true);
1027 string_type = CoreLookupType ("System", "String", Kind.Class, true);
1028 float_type = CoreLookupType ("System", "Single", Kind.Struct, true);
1029 double_type = CoreLookupType ("System", "Double", Kind.Struct, true);
1030 decimal_type = CoreLookupType ("System", "Decimal", Kind.Struct, true);
1031 bool_type = CoreLookupType ("System", "Boolean", Kind.Struct, true);
1032 intptr_type = CoreLookupType ("System", "IntPtr", Kind.Struct, true);
1033 uintptr_type = CoreLookupType ("System", "UIntPtr", Kind.Struct, true);
1035 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate", Kind.Class, true);
1036 delegate_type = CoreLookupType ("System", "Delegate", Kind.Class, true);
1038 enum_type = CoreLookupType ("System", "Enum", Kind.Class, true);
1039 array_type = CoreLookupType ("System", "Array", Kind.Class, true);
1040 void_type = CoreLookupType ("System", "Void", Kind.Struct, true);
1041 type_type = CoreLookupType ("System", "Type", Kind.Class, true);
1042 exception_type = CoreLookupType ("System", "Exception", Kind.Class, true);
1044 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle", Kind.Struct, true);
1045 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle", Kind.Struct, true);
1047 param_array_type = CoreLookupType ("System", "ParamArrayAttribute", Kind.Class, true);
1048 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute", Kind.Class, true);
1050 return Report.Errors == 0;
1054 // Initializes optional core types
1056 public static void InitOptionalCoreTypes ()
1058 system_string_expr.Type = string_type;
1059 system_boolean_expr.Type = bool_type;
1060 system_decimal_expr.Type = decimal_type;
1061 system_single_expr.Type = float_type;
1062 system_double_expr.Type = double_type;
1063 system_sbyte_expr.Type = sbyte_type;
1064 system_byte_expr.Type = byte_type;
1065 system_int16_expr.Type = short_type;
1066 system_uint16_expr.Type = ushort_type;
1067 system_int32_expr.Type = int32_type;
1068 system_uint32_expr.Type = uint32_type;
1069 system_int64_expr.Type = int64_type;
1070 system_uint64_expr.Type = uint64_type;
1071 system_char_expr.Type = char_type;
1072 system_void_expr.Type = void_type;
1075 // These are only used for compare purposes
1077 anonymous_method_type = typeof (AnonymousMethodBody);
1078 null_type = typeof (NullLiteral);
1080 void_ptr_type = GetPointerType (void_type);
1081 char_ptr_type = GetPointerType (char_type);
1084 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
1085 // types cache with incorrect accessiblity when any of optional types is internal.
1087 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute", Kind.Class, false);
1089 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle", Kind.Struct, false);
1090 asynccallback_type = CoreLookupType ("System", "AsyncCallback", Kind.Delegate, false);
1091 iasyncresult_type = CoreLookupType ("System", "IAsyncResult", Kind.Interface, false);
1092 typed_reference_type = CoreLookupType ("System", "TypedReference", Kind.Struct, false);
1093 arg_iterator_type = CoreLookupType ("System", "ArgIterator", Kind.Struct, false);
1094 mbr_type = CoreLookupType ("System", "MarshalByRefObject", Kind.Class, false);
1097 // Optional attributes, used for error reporting only
1099 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute", Kind.Class, false);
1100 if (obsolete_attribute_type != null) {
1101 Class c = TypeManager.LookupClass (obsolete_attribute_type);
1106 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute", Kind.Class, false);
1107 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute", Kind.Class, false);
1109 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute", Kind.Class, false);
1111 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute", Kind.Class, false);
1112 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute", Kind.Class, false);
1113 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute", Kind.Class, false);
1114 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute", Kind.Class, false);
1115 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute", Kind.Class, false);
1116 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", Kind.Class, false);
1117 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute", Kind.Class, false);
1118 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute", Kind.Class, false);
1119 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute", Kind.Class, false);
1120 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute", Kind.Class, false);
1121 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute", Kind.Class, false);
1122 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute", Kind.Class, false);
1123 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", Kind.Class, false);
1126 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute", Kind.Class, false);
1127 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", Kind.Class, false);
1128 generic_ilist_type = CoreLookupType ("System.Collections.Generic", "IList`1", Kind.Interface, false);
1129 generic_icollection_type = CoreLookupType ("System.Collections.Generic", "ICollection`1", Kind.Interface, false);
1130 generic_ienumerable_type = CoreLookupType ("System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
1131 generic_nullable_type = CoreLookupType ("System", "Nullable`1", Kind.Struct, false);
1134 // Optional types which are used as types and for member lookup
1136 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute", Kind.Class, false);
1137 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
1138 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute", Kind.Class, false);
1139 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute", Kind.Class, false);
1140 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute", Kind.Class, false);
1143 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute", Kind.Class, false);
1146 extension_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "ExtensionAttribute", Kind.Class, false);
1147 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", Kind.Class, false);
1149 if (!RootContext.StdLib) {
1151 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1152 // has different predefined types and this method sets mscorlib types
1153 // to be same to avoid any type check errors.
1156 Type type = typeof (Type);
1157 Type [] system_4_type_arg = { type, type, type, type };
1159 MethodInfo set_corlib_type_builders =
1160 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1161 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1162 system_4_type_arg, null);
1164 if (set_corlib_type_builders != null) {
1165 object[] args = new object [4];
1166 args [0] = object_type;
1167 args [1] = value_type;
1168 args [2] = enum_type;
1169 args [3] = void_type;
1171 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1173 Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1174 TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
1175 TypeManager.CSharpName (system_4_type_arg));
1180 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1183 /// This is the "old", non-cache based FindMembers() function. We cannot use
1184 /// the cache here because there is no member name argument.
1186 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1187 MemberFilter filter, object criteria)
1189 #if MS_COMPATIBLE && GMCS_SOURCE
1190 if (t.IsGenericType)
1191 t = t.GetGenericTypeDefinition ();
1194 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1197 // `builder_to_declspace' contains all dynamic types.
1201 Timer.StartTimer (TimerType.FindMembers);
1202 list = decl.FindMembers (mt, bf, filter, criteria);
1203 Timer.StopTimer (TimerType.FindMembers);
1208 // We have to take care of arrays specially, because GetType on
1209 // a TypeBuilder array will return a Type, not a TypeBuilder,
1210 // and we can not call FindMembers on this type.
1213 #if MS_COMPATIBLE && GMCS_SOURCE
1216 t.IsSubclassOf (TypeManager.array_type))
1217 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1220 if (t is GenericTypeParameterBuilder) {
1221 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1223 Timer.StartTimer (TimerType.FindMembers);
1224 MemberList list = tparam.FindMembers (
1225 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1226 Timer.StopTimer (TimerType.FindMembers);
1232 // Since FindMembers will not lookup both static and instance
1233 // members, we emulate this behaviour here.
1235 if ((bf & instance_and_static) == instance_and_static){
1236 MemberInfo [] i_members = t.FindMembers (
1237 mt, bf & ~BindingFlags.Static, filter, criteria);
1239 int i_len = i_members.Length;
1241 MemberInfo one = i_members [0];
1244 // If any of these are present, we are done!
1246 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1247 return new MemberList (i_members);
1250 MemberInfo [] s_members = t.FindMembers (
1251 mt, bf & ~BindingFlags.Instance, filter, criteria);
1253 int s_len = s_members.Length;
1254 if (i_len > 0 || s_len > 0)
1255 return new MemberList (i_members, s_members);
1258 return new MemberList (i_members);
1260 return new MemberList (s_members);
1264 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1269 /// This method is only called from within MemberLookup. It tries to use the member
1270 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1271 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1272 /// our return value will already contain all inherited members and the caller don't need
1273 /// to check base classes and interfaces anymore.
1275 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1276 string name, out bool used_cache)
1281 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1282 // and we can ask the DeclSpace for the MemberCache.
1285 if (t.Assembly == CodeGen.Assembly.Builder) {
1286 if (t.IsGenericParameter) {
1287 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1290 if (tparam.MemberCache == null)
1291 return new MemberInfo[0];
1293 return tparam.MemberCache.FindMembers (
1294 mt, bf, name, FilterWithClosure_delegate, null);
1297 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1298 t = t.GetGenericTypeDefinition ();
1300 if (t is TypeBuilder) {
1302 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1303 cache = decl.MemberCache;
1306 // If this DeclSpace has a MemberCache, use it.
1309 if (cache != null) {
1311 return cache.FindMembers (
1312 mt, bf, name, FilterWithClosure_delegate, null);
1315 // If there is no MemberCache, we need to use the "normal" FindMembers.
1316 // Note, this is a VERY uncommon route!
1319 Timer.StartTimer (TimerType.FindMembers);
1320 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1321 FilterWithClosure_delegate, name);
1322 Timer.StopTimer (TimerType.FindMembers);
1324 return (MemberInfo []) list;
1328 // We have to take care of arrays specially, because GetType on
1329 // a TypeBuilder array will return a Type, not a TypeBuilder,
1330 // and we can not call FindMembers on this type.
1334 return TypeHandle.ArrayType.MemberCache.FindMembers (
1335 mt, bf, name, FilterWithClosure_delegate, null);
1339 if (t is GenericTypeParameterBuilder) {
1340 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1343 if (tparam.MemberCache == null)
1344 return new MemberInfo [0];
1346 return tparam.MemberCache.FindMembers (
1347 mt, bf, name, FilterWithClosure_delegate, null);
1351 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1353 // This happens if we're resolving a class'es base class and interfaces
1354 // in TypeContainer.DefineType(). At this time, the types aren't
1355 // populated yet, so we can't use the cache.
1357 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1358 FilterWithClosure_delegate, name);
1364 // This call will always succeed. There is exactly one TypeHandle instance per
1365 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1366 // the corresponding MemberCache.
1368 cache = TypeHandle.GetMemberCache (t);
1371 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1374 public static bool IsBuiltinType (Type t)
1376 t = TypeToCoreType (t);
1377 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1378 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1379 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1380 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1387 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1388 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1390 public static bool IsPrimitiveType (Type t)
1392 return (t == int32_type || t == uint32_type ||
1393 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1394 t == char_type || t == short_type || t == bool_type ||
1395 t == sbyte_type || t == byte_type || t == ushort_type);
1398 public static bool IsDelegateType (Type t)
1401 if (t.IsGenericParameter)
1405 if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
1408 t = DropGenericTypeArguments (t);
1409 return IsSubclassOf (t, TypeManager.delegate_type);
1412 public static bool IsEnumType (Type t)
1414 t = DropGenericTypeArguments (t);
1415 return t.BaseType == TypeManager.enum_type;
1418 public static bool IsBuiltinOrEnum (Type t)
1420 if (IsBuiltinType (t))
1429 public static bool IsAttributeType (Type t)
1431 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1434 static Stack unmanaged_enclosing_types = new Stack (4);
1437 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1439 public static bool IsUnmanagedType (Type t)
1441 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1442 if (unmanaged_enclosing_types.Contains (t))
1445 // builtins that are not unmanaged types
1446 if (t == TypeManager.object_type || t == TypeManager.string_type)
1449 if (IsGenericType (t) || IsGenericParameter (t))
1452 if (IsBuiltinOrEnum (t))
1455 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1459 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1463 if (!IsValueType (t))
1467 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1468 if (p.IsGenericTypeDefinition)
1473 unmanaged_enclosing_types.Push (t);
1477 if (t is TypeBuilder) {
1478 TypeContainer tc = LookupTypeContainer (t);
1479 if (tc.Fields != null){
1480 foreach (FieldBase f in tc.Fields){
1481 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1482 if ((f.ModFlags & Modifiers.STATIC) != 0)
1484 if (f.MemberType == null)
1486 if (!IsUnmanagedType (f.MemberType)){
1487 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1493 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1495 foreach (FieldInfo f in fields){
1496 if (!IsUnmanagedType (f.FieldType)){
1497 Report.SymbolRelatedToPreviousError (f);
1503 unmanaged_enclosing_types.Pop ();
1509 // Null is considered to be a reference type
1511 public static bool IsReferenceType (Type t)
1513 if (TypeManager.IsGenericParameter (t)) {
1514 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1515 if (constraints == null)
1518 return constraints.IsReferenceType;
1521 return !t.IsValueType;
1524 public static bool IsValueType (Type t)
1526 return t.IsValueType || IsGenericParameter (t);
1529 public static bool IsInterfaceType (Type t)
1531 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1535 return tc.Kind == Kind.Interface;
1538 public static bool IsSubclassOf (Type type, Type base_type)
1540 TypeParameter tparam = LookupTypeParameter (type);
1541 TypeParameter pparam = LookupTypeParameter (base_type);
1543 if ((tparam != null) && (pparam != null)) {
1544 if (tparam == pparam)
1547 return tparam.IsSubclassOf (base_type);
1550 #if MS_COMPATIBLE && GMCS_SOURCE
1551 if (type.IsGenericType)
1552 type = type.GetGenericTypeDefinition ();
1555 if (type.IsSubclassOf (base_type))
1559 if (IsEqual (type, base_type))
1562 type = type.BaseType;
1563 } while (type != null);
1568 public static bool IsPrivateAccessible (Type type, Type parent)
1573 if (type.Equals (parent))
1576 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1579 public static bool IsFamilyAccessible (Type type, Type parent)
1581 TypeParameter tparam = LookupTypeParameter (type);
1582 TypeParameter pparam = LookupTypeParameter (parent);
1584 if ((tparam != null) && (pparam != null)) {
1585 if (tparam == pparam)
1588 return tparam.IsSubclassOf (parent);
1592 if (IsInstantiationOfSameGenericType (type, parent))
1595 type = type.BaseType;
1596 } while (type != null);
1602 // Checks whether `type' is a subclass or nested child of `base_type'.
1604 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1607 if (IsFamilyAccessible (type, base_type))
1610 // Handle nested types.
1611 type = type.DeclaringType;
1612 } while (type != null);
1618 // Checks whether `type' is a nested child of `parent'.
1620 public static bool IsNestedChildOf (Type type, Type parent)
1625 type = DropGenericTypeArguments (type);
1626 parent = DropGenericTypeArguments (parent);
1628 if (IsEqual (type, parent))
1631 type = type.DeclaringType;
1632 while (type != null) {
1633 if (IsEqual (type, parent))
1636 type = type.DeclaringType;
1642 public static bool IsSpecialType (Type t)
1644 return t == arg_iterator_type || t == typed_reference_type;
1648 // Checks whether `extern_type' is friend of the output assembly
1650 public static bool IsThisOrFriendAssembly (Assembly assembly)
1652 if (assembly == CodeGen.Assembly.Builder)
1655 if (assembly_internals_vis_attrs.Contains (assembly))
1656 return (bool)(assembly_internals_vis_attrs [assembly]);
1658 if (internals_visible_attr_type == null)
1661 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1662 if (attrs.Length == 0) {
1663 assembly_internals_vis_attrs.Add (assembly, false);
1667 bool is_friend = false;
1669 AssemblyName this_name = CodeGen.Assembly.Name;
1670 byte [] this_token = this_name.GetPublicKeyToken ();
1671 foreach (InternalsVisibleToAttribute attr in attrs) {
1672 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1675 AssemblyName aname = null;
1677 aname = new AssemblyName (attr.AssemblyName);
1678 } catch (FileLoadException) {
1679 } catch (ArgumentException) {
1682 if (aname == null || aname.Name != this_name.Name)
1685 byte [] key_token = aname.GetPublicKeyToken ();
1686 if (key_token != null) {
1687 if (this_token.Length == 0) {
1688 // Same name, but assembly is not strongnamed
1689 Error_FriendAccessNameNotMatching (aname.FullName);
1693 if (!CompareKeyTokens (this_token, key_token))
1701 assembly_internals_vis_attrs.Add (assembly, is_friend);
1706 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1708 for (int i = 0; i < token1.Length; i++)
1709 if (token1 [i] != token2 [i])
1715 static void Error_FriendAccessNameNotMatching (string other_name)
1718 "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
1719 other_name, CodeGen.Assembly.Name.FullName);
1724 // Do the right thing when returning the element type of an
1725 // array type based on whether we are compiling corlib or not
1727 public static Type GetElementType (Type t)
1729 if (RootContext.StdLib)
1730 return t.GetElementType ();
1732 return TypeToCoreType (t.GetElementType ());
1736 /// This method is not implemented by MS runtime for dynamic types
1738 public static bool HasElementType (Type t)
1740 return t.IsArray || t.IsPointer || t.IsByRef;
1743 public static Type GetEnumUnderlyingType (Type t)
1745 t = DropGenericTypeArguments (t);
1746 Enum e = LookupTypeContainer (t) as Enum;
1748 return e.UnderlyingType;
1751 FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
1753 return TypeManager.int32_type;
1755 return TypeToCoreType (fi.FieldType);
1759 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1763 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1764 /// for anything which is dynamic, and we need this in a number of places,
1765 /// we register this information here, and use it afterwards.
1767 static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
1769 method_params.Add (mb, ip);
1772 static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
1774 method_params.Add (pb, p);
1777 static public AParametersCollection GetParameterData (MethodBase mb)
1779 AParametersCollection pd = (AParametersCollection) method_params [mb];
1782 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1783 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1784 pd = GetParameterData (mi);
1786 if (mi.IsGenericMethod)
1787 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1789 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1791 method_params.Add (mb, pd);
1795 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1796 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1797 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1800 pd = ParametersCollection.Create (mb);
1802 MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
1803 if (generic != mb) {
1804 pd = TypeManager.GetParameterData (generic);
1805 pd = ParametersCollection.Create (pd, mb);
1807 pd = ParametersCollection.Create (mb);
1810 method_params.Add (mb, pd);
1815 public static AParametersCollection GetParameterData (PropertyInfo pi)
1817 AParametersCollection pd = (AParametersCollection)method_params [pi];
1819 if (pi is PropertyBuilder)
1820 return Parameters.EmptyReadOnlyParameters;
1822 ParameterInfo [] p = pi.GetIndexParameters ();
1824 return Parameters.EmptyReadOnlyParameters;
1826 pd = ParametersCollection.Create (p, null);
1827 method_params.Add (pi, pd);
1833 public static AParametersCollection GetDelegateParameters (Type t)
1835 Delegate d = builder_to_declspace [t] as Delegate;
1837 return d.Parameters;
1839 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1840 return GetParameterData (invoke_mb);
1843 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1845 if (!method_overrides.Contains (override_method))
1846 method_overrides [override_method] = base_method;
1847 if (method_overrides [override_method] != base_method)
1848 throw new InternalErrorException ("Override mismatch: " + override_method);
1851 static public bool IsOverride (MethodBase m)
1853 m = DropGenericMethodArguments (m);
1855 return m.IsVirtual &&
1856 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1857 (m is MethodBuilder || method_overrides.Contains (m));
1860 static public MethodBase TryGetBaseDefinition (MethodBase m)
1862 m = DropGenericMethodArguments (m);
1864 return (MethodBase) method_overrides [m];
1867 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1869 fields.Add (fb, ic);
1872 public static IConstant GetConstant (FieldInfo fb)
1877 return (IConstant)fields [fb];
1880 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1882 propertybuilder_to_property.Add (pi, pb);
1885 public static PropertyBase GetProperty (PropertyInfo pi)
1887 return (PropertyBase)propertybuilder_to_property [pi];
1890 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
1892 fieldbuilders_to_fields.Add (fb, f);
1896 // The return value can be null; This will be the case for
1897 // auxiliary FieldBuilders created by the compiler that have no
1898 // real field being declared on the source code
1900 static public FieldBase GetField (FieldInfo fb)
1903 fb = GetGenericFieldDefinition (fb);
1905 return (FieldBase) fieldbuilders_to_fields [fb];
1908 static public MethodInfo GetAddMethod (EventInfo ei)
1910 if (ei is MyEventBuilder) {
1911 return ((MyEventBuilder)ei).GetAddMethod (true);
1913 return ei.GetAddMethod (true);
1916 static public MethodInfo GetRemoveMethod (EventInfo ei)
1918 if (ei is MyEventBuilder) {
1919 return ((MyEventBuilder)ei).GetRemoveMethod (true);
1921 return ei.GetRemoveMethod (true);
1924 static public void RegisterEventField (EventInfo einfo, EventField e)
1927 events = new Hashtable ();
1929 events.Add (einfo, e);
1932 static public EventField GetEventField (EventInfo ei)
1937 return (EventField) events [ei];
1940 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1942 Hashtable hash = new Hashtable ();
1943 return CheckStructCycles (tc, seen, hash);
1946 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1949 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
1953 // `seen' contains all types we've already visited.
1955 if (seen.Contains (tc))
1957 seen.Add (tc, null);
1959 if (tc.Fields == null)
1962 foreach (FieldBase field in tc.Fields) {
1963 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1966 Type ftype = field.FieldBuilder.FieldType;
1967 TypeContainer ftc = LookupTypeContainer (ftype);
1971 if (hash.Contains (ftc)) {
1972 Report.Error (523, tc.Location,
1973 "Struct member `{0}.{1}' of type `{2}' " +
1974 "causes a cycle in the struct layout",
1975 tc.Name, field.Name, ftc.Name);
1980 // `hash' contains all types in the current path.
1982 hash.Add (tc, null);
1984 bool ok = CheckStructCycles (ftc, seen, hash);
1991 if (!seen.Contains (ftc))
1992 seen.Add (ftc, null);
1999 /// Given an array of interface types, expand and eliminate repeated ocurrences
2000 /// of an interface.
2004 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2007 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
2009 ArrayList new_ifaces = new ArrayList ();
2011 foreach (TypeExpr iface in base_interfaces){
2012 Type itype = iface.Type;
2014 if (new_ifaces.Contains (itype))
2017 new_ifaces.Add (itype);
2019 Type [] implementing = GetInterfaces (itype);
2021 foreach (Type imp in implementing){
2022 if (!new_ifaces.Contains (imp))
2023 new_ifaces.Add (imp);
2026 Type [] ret = new Type [new_ifaces.Count];
2027 new_ifaces.CopyTo (ret, 0);
2031 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2033 ArrayList new_ifaces = new ArrayList ();
2035 foreach (Type itype in base_interfaces){
2036 if (new_ifaces.Contains (itype))
2039 new_ifaces.Add (itype);
2041 Type [] implementing = GetInterfaces (itype);
2043 foreach (Type imp in implementing){
2044 if (!new_ifaces.Contains (imp))
2045 new_ifaces.Add (imp);
2048 Type [] ret = new Type [new_ifaces.Count];
2049 new_ifaces.CopyTo (ret, 0);
2053 static PtrHashtable iface_cache = new PtrHashtable ();
2056 /// This function returns the interfaces in the type `t'. Works with
2057 /// both types and TypeBuilders.
2059 public static Type [] GetInterfaces (Type t)
2061 Type [] cached = iface_cache [t] as Type [];
2066 // The reason for catching the Array case is that Reflection.Emit
2067 // will not return a TypeBuilder for Array types of TypeBuilder types,
2068 // but will still throw an exception if we try to call GetInterfaces
2071 // Since the array interfaces are always constant, we return those for
2076 t = TypeManager.array_type;
2078 if ((t is TypeBuilder) || IsGenericType (t)) {
2079 Type [] base_ifaces;
2081 if (t.BaseType == null)
2082 base_ifaces = Type.EmptyTypes;
2084 base_ifaces = GetInterfaces (t.BaseType);
2086 if (IsGenericType (t))
2087 #if MS_COMPATIBLE && GMCS_SOURCE
2088 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2090 type_ifaces = t.GetInterfaces ();
2093 type_ifaces = (Type []) builder_to_ifaces [t];
2094 if (type_ifaces == null || type_ifaces.Length == 0)
2095 type_ifaces = Type.EmptyTypes;
2097 int base_count = base_ifaces.Length;
2098 Type [] result = new Type [base_count + type_ifaces.Length];
2099 base_ifaces.CopyTo (result, 0);
2100 type_ifaces.CopyTo (result, base_count);
2102 iface_cache [t] = result;
2105 } else if (t is GenericTypeParameterBuilder){
2106 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2107 if (type_ifaces == null || type_ifaces.Length == 0)
2108 type_ifaces = Type.EmptyTypes;
2110 iface_cache [t] = type_ifaces;
2114 Type[] ifaces = t.GetInterfaces ();
2115 iface_cache [t] = ifaces;
2121 // gets the interfaces that are declared explicitly on t
2123 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2125 return (Type []) builder_to_ifaces [t];
2129 /// The following is used to check if a given type implements an interface.
2130 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2132 public static bool ImplementsInterface (Type t, Type iface)
2137 // FIXME OPTIMIZATION:
2138 // as soon as we hit a non-TypeBuiler in the interface
2139 // chain, we could return, as the `Type.GetInterfaces'
2140 // will return all the interfaces implement by the type
2144 interfaces = GetInterfaces (t);
2146 if (interfaces != null){
2147 foreach (Type i in interfaces){
2154 } while (t != null);
2159 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2161 // This is a custom version of Convert.ChangeType() which works
2162 // with the TypeBuilder defined types when compiling corlib.
2163 public static object ChangeType (object value, Type conversionType, out bool error)
2165 IConvertible convert_value = value as IConvertible;
2167 if (convert_value == null){
2174 // We must use Type.Equals() here since `conversionType' is
2175 // the TypeBuilder created version of a system type and not
2176 // the system type itself. You cannot use Type.GetTypeCode()
2177 // on such a type - it'd always return TypeCode.Object.
2180 // We cannot rely on build-in type conversions as they are
2181 // more limited than what C# supports.
2182 // See char -> float/decimal/double conversion
2187 if (conversionType.Equals (typeof (Boolean)))
2188 return (object)(convert_value.ToBoolean (nf_provider));
2189 if (conversionType.Equals (typeof (Byte)))
2190 return (object)(convert_value.ToByte (nf_provider));
2191 if (conversionType.Equals (typeof (Char)))
2192 return (object)(convert_value.ToChar (nf_provider));
2193 if (conversionType.Equals (typeof (DateTime)))
2194 return (object)(convert_value.ToDateTime (nf_provider));
2196 if (conversionType.Equals (decimal_type)) {
2197 if (convert_value.GetType () == TypeManager.char_type)
2198 return (decimal)convert_value.ToInt32 (nf_provider);
2199 return convert_value.ToDecimal (nf_provider);
2202 if (conversionType.Equals (typeof (Double))) {
2203 if (convert_value.GetType () == TypeManager.char_type)
2204 return (double)convert_value.ToInt32 (nf_provider);
2205 return convert_value.ToDouble (nf_provider);
2208 if (conversionType.Equals (typeof (Int16)))
2209 return (object)(convert_value.ToInt16 (nf_provider));
2210 if (conversionType.Equals (int32_type))
2211 return (object)(convert_value.ToInt32 (nf_provider));
2212 if (conversionType.Equals (int64_type))
2213 return (object)(convert_value.ToInt64 (nf_provider));
2214 if (conversionType.Equals (typeof (SByte)))
2215 return (object)(convert_value.ToSByte (nf_provider));
2217 if (conversionType.Equals (typeof (Single))) {
2218 if (convert_value.GetType () == TypeManager.char_type)
2219 return (float)convert_value.ToInt32 (nf_provider);
2220 return convert_value.ToSingle (nf_provider);
2223 if (conversionType.Equals (typeof (String)))
2224 return (object)(convert_value.ToString (nf_provider));
2225 if (conversionType.Equals (typeof (UInt16)))
2226 return (object)(convert_value.ToUInt16 (nf_provider));
2227 if (conversionType.Equals (typeof (UInt32)))
2228 return (object)(convert_value.ToUInt32 (nf_provider));
2229 if (conversionType.Equals (typeof (UInt64)))
2230 return (object)(convert_value.ToUInt64 (nf_provider));
2231 if (conversionType.Equals (typeof (Object)))
2232 return (object)(value);
2242 // When compiling with -nostdlib and the type is imported from an external assembly
2243 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2245 public static Type TypeToCoreType (Type t)
2247 if (RootContext.StdLib || t.Module != typeof (object).Module)
2250 TypeCode tc = Type.GetTypeCode (t);
2253 case TypeCode.Boolean:
2254 return TypeManager.bool_type;
2256 return TypeManager.byte_type;
2257 case TypeCode.SByte:
2258 return TypeManager.sbyte_type;
2260 return TypeManager.char_type;
2261 case TypeCode.Int16:
2262 return TypeManager.short_type;
2263 case TypeCode.UInt16:
2264 return TypeManager.ushort_type;
2265 case TypeCode.Int32:
2266 return TypeManager.int32_type;
2267 case TypeCode.UInt32:
2268 return TypeManager.uint32_type;
2269 case TypeCode.Int64:
2270 return TypeManager.int64_type;
2271 case TypeCode.UInt64:
2272 return TypeManager.uint64_type;
2273 case TypeCode.Single:
2274 return TypeManager.float_type;
2275 case TypeCode.Double:
2276 return TypeManager.double_type;
2277 case TypeCode.String:
2278 return TypeManager.string_type;
2279 case TypeCode.Decimal:
2280 return TypeManager.decimal_type;
2283 if (t == typeof (void))
2284 return TypeManager.void_type;
2285 if (t == typeof (object))
2286 return TypeManager.object_type;
2287 if (t == typeof (System.Type))
2288 return TypeManager.type_type;
2289 if (t == typeof (System.IntPtr))
2290 return TypeManager.intptr_type;
2291 if (t == typeof (System.UIntPtr))
2292 return TypeManager.uintptr_type;
2295 int dim = t.GetArrayRank ();
2296 t = GetElementType (t);
2297 return t.MakeArrayType (dim);
2300 t = GetElementType (t);
2301 return t.MakeByRefType ();
2304 t = GetElementType (t);
2305 return t.MakePointerType ();
2312 /// Utility function that can be used to probe whether a type
2313 /// is managed or not.
2315 public static bool VerifyUnManaged (Type t, Location loc)
2317 if (IsUnmanagedType (t))
2320 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2327 /// Returns the name of the indexer in a given type.
2330 /// The default is not always `Item'. The user can change this behaviour by
2331 /// using the IndexerNameAttribute in the container.
2332 /// For example, the String class indexer is named `Chars' not `Item'
2334 public static string IndexerPropertyName (Type t)
2336 t = DropGenericTypeArguments (t);
2337 if (t is TypeBuilder) {
2338 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2339 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2342 System.Attribute attr = System.Attribute.GetCustomAttribute (
2343 t, TypeManager.default_member_type);
2345 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2346 return dma.MemberName;
2349 return TypeContainer.DefaultIndexerName;
2352 static MethodInfo declare_local_method = null;
2354 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2356 if (declare_local_method == null){
2357 declare_local_method = typeof (ILGenerator).GetMethod (
2359 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2361 new Type [] { typeof (Type), typeof (bool)},
2363 if (declare_local_method == null){
2364 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2365 return ig.DeclareLocal (t);
2368 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2371 private static bool IsSignatureEqual (Type a, Type b)
2374 /// Consider the following example (bug #77674):
2376 /// public abstract class A
2378 /// public abstract T Foo<T> ();
2381 /// public abstract class B : A
2383 /// public override U Foo<T> ()
2384 /// { return default (U); }
2387 /// Here, `T' and `U' are method type parameters from different methods
2388 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2390 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2391 /// we need to do a signature based comparision and consider them equal.
2397 if (a.IsGenericParameter && b.IsGenericParameter &&
2398 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2399 return a.GenericParameterPosition == b.GenericParameterPosition;
2403 if (a.IsArray && b.IsArray) {
2404 if (a.GetArrayRank () != b.GetArrayRank ())
2407 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2410 if (a.IsByRef && b.IsByRef)
2411 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2414 if (a.IsGenericType && b.IsGenericType) {
2415 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2418 Type[] aargs = a.GetGenericArguments ();
2419 Type[] bargs = b.GetGenericArguments ();
2421 if (aargs.Length != bargs.Length)
2424 for (int i = 0; i < aargs.Length; i++) {
2425 if (!IsSignatureEqual (aargs [i], bargs [i]))
2437 // Returns whether the array of memberinfos contains the given method
2439 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
2441 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2443 foreach (MethodBase method in array) {
2444 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
2447 if (method.Name != new_method.Name)
2450 if (method is MethodInfo && new_method is MethodInfo &&
2452 TypeToCoreType (((MethodInfo) method).ReturnType),
2453 TypeToCoreType (((MethodInfo) new_method).ReturnType)))
2456 Type [] old_args = TypeManager.GetParameterData (method).Types;
2457 int old_count = old_args.Length;
2460 if (new_args.Length != old_count)
2463 for (i = 0; i < old_count; i++){
2464 if (!IsSignatureEqual (old_args [i], new_args [i]))
2477 // We copy methods from `new_members' into `target_list' if the signature
2478 // for the method from in the new list does not exist in the target_list
2480 // The name is assumed to be the same.
2482 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2484 if (target_list == null){
2485 target_list = new ArrayList ();
2487 foreach (MemberInfo mi in new_members){
2488 if (mi is MethodBase)
2489 target_list.Add (mi);
2494 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2495 target_list.CopyTo (target_array, 0);
2497 foreach (MemberInfo mi in new_members){
2498 MethodBase new_method = (MethodBase) mi;
2500 if (!ArrayContainsMethod (target_array, new_method, true))
2501 target_list.Add (new_method);
2508 // Tracks the generic parameters.
2510 static PtrHashtable builder_to_type_param;
2512 public static void AddTypeParameter (Type t, TypeParameter tparam)
2514 if (!builder_to_type_param.Contains (t))
2515 builder_to_type_param.Add (t, tparam);
2518 public static TypeParameter LookupTypeParameter (Type t)
2520 return (TypeParameter) builder_to_type_param [t];
2523 // This method always return false for non-generic compiler,
2524 // while Type.IsGenericParameter is returned if it is supported.
2525 public static bool IsGenericParameter (Type type)
2528 return type.IsGenericParameter;
2534 public static int GenericParameterPosition (Type type)
2537 return type.GenericParameterPosition;
2539 throw new InternalErrorException ("should not be called");
2543 public static bool IsGenericType (Type type)
2546 return type.IsGenericType;
2552 public static bool IsGenericTypeDefinition (Type type)
2555 return type.IsGenericTypeDefinition;
2561 public static bool ContainsGenericParameters (Type type)
2564 return type.ContainsGenericParameters;
2570 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2573 if (fi.DeclaringType.IsGenericTypeDefinition ||
2574 !fi.DeclaringType.IsGenericType)
2577 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2578 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2579 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2581 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2582 foreach (FieldInfo f in t.GetFields (bf))
2583 if (f.MetadataToken == fi.MetadataToken)
2590 public static bool IsEqual (Type a, Type b)
2593 // MS BCL returns true even if enum types are different
2594 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2595 return a.FullName == b.FullName;
2597 // Some types are never equal
2598 if (a == TypeManager.null_type || a == TypeManager.anonymous_method_type)
2605 if (a.IsGenericParameter && b.IsGenericParameter) {
2606 // TODO: needs more testing before cleaning up
2607 //if (a.DeclaringMethod != b.DeclaringMethod &&
2608 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2610 return a.GenericParameterPosition == b.GenericParameterPosition;
2613 if (a.IsArray && b.IsArray) {
2614 if (a.GetArrayRank () != b.GetArrayRank ())
2616 return IsEqual (a.GetElementType (), b.GetElementType ());
2619 if (a.IsByRef && b.IsByRef)
2620 return IsEqual (a.GetElementType (), b.GetElementType ());
2622 if (a.IsGenericType && b.IsGenericType) {
2623 Type adef = a.GetGenericTypeDefinition ();
2624 Type bdef = b.GetGenericTypeDefinition ();
2629 if (adef.IsEnum && bdef.IsEnum)
2632 Type[] aargs = a.GetGenericArguments ();
2633 Type[] bargs = b.GetGenericArguments ();
2635 if (aargs.Length != bargs.Length)
2638 for (int i = 0; i < aargs.Length; i++) {
2639 if (!IsEqual (aargs [i], bargs [i]))
2650 public static bool IsEqual (Type[] a, Type[] b)
2652 if (a == null || b == null || a.Length != b.Length)
2655 for (int i = 0; i < a.Length; ++i) {
2656 if (a [i] == null || b [i] == null) {
2663 if (!IsEqual (a [i], b [i]))
2670 public static Type DropGenericTypeArguments (Type t)
2673 if (!t.IsGenericType)
2675 // Micro-optimization: a generic typebuilder is always a generic type definition
2676 if (t is TypeBuilder)
2678 return t.GetGenericTypeDefinition ();
2684 public static MethodBase DropGenericMethodArguments (MethodBase m)
2687 if (m.IsGenericMethod)
2688 m = ((MethodInfo) m).GetGenericMethodDefinition ();
2690 Type t = m.DeclaringType;
2691 if (!t.IsGenericType || t.IsGenericTypeDefinition)
2694 t = t.GetGenericTypeDefinition ();
2695 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2696 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2699 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2703 if (m is ConstructorInfo) {
2704 foreach (ConstructorInfo c in t.GetConstructors (bf))
2705 if (c.MetadataToken == m.MetadataToken)
2708 foreach (MethodBase mb in t.GetMethods (bf))
2709 if (mb.MetadataToken == m.MetadataToken)
2717 public static Type[] GetGenericArguments (MethodBase mi)
2720 return mi.GetGenericArguments ();
2722 return Type.EmptyTypes;
2726 public static Type[] GetTypeArguments (Type t)
2729 DeclSpace tc = LookupDeclSpace (t);
2732 return Type.EmptyTypes;
2734 TypeParameter[] tparam = tc.TypeParameters;
2735 Type[] ret = new Type [tparam.Length];
2736 for (int i = 0; i < tparam.Length; i++) {
2737 ret [i] = tparam [i].Type;
2738 if (ret [i] == null)
2739 throw new InternalErrorException ();
2744 return t.GetGenericArguments ();
2746 throw new InternalErrorException ();
2750 public static GenericConstraints GetTypeParameterConstraints (Type t)
2753 if (!t.IsGenericParameter)
2754 throw new InvalidOperationException ();
2756 TypeParameter tparam = LookupTypeParameter (t);
2758 return tparam.GenericConstraints;
2760 return ReflectionConstraints.GetConstraints (t);
2762 throw new InternalErrorException ();
2766 public static bool HasGenericArguments (Type t)
2768 return GetNumberOfTypeArguments (t) > 0;
2771 public static int GetNumberOfTypeArguments (Type t)
2774 if (t.IsGenericParameter)
2776 DeclSpace tc = LookupDeclSpace (t);
2778 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2780 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2787 /// Check whether `type' and `parent' are both instantiations of the same
2788 /// generic type. Note that we do not check the type parameters here.
2790 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2792 int tcount = GetNumberOfTypeArguments (type);
2793 int pcount = GetNumberOfTypeArguments (parent);
2795 if (tcount != pcount)
2798 type = DropGenericTypeArguments (type);
2799 parent = DropGenericTypeArguments (parent);
2801 return type.Equals (parent);
2805 /// Whether `mb' is a generic method definition.
2807 public static bool IsGenericMethodDefinition (MethodBase mb)
2810 if (mb.DeclaringType is TypeBuilder) {
2811 IMethodData method = (IMethodData) builder_to_method [mb];
2815 return method.GenericMethod != null;
2818 return mb.IsGenericMethodDefinition;
2825 /// Whether `mb' is a generic method.
2827 public static bool IsGenericMethod (MethodBase mb)
2830 return mb.IsGenericMethod;
2836 public static bool IsNullableType (Type t)
2839 return generic_nullable_type == DropGenericTypeArguments (t);
2845 public static bool IsNullableTypeOf (Type t, Type nullable)
2848 if (!IsNullableType (t))
2851 return GetTypeArguments (t) [0] == nullable;
2857 public static bool IsNullableValueType (Type t)
2860 if (!IsNullableType (t))
2863 return GetTypeArguments (t) [0].IsValueType;
2870 #region MemberLookup implementation
2873 // Whether we allow private members in the result (since FindMembers
2874 // uses NonPublic for both protected and private), we need to distinguish.
2877 internal class Closure {
2878 internal bool private_ok;
2880 // Who is invoking us and which type is being queried currently.
2881 internal Type invocation_type;
2882 internal Type qualifier_type;
2884 // The assembly that defines the type is that is calling us
2885 internal Assembly invocation_assembly;
2886 internal IList almost_match;
2888 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2890 if (invocation_type == null)
2893 if (is_static && qualifier_type == null)
2894 // It resolved from a simple name, so it should be visible.
2897 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2900 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2901 if (!IsFamilyAccessible (t, m.DeclaringType))
2904 // Although a derived class can access protected members of its base class
2905 // it cannot do so through an instance of the base class (CS1540).
2906 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2907 if (is_static || qualifier_type == null ||
2908 IsInstantiationOfSameGenericType (t, qualifier_type) ||
2909 IsFamilyAccessible (qualifier_type, t))
2913 if (almost_match != null)
2914 almost_match.Add (m);
2920 // This filter filters by name + whether it is ok to include private
2921 // members in the search
2923 internal bool Filter (MemberInfo m, object filter_criteria)
2926 // Hack: we know that the filter criteria will always be in the
2927 // `closure' // fields.
2930 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2933 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2934 (invocation_type != null) &&
2935 IsPrivateAccessible (m.DeclaringType, invocation_type))
2939 // Ugly: we need to find out the type of `m', and depending
2940 // on this, tell whether we accept or not
2942 if (m is MethodBase){
2943 MethodBase mb = (MethodBase) m;
2944 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2946 if (ma == MethodAttributes.Public)
2949 if (ma == MethodAttributes.PrivateScope)
2952 if (ma == MethodAttributes.Private)
2953 return private_ok ||
2954 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2955 IsNestedChildOf (invocation_type, m.DeclaringType);
2957 if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) {
2958 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2961 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2965 // Family, FamORAssem or FamANDAssem
2966 return CheckValidFamilyAccess (mb.IsStatic, m);
2969 if (m is FieldInfo){
2970 FieldInfo fi = (FieldInfo) m;
2971 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2973 if (fa == FieldAttributes.Public)
2976 if (fa == FieldAttributes.PrivateScope)
2979 if (fa == FieldAttributes.Private)
2980 return private_ok ||
2981 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2982 IsNestedChildOf (invocation_type, m.DeclaringType);
2984 if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) {
2985 if ((fa == FieldAttributes.Assembly) ||
2986 (fa == FieldAttributes.FamORAssem))
2989 if ((fa == FieldAttributes.Assembly) ||
2990 (fa == FieldAttributes.FamANDAssem))
2994 // Family, FamORAssem or FamANDAssem
2995 return CheckValidFamilyAccess (fi.IsStatic, m);
2999 // EventInfos and PropertyInfos, return true because they lack
3000 // permission information, so we need to check later on the methods.
3006 static Closure closure = new Closure ();
3007 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3010 // Looks up a member called `name' in the `queried_type'. This lookup
3011 // is done by code that is contained in the definition for `invocation_type'
3012 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3014 // `invocation_type' is used to check whether we're allowed to access the requested
3015 // member wrt its protection level.
3017 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3018 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3019 // is B and qualifier_type is A). This is used to do the CS1540 check.
3021 // When resolving a SimpleName, `qualifier_type' is null.
3023 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3024 // the same than `queried_type' - except when we're being called from BaseAccess;
3025 // in this case, `invocation_type' is the current type and `queried_type' the base
3026 // type, so this'd normally trigger a CS1540.
3028 // The binding flags are `bf' and the kind of members being looked up are `mt'
3030 // The return value always includes private members which code in `invocation_type'
3031 // is allowed to access (using the specified `qualifier_type' if given); only use
3032 // BindingFlags.NonPublic to bypass the permission check.
3034 // The 'almost_match' argument is used for reporting error CS1540.
3036 // Returns an array of a single element for everything but Methods/Constructors
3037 // that might return multiple matches.
3039 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3040 Type queried_type, MemberTypes mt,
3041 BindingFlags original_bf, string name, IList almost_match)
3043 Timer.StartTimer (TimerType.MemberLookup);
3045 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3046 queried_type, mt, original_bf, name, almost_match);
3048 Timer.StopTimer (TimerType.MemberLookup);
3053 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3054 Type queried_type, MemberTypes mt,
3055 BindingFlags original_bf, string name, IList almost_match)
3057 BindingFlags bf = original_bf;
3059 ArrayList method_list = null;
3060 Type current_type = queried_type;
3061 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3062 bool skip_iface_check = true, used_cache = false;
3063 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3065 closure.invocation_type = invocation_type;
3066 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3067 closure.qualifier_type = qualifier_type;
3068 closure.almost_match = almost_match;
3070 // This is from the first time we find a method
3071 // in most cases, we do not actually find a method in the base class
3072 // so we can just ignore it, and save the arraylist allocation
3073 MemberInfo [] first_members_list = null;
3074 bool use_first_members_list = false;
3080 // `NonPublic' is lame, because it includes both protected and
3081 // private methods, so we need to control this behavior by
3082 // explicitly tracking if a private method is ok or not.
3084 // The possible cases are:
3085 // public, private and protected (internal does not come into the
3088 if ((invocation_type != null) &&
3089 ((invocation_type == current_type) ||
3090 IsNestedChildOf (invocation_type, current_type)) ||
3092 bf = original_bf | BindingFlags.NonPublic;
3096 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3098 Timer.StopTimer (TimerType.MemberLookup);
3100 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3102 Timer.StartTimer (TimerType.MemberLookup);
3105 // When queried for an interface type, the cache will automatically check all
3106 // inherited members, so we don't need to do this here. However, this only
3107 // works if we already used the cache in the first iteration of this loop.
3109 // If we used the cache in any further iteration, we can still terminate the
3110 // loop since the cache always looks in all base classes.
3116 skip_iface_check = false;
3118 if (current_type == TypeManager.object_type)
3121 current_type = current_type.BaseType;
3124 // This happens with interfaces, they have a null
3125 // basetype. Look members up in the Object class.
3127 if (current_type == null) {
3128 current_type = TypeManager.object_type;
3133 if (list.Length == 0)
3137 // Events and types are returned by both `static' and `instance'
3138 // searches, which means that our above FindMembers will
3139 // return two copies of the same.
3141 if (list.Length == 1 && !(list [0] is MethodBase)){
3146 // Multiple properties: we query those just to find out the indexer
3149 if (list [0] is PropertyInfo)
3153 // We found an event: the cache lookup returns both the event and
3154 // its private field.
3156 if (list [0] is EventInfo) {
3157 if ((list.Length == 2) && (list [1] is FieldInfo))
3158 return new MemberInfo [] { list [0] };
3164 // We found methods, turn the search into "method scan"
3168 if (first_members_list != null) {
3169 if (use_first_members_list) {
3170 method_list = CopyNewMethods (method_list, first_members_list);
3171 use_first_members_list = false;
3174 method_list = CopyNewMethods (method_list, list);
3176 first_members_list = list;
3177 use_first_members_list = true;
3178 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3180 } while (searching);
3182 if (use_first_members_list)
3183 return first_members_list;
3185 if (method_list != null && method_list.Count > 0) {
3186 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3189 // This happens if we already used the cache in the first iteration, in this case
3190 // the cache already looked in all interfaces.
3192 if (skip_iface_check)
3196 // Interfaces do not list members they inherit, so we have to
3199 if (!queried_type.IsInterface)
3202 if (queried_type.IsArray)
3203 queried_type = TypeManager.array_type;
3205 Type [] ifaces = GetInterfaces (queried_type);
3209 foreach (Type itype in ifaces){
3212 x = MemberLookup (null, null, itype, mt, bf, name, null);
3220 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3221 BindingFlags.Static | BindingFlags.Instance |
3222 BindingFlags.DeclaredOnly;
3224 // Currently is designed to work with external types only
3225 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3227 if (!mb.IsSpecialName)
3230 string name = mb.Name;
3231 if (name.Length < 5)
3234 if (name [3] != '_')
3237 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3238 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3239 Type.FilterName, name.Substring (4));
3244 // This can happen when property is indexer (it can have same name but different parameters)
3245 foreach (PropertyInfo p in pi) {
3246 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3247 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3256 // Currently is designed to work with external types only
3257 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3259 if (!mb.IsSpecialName)
3262 string name = mb.Name;
3263 if (name.Length < 5)
3266 if (name.StartsWith ("add_"))
3267 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3269 if (name.StartsWith ("remove_"))
3270 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3275 // Tests whether external method is really special
3276 public static bool IsSpecialMethod (MethodBase mb)
3278 if (!mb.IsSpecialName)
3281 IMethodData md = TypeManager.GetMethod (mb);
3283 return (md is AbstractPropertyEventMethod || md is Operator);
3285 PropertyInfo pi = GetPropertyFromAccessor (mb);
3287 return IsValidProperty (pi);
3289 if (GetEventFromAccessor (mb) != null)
3292 string name = mb.Name;
3293 if (name.StartsWith ("op_"))
3294 return Operator.GetName (name) != null;
3299 // Tests whether imported property is valid C# property.
3300 // TODO: It seems to me that we should do a lot of sanity tests before
3301 // we accept property as C# property
3302 static bool IsValidProperty (PropertyInfo pi)
3304 MethodInfo get_method = pi.GetGetMethod (true);
3305 MethodInfo set_method = pi.GetSetMethod (true);
3308 if (get_method != null && set_method != null) {
3309 g_count = get_method.GetParameters ().Length;
3310 s_count = set_method.GetParameters ().Length;
3311 if (g_count + 1 != s_count)
3313 } else if (get_method != null) {
3314 g_count = get_method.GetParameters ().Length;
3315 } else if (set_method != null) {
3316 s_count = set_method.GetParameters ().Length;
3320 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3322 if ((s_count > 1 || g_count > 0) && TypeManager.default_member_type != null) {
3323 object[] o = pi.DeclaringType.GetCustomAttributes (TypeManager.default_member_type, false);
3327 DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
3328 if (dma.MemberName != pi.Name)
3330 if (get_method != null && "get_" + dma.MemberName != get_method.Name)
3332 if (set_method != null && "set_" + dma.MemberName != set_method.Name)
3344 /// There is exactly one instance of this class per type.
3346 public sealed class TypeHandle : IMemberContainer {
3347 public readonly IMemberContainer BaseType;
3349 readonly int id = ++next_id;
3350 static int next_id = 0;
3352 static TypeHandle ()
3358 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3359 /// a TypeHandle yet, a new instance of it is created. This static method
3360 /// ensures that we'll only have one TypeHandle instance per type.
3362 private static TypeHandle GetTypeHandle (Type t)
3364 TypeHandle handle = (TypeHandle) type_hash [t];
3368 handle = new TypeHandle (t);
3369 type_hash.Add (t, handle);
3373 public static MemberCache GetMemberCache (Type t)
3375 return GetTypeHandle (t).MemberCache;
3378 public static void CleanUp ()
3383 public static void Reset ()
3385 type_hash = new PtrHashtable ();
3389 /// Returns the TypeHandle for TypeManager.object_type.
3391 public static IMemberContainer ObjectType {
3393 if (object_type != null)
3396 object_type = GetTypeHandle (TypeManager.object_type);
3403 /// Returns the TypeHandle for TypeManager.array_type.
3405 public static TypeHandle ArrayType {
3407 if (array_type != null)
3410 array_type = GetTypeHandle (TypeManager.array_type);
3416 private static PtrHashtable type_hash;
3418 private static TypeHandle object_type = null;
3419 private static TypeHandle array_type = null;
3422 private string full_name;
3423 private bool is_interface;
3424 private MemberCache member_cache;
3425 private MemberCache base_cache;
3427 private TypeHandle (Type type)
3430 full_name = type.FullName != null ? type.FullName : type.Name;
3431 if (type.BaseType != null) {
3432 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3433 BaseType = base_cache.Container;
3434 } else if (type.IsInterface)
3435 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3436 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3437 this.member_cache = new MemberCache (this);
3440 // IMemberContainer methods
3442 public string Name {
3454 public MemberCache BaseCache {
3460 public bool IsInterface {
3462 return is_interface;
3466 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3468 MemberInfo [] members;
3471 if (type is GenericTypeParameterBuilder)
3472 return MemberList.Empty;
3475 if (mt == MemberTypes.Event)
3476 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3478 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3481 if (members.Length == 0)
3482 return MemberList.Empty;
3484 Array.Reverse (members);
3485 return new MemberList (members);
3488 // IMemberFinder methods
3490 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3491 MemberFilter filter, object criteria)
3493 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3496 public MemberCache MemberCache {
3498 return member_cache;
3502 public override string ToString ()
3504 if (BaseType != null)
3505 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3507 return "TypeHandle (" + id + "," + Name + ")";