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";
603 return CSharpName (GetFullName (t));
606 static readonly char [] elements = new char [] { '*', '[' };
608 public static string CSharpName (string name)
610 if (name.Length > 10) {
612 case "System.Int32": return "int";
613 case "System.Int64": return "long";
614 case "System.String": return "string";
615 case "System.Boolean": return "bool";
616 case "System.Void": return "void";
617 case "System.Object": return "object";
618 case "System.UInt32": return "uint";
619 case "System.Int16": return "short";
620 case "System.UInt16": return "ushort";
621 case "System.UInt64": return "ulong";
622 case "System.Single": return "float";
623 case "System.Double": return "double";
624 case "System.Decimal": return "decimal";
625 case "System.Char": return "char";
626 case "System.Byte": return "byte";
627 case "System.SByte": return "sbyte";
630 int idx = name.IndexOfAny (elements, 10);
632 return CSharpName (name.Substring (0, idx)) + name.Substring (idx);
635 if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
636 return AnonymousTypeClass.SignatureForError;
638 return name.Replace ('+', '.');
641 static public string CSharpName (Type[] types)
643 if (types.Length == 0)
646 StringBuilder sb = new StringBuilder ();
647 for (int i = 0; i < types.Length; ++i) {
651 sb.Append (CSharpName (types [i]));
653 return sb.ToString ();
657 /// Returns the signature of the method with full namespace classification
659 static public string GetFullNameSignature (MemberInfo mi)
661 PropertyInfo pi = mi as PropertyInfo;
663 MethodBase pmi = pi.GetGetMethod (true);
665 pmi = pi.GetSetMethod (true);
666 if (GetParameterData (pmi).Count > 0)
669 return (mi is MethodBase)
670 ? CSharpSignature (mi as MethodBase)
671 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
675 private static int GetFullName (Type t, StringBuilder sb)
679 if (!t.IsGenericType) {
680 sb.Append (t.FullName);
684 if (t.DeclaringType != null) {
685 pos = GetFullName (t.DeclaringType, sb);
687 } else if (t.Namespace != null && t.Namespace.Length != 0) {
688 sb.Append (t.Namespace);
691 sb.Append (RemoveGenericArity (t.Name));
693 Type[] this_args = GetTypeArguments (t);
695 if (this_args.Length < pos)
696 throw new InternalErrorException (
697 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
698 if (this_args.Length == pos)
703 sb.Append (CSharpName (this_args [pos++]));
704 if (pos == this_args.Length)
712 static string GetFullName (Type t)
715 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
716 return GetFullName (t.GetElementType ()) + dimension;
719 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
720 t = GetTypeArguments (t)[0];
721 return CSharpName (t) + "?";
724 if (t.IsGenericParameter)
726 if (!t.IsGenericType)
729 StringBuilder sb = new StringBuilder ();
730 int pos = GetFullName (t, sb);
732 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
733 return sb.ToString ();
736 public static string GetFullName (Type t)
742 public static string RemoveGenericArity (string from)
744 int i = from.IndexOf ('`');
746 return from.Substring (0, i);
751 /// When we need to report accessors as well
753 static public string CSharpSignature (MethodBase mb)
755 return CSharpSignature (mb, false);
759 /// Returns the signature of the method
761 static public string CSharpSignature (MethodBase mb, bool show_accessor)
763 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
766 AParametersCollection iparams = GetParameterData (mb);
767 string parameters = iparams.GetSignatureForError ();
768 int accessor_end = 0;
770 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
771 string op_name = Operator.GetName (mb.Name);
772 if (op_name != null) {
773 sig.Append ("operator ");
774 sig.Append (op_name);
775 sig.Append (parameters);
776 return sig.ToString ();
779 bool is_getter = mb.Name.StartsWith ("get_");
780 bool is_setter = mb.Name.StartsWith ("set_");
781 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
783 } else if (mb.Name.StartsWith ("remove_")) {
788 if (iparams.Count > (is_getter ? 0 : 1)) {
789 sig.Append ("this[");
791 sig.Append (parameters.Substring (1, parameters.Length - 2));
793 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
796 sig.Append (mb.Name.Substring (accessor_end + 1));
799 if (mb.Name == ".ctor")
800 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
802 sig.Append (mb.Name);
805 if (TypeManager.IsGenericMethod (mb)) {
806 Type[] args = mb.GetGenericArguments ();
808 for (int i = 0; i < args.Length; i++) {
811 sig.Append (CSharpName (args [i]));
818 sig.Append (parameters);
821 if (show_accessor && accessor_end > 0) {
823 sig.Append (mb.Name.Substring (0, accessor_end));
826 return sig.ToString ();
829 public static string GetMethodName (MethodInfo m)
832 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
835 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
841 static public string CSharpSignature (EventInfo ei)
843 return CSharpName (ei.DeclaringType) + "." + ei.Name;
847 // Looks up a type, and aborts if it is not found. This is used
848 // by predefined types required by the compiler
850 public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required)
853 if (RootContext.StdLib) {
854 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
855 expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
858 Report.DisableReporting ();
860 TypeLookupExpression tle = new TypeLookupExpression (ns_name + "." + name);
861 expr = tle.ResolveAsTypeTerminal (RootContext.ToplevelTypes, false);
864 Report.EnableReporting ();
869 Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
876 if (RootContext.StdLib || t == null || !required)
879 // TODO: All predefined imported types have to have correct signature
880 if (t.Module != CodeGen.Module.Builder)
883 DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
884 if (ds is Delegate) {
885 if (type_kind == Kind.Delegate)
888 TypeContainer tc = (TypeContainer)ds;
889 if (tc.Kind == type_kind)
893 Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
898 static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
900 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
902 MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
903 if (members != null) {
904 for (int i = 0; i < members.Length; ++i) {
905 MemberInfo member = members [i];
906 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
907 MethodBase mb = member as MethodBase;
911 AParametersCollection pd = TypeManager.GetParameterData (mb);
912 if (IsEqual (pd.Types, args))
915 if (mt == MemberTypes.Field) {
916 FieldInfo fi = member as FieldInfo;
920 if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
926 if (mt == MemberTypes.Property) {
927 PropertyInfo pi = member as PropertyInfo;
931 if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
939 string method_args = null;
940 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
941 method_args = "(" + TypeManager.CSharpName (args) + ")";
943 Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
944 TypeManager.CSharpName (t), name, method_args);
950 // Returns the ConstructorInfo for "args"
952 public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
954 return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
958 // Returns the MethodInfo for a method named `name' defined
959 // in type `t' which takes arguments of types `args'
961 public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
963 return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
966 public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
968 return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
971 public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
973 return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
977 /// The types have to be initialized after the initial
978 /// population of the type has happened (for example, to
979 /// bootstrap the corlib.dll
981 public static bool InitCoreTypes ()
983 object_type = CoreLookupType ("System", "Object", Kind.Class, true);
984 system_object_expr.Type = object_type;
985 value_type = CoreLookupType ("System", "ValueType", Kind.Class, true);
986 system_valuetype_expr.Type = value_type;
987 attribute_type = CoreLookupType ("System", "Attribute", Kind.Class, true);
989 int32_type = CoreLookupType ("System", "Int32", Kind.Struct, true);
990 int64_type = CoreLookupType ("System", "Int64", Kind.Struct, true);
991 uint32_type = CoreLookupType ("System", "UInt32", Kind.Struct, true);
992 uint64_type = CoreLookupType ("System", "UInt64", Kind.Struct, true);
993 byte_type = CoreLookupType ("System", "Byte", Kind.Struct, true);
994 sbyte_type = CoreLookupType ("System", "SByte", Kind.Struct, true);
995 short_type = CoreLookupType ("System", "Int16", Kind.Struct, true);
996 ushort_type = CoreLookupType ("System", "UInt16", Kind.Struct, true);
998 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator", Kind.Interface, true);
999 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable", Kind.Interface, true);
1000 idisposable_type = CoreLookupType ("System", "IDisposable", Kind.Interface, true);
1002 // HACK: DefineType immediately resolves iterators (very wrong)
1003 generic_ienumerator_type = CoreLookupType ("System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
1005 char_type = CoreLookupType ("System", "Char", Kind.Struct, true);
1006 string_type = CoreLookupType ("System", "String", Kind.Class, true);
1007 float_type = CoreLookupType ("System", "Single", Kind.Struct, true);
1008 double_type = CoreLookupType ("System", "Double", Kind.Struct, true);
1009 decimal_type = CoreLookupType ("System", "Decimal", Kind.Struct, true);
1010 bool_type = CoreLookupType ("System", "Boolean", Kind.Struct, true);
1011 intptr_type = CoreLookupType ("System", "IntPtr", Kind.Struct, true);
1012 uintptr_type = CoreLookupType ("System", "UIntPtr", Kind.Struct, true);
1014 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate", Kind.Class, true);
1015 delegate_type = CoreLookupType ("System", "Delegate", Kind.Class, true);
1017 enum_type = CoreLookupType ("System", "Enum", Kind.Class, true);
1018 array_type = CoreLookupType ("System", "Array", Kind.Class, true);
1019 void_type = CoreLookupType ("System", "Void", Kind.Struct, true);
1020 type_type = CoreLookupType ("System", "Type", Kind.Class, true);
1021 exception_type = CoreLookupType ("System", "Exception", Kind.Class, true);
1023 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle", Kind.Struct, true);
1024 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle", Kind.Struct, true);
1026 param_array_type = CoreLookupType ("System", "ParamArrayAttribute", Kind.Class, true);
1027 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute", Kind.Class, true);
1029 return Report.Errors == 0;
1033 // Initializes optional core types
1035 public static void InitOptionalCoreTypes ()
1037 system_string_expr.Type = string_type;
1038 system_boolean_expr.Type = bool_type;
1039 system_decimal_expr.Type = decimal_type;
1040 system_single_expr.Type = float_type;
1041 system_double_expr.Type = double_type;
1042 system_sbyte_expr.Type = sbyte_type;
1043 system_byte_expr.Type = byte_type;
1044 system_int16_expr.Type = short_type;
1045 system_uint16_expr.Type = ushort_type;
1046 system_int32_expr.Type = int32_type;
1047 system_uint32_expr.Type = uint32_type;
1048 system_int64_expr.Type = int64_type;
1049 system_uint64_expr.Type = uint64_type;
1050 system_char_expr.Type = char_type;
1051 system_void_expr.Type = void_type;
1054 // These are only used for compare purposes
1056 anonymous_method_type = typeof (AnonymousMethodBody);
1057 null_type = typeof (NullLiteral);
1059 void_ptr_type = GetPointerType (void_type);
1060 char_ptr_type = GetPointerType (char_type);
1063 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
1064 // types cache with incorrect accessiblity when any of optional types is internal.
1066 internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute", Kind.Class, false);
1068 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle", Kind.Struct, false);
1069 asynccallback_type = CoreLookupType ("System", "AsyncCallback", Kind.Delegate, false);
1070 iasyncresult_type = CoreLookupType ("System", "IAsyncResult", Kind.Interface, false);
1071 typed_reference_type = CoreLookupType ("System", "TypedReference", Kind.Struct, false);
1072 arg_iterator_type = CoreLookupType ("System", "ArgIterator", Kind.Struct, false);
1073 mbr_type = CoreLookupType ("System", "MarshalByRefObject", Kind.Class, false);
1076 // Optional attributes, used for error reporting only
1078 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute", Kind.Class, false);
1079 if (obsolete_attribute_type != null) {
1080 Class c = TypeManager.LookupClass (obsolete_attribute_type);
1085 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute", Kind.Class, false);
1086 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute", Kind.Class, false);
1088 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute", Kind.Class, false);
1090 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute", Kind.Class, false);
1091 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute", Kind.Class, false);
1092 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute", Kind.Class, false);
1093 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute", Kind.Class, false);
1094 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute", Kind.Class, false);
1095 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", Kind.Class, false);
1096 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute", Kind.Class, false);
1097 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute", Kind.Class, false);
1098 assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute", Kind.Class, false);
1099 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute", Kind.Class, false);
1100 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute", Kind.Class, false);
1101 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute", Kind.Class, false);
1102 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", Kind.Class, false);
1105 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute", Kind.Class, false);
1106 type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", Kind.Class, false);
1107 generic_ilist_type = CoreLookupType ("System.Collections.Generic", "IList`1", Kind.Interface, false);
1108 generic_icollection_type = CoreLookupType ("System.Collections.Generic", "ICollection`1", Kind.Interface, false);
1109 generic_ienumerable_type = CoreLookupType ("System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
1110 generic_nullable_type = CoreLookupType ("System", "Nullable`1", Kind.Struct, false);
1113 // Optional types which are used as types and for member lookup
1115 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute", Kind.Class, false);
1116 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
1117 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute", Kind.Class, false);
1118 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute", Kind.Class, false);
1119 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute", Kind.Class, false);
1122 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute", Kind.Class, false);
1125 extension_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "ExtensionAttribute", Kind.Class, false);
1126 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", Kind.Class, false);
1128 if (!RootContext.StdLib) {
1130 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1131 // has different predefined types and this method sets mscorlib types
1132 // to be same to avoid any type check errors.
1135 Type type = typeof (Type);
1136 Type [] system_4_type_arg = { type, type, type, type };
1138 MethodInfo set_corlib_type_builders =
1139 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1140 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1141 system_4_type_arg, null);
1143 if (set_corlib_type_builders != null) {
1144 object[] args = new object [4];
1145 args [0] = object_type;
1146 args [1] = value_type;
1147 args [2] = enum_type;
1148 args [3] = void_type;
1150 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1152 Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1153 TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
1154 TypeManager.CSharpName (system_4_type_arg));
1159 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1162 /// This is the "old", non-cache based FindMembers() function. We cannot use
1163 /// the cache here because there is no member name argument.
1165 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1166 MemberFilter filter, object criteria)
1168 #if MS_COMPATIBLE && GMCS_SOURCE
1169 if (t.IsGenericType)
1170 t = t.GetGenericTypeDefinition ();
1173 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1176 // `builder_to_declspace' contains all dynamic types.
1180 Timer.StartTimer (TimerType.FindMembers);
1181 list = decl.FindMembers (mt, bf, filter, criteria);
1182 Timer.StopTimer (TimerType.FindMembers);
1187 // We have to take care of arrays specially, because GetType on
1188 // a TypeBuilder array will return a Type, not a TypeBuilder,
1189 // and we can not call FindMembers on this type.
1192 #if MS_COMPATIBLE && GMCS_SOURCE
1195 t.IsSubclassOf (TypeManager.array_type))
1196 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1199 if (t is GenericTypeParameterBuilder) {
1200 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1202 Timer.StartTimer (TimerType.FindMembers);
1203 MemberList list = tparam.FindMembers (
1204 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1205 Timer.StopTimer (TimerType.FindMembers);
1211 // Since FindMembers will not lookup both static and instance
1212 // members, we emulate this behaviour here.
1214 if ((bf & instance_and_static) == instance_and_static){
1215 MemberInfo [] i_members = t.FindMembers (
1216 mt, bf & ~BindingFlags.Static, filter, criteria);
1218 int i_len = i_members.Length;
1220 MemberInfo one = i_members [0];
1223 // If any of these are present, we are done!
1225 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1226 return new MemberList (i_members);
1229 MemberInfo [] s_members = t.FindMembers (
1230 mt, bf & ~BindingFlags.Instance, filter, criteria);
1232 int s_len = s_members.Length;
1233 if (i_len > 0 || s_len > 0)
1234 return new MemberList (i_members, s_members);
1237 return new MemberList (i_members);
1239 return new MemberList (s_members);
1243 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1248 /// This method is only called from within MemberLookup. It tries to use the member
1249 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1250 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1251 /// our return value will already contain all inherited members and the caller don't need
1252 /// to check base classes and interfaces anymore.
1254 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1255 string name, out bool used_cache)
1260 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1261 // and we can ask the DeclSpace for the MemberCache.
1264 if (t.Assembly == CodeGen.Assembly.Builder) {
1265 if (t.IsGenericParameter) {
1266 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1269 if (tparam.MemberCache == null)
1270 return new MemberInfo[0];
1272 return tparam.MemberCache.FindMembers (
1273 mt, bf, name, FilterWithClosure_delegate, null);
1276 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1277 t = t.GetGenericTypeDefinition ();
1279 if (t is TypeBuilder) {
1281 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1282 cache = decl.MemberCache;
1285 // If this DeclSpace has a MemberCache, use it.
1288 if (cache != null) {
1290 return cache.FindMembers (
1291 mt, bf, name, FilterWithClosure_delegate, null);
1294 // If there is no MemberCache, we need to use the "normal" FindMembers.
1295 // Note, this is a VERY uncommon route!
1298 Timer.StartTimer (TimerType.FindMembers);
1299 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1300 FilterWithClosure_delegate, name);
1301 Timer.StopTimer (TimerType.FindMembers);
1303 return (MemberInfo []) list;
1307 // We have to take care of arrays specially, because GetType on
1308 // a TypeBuilder array will return a Type, not a TypeBuilder,
1309 // and we can not call FindMembers on this type.
1313 return TypeHandle.ArrayType.MemberCache.FindMembers (
1314 mt, bf, name, FilterWithClosure_delegate, null);
1318 if (t is GenericTypeParameterBuilder) {
1319 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1322 if (tparam.MemberCache == null)
1323 return new MemberInfo [0];
1325 return tparam.MemberCache.FindMembers (
1326 mt, bf, name, FilterWithClosure_delegate, null);
1330 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1332 // This happens if we're resolving a class'es base class and interfaces
1333 // in TypeContainer.DefineType(). At this time, the types aren't
1334 // populated yet, so we can't use the cache.
1336 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1337 FilterWithClosure_delegate, name);
1343 // This call will always succeed. There is exactly one TypeHandle instance per
1344 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1345 // the corresponding MemberCache.
1347 cache = TypeHandle.GetMemberCache (t);
1350 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1353 public static bool IsBuiltinType (Type t)
1355 t = TypeToCoreType (t);
1356 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1357 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1358 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1359 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1366 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1367 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1369 public static bool IsPrimitiveType (Type t)
1371 return (t == int32_type || t == uint32_type ||
1372 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1373 t == char_type || t == short_type || t == bool_type ||
1374 t == sbyte_type || t == byte_type || t == ushort_type);
1377 public static bool IsDelegateType (Type t)
1380 if (t.IsGenericParameter)
1384 if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
1387 t = DropGenericTypeArguments (t);
1388 return IsSubclassOf (t, TypeManager.delegate_type);
1391 public static bool IsEnumType (Type t)
1393 t = DropGenericTypeArguments (t);
1394 return t.BaseType == TypeManager.enum_type;
1397 public static bool IsBuiltinOrEnum (Type t)
1399 if (IsBuiltinType (t))
1408 public static bool IsAttributeType (Type t)
1410 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1413 static Stack unmanaged_enclosing_types = new Stack (4);
1416 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1418 public static bool IsUnmanagedType (Type t)
1420 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1421 if (unmanaged_enclosing_types.Contains (t))
1424 // builtins that are not unmanaged types
1425 if (t == TypeManager.object_type || t == TypeManager.string_type)
1428 if (IsGenericType (t) || IsGenericParameter (t))
1431 if (IsBuiltinOrEnum (t))
1434 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1438 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1442 if (!IsValueType (t))
1446 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1447 if (p.IsGenericTypeDefinition)
1452 unmanaged_enclosing_types.Push (t);
1456 if (t is TypeBuilder) {
1457 TypeContainer tc = LookupTypeContainer (t);
1458 if (tc.Fields != null){
1459 foreach (FieldBase f in tc.Fields){
1460 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1461 if ((f.ModFlags & Modifiers.STATIC) != 0)
1463 if (f.MemberType == null)
1465 if (!IsUnmanagedType (f.MemberType)){
1466 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1472 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1474 foreach (FieldInfo f in fields){
1475 if (!IsUnmanagedType (f.FieldType)){
1476 Report.SymbolRelatedToPreviousError (f);
1482 unmanaged_enclosing_types.Pop ();
1488 // Null is considered to be a reference type
1490 public static bool IsReferenceType (Type t)
1492 if (TypeManager.IsGenericParameter (t)) {
1493 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1494 if (constraints == null)
1497 return constraints.IsReferenceType;
1500 return !t.IsValueType;
1503 public static bool IsValueType (Type t)
1505 return t.IsValueType || IsGenericParameter (t);
1508 public static bool IsInterfaceType (Type t)
1510 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1514 return tc.Kind == Kind.Interface;
1517 public static bool IsSubclassOf (Type type, Type base_type)
1519 TypeParameter tparam = LookupTypeParameter (type);
1520 TypeParameter pparam = LookupTypeParameter (base_type);
1522 if ((tparam != null) && (pparam != null)) {
1523 if (tparam == pparam)
1526 return tparam.IsSubclassOf (base_type);
1529 #if MS_COMPATIBLE && GMCS_SOURCE
1530 if (type.IsGenericType)
1531 type = type.GetGenericTypeDefinition ();
1534 if (type.IsSubclassOf (base_type))
1538 if (IsEqual (type, base_type))
1541 type = type.BaseType;
1542 } while (type != null);
1547 public static bool IsPrivateAccessible (Type type, Type parent)
1552 if (type.Equals (parent))
1555 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1558 public static bool IsFamilyAccessible (Type type, Type parent)
1560 TypeParameter tparam = LookupTypeParameter (type);
1561 TypeParameter pparam = LookupTypeParameter (parent);
1563 if ((tparam != null) && (pparam != null)) {
1564 if (tparam == pparam)
1567 return tparam.IsSubclassOf (parent);
1571 if (IsInstantiationOfSameGenericType (type, parent))
1574 type = type.BaseType;
1575 } while (type != null);
1581 // Checks whether `type' is a subclass or nested child of `base_type'.
1583 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1586 if (IsFamilyAccessible (type, base_type))
1589 // Handle nested types.
1590 type = type.DeclaringType;
1591 } while (type != null);
1597 // Checks whether `type' is a nested child of `parent'.
1599 public static bool IsNestedChildOf (Type type, Type parent)
1604 type = DropGenericTypeArguments (type);
1605 parent = DropGenericTypeArguments (parent);
1607 if (IsEqual (type, parent))
1610 type = type.DeclaringType;
1611 while (type != null) {
1612 if (IsEqual (type, parent))
1615 type = type.DeclaringType;
1621 public static bool IsSpecialType (Type t)
1623 return t == arg_iterator_type || t == typed_reference_type;
1627 // Checks whether `extern_type' is friend of the output assembly
1629 public static bool IsThisOrFriendAssembly (Assembly assembly)
1631 if (assembly == CodeGen.Assembly.Builder)
1634 if (assembly_internals_vis_attrs.Contains (assembly))
1635 return (bool)(assembly_internals_vis_attrs [assembly]);
1637 if (internals_visible_attr_type == null)
1640 object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
1641 if (attrs.Length == 0) {
1642 assembly_internals_vis_attrs.Add (assembly, false);
1646 bool is_friend = false;
1648 AssemblyName this_name = CodeGen.Assembly.Name;
1649 byte [] this_token = this_name.GetPublicKeyToken ();
1650 foreach (InternalsVisibleToAttribute attr in attrs) {
1651 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1654 AssemblyName aname = null;
1656 aname = new AssemblyName (attr.AssemblyName);
1657 } catch (FileLoadException) {
1658 } catch (ArgumentException) {
1661 if (aname == null || aname.Name != this_name.Name)
1664 byte [] key_token = aname.GetPublicKeyToken ();
1665 if (key_token != null) {
1666 if (this_token.Length == 0) {
1667 // Same name, but assembly is not strongnamed
1668 Error_FriendAccessNameNotMatching (aname.FullName);
1672 if (!CompareKeyTokens (this_token, key_token))
1680 assembly_internals_vis_attrs.Add (assembly, is_friend);
1685 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1687 for (int i = 0; i < token1.Length; i++)
1688 if (token1 [i] != token2 [i])
1694 static void Error_FriendAccessNameNotMatching (string other_name)
1696 Report.Error (281, "Friend access was granted to `" + other_name +
1697 "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
1698 "'. Try adding a reference to `" + other_name +
1699 "' or change the output assembly name to match it");
1704 // Do the right thing when returning the element type of an
1705 // array type based on whether we are compiling corlib or not
1707 public static Type GetElementType (Type t)
1709 if (RootContext.StdLib)
1710 return t.GetElementType ();
1712 return TypeToCoreType (t.GetElementType ());
1716 /// This method is not implemented by MS runtime for dynamic types
1718 public static bool HasElementType (Type t)
1720 return t.IsArray || t.IsPointer || t.IsByRef;
1723 public static Type GetEnumUnderlyingType (Type t)
1725 t = DropGenericTypeArguments (t);
1726 Enum e = LookupTypeContainer (t) as Enum;
1728 return e.UnderlyingType;
1731 FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
1733 return TypeManager.int32_type;
1735 return TypeToCoreType (fi.FieldType);
1739 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1743 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1744 /// for anything which is dynamic, and we need this in a number of places,
1745 /// we register this information here, and use it afterwards.
1747 static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
1749 method_params.Add (mb, ip);
1752 static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
1754 method_params.Add (pb, p);
1757 static public AParametersCollection GetParameterData (MethodBase mb)
1759 AParametersCollection pd = (AParametersCollection) method_params [mb];
1762 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1763 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1764 pd = GetParameterData (mi);
1766 if (mi.IsGenericMethod)
1767 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1769 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1771 method_params.Add (mb, pd);
1775 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1776 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1777 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1780 pd = ParametersCollection.Create (mb);
1782 MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
1783 if (generic != mb) {
1784 pd = TypeManager.GetParameterData (generic);
1785 pd = ParametersCollection.Create (pd, mb);
1787 pd = ParametersCollection.Create (mb);
1790 method_params.Add (mb, pd);
1795 public static AParametersCollection GetParameterData (PropertyInfo pi)
1797 AParametersCollection pd = (AParametersCollection)method_params [pi];
1799 if (pi is PropertyBuilder)
1800 return Parameters.EmptyReadOnlyParameters;
1802 ParameterInfo [] p = pi.GetIndexParameters ();
1804 return Parameters.EmptyReadOnlyParameters;
1806 pd = ParametersCollection.Create (p, null);
1807 method_params.Add (pi, pd);
1813 public static AParametersCollection GetDelegateParameters (Type t)
1815 Delegate d = builder_to_declspace [t] as Delegate;
1817 return d.Parameters;
1819 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1820 return GetParameterData (invoke_mb);
1823 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1825 if (!method_overrides.Contains (override_method))
1826 method_overrides [override_method] = base_method;
1827 if (method_overrides [override_method] != base_method)
1828 throw new InternalErrorException ("Override mismatch: " + override_method);
1831 static public bool IsOverride (MethodBase m)
1833 m = DropGenericMethodArguments (m);
1835 return m.IsVirtual &&
1836 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1837 (m is MethodBuilder || method_overrides.Contains (m));
1840 static public MethodBase TryGetBaseDefinition (MethodBase m)
1842 m = DropGenericMethodArguments (m);
1844 return (MethodBase) method_overrides [m];
1847 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1849 fields.Add (fb, ic);
1852 public static IConstant GetConstant (FieldInfo fb)
1857 return (IConstant)fields [fb];
1860 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1862 propertybuilder_to_property.Add (pi, pb);
1865 public static PropertyBase GetProperty (PropertyInfo pi)
1867 return (PropertyBase)propertybuilder_to_property [pi];
1870 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
1872 fieldbuilders_to_fields.Add (fb, f);
1876 // The return value can be null; This will be the case for
1877 // auxiliary FieldBuilders created by the compiler that have no
1878 // real field being declared on the source code
1880 static public FieldBase GetField (FieldInfo fb)
1883 fb = GetGenericFieldDefinition (fb);
1885 return (FieldBase) fieldbuilders_to_fields [fb];
1888 static public MethodInfo GetAddMethod (EventInfo ei)
1890 if (ei is MyEventBuilder) {
1891 return ((MyEventBuilder)ei).GetAddMethod (true);
1893 return ei.GetAddMethod (true);
1896 static public MethodInfo GetRemoveMethod (EventInfo ei)
1898 if (ei is MyEventBuilder) {
1899 return ((MyEventBuilder)ei).GetRemoveMethod (true);
1901 return ei.GetRemoveMethod (true);
1904 static public void RegisterEventField (EventInfo einfo, EventField e)
1907 events = new Hashtable ();
1909 events.Add (einfo, e);
1912 static public EventField GetEventField (EventInfo ei)
1917 return (EventField) events [ei];
1920 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1922 Hashtable hash = new Hashtable ();
1923 return CheckStructCycles (tc, seen, hash);
1926 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1929 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
1933 // `seen' contains all types we've already visited.
1935 if (seen.Contains (tc))
1937 seen.Add (tc, null);
1939 if (tc.Fields == null)
1942 foreach (FieldBase field in tc.Fields) {
1943 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1946 Type ftype = field.FieldBuilder.FieldType;
1947 TypeContainer ftc = LookupTypeContainer (ftype);
1951 if (hash.Contains (ftc)) {
1952 Report.Error (523, tc.Location,
1953 "Struct member `{0}.{1}' of type `{2}' " +
1954 "causes a cycle in the struct layout",
1955 tc.Name, field.Name, ftc.Name);
1960 // `hash' contains all types in the current path.
1962 hash.Add (tc, null);
1964 bool ok = CheckStructCycles (ftc, seen, hash);
1971 if (!seen.Contains (ftc))
1972 seen.Add (ftc, null);
1979 /// Given an array of interface types, expand and eliminate repeated ocurrences
1980 /// of an interface.
1984 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1987 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
1989 ArrayList new_ifaces = new ArrayList ();
1991 foreach (TypeExpr iface in base_interfaces){
1992 Type itype = iface.Type;
1994 if (new_ifaces.Contains (itype))
1997 new_ifaces.Add (itype);
1999 Type [] implementing = GetInterfaces (itype);
2001 foreach (Type imp in implementing){
2002 if (!new_ifaces.Contains (imp))
2003 new_ifaces.Add (imp);
2006 Type [] ret = new Type [new_ifaces.Count];
2007 new_ifaces.CopyTo (ret, 0);
2011 public static Type[] ExpandInterfaces (Type [] base_interfaces)
2013 ArrayList new_ifaces = new ArrayList ();
2015 foreach (Type itype in base_interfaces){
2016 if (new_ifaces.Contains (itype))
2019 new_ifaces.Add (itype);
2021 Type [] implementing = GetInterfaces (itype);
2023 foreach (Type imp in implementing){
2024 if (!new_ifaces.Contains (imp))
2025 new_ifaces.Add (imp);
2028 Type [] ret = new Type [new_ifaces.Count];
2029 new_ifaces.CopyTo (ret, 0);
2033 static PtrHashtable iface_cache = new PtrHashtable ();
2036 /// This function returns the interfaces in the type `t'. Works with
2037 /// both types and TypeBuilders.
2039 public static Type [] GetInterfaces (Type t)
2041 Type [] cached = iface_cache [t] as Type [];
2046 // The reason for catching the Array case is that Reflection.Emit
2047 // will not return a TypeBuilder for Array types of TypeBuilder types,
2048 // but will still throw an exception if we try to call GetInterfaces
2051 // Since the array interfaces are always constant, we return those for
2056 t = TypeManager.array_type;
2058 if ((t is TypeBuilder) || IsGenericType (t)) {
2059 Type [] base_ifaces;
2061 if (t.BaseType == null)
2062 base_ifaces = Type.EmptyTypes;
2064 base_ifaces = GetInterfaces (t.BaseType);
2066 if (IsGenericType (t))
2067 #if MS_COMPATIBLE && GMCS_SOURCE
2068 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
2070 type_ifaces = t.GetInterfaces ();
2073 type_ifaces = (Type []) builder_to_ifaces [t];
2074 if (type_ifaces == null || type_ifaces.Length == 0)
2075 type_ifaces = Type.EmptyTypes;
2077 int base_count = base_ifaces.Length;
2078 Type [] result = new Type [base_count + type_ifaces.Length];
2079 base_ifaces.CopyTo (result, 0);
2080 type_ifaces.CopyTo (result, base_count);
2082 iface_cache [t] = result;
2085 } else if (t is GenericTypeParameterBuilder){
2086 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2087 if (type_ifaces == null || type_ifaces.Length == 0)
2088 type_ifaces = Type.EmptyTypes;
2090 iface_cache [t] = type_ifaces;
2094 Type[] ifaces = t.GetInterfaces ();
2095 iface_cache [t] = ifaces;
2101 // gets the interfaces that are declared explicitly on t
2103 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2105 return (Type []) builder_to_ifaces [t];
2109 /// The following is used to check if a given type implements an interface.
2110 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2112 public static bool ImplementsInterface (Type t, Type iface)
2117 // FIXME OPTIMIZATION:
2118 // as soon as we hit a non-TypeBuiler in the interface
2119 // chain, we could return, as the `Type.GetInterfaces'
2120 // will return all the interfaces implement by the type
2124 interfaces = GetInterfaces (t);
2126 if (interfaces != null){
2127 foreach (Type i in interfaces){
2134 } while (t != null);
2139 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2141 // This is a custom version of Convert.ChangeType() which works
2142 // with the TypeBuilder defined types when compiling corlib.
2143 public static object ChangeType (object value, Type conversionType, out bool error)
2145 IConvertible convert_value = value as IConvertible;
2147 if (convert_value == null){
2154 // We must use Type.Equals() here since `conversionType' is
2155 // the TypeBuilder created version of a system type and not
2156 // the system type itself. You cannot use Type.GetTypeCode()
2157 // on such a type - it'd always return TypeCode.Object.
2160 // We cannot rely on build-in type conversions as they are
2161 // more limited than what C# supports.
2162 // See char -> float/decimal/double conversion
2167 if (conversionType.Equals (typeof (Boolean)))
2168 return (object)(convert_value.ToBoolean (nf_provider));
2169 if (conversionType.Equals (typeof (Byte)))
2170 return (object)(convert_value.ToByte (nf_provider));
2171 if (conversionType.Equals (typeof (Char)))
2172 return (object)(convert_value.ToChar (nf_provider));
2173 if (conversionType.Equals (typeof (DateTime)))
2174 return (object)(convert_value.ToDateTime (nf_provider));
2176 if (conversionType.Equals (decimal_type)) {
2177 if (convert_value.GetType () == TypeManager.char_type)
2178 return (decimal)convert_value.ToInt32 (nf_provider);
2179 return convert_value.ToDecimal (nf_provider);
2182 if (conversionType.Equals (typeof (Double))) {
2183 if (convert_value.GetType () == TypeManager.char_type)
2184 return (double)convert_value.ToInt32 (nf_provider);
2185 return convert_value.ToDouble (nf_provider);
2188 if (conversionType.Equals (typeof (Int16)))
2189 return (object)(convert_value.ToInt16 (nf_provider));
2190 if (conversionType.Equals (int32_type))
2191 return (object)(convert_value.ToInt32 (nf_provider));
2192 if (conversionType.Equals (int64_type))
2193 return (object)(convert_value.ToInt64 (nf_provider));
2194 if (conversionType.Equals (typeof (SByte)))
2195 return (object)(convert_value.ToSByte (nf_provider));
2197 if (conversionType.Equals (typeof (Single))) {
2198 if (convert_value.GetType () == TypeManager.char_type)
2199 return (float)convert_value.ToInt32 (nf_provider);
2200 return convert_value.ToSingle (nf_provider);
2203 if (conversionType.Equals (typeof (String)))
2204 return (object)(convert_value.ToString (nf_provider));
2205 if (conversionType.Equals (typeof (UInt16)))
2206 return (object)(convert_value.ToUInt16 (nf_provider));
2207 if (conversionType.Equals (typeof (UInt32)))
2208 return (object)(convert_value.ToUInt32 (nf_provider));
2209 if (conversionType.Equals (typeof (UInt64)))
2210 return (object)(convert_value.ToUInt64 (nf_provider));
2211 if (conversionType.Equals (typeof (Object)))
2212 return (object)(value);
2222 // When compiling with -nostdlib and the type is imported from an external assembly
2223 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2225 public static Type TypeToCoreType (Type t)
2227 if (RootContext.StdLib || t.Module != typeof (object).Module)
2230 TypeCode tc = Type.GetTypeCode (t);
2233 case TypeCode.Boolean:
2234 return TypeManager.bool_type;
2236 return TypeManager.byte_type;
2237 case TypeCode.SByte:
2238 return TypeManager.sbyte_type;
2240 return TypeManager.char_type;
2241 case TypeCode.Int16:
2242 return TypeManager.short_type;
2243 case TypeCode.UInt16:
2244 return TypeManager.ushort_type;
2245 case TypeCode.Int32:
2246 return TypeManager.int32_type;
2247 case TypeCode.UInt32:
2248 return TypeManager.uint32_type;
2249 case TypeCode.Int64:
2250 return TypeManager.int64_type;
2251 case TypeCode.UInt64:
2252 return TypeManager.uint64_type;
2253 case TypeCode.Single:
2254 return TypeManager.float_type;
2255 case TypeCode.Double:
2256 return TypeManager.double_type;
2257 case TypeCode.String:
2258 return TypeManager.string_type;
2259 case TypeCode.Decimal:
2260 return TypeManager.decimal_type;
2263 if (t == typeof (void))
2264 return TypeManager.void_type;
2265 if (t == typeof (object))
2266 return TypeManager.object_type;
2267 if (t == typeof (System.Type))
2268 return TypeManager.type_type;
2269 if (t == typeof (System.IntPtr))
2270 return TypeManager.intptr_type;
2271 if (t == typeof (System.UIntPtr))
2272 return TypeManager.uintptr_type;
2275 int dim = t.GetArrayRank ();
2276 t = GetElementType (t);
2277 return t.MakeArrayType (dim);
2280 t = GetElementType (t);
2281 return t.MakeByRefType ();
2284 t = GetElementType (t);
2285 return t.MakePointerType ();
2292 /// Utility function that can be used to probe whether a type
2293 /// is managed or not.
2295 public static bool VerifyUnManaged (Type t, Location loc)
2297 if (IsUnmanagedType (t))
2300 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2307 /// Returns the name of the indexer in a given type.
2310 /// The default is not always `Item'. The user can change this behaviour by
2311 /// using the IndexerNameAttribute in the container.
2312 /// For example, the String class indexer is named `Chars' not `Item'
2314 public static string IndexerPropertyName (Type t)
2316 t = DropGenericTypeArguments (t);
2317 if (t is TypeBuilder) {
2318 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2319 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2322 System.Attribute attr = System.Attribute.GetCustomAttribute (
2323 t, TypeManager.default_member_type);
2325 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2326 return dma.MemberName;
2329 return TypeContainer.DefaultIndexerName;
2332 static MethodInfo declare_local_method = null;
2334 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2336 if (declare_local_method == null){
2337 declare_local_method = typeof (ILGenerator).GetMethod (
2339 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2341 new Type [] { typeof (Type), typeof (bool)},
2343 if (declare_local_method == null){
2344 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2345 return ig.DeclareLocal (t);
2348 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2351 private static bool IsSignatureEqual (Type a, Type b)
2354 /// Consider the following example (bug #77674):
2356 /// public abstract class A
2358 /// public abstract T Foo<T> ();
2361 /// public abstract class B : A
2363 /// public override U Foo<T> ()
2364 /// { return default (U); }
2367 /// Here, `T' and `U' are method type parameters from different methods
2368 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2370 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2371 /// we need to do a signature based comparision and consider them equal.
2377 if (a.IsGenericParameter && b.IsGenericParameter &&
2378 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2379 return a.GenericParameterPosition == b.GenericParameterPosition;
2383 if (a.IsArray && b.IsArray) {
2384 if (a.GetArrayRank () != b.GetArrayRank ())
2387 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2390 if (a.IsByRef && b.IsByRef)
2391 return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
2394 if (a.IsGenericType && b.IsGenericType) {
2395 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
2398 Type[] aargs = a.GetGenericArguments ();
2399 Type[] bargs = b.GetGenericArguments ();
2401 if (aargs.Length != bargs.Length)
2404 for (int i = 0; i < aargs.Length; i++) {
2405 if (!IsSignatureEqual (aargs [i], bargs [i]))
2417 // Returns whether the array of memberinfos contains the given method
2419 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
2421 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2423 foreach (MethodBase method in array) {
2424 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
2427 if (method.Name != new_method.Name)
2430 if (method is MethodInfo && new_method is MethodInfo &&
2432 TypeToCoreType (((MethodInfo) method).ReturnType),
2433 TypeToCoreType (((MethodInfo) new_method).ReturnType)))
2436 Type [] old_args = TypeManager.GetParameterData (method).Types;
2437 int old_count = old_args.Length;
2440 if (new_args.Length != old_count)
2443 for (i = 0; i < old_count; i++){
2444 if (!IsSignatureEqual (old_args [i], new_args [i]))
2457 // We copy methods from `new_members' into `target_list' if the signature
2458 // for the method from in the new list does not exist in the target_list
2460 // The name is assumed to be the same.
2462 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2464 if (target_list == null){
2465 target_list = new ArrayList ();
2467 foreach (MemberInfo mi in new_members){
2468 if (mi is MethodBase)
2469 target_list.Add (mi);
2474 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2475 target_list.CopyTo (target_array, 0);
2477 foreach (MemberInfo mi in new_members){
2478 MethodBase new_method = (MethodBase) mi;
2480 if (!ArrayContainsMethod (target_array, new_method, true))
2481 target_list.Add (new_method);
2488 // Tracks the generic parameters.
2490 static PtrHashtable builder_to_type_param;
2492 public static void AddTypeParameter (Type t, TypeParameter tparam)
2494 if (!builder_to_type_param.Contains (t))
2495 builder_to_type_param.Add (t, tparam);
2498 public static TypeParameter LookupTypeParameter (Type t)
2500 return (TypeParameter) builder_to_type_param [t];
2503 // This method always return false for non-generic compiler,
2504 // while Type.IsGenericParameter is returned if it is supported.
2505 public static bool IsGenericParameter (Type type)
2508 return type.IsGenericParameter;
2514 public static int GenericParameterPosition (Type type)
2517 return type.GenericParameterPosition;
2519 throw new InternalErrorException ("should not be called");
2523 public static bool IsGenericType (Type type)
2526 return type.IsGenericType;
2532 public static bool IsGenericTypeDefinition (Type type)
2535 return type.IsGenericTypeDefinition;
2541 public static bool ContainsGenericParameters (Type type)
2544 return type.ContainsGenericParameters;
2550 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2553 if (fi.DeclaringType.IsGenericTypeDefinition ||
2554 !fi.DeclaringType.IsGenericType)
2557 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2558 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2559 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2561 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2562 foreach (FieldInfo f in t.GetFields (bf))
2563 if (f.MetadataToken == fi.MetadataToken)
2570 public static bool IsEqual (Type a, Type b)
2573 // MS BCL returns true even if enum types are different
2574 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2575 return a.FullName == b.FullName;
2577 // Some types are never equal
2578 if (a == TypeManager.null_type || a == TypeManager.anonymous_method_type)
2585 if (a.IsGenericParameter && b.IsGenericParameter) {
2586 // TODO: needs more testing before cleaning up
2587 //if (a.DeclaringMethod != b.DeclaringMethod &&
2588 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2590 return a.GenericParameterPosition == b.GenericParameterPosition;
2593 if (a.IsArray && b.IsArray) {
2594 if (a.GetArrayRank () != b.GetArrayRank ())
2596 return IsEqual (a.GetElementType (), b.GetElementType ());
2599 if (a.IsByRef && b.IsByRef)
2600 return IsEqual (a.GetElementType (), b.GetElementType ());
2602 if (a.IsGenericType && b.IsGenericType) {
2603 Type adef = a.GetGenericTypeDefinition ();
2604 Type bdef = b.GetGenericTypeDefinition ();
2609 if (adef.IsEnum && bdef.IsEnum)
2612 Type[] aargs = a.GetGenericArguments ();
2613 Type[] bargs = b.GetGenericArguments ();
2615 if (aargs.Length != bargs.Length)
2618 for (int i = 0; i < aargs.Length; i++) {
2619 if (!IsEqual (aargs [i], bargs [i]))
2630 public static bool IsEqual (Type[] a, Type[] b)
2632 if (a == null || b == null || a.Length != b.Length)
2635 for (int i = 0; i < a.Length; ++i) {
2636 if (a [i] == null || b [i] == null) {
2643 if (!IsEqual (a [i], b [i]))
2650 public static Type DropGenericTypeArguments (Type t)
2653 if (!t.IsGenericType)
2655 // Micro-optimization: a generic typebuilder is always a generic type definition
2656 if (t is TypeBuilder)
2658 return t.GetGenericTypeDefinition ();
2664 public static MethodBase DropGenericMethodArguments (MethodBase m)
2667 if (m.IsGenericMethod)
2668 m = ((MethodInfo) m).GetGenericMethodDefinition ();
2670 Type t = m.DeclaringType;
2671 if (!t.IsGenericType || t.IsGenericTypeDefinition)
2674 t = t.GetGenericTypeDefinition ();
2675 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2676 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2679 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2683 if (m is ConstructorInfo) {
2684 foreach (ConstructorInfo c in t.GetConstructors (bf))
2685 if (c.MetadataToken == m.MetadataToken)
2688 foreach (MethodBase mb in t.GetMethods (bf))
2689 if (mb.MetadataToken == m.MetadataToken)
2697 public static Type[] GetGenericArguments (MethodBase mi)
2700 return mi.GetGenericArguments ();
2702 return Type.EmptyTypes;
2706 public static Type[] GetTypeArguments (Type t)
2709 DeclSpace tc = LookupDeclSpace (t);
2712 return Type.EmptyTypes;
2714 TypeParameter[] tparam = tc.TypeParameters;
2715 Type[] ret = new Type [tparam.Length];
2716 for (int i = 0; i < tparam.Length; i++) {
2717 ret [i] = tparam [i].Type;
2718 if (ret [i] == null)
2719 throw new InternalErrorException ();
2724 return t.GetGenericArguments ();
2726 throw new InternalErrorException ();
2730 public static GenericConstraints GetTypeParameterConstraints (Type t)
2733 if (!t.IsGenericParameter)
2734 throw new InvalidOperationException ();
2736 TypeParameter tparam = LookupTypeParameter (t);
2738 return tparam.GenericConstraints;
2740 return ReflectionConstraints.GetConstraints (t);
2742 throw new InternalErrorException ();
2746 public static bool HasGenericArguments (Type t)
2748 return GetNumberOfTypeArguments (t) > 0;
2751 public static int GetNumberOfTypeArguments (Type t)
2754 if (t.IsGenericParameter)
2756 DeclSpace tc = LookupDeclSpace (t);
2758 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2760 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2767 /// Check whether `type' and `parent' are both instantiations of the same
2768 /// generic type. Note that we do not check the type parameters here.
2770 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2772 int tcount = GetNumberOfTypeArguments (type);
2773 int pcount = GetNumberOfTypeArguments (parent);
2775 if (tcount != pcount)
2778 type = DropGenericTypeArguments (type);
2779 parent = DropGenericTypeArguments (parent);
2781 return type.Equals (parent);
2785 /// Whether `mb' is a generic method definition.
2787 public static bool IsGenericMethodDefinition (MethodBase mb)
2790 if (mb.DeclaringType is TypeBuilder) {
2791 IMethodData method = (IMethodData) builder_to_method [mb];
2795 return method.GenericMethod != null;
2798 return mb.IsGenericMethodDefinition;
2805 /// Whether `mb' is a generic method.
2807 public static bool IsGenericMethod (MethodBase mb)
2810 return mb.IsGenericMethod;
2816 public static bool IsNullableType (Type t)
2819 return generic_nullable_type == DropGenericTypeArguments (t);
2825 public static bool IsNullableTypeOf (Type t, Type nullable)
2828 if (!IsNullableType (t))
2831 return GetTypeArguments (t) [0] == nullable;
2837 public static bool IsNullableValueType (Type t)
2840 if (!IsNullableType (t))
2843 return GetTypeArguments (t) [0].IsValueType;
2850 #region MemberLookup implementation
2853 // Whether we allow private members in the result (since FindMembers
2854 // uses NonPublic for both protected and private), we need to distinguish.
2857 internal class Closure {
2858 internal bool private_ok;
2860 // Who is invoking us and which type is being queried currently.
2861 internal Type invocation_type;
2862 internal Type qualifier_type;
2864 // The assembly that defines the type is that is calling us
2865 internal Assembly invocation_assembly;
2866 internal IList almost_match;
2868 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2870 if (invocation_type == null)
2873 if (is_static && qualifier_type == null)
2874 // It resolved from a simple name, so it should be visible.
2877 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2880 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2881 if (!IsFamilyAccessible (t, m.DeclaringType))
2884 // Although a derived class can access protected members of its base class
2885 // it cannot do so through an instance of the base class (CS1540).
2886 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2887 if (is_static || qualifier_type == null ||
2888 IsInstantiationOfSameGenericType (t, qualifier_type) ||
2889 IsFamilyAccessible (qualifier_type, t))
2893 if (almost_match != null)
2894 almost_match.Add (m);
2900 // This filter filters by name + whether it is ok to include private
2901 // members in the search
2903 internal bool Filter (MemberInfo m, object filter_criteria)
2906 // Hack: we know that the filter criteria will always be in the
2907 // `closure' // fields.
2910 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2913 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2914 (invocation_type != null) &&
2915 IsPrivateAccessible (m.DeclaringType, invocation_type))
2919 // Ugly: we need to find out the type of `m', and depending
2920 // on this, tell whether we accept or not
2922 if (m is MethodBase){
2923 MethodBase mb = (MethodBase) m;
2924 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2926 if (ma == MethodAttributes.Public)
2929 if (ma == MethodAttributes.PrivateScope)
2932 if (ma == MethodAttributes.Private)
2933 return private_ok ||
2934 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2935 IsNestedChildOf (invocation_type, m.DeclaringType);
2937 if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) {
2938 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2941 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2945 // Family, FamORAssem or FamANDAssem
2946 return CheckValidFamilyAccess (mb.IsStatic, m);
2949 if (m is FieldInfo){
2950 FieldInfo fi = (FieldInfo) m;
2951 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2953 if (fa == FieldAttributes.Public)
2956 if (fa == FieldAttributes.PrivateScope)
2959 if (fa == FieldAttributes.Private)
2960 return private_ok ||
2961 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2962 IsNestedChildOf (invocation_type, m.DeclaringType);
2964 if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) {
2965 if ((fa == FieldAttributes.Assembly) ||
2966 (fa == FieldAttributes.FamORAssem))
2969 if ((fa == FieldAttributes.Assembly) ||
2970 (fa == FieldAttributes.FamANDAssem))
2974 // Family, FamORAssem or FamANDAssem
2975 return CheckValidFamilyAccess (fi.IsStatic, m);
2979 // EventInfos and PropertyInfos, return true because they lack
2980 // permission information, so we need to check later on the methods.
2986 static Closure closure = new Closure ();
2987 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2990 // Looks up a member called `name' in the `queried_type'. This lookup
2991 // is done by code that is contained in the definition for `invocation_type'
2992 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2994 // `invocation_type' is used to check whether we're allowed to access the requested
2995 // member wrt its protection level.
2997 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2998 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2999 // is B and qualifier_type is A). This is used to do the CS1540 check.
3001 // When resolving a SimpleName, `qualifier_type' is null.
3003 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3004 // the same than `queried_type' - except when we're being called from BaseAccess;
3005 // in this case, `invocation_type' is the current type and `queried_type' the base
3006 // type, so this'd normally trigger a CS1540.
3008 // The binding flags are `bf' and the kind of members being looked up are `mt'
3010 // The return value always includes private members which code in `invocation_type'
3011 // is allowed to access (using the specified `qualifier_type' if given); only use
3012 // BindingFlags.NonPublic to bypass the permission check.
3014 // The 'almost_match' argument is used for reporting error CS1540.
3016 // Returns an array of a single element for everything but Methods/Constructors
3017 // that might return multiple matches.
3019 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3020 Type queried_type, MemberTypes mt,
3021 BindingFlags original_bf, string name, IList almost_match)
3023 Timer.StartTimer (TimerType.MemberLookup);
3025 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3026 queried_type, mt, original_bf, name, almost_match);
3028 Timer.StopTimer (TimerType.MemberLookup);
3033 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3034 Type queried_type, MemberTypes mt,
3035 BindingFlags original_bf, string name, IList almost_match)
3037 BindingFlags bf = original_bf;
3039 ArrayList method_list = null;
3040 Type current_type = queried_type;
3041 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3042 bool skip_iface_check = true, used_cache = false;
3043 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
3045 closure.invocation_type = invocation_type;
3046 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3047 closure.qualifier_type = qualifier_type;
3048 closure.almost_match = almost_match;
3050 // This is from the first time we find a method
3051 // in most cases, we do not actually find a method in the base class
3052 // so we can just ignore it, and save the arraylist allocation
3053 MemberInfo [] first_members_list = null;
3054 bool use_first_members_list = false;
3060 // `NonPublic' is lame, because it includes both protected and
3061 // private methods, so we need to control this behavior by
3062 // explicitly tracking if a private method is ok or not.
3064 // The possible cases are:
3065 // public, private and protected (internal does not come into the
3068 if ((invocation_type != null) &&
3069 ((invocation_type == current_type) ||
3070 IsNestedChildOf (invocation_type, current_type)) ||
3072 bf = original_bf | BindingFlags.NonPublic;
3076 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3078 Timer.StopTimer (TimerType.MemberLookup);
3080 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
3082 Timer.StartTimer (TimerType.MemberLookup);
3085 // When queried for an interface type, the cache will automatically check all
3086 // inherited members, so we don't need to do this here. However, this only
3087 // works if we already used the cache in the first iteration of this loop.
3089 // If we used the cache in any further iteration, we can still terminate the
3090 // loop since the cache always looks in all base classes.
3096 skip_iface_check = false;
3098 if (current_type == TypeManager.object_type)
3101 current_type = current_type.BaseType;
3104 // This happens with interfaces, they have a null
3105 // basetype. Look members up in the Object class.
3107 if (current_type == null) {
3108 current_type = TypeManager.object_type;
3113 if (list.Length == 0)
3117 // Events and types are returned by both `static' and `instance'
3118 // searches, which means that our above FindMembers will
3119 // return two copies of the same.
3121 if (list.Length == 1 && !(list [0] is MethodBase)){
3126 // Multiple properties: we query those just to find out the indexer
3129 if (list [0] is PropertyInfo)
3133 // We found an event: the cache lookup returns both the event and
3134 // its private field.
3136 if (list [0] is EventInfo) {
3137 if ((list.Length == 2) && (list [1] is FieldInfo))
3138 return new MemberInfo [] { list [0] };
3144 // We found methods, turn the search into "method scan"
3148 if (first_members_list != null) {
3149 if (use_first_members_list) {
3150 method_list = CopyNewMethods (method_list, first_members_list);
3151 use_first_members_list = false;
3154 method_list = CopyNewMethods (method_list, list);
3156 first_members_list = list;
3157 use_first_members_list = true;
3158 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3160 } while (searching);
3162 if (use_first_members_list)
3163 return first_members_list;
3165 if (method_list != null && method_list.Count > 0) {
3166 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3169 // This happens if we already used the cache in the first iteration, in this case
3170 // the cache already looked in all interfaces.
3172 if (skip_iface_check)
3176 // Interfaces do not list members they inherit, so we have to
3179 if (!queried_type.IsInterface)
3182 if (queried_type.IsArray)
3183 queried_type = TypeManager.array_type;
3185 Type [] ifaces = GetInterfaces (queried_type);
3189 foreach (Type itype in ifaces){
3192 x = MemberLookup (null, null, itype, mt, bf, name, null);
3200 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3201 BindingFlags.Static | BindingFlags.Instance |
3202 BindingFlags.DeclaredOnly;
3204 // Currently is designed to work with external types only
3205 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3207 if (!mb.IsSpecialName)
3210 string name = mb.Name;
3211 if (name.Length < 5)
3214 if (name [3] != '_')
3217 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3218 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3219 Type.FilterName, name.Substring (4));
3224 // This can happen when property is indexer (it can have same name but different parameters)
3225 foreach (PropertyInfo p in pi) {
3226 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3227 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3236 // Currently is designed to work with external types only
3237 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3239 if (!mb.IsSpecialName)
3242 string name = mb.Name;
3243 if (name.Length < 5)
3246 if (name.StartsWith ("add_"))
3247 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3249 if (name.StartsWith ("remove_"))
3250 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3255 // Tests whether external method is really special
3256 public static bool IsSpecialMethod (MethodBase mb)
3258 if (!mb.IsSpecialName)
3261 IMethodData md = TypeManager.GetMethod (mb);
3263 return (md is AbstractPropertyEventMethod || md is Operator);
3265 PropertyInfo pi = GetPropertyFromAccessor (mb);
3267 return IsValidProperty (pi);
3269 if (GetEventFromAccessor (mb) != null)
3272 string name = mb.Name;
3273 if (name.StartsWith ("op_"))
3274 return Operator.GetName (name) != null;
3279 // Tests whether imported property is valid C# property.
3280 // TODO: It seems to me that we should do a lot of sanity tests before
3281 // we accept property as C# property
3282 static bool IsValidProperty (PropertyInfo pi)
3284 MethodInfo get_method = pi.GetGetMethod (true);
3285 MethodInfo set_method = pi.GetSetMethod (true);
3288 if (get_method != null && set_method != null) {
3289 g_count = get_method.GetParameters ().Length;
3290 s_count = set_method.GetParameters ().Length;
3291 if (g_count + 1 != s_count)
3293 } else if (get_method != null) {
3294 g_count = get_method.GetParameters ().Length;
3295 } else if (set_method != null) {
3296 s_count = set_method.GetParameters ().Length;
3300 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3302 if ((s_count > 1 || g_count > 0) && TypeManager.default_member_type != null) {
3303 object[] o = pi.DeclaringType.GetCustomAttributes (TypeManager.default_member_type, false);
3307 DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
3308 if (dma.MemberName != pi.Name)
3310 if (get_method != null && "get_" + dma.MemberName != get_method.Name)
3312 if (set_method != null && "set_" + dma.MemberName != set_method.Name)
3324 /// There is exactly one instance of this class per type.
3326 public sealed class TypeHandle : IMemberContainer {
3327 public readonly IMemberContainer BaseType;
3329 readonly int id = ++next_id;
3330 static int next_id = 0;
3332 static TypeHandle ()
3338 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3339 /// a TypeHandle yet, a new instance of it is created. This static method
3340 /// ensures that we'll only have one TypeHandle instance per type.
3342 private static TypeHandle GetTypeHandle (Type t)
3344 TypeHandle handle = (TypeHandle) type_hash [t];
3348 handle = new TypeHandle (t);
3349 type_hash.Add (t, handle);
3353 public static MemberCache GetMemberCache (Type t)
3355 return GetTypeHandle (t).MemberCache;
3358 public static void CleanUp ()
3363 public static void Reset ()
3365 type_hash = new PtrHashtable ();
3369 /// Returns the TypeHandle for TypeManager.object_type.
3371 public static IMemberContainer ObjectType {
3373 if (object_type != null)
3376 object_type = GetTypeHandle (TypeManager.object_type);
3383 /// Returns the TypeHandle for TypeManager.array_type.
3385 public static TypeHandle ArrayType {
3387 if (array_type != null)
3390 array_type = GetTypeHandle (TypeManager.array_type);
3396 private static PtrHashtable type_hash;
3398 private static TypeHandle object_type = null;
3399 private static TypeHandle array_type = null;
3402 private string full_name;
3403 private bool is_interface;
3404 private MemberCache member_cache;
3405 private MemberCache base_cache;
3407 private TypeHandle (Type type)
3410 full_name = type.FullName != null ? type.FullName : type.Name;
3411 if (type.BaseType != null) {
3412 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3413 BaseType = base_cache.Container;
3414 } else if (type.IsInterface)
3415 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3416 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3417 this.member_cache = new MemberCache (this);
3420 // IMemberContainer methods
3422 public string Name {
3434 public MemberCache BaseCache {
3440 public bool IsInterface {
3442 return is_interface;
3446 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3448 MemberInfo [] members;
3451 if (type is GenericTypeParameterBuilder)
3452 return MemberList.Empty;
3455 if (mt == MemberTypes.Event)
3456 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3458 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3461 if (members.Length == 0)
3462 return MemberList.Empty;
3464 Array.Reverse (members);
3465 return new MemberList (members);
3468 // IMemberFinder methods
3470 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3471 MemberFilter filter, object criteria)
3473 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3476 public MemberCache MemberCache {
3478 return member_cache;
3482 public override string ToString ()
3484 if (BaseType != null)
3485 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3487 return "TypeHandle (" + id + "," + Name + ")";