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 {
33 partial class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static public Type uint32_type;
42 static public Type int64_type;
43 static public Type uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type short_type;
48 static public Type decimal_type;
49 static public Type bool_type;
50 static public Type sbyte_type;
51 static public Type byte_type;
52 static public Type ushort_type;
53 static public Type enum_type;
54 static public Type delegate_type;
55 static public Type multicast_delegate_type;
56 static public Type void_type;
57 static public Type null_type;
58 static public Type array_type;
59 static public Type runtime_handle_type;
60 static public Type type_type;
61 static public Type ienumerator_type;
62 static public Type ienumerable_type;
63 static public Type idisposable_type;
64 static public Type iasyncresult_type;
65 static public Type asynccallback_type;
66 static public Type intptr_type;
67 static public Type uintptr_type;
68 static public Type runtime_field_handle_type;
69 static public Type runtime_argument_handle_type;
70 static public Type attribute_type;
71 static public Type void_ptr_type;
72 static public Type exception_type;
74 static public Type typed_reference_type;
75 static public Type arg_iterator_type;
76 static public Type mbr_type;
77 public static Type runtime_helpers_type;
82 static internal Type isvolatile_type;
83 static public Type generic_ilist_type;
84 static public Type generic_icollection_type;
85 static public Type generic_ienumerator_type;
86 static public Type generic_ienumerable_type;
87 static public Type generic_nullable_type;
92 static internal Type expression_type;
93 public static Type parameter_expression_type;
96 // Expressions representing the internal types. Used during declaration
99 static public TypeExpr system_object_expr, system_string_expr;
100 static public TypeExpr system_boolean_expr, system_decimal_expr;
101 static public TypeExpr system_single_expr, system_double_expr;
102 static public TypeExpr system_sbyte_expr, system_byte_expr;
103 static public TypeExpr system_int16_expr, system_uint16_expr;
104 static public TypeExpr system_int32_expr, system_uint32_expr;
105 static public TypeExpr system_int64_expr, system_uint64_expr;
106 static public TypeExpr system_char_expr, system_void_expr;
107 static public TypeExpr system_valuetype_expr;
108 static public TypeExpr system_intptr_expr;
109 public static TypeExpr expression_type_expr;
113 // These methods are called by code generated by the compiler
115 static public FieldInfo string_empty;
116 static public MethodInfo system_type_get_type_from_handle;
117 static public MethodInfo bool_movenext_void;
118 static public MethodInfo void_dispose_void;
119 static public MethodInfo void_monitor_enter_object;
120 static public MethodInfo void_monitor_exit_object;
121 static public MethodInfo void_initializearray_array_fieldhandle;
122 static public MethodInfo delegate_combine_delegate_delegate;
123 static public MethodInfo delegate_remove_delegate_delegate;
124 static public PropertyInfo int_get_offset_to_string_data;
125 static public MethodInfo int_interlocked_compare_exchange;
126 static public PropertyInfo ienumerator_getcurrent;
127 public static MethodInfo methodbase_get_type_from_handle;
128 public static MethodInfo methodbase_get_type_from_handle_generic;
129 public static MethodInfo fieldinfo_get_field_from_handle;
130 static public MethodInfo activator_create_instance;
135 static public ConstructorInfo void_decimal_ctor_five_args;
136 static public ConstructorInfo void_decimal_ctor_int_arg;
138 static PtrHashtable builder_to_declspace;
140 static PtrHashtable builder_to_member_cache;
143 // Tracks the interfaces implemented by typebuilders. We only
144 // enter those who do implement or or more interfaces
146 static PtrHashtable builder_to_ifaces;
149 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
151 static Hashtable method_params;
154 // A hash table from override methods to their base virtual method.
156 static Hashtable method_overrides;
159 // Keeps track of methods
162 static Hashtable builder_to_method;
165 // Contains all public types from referenced assemblies.
166 // This member is used only if CLS Compliance verification is required.
168 public static Hashtable AllClsTopLevelTypes;
170 static Hashtable fieldbuilders_to_fields;
171 static Hashtable propertybuilder_to_property;
172 static Hashtable fields;
173 static Hashtable events;
174 static PtrHashtable assembly_internals_vis_attrs;
176 public static void CleanUp ()
178 // Lets get everything clean so that we can collect before generating code
179 builder_to_declspace = null;
180 builder_to_member_cache = null;
181 builder_to_ifaces = null;
182 builder_to_type_param = null;
183 method_params = null;
184 builder_to_method = null;
189 propertybuilder_to_property = null;
191 TypeHandle.CleanUp ();
195 // These are expressions that represent some of the internal data types, used
198 static void InitExpressionTypes ()
200 system_object_expr = new TypeLookupExpression ("System", "Object");
201 system_string_expr = new TypeLookupExpression ("System", "String");
202 system_boolean_expr = new TypeLookupExpression ("System", "Boolean");
203 system_decimal_expr = new TypeLookupExpression ("System", "Decimal");
204 system_single_expr = new TypeLookupExpression ("System", "Single");
205 system_double_expr = new TypeLookupExpression ("System", "Double");
206 system_sbyte_expr = new TypeLookupExpression ("System", "SByte");
207 system_byte_expr = new TypeLookupExpression ("System", "Byte");
208 system_int16_expr = new TypeLookupExpression ("System", "Int16");
209 system_uint16_expr = new TypeLookupExpression ("System", "UInt16");
210 system_int32_expr = new TypeLookupExpression ("System", "Int32");
211 system_uint32_expr = new TypeLookupExpression ("System", "UInt32");
212 system_int64_expr = new TypeLookupExpression ("System", "Int64");
213 system_uint64_expr = new TypeLookupExpression ("System", "UInt64");
214 system_char_expr = new TypeLookupExpression ("System", "Char");
215 system_void_expr = new TypeLookupExpression ("System", "Void");
216 system_valuetype_expr = new TypeLookupExpression ("System", "ValueType");
217 system_intptr_expr = new TypeLookupExpression ("System", "IntPtr");
220 static TypeManager ()
225 static public void Reset ()
227 InitExpressionTypes ();
229 builder_to_declspace = new PtrHashtable ();
230 builder_to_member_cache = new PtrHashtable ();
231 builder_to_method = new PtrHashtable ();
232 builder_to_type_param = new PtrHashtable ();
233 method_params = new PtrHashtable ();
234 method_overrides = new PtrHashtable ();
235 builder_to_ifaces = new PtrHashtable ();
237 fieldbuilders_to_fields = new Hashtable ();
238 propertybuilder_to_property = new Hashtable ();
239 fields = new Hashtable ();
240 type_hash = new DoubleHash ();
241 assembly_internals_vis_attrs = new PtrHashtable ();
242 iface_cache = new PtrHashtable ();
244 closure = new Closure ();
245 FilterWithClosure_delegate = new MemberFilter (closure.Filter);
247 // TODO: I am really bored by all this static stuff
248 system_type_get_type_from_handle =
251 void_monitor_enter_object =
252 void_monitor_exit_object =
253 void_initializearray_array_fieldhandle =
254 delegate_combine_delegate_delegate =
255 delegate_remove_delegate_delegate =
256 int_interlocked_compare_exchange =
257 methodbase_get_type_from_handle =
258 methodbase_get_type_from_handle_generic =
259 fieldinfo_get_field_from_handle =
260 activator_create_instance = null;
262 int_get_offset_to_string_data =
263 ienumerator_getcurrent = null;
265 void_decimal_ctor_five_args =
266 void_decimal_ctor_int_arg = null;
268 isvolatile_type = null;
270 // to uncover regressions
271 AllClsTopLevelTypes = null;
274 public static void AddUserType (DeclSpace ds)
276 builder_to_declspace.Add (ds.TypeBuilder, ds);
280 // This entry point is used by types that we define under the covers
282 public static void RegisterBuilder (Type tb, Type [] ifaces)
285 builder_to_ifaces [tb] = ifaces;
288 public static void AddMethod (MethodBase builder, IMethodData method)
290 builder_to_method.Add (builder, method);
291 method_params.Add (builder, method.ParameterInfo);
294 public static IMethodData GetMethod (MethodBase builder)
296 return (IMethodData) builder_to_method [builder];
300 /// Returns the DeclSpace whose Type is `t' or null if there is no
301 /// DeclSpace for `t' (ie, the Type comes from a library)
303 public static DeclSpace LookupDeclSpace (Type t)
305 return builder_to_declspace [t] as DeclSpace;
309 /// Returns the TypeContainer whose Type is `t' or null if there is no
310 /// TypeContainer for `t' (ie, the Type comes from a library)
312 public static TypeContainer LookupTypeContainer (Type t)
314 return builder_to_declspace [t] as TypeContainer;
317 public static MemberCache LookupMemberCache (Type t)
319 if (t.Module == RootContext.ToplevelTypes.Builder) {
320 DeclSpace container = (DeclSpace)builder_to_declspace [t];
321 if (container != null)
322 return container.MemberCache;
326 if (t is GenericTypeParameterBuilder) {
327 TypeParameter container = builder_to_type_param [t] as TypeParameter;
329 if (container != null)
330 return container.MemberCache;
334 return TypeHandle.GetMemberCache (t);
337 public static MemberCache LookupBaseInterfacesCache (Type t)
339 Type [] ifaces = GetInterfaces (t);
341 if (ifaces != null && ifaces.Length == 1)
342 return LookupMemberCache (ifaces [0]);
344 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
345 MemberCache cache = builder_to_member_cache [t] as MemberCache;
349 cache = new MemberCache (ifaces);
350 builder_to_member_cache.Add (t, cache);
354 public static TypeContainer LookupInterface (Type t)
356 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
357 if ((tc == null) || (tc.Kind != Kind.Interface))
363 public static Delegate LookupDelegate (Type t)
365 return builder_to_declspace [t] as Delegate;
368 public static Class LookupClass (Type t)
370 return (Class) builder_to_declspace [t];
374 // We use this hash for multiple kinds of constructed types:
376 // (T, "&") Given T, get T &
377 // (T, "*") Given T, get T *
378 // (T, "[]") Given T and a array dimension, get T []
379 // (T, X) Given a type T and a simple name X, get the type T+X
381 // Accessibility tests, if necessary, should be done by the user
383 static DoubleHash type_hash = new DoubleHash ();
386 // Gets the reference to T version of the Type (T&)
388 public static Type GetReferenceType (Type t)
391 return t.MakeByRefType ();
393 return GetConstructedType (t, "&");
398 // Gets the pointer to T version of the Type (T*)
400 public static Type GetPointerType (Type t)
402 return GetConstructedType (t, "*");
405 public static Type GetConstructedType (Type t, string dim)
408 if (type_hash.Lookup (t, dim, out ret))
411 ret = t.Module.GetType (t.ToString () + dim);
413 type_hash.Insert (t, dim, ret);
418 ret = GetReferenceType (t);
419 type_hash.Insert (t, dim, ret);
424 if (t.IsGenericParameter || t.IsGenericType) {
427 while ((pos < dim.Length) && (dim [pos] == '[')) {
430 if (dim [pos] == ']') {
431 result = result.MakeArrayType ();
434 if (pos < dim.Length)
437 type_hash.Insert (t, dim, result);
442 while (dim [pos] == ',') {
446 if ((dim [pos] != ']') || (pos != dim.Length-1))
449 result = result.MakeArrayType (rank + 1);
450 type_hash.Insert (t, dim, result);
456 type_hash.Insert (t, dim, null);
460 public static Type GetNestedType (Type t, string name)
463 if (!type_hash.Lookup (t, name, out ret)) {
464 ret = t.GetNestedType (name,
465 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
466 type_hash.Insert (t, name, ret);
472 /// Fills static table with exported types from all referenced assemblies.
473 /// This information is required for CLS Compliance tests.
475 public static void LoadAllImportedTypes ()
477 AllClsTopLevelTypes = new Hashtable (1500);
478 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
479 foreach (Type t in a.GetExportedTypes ()) {
480 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
485 public static bool NamespaceClash (string name, Location loc)
487 if (!GlobalRootNamespace.Instance.IsNamespace (name))
490 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
495 /// Returns the C# name of a type if possible, or the full type name otherwise
497 static public string CSharpName (Type t)
502 if (t == typeof (ArglistAccess))
505 if (t == typeof (AnonymousMethodBody))
506 return "anonymous method";
508 if (t == typeof (MethodGroupExpr))
509 return "method group";
512 return "internal error";
514 return CSharpName (GetFullName (t), t);
517 static readonly char [] elements = new char [] { '*', '[' };
519 public static string CSharpName (string name, Type type)
521 if (name.Length > 10) {
524 case "System.Int32": s = "int"; break;
525 case "System.Int64": s = "long"; break;
526 case "System.String": s = "string"; break;
527 case "System.Boolean": s = "bool"; break;
528 case "System.Void": s = "void"; break;
529 case "System.Object": s = "object"; break;
530 case "System.UInt32": s = "uint"; break;
531 case "System.Int16": s = "short"; break;
532 case "System.UInt16": s = "ushort"; break;
533 case "System.UInt64": s = "ulong"; break;
534 case "System.Single": s = "float"; break;
535 case "System.Double": s = "double"; break;
536 case "System.Decimal": s = "decimal"; break;
537 case "System.Char": s = "char"; break;
538 case "System.Byte": s = "byte"; break;
539 case "System.SByte": s = "sbyte"; break;
540 default: s = null; break;
545 // Predefined names can come from mscorlib only
547 if (type == null || type.Module.Name == "mscorlib.dll" || !RootContext.StdLib)
553 if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
554 return AnonymousTypeClass.SignatureForError;
556 int idx = name.IndexOfAny (elements, 10);
558 return CSharpName (name.Substring (0, idx), type) + name.Substring (idx);
561 return name.Replace ('+', '.');
564 static public string CSharpName (Type[] types)
566 if (types.Length == 0)
569 StringBuilder sb = new StringBuilder ();
570 for (int i = 0; i < types.Length; ++i) {
574 sb.Append (CSharpName (types [i]));
576 return sb.ToString ();
580 /// Returns the signature of the method with full namespace classification
582 static public string GetFullNameSignature (MemberInfo mi)
584 PropertyInfo pi = mi as PropertyInfo;
586 MethodBase pmi = pi.GetGetMethod (true);
588 pmi = pi.GetSetMethod (true);
589 if (GetParameterData (pmi).Count > 0)
592 return (mi is MethodBase)
593 ? CSharpSignature (mi as MethodBase)
594 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
598 private static int GetFullName (Type t, StringBuilder sb)
602 if (!t.IsGenericType) {
603 sb.Append (t.FullName);
607 if (t.DeclaringType != null) {
608 pos = GetFullName (t.DeclaringType, sb);
610 } else if (t.Namespace != null && t.Namespace.Length != 0) {
611 sb.Append (t.Namespace);
614 sb.Append (RemoveGenericArity (t.Name));
616 Type[] this_args = GetTypeArguments (t);
618 if (this_args.Length < pos)
619 throw new InternalErrorException (
620 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
621 if (this_args.Length == pos)
626 sb.Append (CSharpName (this_args [pos++]));
627 if (pos == this_args.Length)
635 static string GetFullName (Type t)
638 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
639 return GetFullName (GetElementType (t)) + dimension;
642 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
643 t = GetTypeArguments (t)[0];
644 return CSharpName (t) + "?";
647 if (t.IsGenericParameter)
649 if (!t.IsGenericType)
652 StringBuilder sb = new StringBuilder ();
653 int pos = GetFullName (t, sb);
655 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
656 return sb.ToString ();
659 public static string GetFullName (Type t)
665 public static string RemoveGenericArity (string from)
667 int i = from.IndexOf ('`');
669 return from.Substring (0, i);
674 /// When we need to report accessors as well
676 static public string CSharpSignature (MethodBase mb)
678 return CSharpSignature (mb, false);
682 /// Returns the signature of the method
684 static public string CSharpSignature (MethodBase mb, bool show_accessor)
686 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
689 AParametersCollection iparams = GetParameterData (mb);
690 string parameters = iparams.GetSignatureForError ();
691 int accessor_end = 0;
693 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
694 string op_name = Operator.GetName (mb.Name);
695 if (op_name != null) {
696 if (op_name == "explicit" || op_name == "implicit") {
697 sig.Append (op_name);
698 sig.Append (" operator ");
699 sig.Append (CSharpName (((MethodInfo)mb).ReturnType));
701 sig.Append ("operator ");
702 sig.Append (op_name);
704 sig.Append (parameters);
705 return sig.ToString ();
708 bool is_getter = mb.Name.StartsWith ("get_");
709 bool is_setter = mb.Name.StartsWith ("set_");
710 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
712 } else if (mb.Name.StartsWith ("remove_")) {
717 if (iparams.Count > (is_getter ? 0 : 1)) {
718 sig.Append ("this[");
720 sig.Append (parameters.Substring (1, parameters.Length - 2));
722 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
725 sig.Append (mb.Name.Substring (accessor_end + 1));
728 if (mb.Name == ".ctor")
729 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
731 sig.Append (mb.Name);
733 if (IsGenericMethod (mb)) {
734 Type[] args = GetGenericArguments (mb);
736 for (int i = 0; i < args.Length; i++) {
739 sig.Append (CSharpName (args [i]));
745 sig.Append (parameters);
748 if (show_accessor && accessor_end > 0) {
750 sig.Append (mb.Name.Substring (0, accessor_end));
753 return sig.ToString ();
756 public static string GetMethodName (MethodInfo m)
758 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
761 return MemberName.MakeName (m.Name, TypeManager.GetGenericArguments (m).Length);
764 static public string CSharpSignature (EventInfo ei)
766 return CSharpName (ei.DeclaringType) + "." + ei.Name;
770 // Looks up a type, and aborts if it is not found. This is used
771 // by predefined types required by the compiler
773 public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required)
775 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
776 Expression expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
780 Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
787 if (RootContext.StdLib || t == null || !required)
790 // TODO: All predefined imported types have to have correct signature
791 if (t.Module != RootContext.ToplevelTypes.Builder)
794 DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
795 if (ds is Delegate) {
796 if (type_kind == Kind.Delegate)
799 TypeContainer tc = (TypeContainer)ds;
800 if (tc.Kind == type_kind)
804 Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
809 static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
811 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
813 MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
814 if (members != null) {
815 for (int i = 0; i < members.Length; ++i) {
816 MemberInfo member = members [i];
817 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
818 MethodBase mb = member as MethodBase;
822 AParametersCollection pd = TypeManager.GetParameterData (mb);
823 if (IsEqual (pd.Types, args))
826 if (mt == MemberTypes.Field) {
827 FieldInfo fi = member as FieldInfo;
831 if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
837 if (mt == MemberTypes.Property) {
838 PropertyInfo pi = member as PropertyInfo;
842 if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
850 string method_args = null;
851 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
852 method_args = "(" + TypeManager.CSharpName (args) + ")";
854 Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
855 TypeManager.CSharpName (t), name, method_args);
861 // Returns the ConstructorInfo for "args"
863 public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
865 return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
869 // Returns the MethodInfo for a method named `name' defined
870 // in type `t' which takes arguments of types `args'
872 public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
874 return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
877 public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
879 return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
882 public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
884 return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
888 /// The types have to be initialized after the initial
889 /// population of the type has happened (for example, to
890 /// bootstrap the corlib.dll
892 public static bool InitCoreTypes ()
894 object_type = CoreLookupType ("System", "Object", Kind.Class, true);
895 system_object_expr.Type = object_type;
896 value_type = CoreLookupType ("System", "ValueType", Kind.Class, true);
897 system_valuetype_expr.Type = value_type;
898 attribute_type = CoreLookupType ("System", "Attribute", Kind.Class, true);
900 int32_type = CoreLookupType ("System", "Int32", Kind.Struct, true);
901 system_int32_expr.Type = int32_type;
902 int64_type = CoreLookupType ("System", "Int64", Kind.Struct, true);
903 system_int64_expr.Type = int64_type;
904 uint32_type = CoreLookupType ("System", "UInt32", Kind.Struct, true);
905 system_uint32_expr.Type = uint32_type;
906 uint64_type = CoreLookupType ("System", "UInt64", Kind.Struct, true);
907 system_uint64_expr.Type = uint64_type;
908 byte_type = CoreLookupType ("System", "Byte", Kind.Struct, true);
909 system_byte_expr.Type = byte_type;
910 sbyte_type = CoreLookupType ("System", "SByte", Kind.Struct, true);
911 system_sbyte_expr.Type = sbyte_type;
912 short_type = CoreLookupType ("System", "Int16", Kind.Struct, true);
913 system_int16_expr.Type = short_type;
914 ushort_type = CoreLookupType ("System", "UInt16", Kind.Struct, true);
915 system_uint16_expr.Type = ushort_type;
917 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator", Kind.Interface, true);
918 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable", Kind.Interface, true);
919 idisposable_type = CoreLookupType ("System", "IDisposable", Kind.Interface, true);
921 // HACK: DefineType immediately resolves iterators (very wrong)
922 generic_ienumerator_type = CoreLookupType ("System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
924 char_type = CoreLookupType ("System", "Char", Kind.Struct, true);
925 system_char_expr.Type = char_type;
926 string_type = CoreLookupType ("System", "String", Kind.Class, true);
927 system_string_expr.Type = string_type;
928 float_type = CoreLookupType ("System", "Single", Kind.Struct, true);
929 system_single_expr.Type = float_type;
930 double_type = CoreLookupType ("System", "Double", Kind.Struct, true);
931 system_double_expr.Type = double_type;
932 decimal_type = CoreLookupType ("System", "Decimal", Kind.Struct, true);
933 system_decimal_expr.Type = decimal_type;
934 bool_type = CoreLookupType ("System", "Boolean", Kind.Struct, true);
935 system_boolean_expr.Type = bool_type;
936 intptr_type = CoreLookupType ("System", "IntPtr", Kind.Struct, true);
937 system_intptr_expr.Type = intptr_type;
938 uintptr_type = CoreLookupType ("System", "UIntPtr", Kind.Struct, true);
940 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate", Kind.Class, true);
941 delegate_type = CoreLookupType ("System", "Delegate", Kind.Class, true);
943 enum_type = CoreLookupType ("System", "Enum", Kind.Class, true);
944 array_type = CoreLookupType ("System", "Array", Kind.Class, true);
945 void_type = CoreLookupType ("System", "Void", Kind.Struct, true);
946 system_void_expr.Type = void_type;
947 type_type = CoreLookupType ("System", "Type", Kind.Class, true);
948 exception_type = CoreLookupType ("System", "Exception", Kind.Class, true);
950 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle", Kind.Struct, true);
951 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle", Kind.Struct, true);
953 PredefinedAttributes.Get.ParamArray.Resolve (false);
954 PredefinedAttributes.Get.Out.Resolve (false);
956 return Report.Errors == 0;
960 // Initializes optional core types
962 public static void InitOptionalCoreTypes ()
965 // These are only used for compare purposes
967 null_type = typeof (NullLiteral);
969 void_ptr_type = GetPointerType (void_type);
972 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
973 // types cache with incorrect accessiblity when any of optional types is internal.
975 PredefinedAttributes.Get.Initialize ();
977 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle", Kind.Struct, false);
978 asynccallback_type = CoreLookupType ("System", "AsyncCallback", Kind.Delegate, false);
979 iasyncresult_type = CoreLookupType ("System", "IAsyncResult", Kind.Interface, false);
980 typed_reference_type = CoreLookupType ("System", "TypedReference", Kind.Struct, false);
981 arg_iterator_type = CoreLookupType ("System", "ArgIterator", Kind.Struct, false);
982 mbr_type = CoreLookupType ("System", "MarshalByRefObject", Kind.Class, false);
985 // Optional attributes, used for error reporting only
987 //if (PredefinedAttributes.Get.Obsolete.IsDefined) {
988 // Class c = TypeManager.LookupClass (PredefinedAttributes.Get.Obsolete.Type);
993 generic_ilist_type = CoreLookupType ("System.Collections.Generic", "IList`1", Kind.Interface, false);
994 generic_icollection_type = CoreLookupType ("System.Collections.Generic", "ICollection`1", Kind.Interface, false);
995 generic_ienumerable_type = CoreLookupType ("System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
996 generic_nullable_type = CoreLookupType ("System", "Nullable`1", Kind.Struct, false);
999 // Optional types which are used as types and for member lookup
1001 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
1004 // Note: extension_attribute_type is already loaded
1005 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", Kind.Class, false);
1007 if (!RootContext.StdLib) {
1009 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1010 // has different predefined types and this method sets mscorlib types
1011 // to be same to avoid any type check errors.
1014 Type type = typeof (Type);
1015 Type [] system_4_type_arg = { type, type, type, type };
1017 MethodInfo set_corlib_type_builders =
1018 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1019 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1020 system_4_type_arg, null);
1022 if (set_corlib_type_builders != null) {
1023 object[] args = new object [4];
1024 args [0] = object_type;
1025 args [1] = value_type;
1026 args [2] = enum_type;
1027 args [3] = void_type;
1029 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1031 Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1032 TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
1033 TypeManager.CSharpName (system_4_type_arg));
1038 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1041 /// This is the "old", non-cache based FindMembers() function. We cannot use
1042 /// the cache here because there is no member name argument.
1044 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1045 MemberFilter filter, object criteria)
1047 #if MS_COMPATIBLE && GMCS_SOURCE
1048 if (t.IsGenericType)
1049 t = t.GetGenericTypeDefinition ();
1052 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1055 // `builder_to_declspace' contains all dynamic types.
1059 Timer.StartTimer (TimerType.FindMembers);
1060 list = decl.FindMembers (mt, bf, filter, criteria);
1061 Timer.StopTimer (TimerType.FindMembers);
1066 // We have to take care of arrays specially, because GetType on
1067 // a TypeBuilder array will return a Type, not a TypeBuilder,
1068 // and we can not call FindMembers on this type.
1071 #if MS_COMPATIBLE && GMCS_SOURCE
1074 t.IsSubclassOf (TypeManager.array_type))
1075 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1078 if (t is GenericTypeParameterBuilder) {
1079 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1081 Timer.StartTimer (TimerType.FindMembers);
1082 MemberList list = tparam.FindMembers (
1083 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1084 Timer.StopTimer (TimerType.FindMembers);
1090 // Since FindMembers will not lookup both static and instance
1091 // members, we emulate this behaviour here.
1093 if ((bf & instance_and_static) == instance_and_static){
1094 MemberInfo [] i_members = t.FindMembers (
1095 mt, bf & ~BindingFlags.Static, filter, criteria);
1097 int i_len = i_members.Length;
1099 MemberInfo one = i_members [0];
1102 // If any of these are present, we are done!
1104 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1105 return new MemberList (i_members);
1108 MemberInfo [] s_members = t.FindMembers (
1109 mt, bf & ~BindingFlags.Instance, filter, criteria);
1111 int s_len = s_members.Length;
1112 if (i_len > 0 || s_len > 0)
1113 return new MemberList (i_members, s_members);
1116 return new MemberList (i_members);
1118 return new MemberList (s_members);
1122 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1127 /// This method is only called from within MemberLookup. It tries to use the member
1128 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1129 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1130 /// our return value will already contain all inherited members and the caller don't need
1131 /// to check base classes and interfaces anymore.
1133 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1134 string name, out bool used_cache)
1139 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1140 // and we can ask the DeclSpace for the MemberCache.
1143 if (t.Assembly == CodeGen.Assembly.Builder) {
1144 if (t.IsGenericParameter) {
1145 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1148 if (tparam.MemberCache == null)
1149 return new MemberInfo[0];
1151 return tparam.MemberCache.FindMembers (
1152 mt, bf, name, FilterWithClosure_delegate, null);
1156 // We have to take care of arrays specially, because GetType on
1157 // a TypeBuilder array will return a Type, not a TypeBuilder,
1158 // and we can not call FindMembers on this type.
1162 return TypeHandle.ArrayType.MemberCache.FindMembers (
1163 mt, bf, name, FilterWithClosure_delegate, null);
1166 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1167 t = t.GetGenericTypeDefinition ();
1169 if (t is TypeBuilder) {
1171 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1172 cache = decl.MemberCache;
1175 // If this DeclSpace has a MemberCache, use it.
1178 if (cache != null) {
1180 return cache.FindMembers (
1181 mt, bf, name, FilterWithClosure_delegate, null);
1184 // If there is no MemberCache, we need to use the "normal" FindMembers.
1185 // Note, this is a VERY uncommon route!
1188 Timer.StartTimer (TimerType.FindMembers);
1189 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1190 FilterWithClosure_delegate, name);
1191 Timer.StopTimer (TimerType.FindMembers);
1193 return (MemberInfo []) list;
1197 // We have to take care of arrays specially, because GetType on
1198 // a TypeBuilder array will return a Type, not a TypeBuilder,
1199 // and we can not call FindMembers on this type.
1203 return TypeHandle.ArrayType.MemberCache.FindMembers (
1204 mt, bf, name, FilterWithClosure_delegate, null);
1208 if (t is GenericTypeParameterBuilder) {
1209 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1212 if (tparam.MemberCache == null)
1213 return new MemberInfo [0];
1215 return tparam.MemberCache.FindMembers (
1216 mt, bf, name, FilterWithClosure_delegate, null);
1220 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1222 // This happens if we're resolving a class'es base class and interfaces
1223 // in TypeContainer.DefineType(). At this time, the types aren't
1224 // populated yet, so we can't use the cache.
1226 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1227 FilterWithClosure_delegate, name);
1233 // This call will always succeed. There is exactly one TypeHandle instance per
1234 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1235 // the corresponding MemberCache.
1237 cache = TypeHandle.GetMemberCache (t);
1240 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1243 public static bool IsBuiltinType (Type t)
1245 t = TypeToCoreType (t);
1246 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1247 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1248 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1249 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1256 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1257 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1259 public static bool IsPrimitiveType (Type t)
1261 return (t == int32_type || t == uint32_type ||
1262 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1263 t == char_type || t == short_type || t == bool_type ||
1264 t == sbyte_type || t == byte_type || t == ushort_type);
1267 public static bool IsDelegateType (Type t)
1269 if (TypeManager.IsGenericParameter (t))
1272 if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
1275 t = DropGenericTypeArguments (t);
1276 return IsSubclassOf (t, TypeManager.delegate_type);
1279 public static bool IsEnumType (Type t)
1281 t = DropGenericTypeArguments (t);
1282 return t.BaseType == TypeManager.enum_type;
1285 public static bool IsBuiltinOrEnum (Type t)
1287 if (IsBuiltinType (t))
1296 public static bool IsAttributeType (Type t)
1298 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1302 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1304 // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
1305 public static bool IsUnmanagedType (Type t)
1307 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1309 return ds.IsUnmanagedType ();
1311 // builtins that are not unmanaged types
1312 if (t == TypeManager.object_type || t == TypeManager.string_type)
1315 if (IsGenericType (t) || IsGenericParameter (t))
1318 if (IsBuiltinOrEnum (t))
1321 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1323 return IsUnmanagedType (GetElementType (t));
1325 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1329 if (!IsValueType (t))
1332 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1333 if (IsGenericTypeDefinition (p))
1339 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1341 foreach (FieldInfo f in fields){
1342 if (!IsUnmanagedType (f.FieldType)){
1352 // Null is considered to be a reference type
1354 public static bool IsReferenceType (Type t)
1356 if (TypeManager.IsGenericParameter (t)) {
1357 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1358 if (constraints == null)
1361 return constraints.IsReferenceType;
1364 return !IsStruct (t) && !IsEnumType (t);
1367 public static bool IsValueType (Type t)
1369 if (TypeManager.IsGenericParameter (t)) {
1370 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1371 if (constraints == null)
1374 return constraints.IsValueType;
1377 return IsStruct (t) || IsEnumType (t);
1380 public static bool IsStruct (Type t)
1382 return t.BaseType == value_type && t != enum_type && t.IsSealed;
1385 public static bool IsInterfaceType (Type t)
1387 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1391 return tc.Kind == Kind.Interface;
1394 public static bool IsSubclassOf (Type type, Type base_type)
1396 TypeParameter tparam = LookupTypeParameter (type);
1397 TypeParameter pparam = LookupTypeParameter (base_type);
1399 if ((tparam != null) && (pparam != null)) {
1400 if (tparam == pparam)
1403 return tparam.IsSubclassOf (base_type);
1406 #if MS_COMPATIBLE && GMCS_SOURCE
1407 if (type.IsGenericType)
1408 type = type.GetGenericTypeDefinition ();
1411 if (type.IsSubclassOf (base_type))
1415 if (IsEqual (type, base_type))
1418 type = type.BaseType;
1419 } while (type != null);
1424 public static bool IsPrivateAccessible (Type type, Type parent)
1429 if (type.Equals (parent))
1432 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1435 public static bool IsFamilyAccessible (Type type, Type parent)
1437 TypeParameter tparam = LookupTypeParameter (type);
1438 TypeParameter pparam = LookupTypeParameter (parent);
1440 if ((tparam != null) && (pparam != null)) {
1441 if (tparam == pparam)
1444 return tparam.IsSubclassOf (parent);
1448 if (IsInstantiationOfSameGenericType (type, parent))
1451 type = type.BaseType;
1452 } while (type != null);
1458 // Checks whether `type' is a subclass or nested child of `base_type'.
1460 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1463 if (IsFamilyAccessible (type, base_type))
1466 // Handle nested types.
1467 type = type.DeclaringType;
1468 } while (type != null);
1474 // Checks whether `type' is a nested child of `parent'.
1476 public static bool IsNestedChildOf (Type type, Type parent)
1481 type = DropGenericTypeArguments (type);
1482 parent = DropGenericTypeArguments (parent);
1484 if (IsEqual (type, parent))
1487 type = type.DeclaringType;
1488 while (type != null) {
1489 if (IsEqual (type, parent))
1492 type = type.DeclaringType;
1498 public static bool IsSpecialType (Type t)
1500 return t == arg_iterator_type || t == typed_reference_type;
1504 // Checks whether `extern_type' is friend of the output assembly
1506 public static bool IsThisOrFriendAssembly (Assembly assembly)
1508 if (assembly == CodeGen.Assembly.Builder)
1511 if (assembly_internals_vis_attrs.Contains (assembly))
1512 return (bool)(assembly_internals_vis_attrs [assembly]);
1514 PredefinedAttribute pa = PredefinedAttributes.Get.InternalsVisibleTo;
1515 // HACK: Do very early resolve of SRE type checking
1516 if (pa.Type == null)
1522 object [] attrs = assembly.GetCustomAttributes (pa.Type, false);
1523 if (attrs.Length == 0) {
1524 assembly_internals_vis_attrs.Add (assembly, false);
1528 bool is_friend = false;
1530 AssemblyName this_name = CodeGen.Assembly.Name;
1531 byte [] this_token = this_name.GetPublicKeyToken ();
1532 foreach (InternalsVisibleToAttribute attr in attrs) {
1533 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1536 AssemblyName aname = null;
1539 aname = new AssemblyName (attr.AssemblyName);
1541 throw new NotSupportedException ();
1543 } catch (FileLoadException) {
1544 } catch (ArgumentException) {
1547 if (aname == null || aname.Name != this_name.Name)
1550 byte [] key_token = aname.GetPublicKeyToken ();
1551 if (key_token != null) {
1552 if (this_token.Length == 0) {
1553 // Same name, but assembly is not strongnamed
1554 Error_FriendAccessNameNotMatching (aname.FullName);
1558 if (!CompareKeyTokens (this_token, key_token))
1566 assembly_internals_vis_attrs.Add (assembly, is_friend);
1570 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1572 for (int i = 0; i < token1.Length; i++)
1573 if (token1 [i] != token2 [i])
1579 static void Error_FriendAccessNameNotMatching (string other_name)
1582 "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",
1583 other_name, CodeGen.Assembly.Name.FullName);
1587 // Do the right thing when returning the element type of an
1588 // array type based on whether we are compiling corlib or not
1590 public static Type GetElementType (Type t)
1592 if (RootContext.StdLib)
1593 return t.GetElementType ();
1595 return TypeToCoreType (t.GetElementType ());
1599 /// This method is not implemented by MS runtime for dynamic types
1601 public static bool HasElementType (Type t)
1603 return t.IsArray || t.IsPointer || t.IsByRef;
1606 public static Type GetEnumUnderlyingType (Type t)
1608 t = DropGenericTypeArguments (t);
1609 Enum e = LookupTypeContainer (t) as Enum;
1611 return e.UnderlyingType;
1614 FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
1616 return TypeManager.int32_type;
1618 return TypeToCoreType (fi.FieldType);
1622 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1626 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1627 /// for anything which is dynamic, and we need this in a number of places,
1628 /// we register this information here, and use it afterwards.
1630 static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
1632 method_params.Add (mb, ip);
1635 static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
1637 method_params.Add (pb, p);
1640 static public AParametersCollection GetParameterData (MethodBase mb)
1642 AParametersCollection pd = (AParametersCollection) method_params [mb];
1645 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1646 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1647 pd = GetParameterData (mi);
1649 if (mi.IsGenericMethod)
1650 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1652 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1654 method_params.Add (mb, pd);
1658 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1659 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1660 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1663 pd = ParametersImported.Create (mb);
1665 MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
1666 if (generic != mb) {
1667 pd = TypeManager.GetParameterData (generic);
1668 pd = ParametersImported.Create (pd, mb);
1670 pd = ParametersImported.Create (mb);
1673 method_params.Add (mb, pd);
1678 public static AParametersCollection GetParameterData (PropertyInfo pi)
1680 AParametersCollection pd = (AParametersCollection)method_params [pi];
1682 if (pi is PropertyBuilder)
1683 return ParametersCompiled.EmptyReadOnlyParameters;
1685 ParameterInfo [] p = pi.GetIndexParameters ();
1687 return ParametersCompiled.EmptyReadOnlyParameters;
1689 pd = ParametersImported.Create (p, null);
1690 method_params.Add (pi, pd);
1696 public static AParametersCollection GetDelegateParameters (Type t)
1698 Delegate d = builder_to_declspace [t] as Delegate;
1700 return d.Parameters;
1702 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1703 return GetParameterData (invoke_mb);
1706 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1708 if (!method_overrides.Contains (override_method))
1709 method_overrides [override_method] = base_method;
1710 if (method_overrides [override_method] != base_method)
1711 throw new InternalErrorException ("Override mismatch: " + override_method);
1714 static public bool IsOverride (MethodBase m)
1716 m = DropGenericMethodArguments (m);
1718 return m.IsVirtual &&
1719 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1720 (m is MethodBuilder || method_overrides.Contains (m));
1723 static public MethodBase TryGetBaseDefinition (MethodBase m)
1725 m = DropGenericMethodArguments (m);
1727 return (MethodBase) method_overrides [m];
1730 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1732 fields.Add (fb, ic);
1735 public static IConstant GetConstant (FieldInfo fb)
1740 return (IConstant)fields [fb];
1743 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1745 propertybuilder_to_property.Add (pi, pb);
1748 public static PropertyBase GetProperty (PropertyInfo pi)
1750 return (PropertyBase)propertybuilder_to_property [pi];
1753 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
1755 fieldbuilders_to_fields.Add (fb, f);
1759 // The return value can be null; This will be the case for
1760 // auxiliary FieldBuilders created by the compiler that have no
1761 // real field being declared on the source code
1763 static public FieldBase GetField (FieldInfo fb)
1766 fb = GetGenericFieldDefinition (fb);
1768 return (FieldBase) fieldbuilders_to_fields [fb];
1771 static public MethodInfo GetAddMethod (EventInfo ei)
1773 if (ei is MyEventBuilder) {
1774 return ((MyEventBuilder)ei).GetAddMethod (true);
1776 return ei.GetAddMethod (true);
1779 static public MethodInfo GetRemoveMethod (EventInfo ei)
1781 if (ei is MyEventBuilder) {
1782 return ((MyEventBuilder)ei).GetRemoveMethod (true);
1784 return ei.GetRemoveMethod (true);
1787 static public void RegisterEventField (EventInfo einfo, EventField e)
1790 events = new Hashtable ();
1792 events.Add (einfo, e);
1795 static public EventField GetEventField (EventInfo ei)
1800 return (EventField) events [ei];
1803 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1805 Hashtable hash = new Hashtable ();
1806 return CheckStructCycles (tc, seen, hash);
1809 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1812 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
1816 // `seen' contains all types we've already visited.
1818 if (seen.Contains (tc))
1820 seen.Add (tc, null);
1822 if (tc.Fields == null)
1825 foreach (FieldBase field in tc.Fields) {
1826 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1829 Type ftype = field.FieldBuilder.FieldType;
1830 TypeContainer ftc = LookupTypeContainer (ftype);
1834 if (hash.Contains (ftc)) {
1835 Report.Error (523, tc.Location,
1836 "Struct member `{0}.{1}' of type `{2}' " +
1837 "causes a cycle in the struct layout",
1838 tc.Name, field.Name, ftc.Name);
1843 // `hash' contains all types in the current path.
1845 hash.Add (tc, null);
1847 bool ok = CheckStructCycles (ftc, seen, hash);
1854 if (!seen.Contains (ftc))
1855 seen.Add (ftc, null);
1862 /// Given an array of interface types, expand and eliminate repeated ocurrences
1863 /// of an interface.
1867 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1870 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
1872 ArrayList new_ifaces = new ArrayList ();
1874 foreach (TypeExpr iface in base_interfaces){
1875 Type itype = iface.Type;
1877 if (new_ifaces.Contains (itype))
1880 new_ifaces.Add (itype);
1882 Type [] implementing = GetInterfaces (itype);
1884 foreach (Type imp in implementing){
1885 if (!new_ifaces.Contains (imp))
1886 new_ifaces.Add (imp);
1889 Type [] ret = new Type [new_ifaces.Count];
1890 new_ifaces.CopyTo (ret, 0);
1894 public static Type[] ExpandInterfaces (Type [] base_interfaces)
1896 ArrayList new_ifaces = new ArrayList ();
1898 foreach (Type itype in base_interfaces){
1899 if (new_ifaces.Contains (itype))
1902 new_ifaces.Add (itype);
1904 Type [] implementing = GetInterfaces (itype);
1906 foreach (Type imp in implementing){
1907 if (!new_ifaces.Contains (imp))
1908 new_ifaces.Add (imp);
1911 Type [] ret = new Type [new_ifaces.Count];
1912 new_ifaces.CopyTo (ret, 0);
1916 static PtrHashtable iface_cache;
1919 /// This function returns the interfaces in the type `t'. Works with
1920 /// both types and TypeBuilders.
1922 public static Type [] GetInterfaces (Type t)
1924 Type [] cached = iface_cache [t] as Type [];
1929 // The reason for catching the Array case is that Reflection.Emit
1930 // will not return a TypeBuilder for Array types of TypeBuilder types,
1931 // but will still throw an exception if we try to call GetInterfaces
1934 // Since the array interfaces are always constant, we return those for
1939 t = TypeManager.array_type;
1941 if ((t is TypeBuilder) || IsGenericType (t)) {
1942 Type [] base_ifaces;
1944 if (t.BaseType == null)
1945 base_ifaces = Type.EmptyTypes;
1947 base_ifaces = GetInterfaces (t.BaseType);
1949 if (IsGenericType (t))
1950 #if MS_COMPATIBLE && GMCS_SOURCE
1951 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
1953 type_ifaces = t.GetInterfaces ();
1956 type_ifaces = (Type []) builder_to_ifaces [t];
1957 if (type_ifaces == null || type_ifaces.Length == 0)
1958 type_ifaces = Type.EmptyTypes;
1960 int base_count = base_ifaces.Length;
1961 Type [] result = new Type [base_count + type_ifaces.Length];
1962 base_ifaces.CopyTo (result, 0);
1963 type_ifaces.CopyTo (result, base_count);
1965 iface_cache [t] = result;
1967 } else if (t is GenericTypeParameterBuilder){
1968 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
1969 if (type_ifaces == null || type_ifaces.Length == 0)
1970 type_ifaces = Type.EmptyTypes;
1972 iface_cache [t] = type_ifaces;
1975 Type[] ifaces = t.GetInterfaces ();
1976 iface_cache [t] = ifaces;
1982 // gets the interfaces that are declared explicitly on t
1984 public static Type [] GetExplicitInterfaces (TypeBuilder t)
1986 return (Type []) builder_to_ifaces [t];
1990 /// The following is used to check if a given type implements an interface.
1991 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1993 public static bool ImplementsInterface (Type t, Type iface)
1998 // FIXME OPTIMIZATION:
1999 // as soon as we hit a non-TypeBuiler in the interface
2000 // chain, we could return, as the `Type.GetInterfaces'
2001 // will return all the interfaces implement by the type
2005 interfaces = GetInterfaces (t);
2007 if (interfaces != null){
2008 foreach (Type i in interfaces){
2009 if (i == iface || IsVariantOf (i, iface))
2015 } while (t != null);
2020 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2022 // This is a custom version of Convert.ChangeType() which works
2023 // with the TypeBuilder defined types when compiling corlib.
2024 public static object ChangeType (object value, Type conversionType, out bool error)
2026 IConvertible convert_value = value as IConvertible;
2028 if (convert_value == null){
2035 // We must use Type.Equals() here since `conversionType' is
2036 // the TypeBuilder created version of a system type and not
2037 // the system type itself. You cannot use Type.GetTypeCode()
2038 // on such a type - it'd always return TypeCode.Object.
2041 // We cannot rely on build-in type conversions as they are
2042 // more limited than what C# supports.
2043 // See char -> float/decimal/double conversion
2048 if (conversionType.Equals (typeof (Boolean)))
2049 return (object)(convert_value.ToBoolean (nf_provider));
2050 if (conversionType.Equals (typeof (Byte)))
2051 return (object)(convert_value.ToByte (nf_provider));
2052 if (conversionType.Equals (typeof (Char)))
2053 return (object)(convert_value.ToChar (nf_provider));
2054 if (conversionType.Equals (typeof (DateTime)))
2055 return (object)(convert_value.ToDateTime (nf_provider));
2057 if (conversionType.Equals (decimal_type)) {
2058 if (convert_value.GetType () == TypeManager.char_type)
2059 return (decimal)convert_value.ToInt32 (nf_provider);
2060 return convert_value.ToDecimal (nf_provider);
2063 if (conversionType.Equals (typeof (Double))) {
2064 if (convert_value.GetType () == TypeManager.char_type)
2065 return (double)convert_value.ToInt32 (nf_provider);
2066 return convert_value.ToDouble (nf_provider);
2069 if (conversionType.Equals (typeof (Int16)))
2070 return (object)(convert_value.ToInt16 (nf_provider));
2071 if (conversionType.Equals (int32_type))
2072 return (object)(convert_value.ToInt32 (nf_provider));
2073 if (conversionType.Equals (int64_type))
2074 return (object)(convert_value.ToInt64 (nf_provider));
2075 if (conversionType.Equals (typeof (SByte)))
2076 return (object)(convert_value.ToSByte (nf_provider));
2078 if (conversionType.Equals (typeof (Single))) {
2079 if (convert_value.GetType () == TypeManager.char_type)
2080 return (float)convert_value.ToInt32 (nf_provider);
2081 return convert_value.ToSingle (nf_provider);
2084 if (conversionType.Equals (typeof (String)))
2085 return (object)(convert_value.ToString (nf_provider));
2086 if (conversionType.Equals (typeof (UInt16)))
2087 return (object)(convert_value.ToUInt16 (nf_provider));
2088 if (conversionType.Equals (typeof (UInt32)))
2089 return (object)(convert_value.ToUInt32 (nf_provider));
2090 if (conversionType.Equals (typeof (UInt64)))
2091 return (object)(convert_value.ToUInt64 (nf_provider));
2092 if (conversionType.Equals (typeof (Object)))
2093 return (object)(value);
2103 // When compiling with -nostdlib and the type is imported from an external assembly
2104 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2106 public static Type TypeToCoreType (Type t)
2108 if (RootContext.StdLib || t.Module != typeof (object).Module)
2111 TypeCode tc = Type.GetTypeCode (t);
2114 case TypeCode.Boolean:
2115 return TypeManager.bool_type;
2117 return TypeManager.byte_type;
2118 case TypeCode.SByte:
2119 return TypeManager.sbyte_type;
2121 return TypeManager.char_type;
2122 case TypeCode.Int16:
2123 return TypeManager.short_type;
2124 case TypeCode.UInt16:
2125 return TypeManager.ushort_type;
2126 case TypeCode.Int32:
2127 return TypeManager.int32_type;
2128 case TypeCode.UInt32:
2129 return TypeManager.uint32_type;
2130 case TypeCode.Int64:
2131 return TypeManager.int64_type;
2132 case TypeCode.UInt64:
2133 return TypeManager.uint64_type;
2134 case TypeCode.Single:
2135 return TypeManager.float_type;
2136 case TypeCode.Double:
2137 return TypeManager.double_type;
2138 case TypeCode.String:
2139 return TypeManager.string_type;
2140 case TypeCode.Decimal:
2141 return TypeManager.decimal_type;
2144 if (t == typeof (void))
2145 return TypeManager.void_type;
2146 if (t == typeof (object))
2147 return TypeManager.object_type;
2148 if (t == typeof (System.Type))
2149 return TypeManager.type_type;
2150 if (t == typeof (System.IntPtr))
2151 return TypeManager.intptr_type;
2152 if (t == typeof (System.UIntPtr))
2153 return TypeManager.uintptr_type;
2156 int dim = t.GetArrayRank ();
2157 t = GetElementType (t);
2158 return t.MakeArrayType (dim);
2161 t = GetElementType (t);
2162 return t.MakeByRefType ();
2165 t = GetElementType (t);
2166 return t.MakePointerType ();
2173 /// Utility function that can be used to probe whether a type
2174 /// is managed or not.
2176 public static bool VerifyUnManaged (Type t, Location loc)
2178 if (IsUnmanagedType (t))
2182 t = GetElementType (t);
2184 Report.SymbolRelatedToPreviousError (t);
2185 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2192 /// Returns the name of the indexer in a given type.
2195 /// The default is not always `Item'. The user can change this behaviour by
2196 /// using the IndexerNameAttribute in the container.
2197 /// For example, the String class indexer is named `Chars' not `Item'
2199 public static string IndexerPropertyName (Type t)
2201 t = DropGenericTypeArguments (t);
2202 if (t is TypeBuilder) {
2203 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2204 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2207 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
2209 System.Attribute attr = System.Attribute.GetCustomAttribute (
2212 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2213 return dma.MemberName;
2217 return TypeContainer.DefaultIndexerName;
2220 static MethodInfo declare_local_method = null;
2222 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2224 if (declare_local_method == null){
2225 declare_local_method = typeof (ILGenerator).GetMethod (
2227 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2229 new Type [] { typeof (Type), typeof (bool)},
2231 if (declare_local_method == null){
2232 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2233 return ig.DeclareLocal (t);
2236 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2239 private static bool IsSignatureEqual (Type a, Type b)
2242 /// Consider the following example (bug #77674):
2244 /// public abstract class A
2246 /// public abstract T Foo<T> ();
2249 /// public abstract class B : A
2251 /// public override U Foo<T> ()
2252 /// { return default (U); }
2255 /// Here, `T' and `U' are method type parameters from different methods
2256 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2258 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2259 /// we need to do a signature based comparision and consider them equal.
2265 if (a.IsGenericParameter && b.IsGenericParameter &&
2266 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2267 return a.GenericParameterPosition == b.GenericParameterPosition;
2271 if (a.IsArray && b.IsArray) {
2272 if (a.GetArrayRank () != b.GetArrayRank ())
2275 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2278 if (a.IsByRef && b.IsByRef)
2279 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2281 if (IsGenericType (a) && IsGenericType (b)) {
2282 if (DropGenericTypeArguments (a) != DropGenericTypeArguments (b))
2285 Type[] aargs = GetTypeArguments (a);
2286 Type[] bargs = GetTypeArguments (b);
2288 if (aargs.Length != bargs.Length)
2291 for (int i = 0; i < aargs.Length; i++) {
2292 if (!IsSignatureEqual (aargs [i], bargs [i]))
2303 // Returns whether the array of memberinfos contains the given method
2305 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
2307 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2309 foreach (MethodBase method in array) {
2310 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
2313 if (method.Name != new_method.Name)
2316 if (method is MethodInfo && new_method is MethodInfo &&
2318 TypeToCoreType (((MethodInfo) method).ReturnType),
2319 TypeToCoreType (((MethodInfo) new_method).ReturnType)))
2322 Type [] old_args = TypeManager.GetParameterData (method).Types;
2323 int old_count = old_args.Length;
2326 if (new_args.Length != old_count)
2329 for (i = 0; i < old_count; i++){
2330 if (!IsSignatureEqual (old_args [i], new_args [i]))
2343 // We copy methods from `new_members' into `target_list' if the signature
2344 // for the method from in the new list does not exist in the target_list
2346 // The name is assumed to be the same.
2348 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2350 if (target_list == null){
2351 target_list = new ArrayList ();
2353 foreach (MemberInfo mi in new_members){
2354 if (mi is MethodBase)
2355 target_list.Add (mi);
2360 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2361 target_list.CopyTo (target_array, 0);
2363 foreach (MemberInfo mi in new_members){
2364 MethodBase new_method = (MethodBase) mi;
2366 if (!ArrayContainsMethod (target_array, new_method, true))
2367 target_list.Add (new_method);
2374 // Tracks the generic parameters.
2376 static PtrHashtable builder_to_type_param;
2378 public static void AddTypeParameter (Type t, TypeParameter tparam)
2380 if (!builder_to_type_param.Contains (t))
2381 builder_to_type_param.Add (t, tparam);
2384 public static TypeParameter LookupTypeParameter (Type t)
2386 return (TypeParameter) builder_to_type_param [t];
2389 // This method always return false for non-generic compiler,
2390 // while Type.IsGenericParameter is returned if it is supported.
2391 public static bool IsGenericParameter (Type type)
2394 return type.IsGenericParameter;
2400 public static int GenericParameterPosition (Type type)
2403 return type.GenericParameterPosition;
2405 throw new InternalErrorException ("should not be called");
2409 public static bool IsGenericType (Type type)
2412 return type.IsGenericType;
2418 public static bool IsGenericTypeDefinition (Type type)
2421 return type.IsGenericTypeDefinition;
2427 public static bool ContainsGenericParameters (Type type)
2430 return type.ContainsGenericParameters;
2436 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2439 if (fi.DeclaringType.IsGenericTypeDefinition ||
2440 !fi.DeclaringType.IsGenericType)
2443 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2444 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2445 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2447 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2448 foreach (FieldInfo f in t.GetFields (bf))
2449 if (f.MetadataToken == fi.MetadataToken)
2456 public static bool IsEqual (Type a, Type b)
2459 // MS BCL returns true even if enum types are different
2460 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2461 return a.FullName == b.FullName;
2463 // Some types are never equal
2464 if (a == TypeManager.null_type || a == InternalType.AnonymousMethod)
2470 if (IsGenericParameter (a) && IsGenericParameter (b)) {
2471 // TODO: needs more testing before cleaning up
2472 //if (a.DeclaringMethod != b.DeclaringMethod &&
2473 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2476 return a.GenericParameterPosition == b.GenericParameterPosition;
2478 throw new NotSupportedException ();
2482 if (a.IsArray && b.IsArray) {
2483 if (a.GetArrayRank () != b.GetArrayRank ())
2485 return IsEqual (GetElementType (a), GetElementType (b));
2488 if (a.IsByRef && b.IsByRef)
2489 return IsEqual (a.GetElementType (), b.GetElementType ());
2491 if (IsGenericType (a) && IsGenericType (b)) {
2492 Type adef = DropGenericTypeArguments (a);
2493 Type bdef = DropGenericTypeArguments (b);
2498 if (adef.IsEnum && bdef.IsEnum)
2501 Type[] aargs = GetTypeArguments (a);
2502 Type[] bargs = GetTypeArguments (b);
2504 if (aargs.Length != bargs.Length)
2507 for (int i = 0; i < aargs.Length; i++) {
2508 if (!IsEqual (aargs [i], bargs [i]))
2518 public static bool IsEqual (Type[] a, Type[] b)
2520 if (a == null || b == null || a.Length != b.Length)
2523 for (int i = 0; i < a.Length; ++i) {
2524 if (a [i] == null || b [i] == null) {
2531 if (!IsEqual (a [i], b [i]))
2538 public static Type DropGenericTypeArguments (Type t)
2541 if (!t.IsGenericType)
2543 // Micro-optimization: a generic typebuilder is always a generic type definition
2544 if (t is TypeBuilder)
2546 return t.GetGenericTypeDefinition ();
2552 public static MethodBase DropGenericMethodArguments (MethodBase m)
2555 if (m.IsGenericMethod)
2556 m = ((MethodInfo) m).GetGenericMethodDefinition ();
2558 Type t = m.DeclaringType;
2559 if (!t.IsGenericType || t.IsGenericTypeDefinition)
2562 t = t.GetGenericTypeDefinition ();
2563 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2564 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2567 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2571 if (m is ConstructorInfo) {
2572 foreach (ConstructorInfo c in t.GetConstructors (bf))
2573 if (c.MetadataToken == m.MetadataToken)
2576 foreach (MethodBase mb in t.GetMethods (bf))
2577 if (mb.MetadataToken == m.MetadataToken)
2585 public static Type[] GetGenericArguments (MethodBase mi)
2588 return mi.GetGenericArguments ();
2590 return Type.EmptyTypes;
2594 public static Type[] GetTypeArguments (Type t)
2597 DeclSpace tc = LookupDeclSpace (t);
2600 return Type.EmptyTypes;
2602 TypeParameter[] tparam = tc.TypeParameters;
2603 Type[] ret = new Type [tparam.Length];
2604 for (int i = 0; i < tparam.Length; i++) {
2605 ret [i] = tparam [i].Type;
2606 if (ret [i] == null)
2607 throw new InternalErrorException ();
2612 return t.GetGenericArguments ();
2614 throw new InternalErrorException ();
2618 public static GenericConstraints GetTypeParameterConstraints (Type t)
2621 if (!t.IsGenericParameter)
2622 throw new InvalidOperationException ();
2624 TypeParameter tparam = LookupTypeParameter (t);
2626 return tparam.GenericConstraints;
2628 return ReflectionConstraints.GetConstraints (t);
2630 throw new InternalErrorException ();
2634 public static bool HasGenericArguments (Type t)
2636 return GetNumberOfTypeArguments (t) > 0;
2639 public static int GetNumberOfTypeArguments (Type t)
2642 if (t.IsGenericParameter)
2644 DeclSpace tc = LookupDeclSpace (t);
2646 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2648 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2655 /// Check whether `type' and `parent' are both instantiations of the same
2656 /// generic type. Note that we do not check the type parameters here.
2658 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2660 int tcount = GetNumberOfTypeArguments (type);
2661 int pcount = GetNumberOfTypeArguments (parent);
2663 if (tcount != pcount)
2666 type = DropGenericTypeArguments (type);
2667 parent = DropGenericTypeArguments (parent);
2669 return type.Equals (parent);
2673 /// Whether `mb' is a generic method definition.
2675 public static bool IsGenericMethodDefinition (MethodBase mb)
2678 if (mb.DeclaringType is TypeBuilder) {
2679 IMethodData method = (IMethodData) builder_to_method [mb];
2683 return method.GenericMethod != null;
2686 return mb.IsGenericMethodDefinition;
2693 /// Whether `mb' is a generic method.
2695 public static bool IsGenericMethod (MethodBase mb)
2698 return mb.IsGenericMethod;
2704 public static bool IsNullableType (Type t)
2707 return generic_nullable_type == DropGenericTypeArguments (t);
2714 #region MemberLookup implementation
2717 // Whether we allow private members in the result (since FindMembers
2718 // uses NonPublic for both protected and private), we need to distinguish.
2721 internal class Closure {
2722 internal bool private_ok;
2724 // Who is invoking us and which type is being queried currently.
2725 internal Type invocation_type;
2726 internal Type qualifier_type;
2728 // The assembly that defines the type is that is calling us
2729 internal Assembly invocation_assembly;
2730 internal IList almost_match;
2732 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2734 if (invocation_type == null)
2737 if (is_static && qualifier_type == null)
2738 // It resolved from a simple name, so it should be visible.
2741 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2744 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2745 if (!IsFamilyAccessible (t, m.DeclaringType))
2748 // Although a derived class can access protected members of its base class
2749 // it cannot do so through an instance of the base class (CS1540).
2750 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2751 if (is_static || qualifier_type == null ||
2752 IsInstantiationOfSameGenericType (t, qualifier_type) ||
2753 IsFamilyAccessible (qualifier_type, t))
2757 if (almost_match != null)
2758 almost_match.Add (m);
2764 // This filter filters by name + whether it is ok to include private
2765 // members in the search
2767 internal bool Filter (MemberInfo m, object filter_criteria)
2770 // Hack: we know that the filter criteria will always be in the
2771 // `closure' // fields.
2774 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2777 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2778 (invocation_type != null) &&
2779 IsPrivateAccessible (m.DeclaringType, invocation_type))
2783 // Ugly: we need to find out the type of `m', and depending
2784 // on this, tell whether we accept or not
2786 if (m is MethodBase){
2787 MethodBase mb = (MethodBase) m;
2788 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2790 if (ma == MethodAttributes.Public)
2793 if (ma == MethodAttributes.PrivateScope)
2796 if (ma == MethodAttributes.Private)
2797 return private_ok ||
2798 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2799 IsNestedChildOf (invocation_type, m.DeclaringType);
2801 if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) {
2802 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2805 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2809 // Family, FamORAssem or FamANDAssem
2810 return CheckValidFamilyAccess (mb.IsStatic, m);
2813 if (m is FieldInfo){
2814 FieldInfo fi = (FieldInfo) m;
2815 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2817 if (fa == FieldAttributes.Public)
2820 if (fa == FieldAttributes.PrivateScope)
2823 if (fa == FieldAttributes.Private)
2824 return private_ok ||
2825 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2826 IsNestedChildOf (invocation_type, m.DeclaringType);
2828 if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) {
2829 if ((fa == FieldAttributes.Assembly) ||
2830 (fa == FieldAttributes.FamORAssem))
2833 if ((fa == FieldAttributes.Assembly) ||
2834 (fa == FieldAttributes.FamANDAssem))
2838 // Family, FamORAssem or FamANDAssem
2839 return CheckValidFamilyAccess (fi.IsStatic, m);
2843 // EventInfos and PropertyInfos, return true because they lack
2844 // permission information, so we need to check later on the methods.
2850 static Closure closure;
2851 static MemberFilter FilterWithClosure_delegate;
2854 // Looks up a member called `name' in the `queried_type'. This lookup
2855 // is done by code that is contained in the definition for `invocation_type'
2856 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2858 // `invocation_type' is used to check whether we're allowed to access the requested
2859 // member wrt its protection level.
2861 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2862 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2863 // is B and qualifier_type is A). This is used to do the CS1540 check.
2865 // When resolving a SimpleName, `qualifier_type' is null.
2867 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2868 // the same than `queried_type' - except when we're being called from BaseAccess;
2869 // in this case, `invocation_type' is the current type and `queried_type' the base
2870 // type, so this'd normally trigger a CS1540.
2872 // The binding flags are `bf' and the kind of members being looked up are `mt'
2874 // The return value always includes private members which code in `invocation_type'
2875 // is allowed to access (using the specified `qualifier_type' if given); only use
2876 // BindingFlags.NonPublic to bypass the permission check.
2878 // The 'almost_match' argument is used for reporting error CS1540.
2880 // Returns an array of a single element for everything but Methods/Constructors
2881 // that might return multiple matches.
2883 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2884 Type queried_type, MemberTypes mt,
2885 BindingFlags original_bf, string name, IList almost_match)
2887 Timer.StartTimer (TimerType.MemberLookup);
2889 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2890 queried_type, mt, original_bf, name, almost_match);
2892 Timer.StopTimer (TimerType.MemberLookup);
2897 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2898 Type queried_type, MemberTypes mt,
2899 BindingFlags original_bf, string name, IList almost_match)
2901 BindingFlags bf = original_bf;
2903 ArrayList method_list = null;
2904 Type current_type = queried_type;
2905 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2906 bool skip_iface_check = true, used_cache = false;
2907 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
2909 closure.invocation_type = invocation_type;
2910 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2911 closure.qualifier_type = qualifier_type;
2912 closure.almost_match = almost_match;
2914 // This is from the first time we find a method
2915 // in most cases, we do not actually find a method in the base class
2916 // so we can just ignore it, and save the arraylist allocation
2917 MemberInfo [] first_members_list = null;
2918 bool use_first_members_list = false;
2924 // `NonPublic' is lame, because it includes both protected and
2925 // private methods, so we need to control this behavior by
2926 // explicitly tracking if a private method is ok or not.
2928 // The possible cases are:
2929 // public, private and protected (internal does not come into the
2932 if ((invocation_type != null) &&
2933 ((invocation_type == current_type) ||
2934 IsNestedChildOf (invocation_type, current_type)) ||
2936 bf = original_bf | BindingFlags.NonPublic;
2940 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2942 Timer.StopTimer (TimerType.MemberLookup);
2944 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2946 Timer.StartTimer (TimerType.MemberLookup);
2949 // When queried for an interface type, the cache will automatically check all
2950 // inherited members, so we don't need to do this here. However, this only
2951 // works if we already used the cache in the first iteration of this loop.
2953 // If we used the cache in any further iteration, we can still terminate the
2954 // loop since the cache always looks in all base classes.
2960 skip_iface_check = false;
2962 if (current_type == TypeManager.object_type)
2965 current_type = current_type.BaseType;
2968 // This happens with interfaces, they have a null
2969 // basetype. Look members up in the Object class.
2971 if (current_type == null) {
2972 current_type = TypeManager.object_type;
2977 if (list.Length == 0)
2981 // Events and types are returned by both `static' and `instance'
2982 // searches, which means that our above FindMembers will
2983 // return two copies of the same.
2985 if (list.Length == 1 && !(list [0] is MethodBase)){
2990 // Multiple properties: we query those just to find out the indexer
2993 if (list [0] is PropertyInfo)
2997 // We found an event: the cache lookup returns both the event and
2998 // its private field.
3000 if (list [0] is EventInfo) {
3001 if ((list.Length == 2) && (list [1] is FieldInfo))
3002 return new MemberInfo [] { list [0] };
3008 // We found methods, turn the search into "method scan"
3012 if (first_members_list != null) {
3013 if (use_first_members_list) {
3014 method_list = CopyNewMethods (method_list, first_members_list);
3015 use_first_members_list = false;
3018 method_list = CopyNewMethods (method_list, list);
3020 first_members_list = list;
3021 use_first_members_list = true;
3022 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3024 } while (searching);
3026 if (use_first_members_list)
3027 return first_members_list;
3029 if (method_list != null && method_list.Count > 0) {
3030 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3033 // This happens if we already used the cache in the first iteration, in this case
3034 // the cache already looked in all interfaces.
3036 if (skip_iface_check)
3040 // Interfaces do not list members they inherit, so we have to
3043 if (!queried_type.IsInterface)
3046 if (queried_type.IsArray)
3047 queried_type = TypeManager.array_type;
3049 Type [] ifaces = GetInterfaces (queried_type);
3053 foreach (Type itype in ifaces){
3056 x = MemberLookup (null, null, itype, mt, bf, name, null);
3064 const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3065 BindingFlags.Static | BindingFlags.Instance |
3066 BindingFlags.DeclaredOnly;
3068 // Currently is designed to work with external types only
3069 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3071 if (!mb.IsSpecialName)
3074 string name = mb.Name;
3075 if (name.Length < 5)
3078 if (name [3] != '_')
3081 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3082 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3083 Type.FilterName, name.Substring (4));
3088 // This can happen when property is indexer (it can have same name but different parameters)
3089 foreach (PropertyInfo p in pi) {
3090 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3091 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3100 // Currently is designed to work with external types only
3101 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3103 if (!mb.IsSpecialName)
3106 string name = mb.Name;
3107 if (name.Length < 5)
3110 if (name.StartsWith ("add_"))
3111 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3113 if (name.StartsWith ("remove_"))
3114 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3119 // Tests whether external method is really special
3120 public static bool IsSpecialMethod (MethodBase mb)
3122 if (!mb.IsSpecialName)
3125 IMethodData md = TypeManager.GetMethod (mb);
3127 return (md is AbstractPropertyEventMethod || md is Operator);
3129 PropertyInfo pi = GetPropertyFromAccessor (mb);
3131 return IsValidProperty (pi);
3133 if (GetEventFromAccessor (mb) != null)
3136 string name = mb.Name;
3137 if (name.StartsWith ("op_"))
3138 return Operator.GetName (name) != null;
3143 // Tests whether imported property is valid C# property.
3144 // TODO: It seems to me that we should do a lot of sanity tests before
3145 // we accept property as C# property
3146 static bool IsValidProperty (PropertyInfo pi)
3148 MethodInfo get_method = pi.GetGetMethod (true);
3149 MethodInfo set_method = pi.GetSetMethod (true);
3152 if (get_method != null && set_method != null) {
3153 g_count = get_method.GetParameters ().Length;
3154 s_count = set_method.GetParameters ().Length;
3155 if (g_count + 1 != s_count)
3157 } else if (get_method != null) {
3158 g_count = get_method.GetParameters ().Length;
3159 } else if (set_method != null) {
3160 s_count = set_method.GetParameters ().Length;
3164 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3166 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
3167 if ((s_count > 1 || g_count > 0) && pa.IsDefined) {
3168 object[] o = pi.DeclaringType.GetCustomAttributes (pa.Type, false);
3172 DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
3173 if (dma.MemberName != pi.Name)
3175 if (get_method != null && "get_" + dma.MemberName != get_method.Name)
3177 if (set_method != null && "set_" + dma.MemberName != set_method.Name)
3190 public static readonly Type AnonymousMethod = typeof (AnonymousMethodBody);
3191 public static readonly Type Arglist = typeof (ArglistAccess);
3192 public static readonly Type Dynamic = new DynamicType ();
3193 public static readonly Type MethodGroup = typeof (MethodGroupExpr);
3197 /// There is exactly one instance of this class per type.
3199 public sealed class TypeHandle : IMemberContainer {
3200 public readonly IMemberContainer BaseType;
3202 readonly int id = ++next_id;
3203 static int next_id = 0;
3205 static TypeHandle ()
3211 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3212 /// a TypeHandle yet, a new instance of it is created. This static method
3213 /// ensures that we'll only have one TypeHandle instance per type.
3215 private static TypeHandle GetTypeHandle (Type t)
3217 TypeHandle handle = (TypeHandle) type_hash [t];
3221 handle = new TypeHandle (t);
3222 type_hash.Add (t, handle);
3226 public static MemberCache GetMemberCache (Type t)
3228 return GetTypeHandle (t).MemberCache;
3231 public static void CleanUp ()
3236 public static void Reset ()
3238 type_hash = new PtrHashtable ();
3242 /// Returns the TypeHandle for TypeManager.object_type.
3244 public static IMemberContainer ObjectType {
3246 if (object_type != null)
3249 object_type = GetTypeHandle (TypeManager.object_type);
3256 /// Returns the TypeHandle for TypeManager.array_type.
3258 public static TypeHandle ArrayType {
3260 if (array_type != null)
3263 array_type = GetTypeHandle (TypeManager.array_type);
3269 private static PtrHashtable type_hash;
3271 private static TypeHandle object_type = null;
3272 private static TypeHandle array_type = null;
3275 private string full_name;
3276 private bool is_interface;
3277 private MemberCache member_cache;
3278 private MemberCache base_cache;
3280 private TypeHandle (Type type)
3283 full_name = type.FullName != null ? type.FullName : type.Name;
3284 if (type.BaseType != null) {
3285 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3286 BaseType = base_cache.Container;
3287 } else if (type.IsInterface)
3288 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3289 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3290 this.member_cache = new MemberCache (this);
3293 // IMemberContainer methods
3295 public string Name {
3307 public MemberCache BaseCache {
3313 public bool IsInterface {
3315 return is_interface;
3319 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3321 MemberInfo [] members;
3323 if (type is GenericTypeParameterBuilder)
3324 return MemberList.Empty;
3327 type = TypeManager.DropGenericTypeArguments (type);
3329 if (mt == MemberTypes.Event)
3330 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3332 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3335 if (members.Length == 0)
3336 return MemberList.Empty;
3338 Array.Reverse (members);
3339 return new MemberList (members);
3342 // IMemberFinder methods
3344 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3345 MemberFilter filter, object criteria)
3347 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3350 public MemberCache MemberCache {
3352 return member_cache;
3356 public override string ToString ()
3358 if (BaseType != null)
3359 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3361 return "TypeHandle (" + id + "," + Name + ")";