2009-11-24 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / typemanager.cs
blob050971ec40e052026fa9a3f1116faaa0bb4883db
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
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
21 using System;
22 using System.IO;
23 using System.Globalization;
24 using System.Collections;
25 using System.Reflection;
26 using System.Reflection.Emit;
27 using System.Text;
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;
79 //
80 // C# 2.0
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;
90 // C# 3.0
92 static internal Type expression_type;
93 public static Type parameter_expression_type;
94 public static Type fieldinfo_type;
95 public static Type methodinfo_type;
96 public static Type ctorinfo_type;
99 // C# 4.0
101 public static Type call_site_type;
102 public static Type generic_call_site_type;
103 public static TypeExpr binder_type;
104 public static Type binder_flags;
107 // Expressions representing the internal types. Used during declaration
108 // definition.
110 static public TypeExpr system_object_expr, system_string_expr;
111 static public TypeExpr system_boolean_expr, system_decimal_expr;
112 static public TypeExpr system_single_expr, system_double_expr;
113 static public TypeExpr system_sbyte_expr, system_byte_expr;
114 static public TypeExpr system_int16_expr, system_uint16_expr;
115 static public TypeExpr system_int32_expr, system_uint32_expr;
116 static public TypeExpr system_int64_expr, system_uint64_expr;
117 static public TypeExpr system_char_expr, system_void_expr;
118 static public TypeExpr system_valuetype_expr;
119 static public TypeExpr system_intptr_expr;
120 public static TypeExpr expression_type_expr;
124 // These methods are called by code generated by the compiler
126 static public FieldInfo string_empty;
127 static public MethodInfo system_type_get_type_from_handle;
128 static public MethodInfo bool_movenext_void;
129 static public MethodInfo void_dispose_void;
130 static public MethodInfo void_monitor_enter_object;
131 static public MethodInfo void_monitor_exit_object;
132 static public MethodInfo void_initializearray_array_fieldhandle;
133 static public MethodInfo delegate_combine_delegate_delegate;
134 static public MethodInfo delegate_remove_delegate_delegate;
135 static public PropertyInfo int_get_offset_to_string_data;
136 static public MethodInfo int_interlocked_compare_exchange;
137 static public PropertyInfo ienumerator_getcurrent;
138 public static MethodInfo methodbase_get_type_from_handle;
139 public static MethodInfo methodbase_get_type_from_handle_generic;
140 public static MethodInfo fieldinfo_get_field_from_handle;
141 public static MethodInfo fieldinfo_get_field_from_handle_generic;
142 static public MethodInfo activator_create_instance;
145 // The constructors.
147 static public ConstructorInfo void_decimal_ctor_five_args;
148 static public ConstructorInfo void_decimal_ctor_int_arg;
149 public static ConstructorInfo void_decimal_ctor_long_arg;
151 static PtrHashtable builder_to_declspace;
153 static PtrHashtable builder_to_member_cache;
155 // <remarks>
156 // Tracks the interfaces implemented by typebuilders. We only
157 // enter those who do implement or or more interfaces
158 // </remarks>
159 static PtrHashtable builder_to_ifaces;
161 // <remarks>
162 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
163 // <remarks>
164 static Hashtable method_params;
166 // <remarks>
167 // A hash table from override methods to their base virtual method.
168 // <remarks>
169 static Hashtable method_overrides;
171 // <remarks>
172 // Keeps track of methods
173 // </remarks>
175 static Hashtable builder_to_method;
177 // <remarks>
178 // Contains all public types from referenced assemblies.
179 // This member is used only if CLS Compliance verification is required.
180 // </remarks>
181 public static Hashtable AllClsTopLevelTypes;
183 static Hashtable fieldbuilders_to_fields;
184 static Hashtable propertybuilder_to_property;
185 static Hashtable fields;
186 static Hashtable events;
187 static PtrHashtable assembly_internals_vis_attrs;
189 public static void CleanUp ()
191 // Lets get everything clean so that we can collect before generating code
192 builder_to_declspace = null;
193 builder_to_member_cache = null;
194 builder_to_ifaces = null;
195 builder_to_type_param = null;
196 method_params = null;
197 builder_to_method = null;
199 fields = null;
200 events = null;
201 type_hash = null;
202 propertybuilder_to_property = null;
204 TypeHandle.CleanUp ();
208 // These are expressions that represent some of the internal data types, used
209 // elsewhere
211 static void InitExpressionTypes ()
213 system_object_expr = new TypeLookupExpression ("System", "Object");
214 system_string_expr = new TypeLookupExpression ("System", "String");
215 system_boolean_expr = new TypeLookupExpression ("System", "Boolean");
216 system_decimal_expr = new TypeLookupExpression ("System", "Decimal");
217 system_single_expr = new TypeLookupExpression ("System", "Single");
218 system_double_expr = new TypeLookupExpression ("System", "Double");
219 system_sbyte_expr = new TypeLookupExpression ("System", "SByte");
220 system_byte_expr = new TypeLookupExpression ("System", "Byte");
221 system_int16_expr = new TypeLookupExpression ("System", "Int16");
222 system_uint16_expr = new TypeLookupExpression ("System", "UInt16");
223 system_int32_expr = new TypeLookupExpression ("System", "Int32");
224 system_uint32_expr = new TypeLookupExpression ("System", "UInt32");
225 system_int64_expr = new TypeLookupExpression ("System", "Int64");
226 system_uint64_expr = new TypeLookupExpression ("System", "UInt64");
227 system_char_expr = new TypeLookupExpression ("System", "Char");
228 system_void_expr = new TypeLookupExpression ("System", "Void");
229 system_valuetype_expr = new TypeLookupExpression ("System", "ValueType");
230 system_intptr_expr = new TypeLookupExpression ("System", "IntPtr");
233 static TypeManager ()
235 Reset ();
238 static public void Reset ()
240 object_type = null;
242 InitExpressionTypes ();
244 builder_to_declspace = new PtrHashtable ();
245 builder_to_member_cache = new PtrHashtable ();
246 builder_to_method = new PtrHashtable ();
247 builder_to_type_param = new PtrHashtable ();
248 method_params = new PtrHashtable ();
249 method_overrides = new PtrHashtable ();
250 builder_to_ifaces = new PtrHashtable ();
252 fieldbuilders_to_fields = new Hashtable ();
253 propertybuilder_to_property = new Hashtable ();
254 fields = new Hashtable ();
255 type_hash = new DoubleHash ();
256 assembly_internals_vis_attrs = new PtrHashtable ();
257 iface_cache = new PtrHashtable ();
259 closure = new Closure ();
260 FilterWithClosure_delegate = new MemberFilter (closure.Filter);
262 // TODO: I am really bored by all this static stuff
263 system_type_get_type_from_handle =
264 bool_movenext_void =
265 void_dispose_void =
266 void_monitor_enter_object =
267 void_monitor_exit_object =
268 void_initializearray_array_fieldhandle =
269 delegate_combine_delegate_delegate =
270 delegate_remove_delegate_delegate =
271 int_interlocked_compare_exchange =
272 methodbase_get_type_from_handle =
273 methodbase_get_type_from_handle_generic =
274 fieldinfo_get_field_from_handle =
275 fieldinfo_get_field_from_handle_generic =
276 activator_create_instance = null;
278 int_get_offset_to_string_data =
279 ienumerator_getcurrent = null;
281 void_decimal_ctor_five_args =
282 void_decimal_ctor_int_arg =
283 void_decimal_ctor_long_arg = null;
285 isvolatile_type = null;
287 call_site_type =
288 generic_call_site_type =
289 binder_flags = null;
291 binder_type = null;
293 // to uncover regressions
294 AllClsTopLevelTypes = null;
297 public static void AddUserType (DeclSpace ds)
299 builder_to_declspace.Add (ds.TypeBuilder, ds);
303 // This entry point is used by types that we define under the covers
305 public static void RegisterBuilder (Type tb, Type [] ifaces)
307 if (ifaces != null)
308 builder_to_ifaces [tb] = ifaces;
311 public static void AddMethod (MethodBase builder, IMethodData method)
313 builder_to_method.Add (builder, method);
314 method_params.Add (builder, method.ParameterInfo);
317 public static IMethodData GetMethod (MethodBase builder)
319 return (IMethodData) builder_to_method [builder];
322 /// <summary>
323 /// Returns the DeclSpace whose Type is `t' or null if there is no
324 /// DeclSpace for `t' (ie, the Type comes from a library)
325 /// </summary>
326 public static DeclSpace LookupDeclSpace (Type t)
328 return builder_to_declspace [t] as DeclSpace;
331 /// <summary>
332 /// Returns the TypeContainer whose Type is `t' or null if there is no
333 /// TypeContainer for `t' (ie, the Type comes from a library)
334 /// </summary>
335 public static TypeContainer LookupTypeContainer (Type t)
337 return builder_to_declspace [t] as TypeContainer;
340 public static MemberCache LookupMemberCache (Type t)
342 if (IsBeingCompiled (t)) {
343 DeclSpace container = (DeclSpace)builder_to_declspace [t];
344 if (container != null)
345 return container.MemberCache;
348 if (t is GenericTypeParameterBuilder) {
349 TypeParameter container = builder_to_type_param [t] as TypeParameter;
351 if (container != null)
352 return container.MemberCache;
355 return TypeHandle.GetMemberCache (t);
358 public static MemberCache LookupBaseInterfacesCache (Type t)
360 Type [] ifaces = GetInterfaces (t);
362 if (ifaces != null && ifaces.Length == 1)
363 return LookupMemberCache (ifaces [0]);
365 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
366 MemberCache cache = builder_to_member_cache [t] as MemberCache;
367 if (cache != null)
368 return cache;
370 cache = new MemberCache (ifaces);
371 builder_to_member_cache.Add (t, cache);
372 return cache;
375 public static TypeContainer LookupInterface (Type t)
377 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
378 if ((tc == null) || (tc.Kind != Kind.Interface))
379 return null;
381 return tc;
384 public static Delegate LookupDelegate (Type t)
386 return builder_to_declspace [t] as Delegate;
389 public static Class LookupClass (Type t)
391 return (Class) builder_to_declspace [t];
395 // We use this hash for multiple kinds of constructed types:
397 // (T, "&") Given T, get T &
398 // (T, "*") Given T, get T *
399 // (T, "[]") Given T and a array dimension, get T []
400 // (T, X) Given a type T and a simple name X, get the type T+X
402 // Accessibility tests, if necessary, should be done by the user
404 static DoubleHash type_hash = new DoubleHash ();
407 // Gets the reference to T version of the Type (T&)
409 public static Type GetReferenceType (Type t)
411 return t.MakeByRefType ();
415 // Gets the pointer to T version of the Type (T*)
417 public static Type GetPointerType (Type t)
419 return GetConstructedType (t, "*");
422 public static Type GetConstructedType (Type t, string dim)
424 object ret = null;
425 if (type_hash.Lookup (t, dim, out ret))
426 return (Type) ret;
428 if (IsDynamicType (t)) {
429 ret = new DynamicArrayType (dim.Length - 1);
430 type_hash.Insert (t, dim, ret);
431 return (Type) ret;
434 ret = t.Module.GetType (t.ToString () + dim);
435 if (ret != null) {
436 type_hash.Insert (t, dim, ret);
437 return (Type) ret;
440 if (dim == "&") {
441 ret = GetReferenceType (t);
442 type_hash.Insert (t, dim, ret);
443 return (Type) ret;
446 if (t.IsGenericParameter || t.IsGenericType) {
447 int pos = 0;
448 Type result = t;
449 while ((pos < dim.Length) && (dim [pos] == '[')) {
450 pos++;
452 if (dim [pos] == ']') {
453 result = result.MakeArrayType ();
454 pos++;
456 if (pos < dim.Length)
457 continue;
459 type_hash.Insert (t, dim, result);
460 return result;
463 int rank = 0;
464 while (dim [pos] == ',') {
465 pos++; rank++;
468 if ((dim [pos] != ']') || (pos != dim.Length-1))
469 break;
471 result = result.MakeArrayType (rank + 1);
472 type_hash.Insert (t, dim, result);
473 return result;
477 type_hash.Insert (t, dim, null);
478 return null;
481 public static Type GetNestedType (Type t, string name)
483 object ret = null;
484 if (!type_hash.Lookup (t, name, out ret)) {
485 ret = t.GetNestedType (name,
486 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
487 type_hash.Insert (t, name, ret);
489 return (Type) ret;
492 /// <summary>
493 /// Fills static table with exported types from all referenced assemblies.
494 /// This information is required for CLS Compliance tests.
495 /// </summary>
496 public static void LoadAllImportedTypes ()
498 AllClsTopLevelTypes = new Hashtable (1500);
499 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
500 foreach (Type t in a.GetExportedTypes ()) {
501 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
506 /// <summary>
507 /// Returns the C# name of a type if possible, or the full type name otherwise
508 /// </summary>
509 static public string CSharpName (Type t)
511 if (t == null_type)
512 return "null";
514 if (t == typeof (ArglistAccess))
515 return "__arglist";
517 if (t == typeof (AnonymousMethodBody))
518 return "anonymous method";
520 if (t == typeof (MethodGroupExpr))
521 return "method group";
523 if (IsDynamicType (t))
524 return "dynamic";
526 if (t == null)
527 return "internal error";
529 return CSharpName (GetFullName (t), t);
532 static readonly char [] elements = new char [] { '*', '[' };
534 public static string CSharpName (string name, Type type)
536 if (name.Length > 10) {
537 string s;
538 switch (name) {
539 case "System.Int32": s = "int"; break;
540 case "System.Int64": s = "long"; break;
541 case "System.String": s = "string"; break;
542 case "System.Boolean": s = "bool"; break;
543 case "System.Void": s = "void"; break;
544 case "System.Object": s = "object"; break;
545 case "System.UInt32": s = "uint"; break;
546 case "System.Int16": s = "short"; break;
547 case "System.UInt16": s = "ushort"; break;
548 case "System.UInt64": s = "ulong"; break;
549 case "System.Single": s = "float"; break;
550 case "System.Double": s = "double"; break;
551 case "System.Decimal": s = "decimal"; break;
552 case "System.Char": s = "char"; break;
553 case "System.Byte": s = "byte"; break;
554 case "System.SByte": s = "sbyte"; break;
555 default: s = null; break;
558 if (s != null) {
560 // Predefined names can come from mscorlib only
562 if (type == null || type.Module.Name == "mscorlib.dll" || !RootContext.StdLib)
563 return s;
565 return name;
568 if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
569 return AnonymousTypeClass.SignatureForError;
571 int idx = name.IndexOfAny (elements, 10);
572 if (idx > 0)
573 return CSharpName (name.Substring (0, idx), type) + name.Substring (idx);
576 return name.Replace ('+', '.');
579 static public string CSharpName (Type[] types)
581 if (types.Length == 0)
582 return string.Empty;
584 StringBuilder sb = new StringBuilder ();
585 for (int i = 0; i < types.Length; ++i) {
586 if (i > 0)
587 sb.Append (", ");
589 sb.Append (CSharpName (types [i]));
591 return sb.ToString ();
594 /// <summary>
595 /// Returns the signature of the method with full namespace classification
596 /// </summary>
597 static public string GetFullNameSignature (MemberInfo mi)
599 PropertyInfo pi = mi as PropertyInfo;
600 if (pi != null) {
601 MethodBase pmi = pi.GetGetMethod (true);
602 if (pmi == null)
603 pmi = pi.GetSetMethod (true);
604 if (GetParameterData (pmi).Count > 0)
605 mi = pmi;
607 return (mi is MethodBase)
608 ? CSharpSignature (mi as MethodBase)
609 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
612 private static int GetFullName (Type t, StringBuilder sb)
614 int pos = 0;
616 if (!t.IsGenericType) {
617 sb.Append (t.FullName);
618 return 0;
621 if (t.DeclaringType != null) {
622 pos = GetFullName (t.DeclaringType, sb);
623 sb.Append ('.');
624 } else if (t.Namespace != null && t.Namespace.Length != 0) {
625 sb.Append (t.Namespace);
626 sb.Append ('.');
628 sb.Append (RemoveGenericArity (t.Name));
630 Type[] this_args = GetTypeArguments (t);
632 if (this_args.Length < pos)
633 throw new InternalErrorException (
634 "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
635 if (this_args.Length == pos)
636 return pos;
638 sb.Append ('<');
639 for (;;) {
640 sb.Append (CSharpName (this_args [pos++]));
641 if (pos == this_args.Length)
642 break;
643 sb.Append (',');
645 sb.Append ('>');
646 return pos;
649 static string GetFullName (Type t)
651 if (t.IsArray) {
652 string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
653 return GetFullName (GetElementType (t)) + dimension;
656 if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
657 t = TypeToCoreType (GetTypeArguments (t)[0]);
658 return CSharpName (t) + "?";
661 if (t.IsGenericParameter)
662 return t.Name;
663 if (!t.IsGenericType)
664 return t.FullName;
666 StringBuilder sb = new StringBuilder ();
667 int pos = GetFullName (t, sb);
668 if (pos <= 0)
669 throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
670 return sb.ToString ();
673 public static string RemoveGenericArity (string from)
675 int i = from.IndexOf ('`');
676 if (i > 0)
677 return from.Substring (0, i);
678 return from;
681 /// <summary>
682 /// When we need to report accessors as well
683 /// </summary>
684 static public string CSharpSignature (MethodBase mb)
686 return CSharpSignature (mb, false);
689 /// <summary>
690 /// Returns the signature of the method
691 /// </summary>
692 static public string CSharpSignature (MethodBase mb, bool show_accessor)
694 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
695 sig.Append ('.');
697 AParametersCollection iparams = GetParameterData (mb);
698 string parameters = iparams.GetSignatureForError ();
699 int accessor_end = 0;
701 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
702 string op_name = Operator.GetName (mb.Name);
703 if (op_name != null) {
704 if (op_name == "explicit" || op_name == "implicit") {
705 sig.Append (op_name);
706 sig.Append (" operator ");
707 sig.Append (CSharpName (((MethodInfo)mb).ReturnType));
708 } else {
709 sig.Append ("operator ");
710 sig.Append (op_name);
712 sig.Append (parameters);
713 return sig.ToString ();
716 bool is_getter = mb.Name.StartsWith ("get_");
717 bool is_setter = mb.Name.StartsWith ("set_");
718 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
719 accessor_end = 3;
720 } else if (mb.Name.StartsWith ("remove_")) {
721 accessor_end = 6;
724 // Is indexer
725 if (iparams.Count > (is_getter ? 0 : 1)) {
726 sig.Append ("this[");
727 if (is_getter)
728 sig.Append (parameters.Substring (1, parameters.Length - 2));
729 else
730 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
731 sig.Append (']');
732 } else {
733 sig.Append (mb.Name.Substring (accessor_end + 1));
735 } else {
736 if (mb.Name == ".ctor")
737 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
738 else {
739 sig.Append (mb.Name);
741 if (IsGenericMethod (mb)) {
742 Type[] args = GetGenericArguments (mb);
743 sig.Append ('<');
744 for (int i = 0; i < args.Length; i++) {
745 if (i > 0)
746 sig.Append (',');
747 sig.Append (CSharpName (args [i]));
749 sig.Append ('>');
753 sig.Append (parameters);
756 if (show_accessor && accessor_end > 0) {
757 sig.Append ('.');
758 sig.Append (mb.Name.Substring (0, accessor_end));
761 return sig.ToString ();
764 public static string GetMethodName (MethodInfo m)
766 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
767 return m.Name;
769 return MemberName.MakeName (m.Name, TypeManager.GetGenericArguments (m).Length);
772 static public string CSharpSignature (EventInfo ei)
774 return CSharpName (ei.DeclaringType) + "." + ei.Name;
778 // Looks up a type, and aborts if it is not found. This is used
779 // by predefined types required by the compiler
781 public static Type CoreLookupType (CompilerContext ctx, string ns_name, string name, Kind type_kind, bool required)
783 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
784 Expression expr = ns.Lookup (ctx, name, Location.Null);
786 if (expr == null) {
787 if (required) {
788 ctx.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
789 ns_name, name);
791 return null;
794 Type t = expr.Type;
795 if (RootContext.StdLib || t == null || !required)
796 return t;
798 // TODO: All predefined imported types have to have correct signature
799 if (!IsBeingCompiled (t))
800 return t;
802 DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
803 if (ds is Delegate) {
804 if (type_kind == Kind.Delegate)
805 return t;
806 } else {
807 TypeContainer tc = (TypeContainer)ds;
808 if (tc.Kind == type_kind)
809 return t;
812 ctx.Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
813 ns_name, name);
814 return null;
817 static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
819 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
821 MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
822 if (members != null) {
823 for (int i = 0; i < members.Length; ++i) {
824 MemberInfo member = members [i];
825 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
826 MethodBase mb = member as MethodBase;
827 if (mb == null)
828 continue;
830 AParametersCollection pd = TypeManager.GetParameterData (mb);
831 if (IsEqual (pd.Types, args))
832 return member;
834 if (mt == MemberTypes.Field) {
835 FieldInfo fi = member as FieldInfo;
836 if (fi == null)
837 continue;
839 if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
840 continue;
842 return member;
845 if (mt == MemberTypes.Property) {
846 PropertyInfo pi = member as PropertyInfo;
847 if (pi == null)
848 continue;
850 if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
851 continue;
853 return member;
858 string method_args = null;
859 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
860 method_args = "(" + TypeManager.CSharpName (args) + ")";
862 RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
863 TypeManager.CSharpName (t), name, method_args);
865 return null;
869 // Returns the ConstructorInfo for "args"
871 public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
873 return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
877 // Returns the MethodInfo for a method named `name' defined
878 // in type `t' which takes arguments of types `args'
880 public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
882 return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
885 public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
887 return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
890 public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
892 return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
895 /// <remarks>
896 /// The types have to be initialized after the initial
897 /// population of the type has happened (for example, to
898 /// bootstrap the corlib.dll
899 /// </remarks>
900 public static bool InitCoreTypes (CompilerContext ctx)
902 object_type = CoreLookupType (ctx, "System", "Object", Kind.Class, true);
903 system_object_expr.Type = object_type;
904 value_type = CoreLookupType (ctx, "System", "ValueType", Kind.Class, true);
905 system_valuetype_expr.Type = value_type;
906 attribute_type = CoreLookupType (ctx, "System", "Attribute", Kind.Class, true);
908 int32_type = CoreLookupType (ctx, "System", "Int32", Kind.Struct, true);
909 system_int32_expr.Type = int32_type;
910 int64_type = CoreLookupType (ctx, "System", "Int64", Kind.Struct, true);
911 system_int64_expr.Type = int64_type;
912 uint32_type = CoreLookupType (ctx, "System", "UInt32", Kind.Struct, true);
913 system_uint32_expr.Type = uint32_type;
914 uint64_type = CoreLookupType (ctx, "System", "UInt64", Kind.Struct, true);
915 system_uint64_expr.Type = uint64_type;
916 byte_type = CoreLookupType (ctx, "System", "Byte", Kind.Struct, true);
917 system_byte_expr.Type = byte_type;
918 sbyte_type = CoreLookupType (ctx, "System", "SByte", Kind.Struct, true);
919 system_sbyte_expr.Type = sbyte_type;
920 short_type = CoreLookupType (ctx, "System", "Int16", Kind.Struct, true);
921 system_int16_expr.Type = short_type;
922 ushort_type = CoreLookupType (ctx, "System", "UInt16", Kind.Struct, true);
923 system_uint16_expr.Type = ushort_type;
925 ienumerator_type = CoreLookupType (ctx, "System.Collections", "IEnumerator", Kind.Interface, true);
926 ienumerable_type = CoreLookupType (ctx, "System.Collections", "IEnumerable", Kind.Interface, true);
927 idisposable_type = CoreLookupType (ctx, "System", "IDisposable", Kind.Interface, true);
929 // HACK: DefineType immediately resolves iterators (very wrong)
930 generic_ienumerator_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
932 char_type = CoreLookupType (ctx, "System", "Char", Kind.Struct, true);
933 system_char_expr.Type = char_type;
934 string_type = CoreLookupType (ctx, "System", "String", Kind.Class, true);
935 system_string_expr.Type = string_type;
936 float_type = CoreLookupType (ctx, "System", "Single", Kind.Struct, true);
937 system_single_expr.Type = float_type;
938 double_type = CoreLookupType (ctx, "System", "Double", Kind.Struct, true);
939 system_double_expr.Type = double_type;
940 decimal_type = CoreLookupType (ctx, "System", "Decimal", Kind.Struct, true);
941 system_decimal_expr.Type = decimal_type;
942 bool_type = CoreLookupType (ctx, "System", "Boolean", Kind.Struct, true);
943 system_boolean_expr.Type = bool_type;
944 intptr_type = CoreLookupType (ctx, "System", "IntPtr", Kind.Struct, true);
945 system_intptr_expr.Type = intptr_type;
946 uintptr_type = CoreLookupType (ctx, "System", "UIntPtr", Kind.Struct, true);
948 multicast_delegate_type = CoreLookupType (ctx, "System", "MulticastDelegate", Kind.Class, true);
949 delegate_type = CoreLookupType (ctx, "System", "Delegate", Kind.Class, true);
951 enum_type = CoreLookupType (ctx, "System", "Enum", Kind.Class, true);
952 array_type = CoreLookupType (ctx, "System", "Array", Kind.Class, true);
953 void_type = CoreLookupType (ctx, "System", "Void", Kind.Struct, true);
954 system_void_expr.Type = void_type;
955 type_type = CoreLookupType (ctx, "System", "Type", Kind.Class, true);
956 exception_type = CoreLookupType (ctx, "System", "Exception", Kind.Class, true);
958 runtime_field_handle_type = CoreLookupType (ctx, "System", "RuntimeFieldHandle", Kind.Struct, true);
959 runtime_handle_type = CoreLookupType (ctx, "System", "RuntimeTypeHandle", Kind.Struct, true);
961 PredefinedAttributes.Get.ParamArray.Initialize (ctx, false);
962 PredefinedAttributes.Get.Out.Initialize (ctx, false);
964 return ctx.Report.Errors == 0;
968 // Initializes optional core types
970 public static void InitOptionalCoreTypes (CompilerContext ctx)
973 // These are only used for compare purposes
975 null_type = typeof (NullLiteral);
977 void_ptr_type = GetPointerType (void_type);
980 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
981 // types cache with incorrect accessiblity when any of optional types is internal.
983 PredefinedAttributes.Get.Initialize (ctx);
985 runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", Kind.Struct, false);
986 asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", Kind.Delegate, false);
987 iasyncresult_type = CoreLookupType (ctx, "System", "IAsyncResult", Kind.Interface, false);
988 typed_reference_type = CoreLookupType (ctx, "System", "TypedReference", Kind.Struct, false);
989 arg_iterator_type = CoreLookupType (ctx, "System", "ArgIterator", Kind.Struct, false);
990 mbr_type = CoreLookupType (ctx, "System", "MarshalByRefObject", Kind.Class, false);
993 // Optional attributes, used for error reporting only
995 //if (PredefinedAttributes.Get.Obsolete.IsDefined) {
996 // Class c = TypeManager.LookupClass (PredefinedAttributes.Get.Obsolete.Type);
997 // if (c != null)
998 // c.Define ();
1001 generic_ilist_type = CoreLookupType (ctx, "System.Collections.Generic", "IList`1", Kind.Interface, false);
1002 generic_icollection_type = CoreLookupType (ctx, "System.Collections.Generic", "ICollection`1", Kind.Interface, false);
1003 generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
1004 generic_nullable_type = CoreLookupType (ctx, "System", "Nullable`1", Kind.Struct, false);
1007 // Optional types which are used as types and for member lookup
1009 runtime_helpers_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
1011 // New in .NET 3.5
1012 // Note: extension_attribute_type is already loaded
1013 expression_type = CoreLookupType (ctx, "System.Linq.Expressions", "Expression`1", Kind.Class, false);
1015 if (!RootContext.StdLib) {
1017 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1018 // has different predefined types and this method sets mscorlib types
1019 // to be same to avoid any type check errors.
1022 Type type = typeof (Type);
1023 Type [] system_4_type_arg = { type, type, type, type };
1025 MethodInfo set_corlib_type_builders =
1026 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1027 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1028 system_4_type_arg, null);
1030 if (set_corlib_type_builders != null) {
1031 object[] args = new object [4];
1032 args [0] = object_type;
1033 args [1] = value_type;
1034 args [2] = enum_type;
1035 args [3] = void_type;
1037 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1038 } else {
1039 ctx.Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1040 TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
1041 TypeManager.CSharpName (system_4_type_arg));
1046 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1048 /// <remarks>
1049 /// This is the "old", non-cache based FindMembers() function. We cannot use
1050 /// the cache here because there is no member name argument.
1051 /// </remarks>
1052 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1053 MemberFilter filter, object criteria)
1055 #if MS_COMPATIBLE
1056 if (t.IsGenericType)
1057 t = t.GetGenericTypeDefinition ();
1058 #endif
1060 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1063 // `builder_to_declspace' contains all dynamic types.
1065 if (decl != null) {
1066 MemberList list;
1067 Timer.StartTimer (TimerType.FindMembers);
1068 list = decl.FindMembers (mt, bf, filter, criteria);
1069 Timer.StopTimer (TimerType.FindMembers);
1070 return list;
1074 // We have to take care of arrays specially, because GetType on
1075 // a TypeBuilder array will return a Type, not a TypeBuilder,
1076 // and we can not call FindMembers on this type.
1078 if (
1079 #if MS_COMPATIBLE
1080 !t.IsGenericType &&
1081 #endif
1082 t.IsSubclassOf (TypeManager.array_type))
1083 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1085 if (t is GenericTypeParameterBuilder) {
1086 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1088 Timer.StartTimer (TimerType.FindMembers);
1089 MemberList list = tparam.FindMembers (
1090 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1091 Timer.StopTimer (TimerType.FindMembers);
1092 return list;
1096 // Since FindMembers will not lookup both static and instance
1097 // members, we emulate this behaviour here.
1099 if ((bf & instance_and_static) == instance_and_static){
1100 MemberInfo [] i_members = t.FindMembers (
1101 mt, bf & ~BindingFlags.Static, filter, criteria);
1103 int i_len = i_members.Length;
1104 if (i_len == 1){
1105 MemberInfo one = i_members [0];
1108 // If any of these are present, we are done!
1110 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1111 return new MemberList (i_members);
1114 MemberInfo [] s_members = t.FindMembers (
1115 mt, bf & ~BindingFlags.Instance, filter, criteria);
1117 int s_len = s_members.Length;
1118 if (i_len > 0 || s_len > 0)
1119 return new MemberList (i_members, s_members);
1120 else {
1121 if (i_len > 0)
1122 return new MemberList (i_members);
1123 else
1124 return new MemberList (s_members);
1128 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1132 /// <summary>
1133 /// This method is only called from within MemberLookup. It tries to use the member
1134 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1135 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1136 /// our return value will already contain all inherited members and the caller don't need
1137 /// to check base classes and interfaces anymore.
1138 /// </summary>
1139 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1140 string name, out bool used_cache)
1142 MemberCache cache;
1145 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1146 // and we can ask the DeclSpace for the MemberCache.
1148 #if MS_COMPATIBLE
1149 if (t.Assembly == CodeGen.Assembly.Builder) {
1150 if (t.IsGenericParameter) {
1151 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1153 used_cache = true;
1154 if (tparam.MemberCache == null)
1155 return new MemberInfo[0];
1157 return tparam.MemberCache.FindMembers (
1158 mt, bf, name, FilterWithClosure_delegate, null);
1162 // We have to take care of arrays specially, because GetType on
1163 // a TypeBuilder array will return a Type, not a TypeBuilder,
1164 // and we can not call FindMembers on this type.
1166 if (t.IsArray) {
1167 used_cache = true;
1168 return TypeHandle.ArrayType.MemberCache.FindMembers (
1169 mt, bf, name, FilterWithClosure_delegate, null);
1172 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1173 t = t.GetGenericTypeDefinition ();
1174 #else
1175 if (t is TypeBuilder) {
1176 #endif
1177 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1178 cache = decl.MemberCache;
1181 // If this DeclSpace has a MemberCache, use it.
1184 if (cache != null) {
1185 used_cache = true;
1186 return cache.FindMembers (
1187 mt, bf, name, FilterWithClosure_delegate, null);
1190 // If there is no MemberCache, we need to use the "normal" FindMembers.
1191 // Note, this is a VERY uncommon route!
1193 MemberList list;
1194 Timer.StartTimer (TimerType.FindMembers);
1195 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1196 FilterWithClosure_delegate, name);
1197 Timer.StopTimer (TimerType.FindMembers);
1198 used_cache = false;
1199 return (MemberInfo []) list;
1203 // We have to take care of arrays specially, because GetType on
1204 // a TypeBuilder array will return a Type, not a TypeBuilder,
1205 // and we can not call FindMembers on this type.
1207 if (t.IsArray) {
1208 used_cache = true;
1209 return TypeHandle.ArrayType.MemberCache.FindMembers (
1210 mt, bf, name, FilterWithClosure_delegate, null);
1213 if (t is GenericTypeParameterBuilder) {
1214 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1216 used_cache = true;
1217 if (tparam.MemberCache == null)
1218 return new MemberInfo [0];
1220 return tparam.MemberCache.FindMembers (
1221 mt, bf, name, FilterWithClosure_delegate, null);
1224 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1226 // This happens if we're resolving a class'es base class and interfaces
1227 // in TypeContainer.DefineType(). At this time, the types aren't
1228 // populated yet, so we can't use the cache.
1230 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1231 FilterWithClosure_delegate, name);
1232 used_cache = false;
1233 return info;
1237 // This call will always succeed. There is exactly one TypeHandle instance per
1238 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1239 // the corresponding MemberCache.
1241 cache = TypeHandle.GetMemberCache (t);
1243 used_cache = true;
1244 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1248 // Return true for SRE dynamic/unclosed members
1250 public static bool IsBeingCompiled (MemberInfo mi)
1252 return mi.Module.Assembly == CodeGen.Assembly.Builder;
1255 public static bool IsBuiltinType (Type t)
1257 t = TypeToCoreType (t);
1258 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1259 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1260 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1261 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1262 return true;
1263 else
1264 return false;
1268 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1269 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1271 public static bool IsPrimitiveType (Type t)
1273 return (t == int32_type || t == uint32_type ||
1274 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1275 t == char_type || t == short_type || t == bool_type ||
1276 t == sbyte_type || t == byte_type || t == ushort_type);
1279 public static bool IsDelegateType (Type t)
1281 if (TypeManager.IsGenericParameter (t))
1282 return false;
1284 if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
1285 return false;
1287 t = DropGenericTypeArguments (t);
1288 return IsSubclassOf (t, TypeManager.delegate_type);
1292 // Is a type of dynamic type
1294 public static bool IsDynamicType (Type t)
1296 if (object.ReferenceEquals (InternalType.Dynamic, t))
1297 return true;
1299 if (t != object_type)
1300 return false;
1302 if (IsBeingCompiled (t))
1303 return false;
1305 PredefinedAttribute pa = PredefinedAttributes.Get.Dynamic;
1306 if (pa == null)
1307 return false;
1309 object[] res = t.GetCustomAttributes (pa.Type, false);
1310 return res != null && res.Length != 0;
1313 public static bool IsEnumType (Type t)
1315 t = DropGenericTypeArguments (t);
1316 return t.BaseType == TypeManager.enum_type;
1319 public static bool IsBuiltinOrEnum (Type t)
1321 if (IsBuiltinType (t))
1322 return true;
1324 if (IsEnumType (t))
1325 return true;
1327 return false;
1330 public static bool IsAttributeType (Type t)
1332 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1336 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1338 // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
1339 public static bool IsUnmanagedType (Type t)
1341 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1342 if (ds != null)
1343 return ds.IsUnmanagedType ();
1345 // builtins that are not unmanaged types
1346 if (t == TypeManager.object_type || t == TypeManager.string_type)
1347 return false;
1349 if (IsGenericType (t) || IsGenericParameter (t))
1350 return false;
1352 if (IsBuiltinOrEnum (t))
1353 return true;
1355 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1356 if (t.IsPointer)
1357 return IsUnmanagedType (GetElementType (t));
1359 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1360 if (t.IsArray)
1361 return false;
1363 if (!IsValueType (t))
1364 return false;
1366 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1367 if (IsGenericTypeDefinition (p))
1368 return false;
1371 bool retval = true;
1373 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1375 foreach (FieldInfo f in fields){
1376 if (!IsUnmanagedType (f.FieldType)){
1377 retval = false;
1382 return retval;
1386 // Null is considered to be a reference type
1388 public static bool IsReferenceType (Type t)
1390 if (TypeManager.IsGenericParameter (t)) {
1391 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1392 if (constraints == null)
1393 return false;
1395 return constraints.IsReferenceType;
1398 return !IsStruct (t) && !IsEnumType (t);
1401 public static bool IsValueType (Type t)
1403 if (TypeManager.IsGenericParameter (t)) {
1404 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1405 if (constraints == null)
1406 return false;
1408 return constraints.IsValueType;
1411 return IsStruct (t) || IsEnumType (t);
1414 public static bool IsStruct (Type t)
1416 return t.BaseType == value_type && t != enum_type && t.IsSealed;
1419 public static bool IsInterfaceType (Type t)
1421 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1422 if (tc == null)
1423 return false;
1425 return tc.Kind == Kind.Interface;
1428 public static bool IsSubclassOf (Type type, Type base_type)
1430 TypeParameter tparam = LookupTypeParameter (type);
1431 TypeParameter pparam = LookupTypeParameter (base_type);
1433 if ((tparam != null) && (pparam != null)) {
1434 if (tparam == pparam)
1435 return true;
1437 return tparam.IsSubclassOf (base_type);
1440 #if MS_COMPATIBLE
1441 if (tparam != pparam)
1442 return false;
1444 if (type.IsGenericType)
1445 type = type.GetGenericTypeDefinition ();
1446 #endif
1448 if (type.IsSubclassOf (base_type))
1449 return true;
1451 do {
1452 if (IsEqual (type, base_type))
1453 return true;
1455 type = type.BaseType;
1456 } while (type != null);
1458 return false;
1461 public static bool IsPrivateAccessible (Type type, Type parent)
1463 if (type == null)
1464 return false;
1466 if (type.Equals (parent))
1467 return true;
1469 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1472 public static bool IsFamilyAccessible (Type type, Type parent)
1474 TypeParameter tparam = LookupTypeParameter (type);
1475 TypeParameter pparam = LookupTypeParameter (parent);
1477 if ((tparam != null) && (pparam != null)) {
1478 if (tparam == pparam)
1479 return true;
1481 return tparam.IsSubclassOf (parent);
1484 do {
1485 if (IsInstantiationOfSameGenericType (type, parent))
1486 return true;
1488 type = type.BaseType;
1489 } while (type != null);
1491 return false;
1495 // Checks whether `type' is a subclass or nested child of `base_type'.
1497 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1499 do {
1500 if (IsFamilyAccessible (type, base_type))
1501 return true;
1503 // Handle nested types.
1504 type = type.DeclaringType;
1505 } while (type != null);
1507 return false;
1511 // Checks whether `type' is a nested child of `parent'.
1513 public static bool IsNestedChildOf (Type type, Type parent)
1515 if (type == null)
1516 return false;
1518 type = DropGenericTypeArguments (type);
1519 parent = DropGenericTypeArguments (parent);
1521 if (IsEqual (type, parent))
1522 return false;
1524 type = type.DeclaringType;
1525 while (type != null) {
1526 if (IsEqual (type, parent))
1527 return true;
1529 type = type.DeclaringType;
1532 return false;
1535 public static bool IsSpecialType (Type t)
1537 return t == arg_iterator_type || t == typed_reference_type;
1541 // Checks whether `invocationAssembly' is same or a friend of the assembly
1543 public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly)
1545 if (assembly == null)
1546 throw new ArgumentNullException ("assembly");
1548 // TODO: This can happen for constants used at assembly level and
1549 // predefined members
1550 // But there is no way to test for it for now, so it could be abused
1551 // elsewhere too.
1552 if (invocationAssembly == null)
1553 invocationAssembly = CodeGen.Assembly.Builder;
1555 if (invocationAssembly == assembly)
1556 return true;
1558 if (assembly_internals_vis_attrs.Contains (assembly))
1559 return (bool)(assembly_internals_vis_attrs [assembly]);
1561 PredefinedAttribute pa = PredefinedAttributes.Get.InternalsVisibleTo;
1562 // HACK: Do very early resolve of SRE type checking
1563 if (pa.Type == null)
1564 pa.Resolve (true);
1566 if (!pa.IsDefined)
1567 return false;
1569 object [] attrs = assembly.GetCustomAttributes (pa.Type, false);
1570 if (attrs.Length == 0) {
1571 assembly_internals_vis_attrs.Add (assembly, false);
1572 return false;
1575 bool is_friend = false;
1577 AssemblyName this_name = CodeGen.Assembly.Name;
1578 byte [] this_token = this_name.GetPublicKeyToken ();
1579 foreach (InternalsVisibleToAttribute attr in attrs) {
1580 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1581 continue;
1583 AssemblyName aname = null;
1584 try {
1585 aname = new AssemblyName (attr.AssemblyName);
1586 } catch (FileLoadException) {
1587 } catch (ArgumentException) {
1590 if (aname == null || aname.Name != this_name.Name)
1591 continue;
1593 byte [] key_token = aname.GetPublicKeyToken ();
1594 if (key_token != null) {
1595 if (this_token.Length == 0) {
1596 // Same name, but assembly is not strongnamed
1597 Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report);
1598 break;
1601 if (!CompareKeyTokens (this_token, key_token))
1602 continue;
1605 is_friend = true;
1606 break;
1609 assembly_internals_vis_attrs.Add (assembly, is_friend);
1610 return is_friend;
1613 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1615 for (int i = 0; i < token1.Length; i++)
1616 if (token1 [i] != token2 [i])
1617 return false;
1619 return true;
1622 static void Error_FriendAccessNameNotMatching (string other_name, Report Report)
1624 Report.Error (281,
1625 "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",
1626 other_name, CodeGen.Assembly.Name.FullName);
1630 // Do the right thing when returning the element type of an
1631 // array type based on whether we are compiling corlib or not
1633 public static Type GetElementType (Type t)
1635 if (RootContext.StdLib)
1636 return t.GetElementType ();
1637 else
1638 return TypeToCoreType (t.GetElementType ());
1641 /// <summary>
1642 /// This method is not implemented by MS runtime for dynamic types
1643 /// </summary>
1644 public static bool HasElementType (Type t)
1646 return t.IsArray || t.IsPointer || t.IsByRef;
1649 public static Type GetEnumUnderlyingType (Type t)
1651 t = DropGenericTypeArguments (t);
1652 Enum e = LookupTypeContainer (t) as Enum;
1653 if (e != null)
1654 return e.UnderlyingType;
1656 // TODO: cache it ?
1657 FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
1658 if (fi == null)
1659 return TypeManager.int32_type;
1661 return TypeToCoreType (fi.FieldType);
1664 /// <summary>
1665 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1666 /// </summary>
1668 /// <remarks>
1669 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1670 /// for anything which is dynamic, and we need this in a number of places,
1671 /// we register this information here, and use it afterwards.
1672 /// </remarks>
1673 static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
1675 method_params.Add (mb, ip);
1678 static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
1680 method_params.Add (pb, p);
1683 static public AParametersCollection GetParameterData (MethodBase mb)
1685 AParametersCollection pd = (AParametersCollection) method_params [mb];
1686 if (pd == null) {
1687 #if MS_COMPATIBLE
1688 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1689 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1690 pd = GetParameterData (mi);
1692 if (mi.IsGenericMethod)
1693 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1694 else
1695 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1697 method_params.Add (mb, pd);
1698 return pd;
1701 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1702 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1703 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1706 pd = ParametersImported.Create (mb);
1707 #else
1708 MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
1709 if (generic != mb) {
1710 pd = TypeManager.GetParameterData (generic);
1711 pd = ParametersImported.Create (pd, mb);
1712 } else {
1713 pd = ParametersImported.Create (mb);
1715 #endif
1716 method_params.Add (mb, pd);
1718 return pd;
1721 public static AParametersCollection GetParameterData (PropertyInfo pi)
1723 AParametersCollection pd = (AParametersCollection)method_params [pi];
1724 if (pd == null) {
1725 if (pi is PropertyBuilder)
1726 return ParametersCompiled.EmptyReadOnlyParameters;
1728 ParameterInfo [] p = pi.GetIndexParameters ();
1729 if (p == null)
1730 return ParametersCompiled.EmptyReadOnlyParameters;
1732 pd = ParametersImported.Create (p, null);
1733 method_params.Add (pi, pd);
1736 return pd;
1739 public static AParametersCollection GetDelegateParameters (ResolveContext ec, Type t)
1741 Delegate d = builder_to_declspace [t] as Delegate;
1742 if (d != null)
1743 return d.Parameters;
1745 MethodInfo invoke_mb = Delegate.GetInvokeMethod (ec.Compiler, t, t);
1746 return GetParameterData (invoke_mb);
1749 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1751 if (!method_overrides.Contains (override_method))
1752 method_overrides [override_method] = base_method;
1753 if (method_overrides [override_method] != base_method)
1754 throw new InternalErrorException ("Override mismatch: " + override_method);
1757 static public bool IsOverride (MethodBase m)
1759 m = DropGenericMethodArguments (m);
1761 return m.IsVirtual &&
1762 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1763 (m is MethodBuilder || method_overrides.Contains (m));
1766 static public MethodBase TryGetBaseDefinition (MethodBase m)
1768 m = DropGenericMethodArguments (m);
1770 return (MethodBase) method_overrides [m];
1773 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1775 fields.Add (fb, ic);
1778 public static IConstant GetConstant (FieldInfo fb)
1780 if (fb == null)
1781 return null;
1783 return (IConstant)fields [fb];
1786 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1788 propertybuilder_to_property.Add (pi, pb);
1791 public static PropertyBase GetProperty (PropertyInfo pi)
1793 return (PropertyBase)propertybuilder_to_property [pi];
1796 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
1798 fieldbuilders_to_fields.Add (fb, f);
1802 // The return value can be null; This will be the case for
1803 // auxiliary FieldBuilders created by the compiler that have no
1804 // real field being declared on the source code
1806 static public FieldBase GetField (FieldInfo fb)
1808 fb = GetGenericFieldDefinition (fb);
1809 return (FieldBase) fieldbuilders_to_fields [fb];
1812 static public MethodInfo GetAddMethod (EventInfo ei)
1814 if (ei is MyEventBuilder) {
1815 return ((MyEventBuilder)ei).GetAddMethod (true);
1817 return ei.GetAddMethod (true);
1820 static public MethodInfo GetRemoveMethod (EventInfo ei)
1822 if (ei is MyEventBuilder) {
1823 return ((MyEventBuilder)ei).GetRemoveMethod (true);
1825 return ei.GetRemoveMethod (true);
1828 static public void RegisterEventField (EventInfo einfo, EventField e)
1830 if (events == null)
1831 events = new Hashtable ();
1833 events.Add (einfo, e);
1836 static public EventField GetEventField (EventInfo ei)
1838 if (events == null)
1839 return null;
1841 return (EventField) events [ei];
1844 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1846 Hashtable hash = new Hashtable ();
1847 return CheckStructCycles (tc, seen, hash);
1850 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1851 Hashtable hash)
1853 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
1854 return true;
1857 // `seen' contains all types we've already visited.
1859 if (seen.Contains (tc))
1860 return true;
1861 seen.Add (tc, null);
1863 if (tc.Fields == null)
1864 return true;
1866 foreach (FieldBase field in tc.Fields) {
1867 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1868 continue;
1870 Type ftype = field.FieldBuilder.FieldType;
1871 TypeContainer ftc = LookupTypeContainer (ftype);
1872 if (ftc == null)
1873 continue;
1875 if (hash.Contains (ftc)) {
1876 tc.Compiler.Report.Error (523, tc.Location,
1877 "Struct member `{0}.{1}' of type `{2}' " +
1878 "causes a cycle in the struct layout",
1879 tc.Name, field.Name, ftc.Name);
1880 return false;
1884 // `hash' contains all types in the current path.
1886 hash.Add (tc, null);
1888 bool ok = CheckStructCycles (ftc, seen, hash);
1890 hash.Remove (tc);
1892 if (!ok)
1893 return false;
1895 if (!seen.Contains (ftc))
1896 seen.Add (ftc, null);
1899 return true;
1902 /// <summary>
1903 /// Given an array of interface types, expand and eliminate repeated ocurrences
1904 /// of an interface.
1905 /// </summary>
1907 /// <remarks>
1908 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1909 /// be IA, IB, IC.
1910 /// </remarks>
1911 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
1913 ArrayList new_ifaces = new ArrayList ();
1915 foreach (TypeExpr iface in base_interfaces){
1916 Type itype = iface.Type;
1918 if (new_ifaces.Contains (itype))
1919 continue;
1921 new_ifaces.Add (itype);
1923 Type [] implementing = GetInterfaces (itype);
1925 foreach (Type imp in implementing){
1926 if (!new_ifaces.Contains (imp))
1927 new_ifaces.Add (imp);
1930 Type [] ret = new Type [new_ifaces.Count];
1931 new_ifaces.CopyTo (ret, 0);
1932 return ret;
1935 public static Type[] ExpandInterfaces (Type [] base_interfaces)
1937 ArrayList new_ifaces = new ArrayList ();
1939 foreach (Type itype in base_interfaces){
1940 if (new_ifaces.Contains (itype))
1941 continue;
1943 new_ifaces.Add (itype);
1945 Type [] implementing = GetInterfaces (itype);
1947 foreach (Type imp in implementing){
1948 if (!new_ifaces.Contains (imp))
1949 new_ifaces.Add (imp);
1952 Type [] ret = new Type [new_ifaces.Count];
1953 new_ifaces.CopyTo (ret, 0);
1954 return ret;
1957 static PtrHashtable iface_cache;
1959 /// <summary>
1960 /// This function returns the interfaces in the type `t'. Works with
1961 /// both types and TypeBuilders.
1962 /// </summary>
1963 public static Type [] GetInterfaces (Type t)
1965 Type [] cached = iface_cache [t] as Type [];
1966 if (cached != null)
1967 return cached;
1970 // The reason for catching the Array case is that Reflection.Emit
1971 // will not return a TypeBuilder for Array types of TypeBuilder types,
1972 // but will still throw an exception if we try to call GetInterfaces
1973 // on the type.
1975 // Since the array interfaces are always constant, we return those for
1976 // the System.Array
1979 if (t.IsArray)
1980 t = TypeManager.array_type;
1982 if ((t is TypeBuilder) || IsGenericType (t)) {
1983 Type [] base_ifaces;
1985 if (t.BaseType == null)
1986 base_ifaces = Type.EmptyTypes;
1987 else
1988 base_ifaces = GetInterfaces (t.BaseType);
1989 Type[] type_ifaces;
1990 if (IsGenericType (t))
1991 #if MS_COMPATIBLE
1992 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
1993 #else
1994 type_ifaces = t.GetInterfaces ();
1995 #endif
1996 else
1997 type_ifaces = (Type []) builder_to_ifaces [t];
1998 if (type_ifaces == null || type_ifaces.Length == 0)
1999 type_ifaces = Type.EmptyTypes;
2001 int base_count = base_ifaces.Length;
2002 Type [] result = new Type [base_count + type_ifaces.Length];
2003 base_ifaces.CopyTo (result, 0);
2004 type_ifaces.CopyTo (result, base_count);
2006 iface_cache [t] = result;
2007 return result;
2008 } else if (t is GenericTypeParameterBuilder){
2009 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2010 if (type_ifaces == null || type_ifaces.Length == 0)
2011 type_ifaces = Type.EmptyTypes;
2013 iface_cache [t] = type_ifaces;
2014 return type_ifaces;
2015 } else {
2016 Type[] ifaces = t.GetInterfaces ();
2017 iface_cache [t] = ifaces;
2018 return ifaces;
2023 // gets the interfaces that are declared explicitly on t
2025 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2027 return (Type []) builder_to_ifaces [t];
2030 /// <remarks>
2031 /// The following is used to check if a given type implements an interface.
2032 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2033 /// </remarks>
2034 public static bool ImplementsInterface (Type t, Type iface)
2036 Type [] interfaces;
2039 // FIXME OPTIMIZATION:
2040 // as soon as we hit a non-TypeBuiler in the interface
2041 // chain, we could return, as the `Type.GetInterfaces'
2042 // will return all the interfaces implement by the type
2043 // or its bases.
2045 do {
2046 interfaces = GetInterfaces (t);
2048 if (interfaces != null){
2049 foreach (Type i in interfaces){
2050 if (i == iface || IsVariantOf (i, iface))
2051 return true;
2055 t = t.BaseType;
2056 } while (t != null);
2058 return false;
2061 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2063 // This is a custom version of Convert.ChangeType() which works
2064 // with the TypeBuilder defined types when compiling corlib.
2065 public static object ChangeType (object value, Type conversionType, out bool error)
2067 IConvertible convert_value = value as IConvertible;
2069 if (convert_value == null){
2070 error = true;
2071 return null;
2075 // NOTE 1:
2076 // We must use Type.Equals() here since `conversionType' is
2077 // the TypeBuilder created version of a system type and not
2078 // the system type itself. You cannot use Type.GetTypeCode()
2079 // on such a type - it'd always return TypeCode.Object.
2081 // NOTE 2:
2082 // We cannot rely on build-in type conversions as they are
2083 // more limited than what C# supports.
2084 // See char -> float/decimal/double conversion
2087 error = false;
2088 try {
2089 if (conversionType.Equals (typeof (Boolean)))
2090 return (object)(convert_value.ToBoolean (nf_provider));
2091 if (conversionType.Equals (typeof (Byte)))
2092 return (object)(convert_value.ToByte (nf_provider));
2093 if (conversionType.Equals (typeof (Char)))
2094 return (object)(convert_value.ToChar (nf_provider));
2095 if (conversionType.Equals (typeof (DateTime)))
2096 return (object)(convert_value.ToDateTime (nf_provider));
2098 if (conversionType.Equals (decimal_type)) {
2099 if (convert_value.GetType () == TypeManager.char_type)
2100 return (decimal)convert_value.ToInt32 (nf_provider);
2101 return convert_value.ToDecimal (nf_provider);
2104 if (conversionType.Equals (typeof (Double))) {
2105 if (convert_value.GetType () == TypeManager.char_type)
2106 return (double)convert_value.ToInt32 (nf_provider);
2107 return convert_value.ToDouble (nf_provider);
2110 if (conversionType.Equals (typeof (Int16)))
2111 return (object)(convert_value.ToInt16 (nf_provider));
2112 if (conversionType.Equals (int32_type))
2113 return (object)(convert_value.ToInt32 (nf_provider));
2114 if (conversionType.Equals (int64_type))
2115 return (object)(convert_value.ToInt64 (nf_provider));
2116 if (conversionType.Equals (typeof (SByte)))
2117 return (object)(convert_value.ToSByte (nf_provider));
2119 if (conversionType.Equals (typeof (Single))) {
2120 if (convert_value.GetType () == TypeManager.char_type)
2121 return (float)convert_value.ToInt32 (nf_provider);
2122 return convert_value.ToSingle (nf_provider);
2125 if (conversionType.Equals (typeof (String)))
2126 return (object)(convert_value.ToString (nf_provider));
2127 if (conversionType.Equals (typeof (UInt16)))
2128 return (object)(convert_value.ToUInt16 (nf_provider));
2129 if (conversionType.Equals (typeof (UInt32)))
2130 return (object)(convert_value.ToUInt32 (nf_provider));
2131 if (conversionType.Equals (typeof (UInt64)))
2132 return (object)(convert_value.ToUInt64 (nf_provider));
2133 if (conversionType.Equals (typeof (Object)))
2134 return (object)(value);
2135 else
2136 error = true;
2137 } catch {
2138 error = true;
2140 return null;
2144 // When compiling with -nostdlib and the type is imported from an external assembly
2145 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2147 public static Type TypeToCoreType (Type t)
2149 if (RootContext.StdLib || t.Module != typeof (object).Module)
2150 return t;
2152 // TODO: GetTypeCode returns underlying type for enums !!
2153 TypeCode tc = Type.GetTypeCode (t);
2155 switch (tc){
2156 case TypeCode.Boolean:
2157 return TypeManager.bool_type;
2158 case TypeCode.Byte:
2159 return TypeManager.byte_type;
2160 case TypeCode.SByte:
2161 return TypeManager.sbyte_type;
2162 case TypeCode.Char:
2163 return TypeManager.char_type;
2164 case TypeCode.Int16:
2165 return TypeManager.short_type;
2166 case TypeCode.UInt16:
2167 return TypeManager.ushort_type;
2168 case TypeCode.Int32:
2169 return TypeManager.int32_type;
2170 case TypeCode.UInt32:
2171 return TypeManager.uint32_type;
2172 case TypeCode.Int64:
2173 return TypeManager.int64_type;
2174 case TypeCode.UInt64:
2175 return TypeManager.uint64_type;
2176 case TypeCode.Single:
2177 return TypeManager.float_type;
2178 case TypeCode.Double:
2179 return TypeManager.double_type;
2180 case TypeCode.String:
2181 return TypeManager.string_type;
2182 case TypeCode.Decimal:
2183 return TypeManager.decimal_type;
2186 if (t == typeof (void))
2187 return TypeManager.void_type;
2188 if (t == typeof (object))
2189 return TypeManager.object_type;
2190 if (t == typeof (System.Type))
2191 return TypeManager.type_type;
2192 if (t == typeof (System.IntPtr))
2193 return TypeManager.intptr_type;
2194 if (t == typeof (System.UIntPtr))
2195 return TypeManager.uintptr_type;
2197 if (t.IsArray) {
2198 int dim = t.GetArrayRank ();
2199 t = GetElementType (t);
2200 return t.MakeArrayType (dim);
2202 if (t.IsByRef) {
2203 t = GetElementType (t);
2204 return t.MakeByRefType ();
2206 if (t.IsPointer) {
2207 t = GetElementType (t);
2208 return t.MakePointerType ();
2211 return t;
2215 // Converts any type to reflection supported type
2217 public static Type TypeToReflectionType (Type type)
2219 // TODO: Very lame and painful, GetReference () is enough for mcs-cecil
2220 if (IsDynamicType (type))
2221 return object_type;
2223 if (type is DynamicArrayType)
2224 return type.UnderlyingSystemType;
2226 return type;
2229 /// <summary>
2230 /// Utility function that can be used to probe whether a type
2231 /// is managed or not.
2232 /// </summary>
2233 public static bool VerifyUnmanaged (CompilerContext ctx, Type t, Location loc)
2235 if (IsUnmanagedType (t))
2236 return true;
2238 while (t.IsPointer)
2239 t = GetElementType (t);
2241 ctx.Report.SymbolRelatedToPreviousError (t);
2242 ctx.Report.Error (208, loc,
2243 "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2244 CSharpName (t));
2246 return false;
2249 /// <summary>
2250 /// Returns the name of the indexer in a given type.
2251 /// </summary>
2252 /// <remarks>
2253 /// The default is not always `Item'. The user can change this behaviour by
2254 /// using the IndexerNameAttribute in the container.
2255 /// For example, the String class indexer is named `Chars' not `Item'
2256 /// </remarks>
2257 public static string IndexerPropertyName (Type t)
2259 t = DropGenericTypeArguments (t);
2260 if (t is TypeBuilder) {
2261 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2262 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2265 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
2266 if (pa.IsDefined) {
2267 System.Attribute attr = System.Attribute.GetCustomAttribute (
2268 t, pa.Type);
2269 if (attr != null) {
2270 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2271 return dma.MemberName;
2275 return TypeContainer.DefaultIndexerName;
2278 private static bool IsSignatureEqual (Type a, Type b)
2281 /// Consider the following example (bug #77674):
2283 /// public abstract class A
2284 /// {
2285 /// public abstract T Foo<T> ();
2286 /// }
2288 /// public abstract class B : A
2289 /// {
2290 /// public override U Foo<T> ()
2291 /// { return default (U); }
2292 /// }
2294 /// Here, `T' and `U' are method type parameters from different methods
2295 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2297 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2298 /// we need to do a signature based comparision and consider them equal.
2300 if (a == b)
2301 return true;
2303 if (a.IsGenericParameter && b.IsGenericParameter &&
2304 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2305 return a.GenericParameterPosition == b.GenericParameterPosition;
2308 if (a.IsArray && b.IsArray) {
2309 if (a.GetArrayRank () != b.GetArrayRank ())
2310 return false;
2312 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2315 if (a.IsByRef && b.IsByRef)
2316 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2318 if (IsGenericType (a) && IsGenericType (b)) {
2319 if (DropGenericTypeArguments (a) != DropGenericTypeArguments (b))
2320 return false;
2322 Type[] aargs = GetTypeArguments (a);
2323 Type[] bargs = GetTypeArguments (b);
2325 if (aargs.Length != bargs.Length)
2326 return false;
2328 for (int i = 0; i < aargs.Length; i++) {
2329 if (!IsSignatureEqual (aargs [i], bargs [i]))
2330 return false;
2333 return true;
2336 return false;
2340 // Returns whether the array of memberinfos contains the given method
2342 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
2344 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2346 foreach (MethodBase method in array) {
2347 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
2348 continue;
2350 if (method.Name != new_method.Name)
2351 continue;
2353 if (method is MethodInfo && new_method is MethodInfo &&
2354 !IsSignatureEqual (
2355 TypeToCoreType (((MethodInfo) method).ReturnType),
2356 TypeToCoreType (((MethodInfo) new_method).ReturnType)))
2357 continue;
2359 Type [] old_args = TypeManager.GetParameterData (method).Types;
2360 int old_count = old_args.Length;
2361 int i;
2363 if (new_args.Length != old_count)
2364 continue;
2366 for (i = 0; i < old_count; i++){
2367 if (!IsSignatureEqual (old_args [i], new_args [i]))
2368 break;
2370 if (i != old_count)
2371 continue;
2373 return true;
2376 return false;
2380 // We copy methods from `new_members' into `target_list' if the signature
2381 // for the method from in the new list does not exist in the target_list
2383 // The name is assumed to be the same.
2385 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2387 if (target_list == null){
2388 target_list = new ArrayList ();
2390 foreach (MemberInfo mi in new_members){
2391 if (mi is MethodBase)
2392 target_list.Add (mi);
2394 return target_list;
2397 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2398 target_list.CopyTo (target_array, 0);
2400 foreach (MemberInfo mi in new_members){
2401 MethodBase new_method = (MethodBase) mi;
2403 if (!ArrayContainsMethod (target_array, new_method, true))
2404 target_list.Add (new_method);
2406 return target_list;
2409 #region Generics
2410 // <remarks>
2411 // Tracks the generic parameters.
2412 // </remarks>
2413 static PtrHashtable builder_to_type_param;
2415 public static void AddTypeParameter (Type t, TypeParameter tparam)
2417 if (!builder_to_type_param.Contains (t))
2418 builder_to_type_param.Add (t, tparam);
2421 public static TypeParameter LookupTypeParameter (Type t)
2423 return (TypeParameter) builder_to_type_param [t];
2426 // This method always return false for non-generic compiler,
2427 // while Type.IsGenericParameter is returned if it is supported.
2428 public static bool IsGenericParameter (Type type)
2430 return type.IsGenericParameter;
2433 public static int GenericParameterPosition (Type type)
2435 return type.GenericParameterPosition;
2438 public static bool IsGenericType (Type type)
2440 return type.IsGenericType;
2443 public static bool IsGenericTypeDefinition (Type type)
2445 return type.IsGenericTypeDefinition;
2448 public static bool ContainsGenericParameters (Type type)
2450 return type.ContainsGenericParameters;
2453 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2455 if (fi.DeclaringType.IsGenericTypeDefinition ||
2456 !fi.DeclaringType.IsGenericType)
2457 return fi;
2459 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2460 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2461 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2463 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2464 foreach (FieldInfo f in t.GetFields (bf))
2465 if (f.MetadataToken == fi.MetadataToken)
2466 return f;
2468 return fi;
2471 public static bool IsEqual (Type a, Type b)
2473 if (a.Equals (b)) {
2474 // MS BCL returns true even if enum types are different
2475 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2476 return a.FullName == b.FullName;
2478 // Some types are never equal
2479 if (a == TypeManager.null_type || a == InternalType.AnonymousMethod)
2480 return false;
2482 return true;
2485 if (IsGenericParameter (a) && IsGenericParameter (b)) {
2486 // TODO: needs more testing before cleaning up
2487 //if (a.DeclaringMethod != b.DeclaringMethod &&
2488 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2489 // return false;
2490 return a.GenericParameterPosition == b.GenericParameterPosition;
2493 if (a.IsArray && b.IsArray) {
2494 if (a.GetArrayRank () != b.GetArrayRank ())
2495 return false;
2496 return IsEqual (GetElementType (a), GetElementType (b));
2499 if (a.IsByRef && b.IsByRef)
2500 return IsEqual (a.GetElementType (), b.GetElementType ());
2502 if (IsGenericType (a) && IsGenericType (b)) {
2503 Type adef = DropGenericTypeArguments (a);
2504 Type bdef = DropGenericTypeArguments (b);
2506 if (adef != bdef)
2507 return false;
2509 if (adef.IsEnum && bdef.IsEnum)
2510 return true;
2512 Type[] aargs = GetTypeArguments (a);
2513 Type[] bargs = GetTypeArguments (b);
2515 if (aargs.Length != bargs.Length)
2516 return false;
2518 for (int i = 0; i < aargs.Length; i++) {
2519 if (!IsEqual (aargs [i], bargs [i]))
2520 return false;
2523 return true;
2526 return false;
2529 public static bool IsEqual (Type[] a, Type[] b)
2531 if (a == null || b == null || a.Length != b.Length)
2532 return false;
2534 for (int i = 0; i < a.Length; ++i) {
2535 if (a [i] == null || b [i] == null) {
2536 if (a [i] == b [i])
2537 continue;
2539 return false;
2542 if (!IsEqual (a [i], b [i]))
2543 return false;
2546 return true;
2549 public static Type DropGenericTypeArguments (Type t)
2551 if (!t.IsGenericType)
2552 return t;
2553 // Micro-optimization: a generic typebuilder is always a generic type definition
2554 if (t is TypeBuilder)
2555 return t;
2556 return t.GetGenericTypeDefinition ();
2559 public static MethodBase DropGenericMethodArguments (MethodBase m)
2561 if (m.IsGenericMethod)
2562 m = ((MethodInfo) m).GetGenericMethodDefinition ();
2564 Type t = m.DeclaringType;
2565 if (!t.IsGenericType || t.IsGenericTypeDefinition)
2566 return m;
2568 t = t.GetGenericTypeDefinition ();
2569 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2570 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2572 #if MS_COMPATIBLE
2573 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2574 return m;
2575 #endif
2577 if (m is ConstructorInfo) {
2578 foreach (ConstructorInfo c in t.GetConstructors (bf))
2579 if (c.MetadataToken == m.MetadataToken)
2580 return c;
2581 } else {
2582 foreach (MethodBase mb in t.GetMethods (bf))
2583 if (mb.MetadataToken == m.MetadataToken)
2584 return mb;
2587 return m;
2590 public static Type[] GetGenericArguments (MethodBase mi)
2592 return mi.GetGenericArguments () ?? Type.EmptyTypes;
2595 public static Type[] GetTypeArguments (Type t)
2597 DeclSpace tc = LookupDeclSpace (t);
2598 if (tc != null) {
2599 if (!tc.IsGeneric)
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 ();
2610 return ret;
2611 } else
2612 return t.GetGenericArguments ();
2615 public static GenericConstraints GetTypeParameterConstraints (Type t)
2617 if (!t.IsGenericParameter)
2618 throw new InvalidOperationException ();
2620 TypeParameter tparam = LookupTypeParameter (t);
2621 if (tparam != null)
2622 return tparam.GenericConstraints;
2624 return ReflectionConstraints.GetConstraints (t);
2627 public static bool HasGenericArguments (Type t)
2629 return GetNumberOfTypeArguments (t) > 0;
2632 public static int GetNumberOfTypeArguments (Type t)
2634 if (t.IsGenericParameter)
2635 return 0;
2636 DeclSpace tc = LookupDeclSpace (t);
2637 if (tc != null)
2638 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2639 else
2640 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2643 /// <summary>
2644 /// Check whether `type' and `parent' are both instantiations of the same
2645 /// generic type. Note that we do not check the type parameters here.
2646 /// </summary>
2647 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2649 int tcount = GetNumberOfTypeArguments (type);
2650 int pcount = GetNumberOfTypeArguments (parent);
2652 if (tcount != pcount)
2653 return false;
2655 type = DropGenericTypeArguments (type);
2656 parent = DropGenericTypeArguments (parent);
2658 return type.Equals (parent);
2661 /// <summary>
2662 /// Whether `mb' is a generic method definition.
2663 /// </summary>
2664 public static bool IsGenericMethodDefinition (MethodBase mb)
2666 if (mb.DeclaringType is TypeBuilder) {
2667 IMethodData method = (IMethodData) builder_to_method [mb];
2668 if (method == null)
2669 return false;
2671 return method.GenericMethod != null;
2674 return mb.IsGenericMethodDefinition;
2677 /// <summary>
2678 /// Whether `mb' is a generic method.
2679 /// </summary>
2680 public static bool IsGenericMethod (MethodBase mb)
2682 return mb.IsGenericMethod;
2685 public static bool IsNullableType (Type t)
2687 return generic_nullable_type == DropGenericTypeArguments (t);
2689 #endregion
2691 #region MemberLookup implementation
2694 // Whether we allow private members in the result (since FindMembers
2695 // uses NonPublic for both protected and private), we need to distinguish.
2698 internal class Closure {
2699 internal bool private_ok;
2701 // Who is invoking us and which type is being queried currently.
2702 internal Type invocation_type;
2703 internal Type qualifier_type;
2705 // The assembly that defines the type is that is calling us
2706 internal Assembly invocation_assembly;
2707 internal IList almost_match;
2709 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2711 if (invocation_type == null)
2712 return false;
2714 if (is_static && qualifier_type == null)
2715 // It resolved from a simple name, so it should be visible.
2716 return true;
2718 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2719 return true;
2721 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2722 if (!IsFamilyAccessible (t, m.DeclaringType))
2723 continue;
2725 // Although a derived class can access protected members of its base class
2726 // it cannot do so through an instance of the base class (CS1540).
2727 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2728 if (is_static || qualifier_type == null ||
2729 IsInstantiationOfSameGenericType (t, qualifier_type) ||
2730 IsFamilyAccessible (qualifier_type, t))
2731 return true;
2734 if (almost_match != null)
2735 almost_match.Add (m);
2737 return false;
2741 // This filter filters by name + whether it is ok to include private
2742 // members in the search
2744 internal bool Filter (MemberInfo m, object filter_criteria)
2747 // Hack: we know that the filter criteria will always be in the
2748 // `closure' // fields.
2751 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2752 return false;
2754 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2755 (invocation_type != null) &&
2756 IsPrivateAccessible (m.DeclaringType, invocation_type))
2757 return true;
2760 // Ugly: we need to find out the type of `m', and depending
2761 // on this, tell whether we accept or not
2763 if (m is MethodBase){
2764 MethodBase mb = (MethodBase) m;
2765 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2767 if (ma == MethodAttributes.Public)
2768 return true;
2770 if (ma == MethodAttributes.PrivateScope)
2771 return false;
2773 if (ma == MethodAttributes.Private)
2774 return private_ok ||
2775 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2776 IsNestedChildOf (invocation_type, m.DeclaringType);
2778 if (TypeManager.IsThisOrFriendAssembly (invocation_assembly, mb.DeclaringType.Assembly)) {
2779 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2780 return true;
2781 } else {
2782 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2783 return false;
2786 // Family, FamORAssem or FamANDAssem
2787 return CheckValidFamilyAccess (mb.IsStatic, m);
2790 if (m is FieldInfo){
2791 FieldInfo fi = (FieldInfo) m;
2792 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2794 if (fa == FieldAttributes.Public)
2795 return true;
2797 if (fa == FieldAttributes.PrivateScope)
2798 return false;
2800 if (fa == FieldAttributes.Private)
2801 return private_ok ||
2802 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2803 IsNestedChildOf (invocation_type, m.DeclaringType);
2805 if (TypeManager.IsThisOrFriendAssembly (invocation_assembly, fi.DeclaringType.Assembly)) {
2806 if ((fa == FieldAttributes.Assembly) ||
2807 (fa == FieldAttributes.FamORAssem))
2808 return true;
2809 } else {
2810 if ((fa == FieldAttributes.Assembly) ||
2811 (fa == FieldAttributes.FamANDAssem))
2812 return false;
2815 // Family, FamORAssem or FamANDAssem
2816 return CheckValidFamilyAccess (fi.IsStatic, m);
2820 // EventInfos and PropertyInfos, return true because they lack
2821 // permission information, so we need to check later on the methods.
2823 return true;
2827 static Closure closure;
2828 static MemberFilter FilterWithClosure_delegate;
2831 // Looks up a member called `name' in the `queried_type'. This lookup
2832 // is done by code that is contained in the definition for `invocation_type'
2833 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2835 // `invocation_type' is used to check whether we're allowed to access the requested
2836 // member wrt its protection level.
2838 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2839 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2840 // is B and qualifier_type is A). This is used to do the CS1540 check.
2842 // When resolving a SimpleName, `qualifier_type' is null.
2844 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2845 // the same than `queried_type' - except when we're being called from BaseAccess;
2846 // in this case, `invocation_type' is the current type and `queried_type' the base
2847 // type, so this'd normally trigger a CS1540.
2849 // The binding flags are `bf' and the kind of members being looked up are `mt'
2851 // The return value always includes private members which code in `invocation_type'
2852 // is allowed to access (using the specified `qualifier_type' if given); only use
2853 // BindingFlags.NonPublic to bypass the permission check.
2855 // The 'almost_match' argument is used for reporting error CS1540.
2857 // Returns an array of a single element for everything but Methods/Constructors
2858 // that might return multiple matches.
2860 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2861 Type queried_type, MemberTypes mt,
2862 BindingFlags original_bf, string name, IList almost_match)
2864 Timer.StartTimer (TimerType.MemberLookup);
2866 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2867 queried_type, mt, original_bf, name, almost_match);
2869 Timer.StopTimer (TimerType.MemberLookup);
2871 return retval;
2874 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2875 Type queried_type, MemberTypes mt,
2876 BindingFlags original_bf, string name, IList almost_match)
2878 BindingFlags bf = original_bf;
2880 ArrayList method_list = null;
2881 Type current_type = queried_type;
2882 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2883 bool skip_iface_check = true, used_cache = false;
2884 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
2886 closure.invocation_type = invocation_type;
2887 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2888 closure.qualifier_type = qualifier_type;
2889 closure.almost_match = almost_match;
2891 // This is from the first time we find a method
2892 // in most cases, we do not actually find a method in the base class
2893 // so we can just ignore it, and save the arraylist allocation
2894 MemberInfo [] first_members_list = null;
2895 bool use_first_members_list = false;
2897 do {
2898 MemberInfo [] list;
2901 // `NonPublic' is lame, because it includes both protected and
2902 // private methods, so we need to control this behavior by
2903 // explicitly tracking if a private method is ok or not.
2905 // The possible cases are:
2906 // public, private and protected (internal does not come into the
2907 // equation)
2909 if ((invocation_type != null) &&
2910 ((invocation_type == current_type) ||
2911 IsNestedChildOf (invocation_type, current_type)) ||
2912 always_ok_flag)
2913 bf = original_bf | BindingFlags.NonPublic;
2914 else
2915 bf = original_bf;
2917 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2919 Timer.StopTimer (TimerType.MemberLookup);
2921 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2923 Timer.StartTimer (TimerType.MemberLookup);
2926 // When queried for an interface type, the cache will automatically check all
2927 // inherited members, so we don't need to do this here. However, this only
2928 // works if we already used the cache in the first iteration of this loop.
2930 // If we used the cache in any further iteration, we can still terminate the
2931 // loop since the cache always looks in all base classes.
2934 if (used_cache)
2935 searching = false;
2936 else
2937 skip_iface_check = false;
2939 if (current_type == TypeManager.object_type)
2940 searching = false;
2941 else {
2942 current_type = current_type.BaseType;
2945 // This happens with interfaces, they have a null
2946 // basetype. Look members up in the Object class.
2948 if (current_type == null) {
2949 current_type = TypeManager.object_type;
2950 searching = true;
2954 if (list.Length == 0)
2955 continue;
2958 // Events and types are returned by both `static' and `instance'
2959 // searches, which means that our above FindMembers will
2960 // return two copies of the same.
2962 if (list.Length == 1 && !(list [0] is MethodBase)){
2963 return list;
2967 // Multiple properties: we query those just to find out the indexer
2968 // name
2970 if (list [0] is PropertyInfo)
2971 return list;
2974 // We found an event: the cache lookup returns both the event and
2975 // its private field.
2977 if (list [0] is EventInfo) {
2978 if ((list.Length == 2) && (list [1] is FieldInfo))
2979 return new MemberInfo [] { list [0] };
2981 return list;
2985 // We found methods, turn the search into "method scan"
2986 // mode.
2989 if (first_members_list != null) {
2990 if (use_first_members_list) {
2991 method_list = CopyNewMethods (method_list, first_members_list);
2992 use_first_members_list = false;
2995 method_list = CopyNewMethods (method_list, list);
2996 } else {
2997 first_members_list = list;
2998 use_first_members_list = true;
2999 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3001 } while (searching);
3003 if (use_first_members_list)
3004 return first_members_list;
3006 if (method_list != null && method_list.Count > 0) {
3007 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3010 // This happens if we already used the cache in the first iteration, in this case
3011 // the cache already looked in all interfaces.
3013 if (skip_iface_check)
3014 return null;
3017 // Interfaces do not list members they inherit, so we have to
3018 // scan those.
3020 if (!queried_type.IsInterface)
3021 return null;
3023 if (queried_type.IsArray)
3024 queried_type = TypeManager.array_type;
3026 Type [] ifaces = GetInterfaces (queried_type);
3027 if (ifaces == null)
3028 return null;
3030 foreach (Type itype in ifaces){
3031 MemberInfo [] x;
3033 x = MemberLookup (null, null, itype, mt, bf, name, null);
3034 if (x != null)
3035 return x;
3038 return null;
3041 public const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3042 BindingFlags.Static | BindingFlags.Instance |
3043 BindingFlags.DeclaredOnly;
3045 // Currently is designed to work with external types only
3046 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3048 if (!mb.IsSpecialName)
3049 return null;
3051 string name = mb.Name;
3052 if (name.Length < 5)
3053 return null;
3055 if (name [3] != '_')
3056 return null;
3058 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3059 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3060 Type.FilterName, name.Substring (4));
3062 if (pi == null)
3063 return null;
3065 // This can happen when property is indexer (it can have same name but different parameters)
3066 foreach (PropertyInfo p in pi) {
3067 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3068 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3069 return p;
3074 return null;
3077 // Currently is designed to work with external types only
3078 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3080 if (!mb.IsSpecialName)
3081 return null;
3083 string name = mb.Name;
3084 if (name.Length < 5)
3085 return null;
3087 if (name.StartsWith ("add_"))
3088 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3090 if (name.StartsWith ("remove_"))
3091 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3093 return null;
3096 // Tests whether external method is really special
3097 public static bool IsSpecialMethod (MethodBase mb)
3099 if (!mb.IsSpecialName)
3100 return false;
3102 IMethodData md = TypeManager.GetMethod (mb);
3103 if (md != null)
3104 return (md is AbstractPropertyEventMethod || md is Operator);
3106 PropertyInfo pi = GetPropertyFromAccessor (mb);
3107 if (pi != null)
3108 return IsValidProperty (pi);
3110 if (GetEventFromAccessor (mb) != null)
3111 return true;
3113 string name = mb.Name;
3114 if (name.StartsWith ("op_"))
3115 return Operator.GetName (name) != null;
3117 return false;
3120 // Tests whether imported property is valid C# property.
3121 // TODO: It seems to me that we should do a lot of sanity tests before
3122 // we accept property as C# property
3123 static bool IsValidProperty (PropertyInfo pi)
3125 MethodInfo get_method = pi.GetGetMethod (true);
3126 MethodInfo set_method = pi.GetSetMethod (true);
3127 int g_count = 0;
3128 int s_count = 0;
3129 if (get_method != null && set_method != null) {
3130 g_count = get_method.GetParameters ().Length;
3131 s_count = set_method.GetParameters ().Length;
3132 if (g_count + 1 != s_count)
3133 return false;
3134 } else if (get_method != null) {
3135 g_count = get_method.GetParameters ().Length;
3136 } else if (set_method != null) {
3137 s_count = set_method.GetParameters ().Length;
3141 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3143 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
3144 if ((s_count > 1 || g_count > 0) && pa.IsDefined) {
3145 object[] o = pi.DeclaringType.GetCustomAttributes (pa.Type, false);
3146 if (o.Length == 0)
3147 return false;
3149 DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
3150 if (dma.MemberName != pi.Name)
3151 return false;
3152 if (get_method != null && "get_" + dma.MemberName != get_method.Name)
3153 return false;
3154 if (set_method != null && "set_" + dma.MemberName != set_method.Name)
3155 return false;
3158 return true;
3161 #endregion
3165 class InternalType
3167 public static readonly Type AnonymousMethod = typeof (AnonymousMethodBody);
3168 public static readonly Type Arglist = typeof (ArglistAccess);
3169 public static readonly Type Dynamic = new DynamicType ();
3170 public static readonly Type MethodGroup = typeof (MethodGroupExpr);
3173 /// <summary>
3174 /// There is exactly one instance of this class per type.
3175 /// </summary>
3176 public sealed class TypeHandle : IMemberContainer {
3177 public readonly IMemberContainer BaseType;
3179 readonly int id = ++next_id;
3180 static int next_id = 0;
3182 static TypeHandle ()
3184 Reset ();
3187 /// <summary>
3188 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3189 /// a TypeHandle yet, a new instance of it is created. This static method
3190 /// ensures that we'll only have one TypeHandle instance per type.
3191 /// </summary>
3192 private static TypeHandle GetTypeHandle (Type t)
3194 TypeHandle handle = (TypeHandle) type_hash [t];
3195 if (handle != null)
3196 return handle;
3198 handle = new TypeHandle (t);
3199 type_hash.Add (t, handle);
3200 return handle;
3203 public static MemberCache GetMemberCache (Type t)
3205 return GetTypeHandle (t).MemberCache;
3208 public static void CleanUp ()
3210 type_hash = null;
3213 public static void Reset ()
3215 type_hash = new PtrHashtable ();
3218 /// <summary>
3219 /// Returns the TypeHandle for TypeManager.object_type.
3220 /// </summary>
3221 public static IMemberContainer ObjectType {
3222 get {
3223 if (object_type != null)
3224 return object_type;
3226 object_type = GetTypeHandle (TypeManager.object_type);
3228 return object_type;
3232 /// <summary>
3233 /// Returns the TypeHandle for TypeManager.array_type.
3234 /// </summary>
3235 public static TypeHandle ArrayType {
3236 get {
3237 if (array_type != null)
3238 return array_type;
3240 array_type = GetTypeHandle (TypeManager.array_type);
3242 return array_type;
3246 private static PtrHashtable type_hash;
3248 private static TypeHandle object_type = null;
3249 private static TypeHandle array_type = null;
3251 private Type type;
3252 private string full_name;
3253 private bool is_interface;
3254 private MemberCache member_cache;
3255 private MemberCache base_cache;
3257 private TypeHandle (Type type)
3259 this.type = type;
3260 full_name = type.FullName != null ? type.FullName : type.Name;
3261 if (type.BaseType != null) {
3262 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3263 BaseType = base_cache.Container;
3264 } else if (type.IsInterface)
3265 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3266 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3267 this.member_cache = new MemberCache (this);
3270 // IMemberContainer methods
3272 public string Name {
3273 get {
3274 return full_name;
3278 public Type Type {
3279 get {
3280 return type;
3284 public MemberCache BaseCache {
3285 get {
3286 return base_cache;
3290 public bool IsInterface {
3291 get {
3292 return is_interface;
3296 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3298 MemberInfo [] members;
3300 if (type is GenericTypeParameterBuilder)
3301 return MemberList.Empty;
3303 #if MS_COMPATIBLE
3304 type = TypeManager.DropGenericTypeArguments (type);
3305 #endif
3306 if (mt == MemberTypes.Event)
3307 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3308 else
3309 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3310 null, null);
3312 if (members.Length == 0)
3313 return MemberList.Empty;
3315 Array.Reverse (members);
3316 return new MemberList (members);
3319 // IMemberFinder methods
3321 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3322 MemberFilter filter, object criteria)
3324 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3327 public MemberCache MemberCache {
3328 get {
3329 return member_cache;
3333 public override string ToString ()
3335 if (BaseType != null)
3336 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3337 else
3338 return "TypeHandle (" + id + "," + Name + ")";