monotouch uses the real HttpWebRequest
[mcs.git] / mcs / typemanager.cs
blob9d0363490d5caf5d82a451c1c83b0288d37b8c41
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;
105 // Expressions representing the internal types. Used during declaration
106 // definition.
108 static public TypeExpr system_object_expr, system_string_expr;
109 static public TypeExpr system_boolean_expr, system_decimal_expr;
110 static public TypeExpr system_single_expr, system_double_expr;
111 static public TypeExpr system_sbyte_expr, system_byte_expr;
112 static public TypeExpr system_int16_expr, system_uint16_expr;
113 static public TypeExpr system_int32_expr, system_uint32_expr;
114 static public TypeExpr system_int64_expr, system_uint64_expr;
115 static public TypeExpr system_char_expr, system_void_expr;
116 static public TypeExpr system_valuetype_expr;
117 static public TypeExpr system_intptr_expr;
118 public static TypeExpr expression_type_expr;
122 // These methods are called by code generated by the compiler
124 static public FieldInfo string_empty;
125 static public MethodInfo system_type_get_type_from_handle;
126 static public MethodInfo bool_movenext_void;
127 static public MethodInfo void_dispose_void;
128 static public MethodInfo void_monitor_enter_object;
129 static public MethodInfo void_monitor_exit_object;
130 static public MethodInfo void_initializearray_array_fieldhandle;
131 static public MethodInfo delegate_combine_delegate_delegate;
132 static public MethodInfo delegate_remove_delegate_delegate;
133 static public PropertyInfo int_get_offset_to_string_data;
134 static public MethodInfo int_interlocked_compare_exchange;
135 static public PropertyInfo ienumerator_getcurrent;
136 public static MethodInfo methodbase_get_type_from_handle;
137 public static MethodInfo methodbase_get_type_from_handle_generic;
138 public static MethodInfo fieldinfo_get_field_from_handle;
139 public static MethodInfo fieldinfo_get_field_from_handle_generic;
140 static public MethodInfo activator_create_instance;
143 // The constructors.
145 static public ConstructorInfo void_decimal_ctor_five_args;
146 static public ConstructorInfo void_decimal_ctor_int_arg;
148 static PtrHashtable builder_to_declspace;
150 static PtrHashtable builder_to_member_cache;
152 // <remarks>
153 // Tracks the interfaces implemented by typebuilders. We only
154 // enter those who do implement or or more interfaces
155 // </remarks>
156 static PtrHashtable builder_to_ifaces;
158 // <remarks>
159 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
160 // <remarks>
161 static Hashtable method_params;
163 // <remarks>
164 // A hash table from override methods to their base virtual method.
165 // <remarks>
166 static Hashtable method_overrides;
168 // <remarks>
169 // Keeps track of methods
170 // </remarks>
172 static Hashtable builder_to_method;
174 // <remarks>
175 // Contains all public types from referenced assemblies.
176 // This member is used only if CLS Compliance verification is required.
177 // </remarks>
178 public static Hashtable AllClsTopLevelTypes;
180 static Hashtable fieldbuilders_to_fields;
181 static Hashtable propertybuilder_to_property;
182 static Hashtable fields;
183 static Hashtable events;
184 static PtrHashtable assembly_internals_vis_attrs;
186 public static void CleanUp ()
188 // Lets get everything clean so that we can collect before generating code
189 builder_to_declspace = null;
190 builder_to_member_cache = null;
191 builder_to_ifaces = null;
192 builder_to_type_param = null;
193 method_params = null;
194 builder_to_method = null;
196 fields = null;
197 events = null;
198 type_hash = null;
199 propertybuilder_to_property = null;
201 TypeHandle.CleanUp ();
205 // These are expressions that represent some of the internal data types, used
206 // elsewhere
208 static void InitExpressionTypes ()
210 system_object_expr = new TypeLookupExpression ("System", "Object");
211 system_string_expr = new TypeLookupExpression ("System", "String");
212 system_boolean_expr = new TypeLookupExpression ("System", "Boolean");
213 system_decimal_expr = new TypeLookupExpression ("System", "Decimal");
214 system_single_expr = new TypeLookupExpression ("System", "Single");
215 system_double_expr = new TypeLookupExpression ("System", "Double");
216 system_sbyte_expr = new TypeLookupExpression ("System", "SByte");
217 system_byte_expr = new TypeLookupExpression ("System", "Byte");
218 system_int16_expr = new TypeLookupExpression ("System", "Int16");
219 system_uint16_expr = new TypeLookupExpression ("System", "UInt16");
220 system_int32_expr = new TypeLookupExpression ("System", "Int32");
221 system_uint32_expr = new TypeLookupExpression ("System", "UInt32");
222 system_int64_expr = new TypeLookupExpression ("System", "Int64");
223 system_uint64_expr = new TypeLookupExpression ("System", "UInt64");
224 system_char_expr = new TypeLookupExpression ("System", "Char");
225 system_void_expr = new TypeLookupExpression ("System", "Void");
226 system_valuetype_expr = new TypeLookupExpression ("System", "ValueType");
227 system_intptr_expr = new TypeLookupExpression ("System", "IntPtr");
230 static TypeManager ()
232 Reset ();
235 static public void Reset ()
237 InitExpressionTypes ();
239 builder_to_declspace = new PtrHashtable ();
240 builder_to_member_cache = new PtrHashtable ();
241 builder_to_method = new PtrHashtable ();
242 builder_to_type_param = new PtrHashtable ();
243 method_params = new PtrHashtable ();
244 method_overrides = new PtrHashtable ();
245 builder_to_ifaces = new PtrHashtable ();
247 fieldbuilders_to_fields = new Hashtable ();
248 propertybuilder_to_property = new Hashtable ();
249 fields = new Hashtable ();
250 type_hash = new DoubleHash ();
251 assembly_internals_vis_attrs = new PtrHashtable ();
252 iface_cache = new PtrHashtable ();
254 closure = new Closure ();
255 FilterWithClosure_delegate = new MemberFilter (closure.Filter);
257 // TODO: I am really bored by all this static stuff
258 system_type_get_type_from_handle =
259 bool_movenext_void =
260 void_dispose_void =
261 void_monitor_enter_object =
262 void_monitor_exit_object =
263 void_initializearray_array_fieldhandle =
264 delegate_combine_delegate_delegate =
265 delegate_remove_delegate_delegate =
266 int_interlocked_compare_exchange =
267 methodbase_get_type_from_handle =
268 methodbase_get_type_from_handle_generic =
269 fieldinfo_get_field_from_handle =
270 fieldinfo_get_field_from_handle_generic =
271 activator_create_instance = null;
273 int_get_offset_to_string_data =
274 ienumerator_getcurrent = null;
276 void_decimal_ctor_five_args =
277 void_decimal_ctor_int_arg = null;
279 isvolatile_type = null;
281 // to uncover regressions
282 AllClsTopLevelTypes = null;
285 public static void AddUserType (DeclSpace ds)
287 builder_to_declspace.Add (ds.TypeBuilder, ds);
291 // This entry point is used by types that we define under the covers
293 public static void RegisterBuilder (Type tb, Type [] ifaces)
295 if (ifaces != null)
296 builder_to_ifaces [tb] = ifaces;
299 public static void AddMethod (MethodBase builder, IMethodData method)
301 builder_to_method.Add (builder, method);
302 method_params.Add (builder, method.ParameterInfo);
305 public static IMethodData GetMethod (MethodBase builder)
307 return (IMethodData) builder_to_method [builder];
310 /// <summary>
311 /// Returns the DeclSpace whose Type is `t' or null if there is no
312 /// DeclSpace for `t' (ie, the Type comes from a library)
313 /// </summary>
314 public static DeclSpace LookupDeclSpace (Type t)
316 return builder_to_declspace [t] as DeclSpace;
319 /// <summary>
320 /// Returns the TypeContainer whose Type is `t' or null if there is no
321 /// TypeContainer for `t' (ie, the Type comes from a library)
322 /// </summary>
323 public static TypeContainer LookupTypeContainer (Type t)
325 return builder_to_declspace [t] as TypeContainer;
328 public static MemberCache LookupMemberCache (Type t)
330 if (t.Module == RootContext.ToplevelTypes.Builder) {
331 DeclSpace container = (DeclSpace)builder_to_declspace [t];
332 if (container != null)
333 return container.MemberCache;
336 #if GMCS_SOURCE
337 if (t is GenericTypeParameterBuilder) {
338 TypeParameter container = builder_to_type_param [t] as TypeParameter;
340 if (container != null)
341 return container.MemberCache;
343 #endif
345 return TypeHandle.GetMemberCache (t);
348 public static MemberCache LookupBaseInterfacesCache (Type t)
350 Type [] ifaces = GetInterfaces (t);
352 if (ifaces != null && ifaces.Length == 1)
353 return LookupMemberCache (ifaces [0]);
355 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
356 MemberCache cache = builder_to_member_cache [t] as MemberCache;
357 if (cache != null)
358 return cache;
360 cache = new MemberCache (ifaces);
361 builder_to_member_cache.Add (t, cache);
362 return cache;
365 public static TypeContainer LookupInterface (Type t)
367 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
368 if ((tc == null) || (tc.Kind != Kind.Interface))
369 return null;
371 return tc;
374 public static Delegate LookupDelegate (Type t)
376 return builder_to_declspace [t] as Delegate;
379 public static Class LookupClass (Type t)
381 return (Class) builder_to_declspace [t];
385 // We use this hash for multiple kinds of constructed types:
387 // (T, "&") Given T, get T &
388 // (T, "*") Given T, get T *
389 // (T, "[]") Given T and a array dimension, get T []
390 // (T, X) Given a type T and a simple name X, get the type T+X
392 // Accessibility tests, if necessary, should be done by the user
394 static DoubleHash type_hash = new DoubleHash ();
397 // Gets the reference to T version of the Type (T&)
399 public static Type GetReferenceType (Type t)
401 #if GMCS_SOURCE
402 return t.MakeByRefType ();
403 #else
404 return GetConstructedType (t, "&");
405 #endif
409 // Gets the pointer to T version of the Type (T*)
411 public static Type GetPointerType (Type t)
413 return GetConstructedType (t, "*");
416 public static Type GetConstructedType (Type t, string dim)
418 object ret = null;
419 if (type_hash.Lookup (t, dim, out ret))
420 return (Type) ret;
422 ret = t.Module.GetType (t.ToString () + dim);
423 if (ret != null) {
424 type_hash.Insert (t, dim, ret);
425 return (Type) ret;
428 if (dim == "&") {
429 ret = GetReferenceType (t);
430 type_hash.Insert (t, dim, ret);
431 return (Type) ret;
434 #if GMCS_SOURCE
435 if (t.IsGenericParameter || t.IsGenericType) {
436 int pos = 0;
437 Type result = t;
438 while ((pos < dim.Length) && (dim [pos] == '[')) {
439 pos++;
441 if (dim [pos] == ']') {
442 result = result.MakeArrayType ();
443 pos++;
445 if (pos < dim.Length)
446 continue;
448 type_hash.Insert (t, dim, result);
449 return result;
452 int rank = 0;
453 while (dim [pos] == ',') {
454 pos++; rank++;
457 if ((dim [pos] != ']') || (pos != dim.Length-1))
458 break;
460 result = result.MakeArrayType (rank + 1);
461 type_hash.Insert (t, dim, result);
462 return result;
465 #endif
467 type_hash.Insert (t, dim, null);
468 return null;
471 public static Type GetNestedType (Type t, string name)
473 object ret = null;
474 if (!type_hash.Lookup (t, name, out ret)) {
475 ret = t.GetNestedType (name,
476 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
477 type_hash.Insert (t, name, ret);
479 return (Type) ret;
482 /// <summary>
483 /// Fills static table with exported types from all referenced assemblies.
484 /// This information is required for CLS Compliance tests.
485 /// </summary>
486 public static void LoadAllImportedTypes ()
488 AllClsTopLevelTypes = new Hashtable (1500);
489 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
490 foreach (Type t in a.GetExportedTypes ()) {
491 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
496 public static bool NamespaceClash (string name, Location loc)
498 if (!GlobalRootNamespace.Instance.IsNamespace (name))
499 return false;
501 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
502 return true;
505 /// <summary>
506 /// Returns the C# name of a type if possible, or the full type name otherwise
507 /// </summary>
508 static public string CSharpName (Type t)
510 if (t == null_type)
511 return "null";
513 if (t == typeof (ArglistAccess))
514 return "__arglist";
516 if (t == typeof (AnonymousMethodBody))
517 return "anonymous method";
519 if (t == typeof (MethodGroupExpr))
520 return "method group";
522 if (IsDynamicType (t))
523 return "dynamic";
525 if (t == null)
526 return "internal error";
528 return CSharpName (GetFullName (t), t);
531 static readonly char [] elements = new char [] { '*', '[' };
533 public static string CSharpName (string name, Type type)
535 if (name.Length > 10) {
536 string s;
537 switch (name) {
538 case "System.Int32": s = "int"; break;
539 case "System.Int64": s = "long"; break;
540 case "System.String": s = "string"; break;
541 case "System.Boolean": s = "bool"; break;
542 case "System.Void": s = "void"; break;
543 case "System.Object": s = "object"; break;
544 case "System.UInt32": s = "uint"; break;
545 case "System.Int16": s = "short"; break;
546 case "System.UInt16": s = "ushort"; break;
547 case "System.UInt64": s = "ulong"; break;
548 case "System.Single": s = "float"; break;
549 case "System.Double": s = "double"; break;
550 case "System.Decimal": s = "decimal"; break;
551 case "System.Char": s = "char"; break;
552 case "System.Byte": s = "byte"; break;
553 case "System.SByte": s = "sbyte"; break;
554 default: s = null; break;
557 if (s != null) {
559 // Predefined names can come from mscorlib only
561 if (type == null || type.Module.Name == "mscorlib.dll" || !RootContext.StdLib)
562 return s;
564 return name;
567 if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
568 return AnonymousTypeClass.SignatureForError;
570 int idx = name.IndexOfAny (elements, 10);
571 if (idx > 0)
572 return CSharpName (name.Substring (0, idx), type) + name.Substring (idx);
575 return name.Replace ('+', '.');
578 static public string CSharpName (Type[] types)
580 if (types.Length == 0)
581 return string.Empty;
583 StringBuilder sb = new StringBuilder ();
584 for (int i = 0; i < types.Length; ++i) {
585 if (i > 0)
586 sb.Append (", ");
588 sb.Append (CSharpName (types [i]));
590 return sb.ToString ();
593 /// <summary>
594 /// Returns the signature of the method with full namespace classification
595 /// </summary>
596 static public string GetFullNameSignature (MemberInfo mi)
598 PropertyInfo pi = mi as PropertyInfo;
599 if (pi != null) {
600 MethodBase pmi = pi.GetGetMethod (true);
601 if (pmi == null)
602 pmi = pi.GetSetMethod (true);
603 if (GetParameterData (pmi).Count > 0)
604 mi = pmi;
606 return (mi is MethodBase)
607 ? CSharpSignature (mi as MethodBase)
608 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
611 #if GMCS_SOURCE
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 ();
672 #else
673 public static string GetFullName (Type t)
675 return t.FullName;
677 #endif
679 public static string RemoveGenericArity (string from)
681 int i = from.IndexOf ('`');
682 if (i > 0)
683 return from.Substring (0, i);
684 return from;
687 /// <summary>
688 /// When we need to report accessors as well
689 /// </summary>
690 static public string CSharpSignature (MethodBase mb)
692 return CSharpSignature (mb, false);
695 /// <summary>
696 /// Returns the signature of the method
697 /// </summary>
698 static public string CSharpSignature (MethodBase mb, bool show_accessor)
700 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
701 sig.Append ('.');
703 AParametersCollection iparams = GetParameterData (mb);
704 string parameters = iparams.GetSignatureForError ();
705 int accessor_end = 0;
707 if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
708 string op_name = Operator.GetName (mb.Name);
709 if (op_name != null) {
710 if (op_name == "explicit" || op_name == "implicit") {
711 sig.Append (op_name);
712 sig.Append (" operator ");
713 sig.Append (CSharpName (((MethodInfo)mb).ReturnType));
714 } else {
715 sig.Append ("operator ");
716 sig.Append (op_name);
718 sig.Append (parameters);
719 return sig.ToString ();
722 bool is_getter = mb.Name.StartsWith ("get_");
723 bool is_setter = mb.Name.StartsWith ("set_");
724 if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
725 accessor_end = 3;
726 } else if (mb.Name.StartsWith ("remove_")) {
727 accessor_end = 6;
730 // Is indexer
731 if (iparams.Count > (is_getter ? 0 : 1)) {
732 sig.Append ("this[");
733 if (is_getter)
734 sig.Append (parameters.Substring (1, parameters.Length - 2));
735 else
736 sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
737 sig.Append (']');
738 } else {
739 sig.Append (mb.Name.Substring (accessor_end + 1));
741 } else {
742 if (mb.Name == ".ctor")
743 sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
744 else {
745 sig.Append (mb.Name);
747 if (IsGenericMethod (mb)) {
748 Type[] args = GetGenericArguments (mb);
749 sig.Append ('<');
750 for (int i = 0; i < args.Length; i++) {
751 if (i > 0)
752 sig.Append (',');
753 sig.Append (CSharpName (args [i]));
755 sig.Append ('>');
759 sig.Append (parameters);
762 if (show_accessor && accessor_end > 0) {
763 sig.Append ('.');
764 sig.Append (mb.Name.Substring (0, accessor_end));
767 return sig.ToString ();
770 public static string GetMethodName (MethodInfo m)
772 if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
773 return m.Name;
775 return MemberName.MakeName (m.Name, TypeManager.GetGenericArguments (m).Length);
778 static public string CSharpSignature (EventInfo ei)
780 return CSharpName (ei.DeclaringType) + "." + ei.Name;
784 // Looks up a type, and aborts if it is not found. This is used
785 // by predefined types required by the compiler
787 public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required)
789 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
790 Expression expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
792 if (expr == null) {
793 if (required) {
794 Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
795 ns_name, name);
797 return null;
800 Type t = expr.Type;
801 if (RootContext.StdLib || t == null || !required)
802 return t;
804 // TODO: All predefined imported types have to have correct signature
805 if (t.Module != RootContext.ToplevelTypes.Builder)
806 return t;
808 DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
809 if (ds is Delegate) {
810 if (type_kind == Kind.Delegate)
811 return t;
812 } else {
813 TypeContainer tc = (TypeContainer)ds;
814 if (tc.Kind == type_kind)
815 return t;
818 Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
819 ns_name, name);
820 return null;
823 static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
825 const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
827 MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
828 if (members != null) {
829 for (int i = 0; i < members.Length; ++i) {
830 MemberInfo member = members [i];
831 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
832 MethodBase mb = member as MethodBase;
833 if (mb == null)
834 continue;
836 AParametersCollection pd = TypeManager.GetParameterData (mb);
837 if (IsEqual (pd.Types, args))
838 return member;
840 if (mt == MemberTypes.Field) {
841 FieldInfo fi = member as FieldInfo;
842 if (fi == null)
843 continue;
845 if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
846 continue;
848 return member;
851 if (mt == MemberTypes.Property) {
852 PropertyInfo pi = member as PropertyInfo;
853 if (pi == null)
854 continue;
856 if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
857 continue;
859 return member;
864 string method_args = null;
865 if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
866 method_args = "(" + TypeManager.CSharpName (args) + ")";
868 Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
869 TypeManager.CSharpName (t), name, method_args);
871 return null;
875 // Returns the ConstructorInfo for "args"
877 public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
879 return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
883 // Returns the MethodInfo for a method named `name' defined
884 // in type `t' which takes arguments of types `args'
886 public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
888 return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
891 public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
893 return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
896 public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
898 return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
901 /// <remarks>
902 /// The types have to be initialized after the initial
903 /// population of the type has happened (for example, to
904 /// bootstrap the corlib.dll
905 /// </remarks>
906 public static bool InitCoreTypes ()
908 object_type = CoreLookupType ("System", "Object", Kind.Class, true);
909 system_object_expr.Type = object_type;
910 value_type = CoreLookupType ("System", "ValueType", Kind.Class, true);
911 system_valuetype_expr.Type = value_type;
912 attribute_type = CoreLookupType ("System", "Attribute", Kind.Class, true);
914 int32_type = CoreLookupType ("System", "Int32", Kind.Struct, true);
915 system_int32_expr.Type = int32_type;
916 int64_type = CoreLookupType ("System", "Int64", Kind.Struct, true);
917 system_int64_expr.Type = int64_type;
918 uint32_type = CoreLookupType ("System", "UInt32", Kind.Struct, true);
919 system_uint32_expr.Type = uint32_type;
920 uint64_type = CoreLookupType ("System", "UInt64", Kind.Struct, true);
921 system_uint64_expr.Type = uint64_type;
922 byte_type = CoreLookupType ("System", "Byte", Kind.Struct, true);
923 system_byte_expr.Type = byte_type;
924 sbyte_type = CoreLookupType ("System", "SByte", Kind.Struct, true);
925 system_sbyte_expr.Type = sbyte_type;
926 short_type = CoreLookupType ("System", "Int16", Kind.Struct, true);
927 system_int16_expr.Type = short_type;
928 ushort_type = CoreLookupType ("System", "UInt16", Kind.Struct, true);
929 system_uint16_expr.Type = ushort_type;
931 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator", Kind.Interface, true);
932 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable", Kind.Interface, true);
933 idisposable_type = CoreLookupType ("System", "IDisposable", Kind.Interface, true);
935 // HACK: DefineType immediately resolves iterators (very wrong)
936 generic_ienumerator_type = CoreLookupType ("System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
938 char_type = CoreLookupType ("System", "Char", Kind.Struct, true);
939 system_char_expr.Type = char_type;
940 string_type = CoreLookupType ("System", "String", Kind.Class, true);
941 system_string_expr.Type = string_type;
942 float_type = CoreLookupType ("System", "Single", Kind.Struct, true);
943 system_single_expr.Type = float_type;
944 double_type = CoreLookupType ("System", "Double", Kind.Struct, true);
945 system_double_expr.Type = double_type;
946 decimal_type = CoreLookupType ("System", "Decimal", Kind.Struct, true);
947 system_decimal_expr.Type = decimal_type;
948 bool_type = CoreLookupType ("System", "Boolean", Kind.Struct, true);
949 system_boolean_expr.Type = bool_type;
950 intptr_type = CoreLookupType ("System", "IntPtr", Kind.Struct, true);
951 system_intptr_expr.Type = intptr_type;
952 uintptr_type = CoreLookupType ("System", "UIntPtr", Kind.Struct, true);
954 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate", Kind.Class, true);
955 delegate_type = CoreLookupType ("System", "Delegate", Kind.Class, true);
957 enum_type = CoreLookupType ("System", "Enum", Kind.Class, true);
958 array_type = CoreLookupType ("System", "Array", Kind.Class, true);
959 void_type = CoreLookupType ("System", "Void", Kind.Struct, true);
960 system_void_expr.Type = void_type;
961 type_type = CoreLookupType ("System", "Type", Kind.Class, true);
962 exception_type = CoreLookupType ("System", "Exception", Kind.Class, true);
964 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle", Kind.Struct, true);
965 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle", Kind.Struct, true);
967 PredefinedAttributes.Get.ParamArray.Resolve (false);
968 PredefinedAttributes.Get.Out.Resolve (false);
970 return Report.Errors == 0;
974 // Initializes optional core types
976 public static void InitOptionalCoreTypes ()
979 // These are only used for compare purposes
981 null_type = typeof (NullLiteral);
983 void_ptr_type = GetPointerType (void_type);
986 // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
987 // types cache with incorrect accessiblity when any of optional types is internal.
989 PredefinedAttributes.Get.Initialize ();
991 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle", Kind.Struct, false);
992 asynccallback_type = CoreLookupType ("System", "AsyncCallback", Kind.Delegate, false);
993 iasyncresult_type = CoreLookupType ("System", "IAsyncResult", Kind.Interface, false);
994 typed_reference_type = CoreLookupType ("System", "TypedReference", Kind.Struct, false);
995 arg_iterator_type = CoreLookupType ("System", "ArgIterator", Kind.Struct, false);
996 mbr_type = CoreLookupType ("System", "MarshalByRefObject", Kind.Class, false);
999 // Optional attributes, used for error reporting only
1001 //if (PredefinedAttributes.Get.Obsolete.IsDefined) {
1002 // Class c = TypeManager.LookupClass (PredefinedAttributes.Get.Obsolete.Type);
1003 // if (c != null)
1004 // c.Define ();
1007 generic_ilist_type = CoreLookupType ("System.Collections.Generic", "IList`1", Kind.Interface, false);
1008 generic_icollection_type = CoreLookupType ("System.Collections.Generic", "ICollection`1", Kind.Interface, false);
1009 generic_ienumerable_type = CoreLookupType ("System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
1010 generic_nullable_type = CoreLookupType ("System", "Nullable`1", Kind.Struct, false);
1013 // Optional types which are used as types and for member lookup
1015 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
1017 // New in .NET 3.5
1018 // Note: extension_attribute_type is already loaded
1019 expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", Kind.Class, false);
1021 if (!RootContext.StdLib) {
1023 // HACK: When building Mono corlib mcs uses loaded mscorlib which
1024 // has different predefined types and this method sets mscorlib types
1025 // to be same to avoid any type check errors.
1028 Type type = typeof (Type);
1029 Type [] system_4_type_arg = { type, type, type, type };
1031 MethodInfo set_corlib_type_builders =
1032 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
1033 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
1034 system_4_type_arg, null);
1036 if (set_corlib_type_builders != null) {
1037 object[] args = new object [4];
1038 args [0] = object_type;
1039 args [1] = value_type;
1040 args [2] = enum_type;
1041 args [3] = void_type;
1043 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1044 } else {
1045 Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
1046 TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
1047 TypeManager.CSharpName (system_4_type_arg));
1052 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1054 /// <remarks>
1055 /// This is the "old", non-cache based FindMembers() function. We cannot use
1056 /// the cache here because there is no member name argument.
1057 /// </remarks>
1058 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1059 MemberFilter filter, object criteria)
1061 #if MS_COMPATIBLE && GMCS_SOURCE
1062 if (t.IsGenericType)
1063 t = t.GetGenericTypeDefinition ();
1064 #endif
1066 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1069 // `builder_to_declspace' contains all dynamic types.
1071 if (decl != null) {
1072 MemberList list;
1073 Timer.StartTimer (TimerType.FindMembers);
1074 list = decl.FindMembers (mt, bf, filter, criteria);
1075 Timer.StopTimer (TimerType.FindMembers);
1076 return list;
1080 // We have to take care of arrays specially, because GetType on
1081 // a TypeBuilder array will return a Type, not a TypeBuilder,
1082 // and we can not call FindMembers on this type.
1084 if (
1085 #if MS_COMPATIBLE && GMCS_SOURCE
1086 !t.IsGenericType &&
1087 #endif
1088 t.IsSubclassOf (TypeManager.array_type))
1089 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1091 #if GMCS_SOURCE
1092 if (t is GenericTypeParameterBuilder) {
1093 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1095 Timer.StartTimer (TimerType.FindMembers);
1096 MemberList list = tparam.FindMembers (
1097 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1098 Timer.StopTimer (TimerType.FindMembers);
1099 return list;
1101 #endif
1104 // Since FindMembers will not lookup both static and instance
1105 // members, we emulate this behaviour here.
1107 if ((bf & instance_and_static) == instance_and_static){
1108 MemberInfo [] i_members = t.FindMembers (
1109 mt, bf & ~BindingFlags.Static, filter, criteria);
1111 int i_len = i_members.Length;
1112 if (i_len == 1){
1113 MemberInfo one = i_members [0];
1116 // If any of these are present, we are done!
1118 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1119 return new MemberList (i_members);
1122 MemberInfo [] s_members = t.FindMembers (
1123 mt, bf & ~BindingFlags.Instance, filter, criteria);
1125 int s_len = s_members.Length;
1126 if (i_len > 0 || s_len > 0)
1127 return new MemberList (i_members, s_members);
1128 else {
1129 if (i_len > 0)
1130 return new MemberList (i_members);
1131 else
1132 return new MemberList (s_members);
1136 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1140 /// <summary>
1141 /// This method is only called from within MemberLookup. It tries to use the member
1142 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1143 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1144 /// our return value will already contain all inherited members and the caller don't need
1145 /// to check base classes and interfaces anymore.
1146 /// </summary>
1147 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1148 string name, out bool used_cache)
1150 MemberCache cache;
1153 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1154 // and we can ask the DeclSpace for the MemberCache.
1156 #if MS_COMPATIBLE
1157 if (t.Assembly == CodeGen.Assembly.Builder) {
1158 if (t.IsGenericParameter) {
1159 TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
1161 used_cache = true;
1162 if (tparam.MemberCache == null)
1163 return new MemberInfo[0];
1165 return tparam.MemberCache.FindMembers (
1166 mt, bf, name, FilterWithClosure_delegate, null);
1170 // We have to take care of arrays specially, because GetType on
1171 // a TypeBuilder array will return a Type, not a TypeBuilder,
1172 // and we can not call FindMembers on this type.
1174 if (t.IsArray) {
1175 used_cache = true;
1176 return TypeHandle.ArrayType.MemberCache.FindMembers (
1177 mt, bf, name, FilterWithClosure_delegate, null);
1180 if (t.IsGenericType && !t.IsGenericTypeDefinition)
1181 t = t.GetGenericTypeDefinition ();
1182 #else
1183 if (t is TypeBuilder) {
1184 #endif
1185 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1186 cache = decl.MemberCache;
1189 // If this DeclSpace has a MemberCache, use it.
1192 if (cache != null) {
1193 used_cache = true;
1194 return cache.FindMembers (
1195 mt, bf, name, FilterWithClosure_delegate, null);
1198 // If there is no MemberCache, we need to use the "normal" FindMembers.
1199 // Note, this is a VERY uncommon route!
1201 MemberList list;
1202 Timer.StartTimer (TimerType.FindMembers);
1203 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1204 FilterWithClosure_delegate, name);
1205 Timer.StopTimer (TimerType.FindMembers);
1206 used_cache = false;
1207 return (MemberInfo []) list;
1211 // We have to take care of arrays specially, because GetType on
1212 // a TypeBuilder array will return a Type, not a TypeBuilder,
1213 // and we can not call FindMembers on this type.
1215 if (t.IsArray) {
1216 used_cache = true;
1217 return TypeHandle.ArrayType.MemberCache.FindMembers (
1218 mt, bf, name, FilterWithClosure_delegate, null);
1221 #if GMCS_SOURCE
1222 if (t is GenericTypeParameterBuilder) {
1223 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1225 used_cache = true;
1226 if (tparam.MemberCache == null)
1227 return new MemberInfo [0];
1229 return tparam.MemberCache.FindMembers (
1230 mt, bf, name, FilterWithClosure_delegate, null);
1232 #endif
1234 if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
1236 // This happens if we're resolving a class'es base class and interfaces
1237 // in TypeContainer.DefineType(). At this time, the types aren't
1238 // populated yet, so we can't use the cache.
1240 MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1241 FilterWithClosure_delegate, name);
1242 used_cache = false;
1243 return info;
1247 // This call will always succeed. There is exactly one TypeHandle instance per
1248 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1249 // the corresponding MemberCache.
1251 cache = TypeHandle.GetMemberCache (t);
1253 used_cache = true;
1254 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1257 public static bool IsBuiltinType (Type t)
1259 t = TypeToCoreType (t);
1260 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1261 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1262 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1263 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1264 return true;
1265 else
1266 return false;
1270 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1271 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1273 public static bool IsPrimitiveType (Type t)
1275 return (t == int32_type || t == uint32_type ||
1276 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1277 t == char_type || t == short_type || t == bool_type ||
1278 t == sbyte_type || t == byte_type || t == ushort_type);
1281 public static bool IsDelegateType (Type t)
1283 if (TypeManager.IsGenericParameter (t))
1284 return false;
1286 if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
1287 return false;
1289 t = DropGenericTypeArguments (t);
1290 return IsSubclassOf (t, TypeManager.delegate_type);
1294 // Is a type of dynamic type
1296 public static bool IsDynamicType (Type t)
1298 if (t == InternalType.Dynamic)
1299 return true;
1301 if (t != object_type)
1302 return false;
1304 if (t.Module == RootContext.ToplevelTypes.Builder)
1305 return false;
1307 PredefinedAttribute pa = PredefinedAttributes.Get.Dynamic;
1308 if (pa == null)
1309 return false;
1311 object[] res = t.GetCustomAttributes (pa.Type, false);
1312 return res != null && res.Length != 0;
1315 public static bool IsEnumType (Type t)
1317 t = DropGenericTypeArguments (t);
1318 return t.BaseType == TypeManager.enum_type;
1321 public static bool IsBuiltinOrEnum (Type t)
1323 if (IsBuiltinType (t))
1324 return true;
1326 if (IsEnumType (t))
1327 return true;
1329 return false;
1332 public static bool IsAttributeType (Type t)
1334 return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
1338 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1340 // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
1341 public static bool IsUnmanagedType (Type t)
1343 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1344 if (ds != null)
1345 return ds.IsUnmanagedType ();
1347 // builtins that are not unmanaged types
1348 if (t == TypeManager.object_type || t == TypeManager.string_type)
1349 return false;
1351 if (IsGenericType (t) || IsGenericParameter (t))
1352 return false;
1354 if (IsBuiltinOrEnum (t))
1355 return true;
1357 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1358 if (t.IsPointer)
1359 return IsUnmanagedType (GetElementType (t));
1361 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1362 if (t.IsArray)
1363 return false;
1365 if (!IsValueType (t))
1366 return false;
1368 for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
1369 if (IsGenericTypeDefinition (p))
1370 return false;
1373 bool retval = true;
1375 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1377 foreach (FieldInfo f in fields){
1378 if (!IsUnmanagedType (f.FieldType)){
1379 retval = false;
1384 return retval;
1388 // Null is considered to be a reference type
1390 public static bool IsReferenceType (Type t)
1392 if (TypeManager.IsGenericParameter (t)) {
1393 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1394 if (constraints == null)
1395 return false;
1397 return constraints.IsReferenceType;
1400 return !IsStruct (t) && !IsEnumType (t);
1403 public static bool IsValueType (Type t)
1405 if (TypeManager.IsGenericParameter (t)) {
1406 GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
1407 if (constraints == null)
1408 return false;
1410 return constraints.IsValueType;
1413 return IsStruct (t) || IsEnumType (t);
1416 public static bool IsStruct (Type t)
1418 return t.BaseType == value_type && t != enum_type && t.IsSealed;
1421 public static bool IsInterfaceType (Type t)
1423 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1424 if (tc == null)
1425 return false;
1427 return tc.Kind == Kind.Interface;
1430 public static bool IsSubclassOf (Type type, Type base_type)
1432 TypeParameter tparam = LookupTypeParameter (type);
1433 TypeParameter pparam = LookupTypeParameter (base_type);
1435 if ((tparam != null) && (pparam != null)) {
1436 if (tparam == pparam)
1437 return true;
1439 return tparam.IsSubclassOf (base_type);
1442 #if MS_COMPATIBLE && GMCS_SOURCE
1443 if (type.IsGenericType)
1444 type = type.GetGenericTypeDefinition ();
1445 #endif
1447 if (type.IsSubclassOf (base_type))
1448 return true;
1450 do {
1451 if (IsEqual (type, base_type))
1452 return true;
1454 type = type.BaseType;
1455 } while (type != null);
1457 return false;
1460 public static bool IsPrivateAccessible (Type type, Type parent)
1462 if (type == null)
1463 return false;
1465 if (type.Equals (parent))
1466 return true;
1468 return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
1471 public static bool IsFamilyAccessible (Type type, Type parent)
1473 TypeParameter tparam = LookupTypeParameter (type);
1474 TypeParameter pparam = LookupTypeParameter (parent);
1476 if ((tparam != null) && (pparam != null)) {
1477 if (tparam == pparam)
1478 return true;
1480 return tparam.IsSubclassOf (parent);
1483 do {
1484 if (IsInstantiationOfSameGenericType (type, parent))
1485 return true;
1487 type = type.BaseType;
1488 } while (type != null);
1490 return false;
1494 // Checks whether `type' is a subclass or nested child of `base_type'.
1496 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1498 do {
1499 if (IsFamilyAccessible (type, base_type))
1500 return true;
1502 // Handle nested types.
1503 type = type.DeclaringType;
1504 } while (type != null);
1506 return false;
1510 // Checks whether `type' is a nested child of `parent'.
1512 public static bool IsNestedChildOf (Type type, Type parent)
1514 if (type == null)
1515 return false;
1517 type = DropGenericTypeArguments (type);
1518 parent = DropGenericTypeArguments (parent);
1520 if (IsEqual (type, parent))
1521 return false;
1523 type = type.DeclaringType;
1524 while (type != null) {
1525 if (IsEqual (type, parent))
1526 return true;
1528 type = type.DeclaringType;
1531 return false;
1534 public static bool IsSpecialType (Type t)
1536 return t == arg_iterator_type || t == typed_reference_type;
1540 // Checks whether `extern_type' is friend of the output assembly
1542 public static bool IsThisOrFriendAssembly (Assembly assembly)
1544 if (assembly == CodeGen.Assembly.Builder)
1545 return true;
1547 if (assembly_internals_vis_attrs.Contains (assembly))
1548 return (bool)(assembly_internals_vis_attrs [assembly]);
1550 PredefinedAttribute pa = PredefinedAttributes.Get.InternalsVisibleTo;
1551 // HACK: Do very early resolve of SRE type checking
1552 if (pa.Type == null)
1553 pa.Resolve (true);
1555 if (!pa.IsDefined)
1556 return false;
1558 object [] attrs = assembly.GetCustomAttributes (pa.Type, false);
1559 if (attrs.Length == 0) {
1560 assembly_internals_vis_attrs.Add (assembly, false);
1561 return false;
1564 bool is_friend = false;
1566 AssemblyName this_name = CodeGen.Assembly.Name;
1567 byte [] this_token = this_name.GetPublicKeyToken ();
1568 foreach (InternalsVisibleToAttribute attr in attrs) {
1569 if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
1570 continue;
1572 AssemblyName aname = null;
1573 try {
1574 #if GMCS_SOURCE
1575 aname = new AssemblyName (attr.AssemblyName);
1576 #else
1577 throw new NotSupportedException ();
1578 #endif
1579 } catch (FileLoadException) {
1580 } catch (ArgumentException) {
1583 if (aname == null || aname.Name != this_name.Name)
1584 continue;
1586 byte [] key_token = aname.GetPublicKeyToken ();
1587 if (key_token != null) {
1588 if (this_token.Length == 0) {
1589 // Same name, but assembly is not strongnamed
1590 Error_FriendAccessNameNotMatching (aname.FullName);
1591 break;
1594 if (!CompareKeyTokens (this_token, key_token))
1595 continue;
1598 is_friend = true;
1599 break;
1602 assembly_internals_vis_attrs.Add (assembly, is_friend);
1603 return is_friend;
1606 static bool CompareKeyTokens (byte [] token1, byte [] token2)
1608 for (int i = 0; i < token1.Length; i++)
1609 if (token1 [i] != token2 [i])
1610 return false;
1612 return true;
1615 static void Error_FriendAccessNameNotMatching (string other_name)
1617 Report.Error (281,
1618 "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",
1619 other_name, CodeGen.Assembly.Name.FullName);
1623 // Do the right thing when returning the element type of an
1624 // array type based on whether we are compiling corlib or not
1626 public static Type GetElementType (Type t)
1628 if (RootContext.StdLib)
1629 return t.GetElementType ();
1630 else
1631 return TypeToCoreType (t.GetElementType ());
1634 /// <summary>
1635 /// This method is not implemented by MS runtime for dynamic types
1636 /// </summary>
1637 public static bool HasElementType (Type t)
1639 return t.IsArray || t.IsPointer || t.IsByRef;
1642 public static Type GetEnumUnderlyingType (Type t)
1644 t = DropGenericTypeArguments (t);
1645 Enum e = LookupTypeContainer (t) as Enum;
1646 if (e != null)
1647 return e.UnderlyingType;
1649 // TODO: cache it ?
1650 FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
1651 if (fi == null)
1652 return TypeManager.int32_type;
1654 return TypeToCoreType (fi.FieldType);
1657 /// <summary>
1658 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1659 /// </summary>
1661 /// <remarks>
1662 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1663 /// for anything which is dynamic, and we need this in a number of places,
1664 /// we register this information here, and use it afterwards.
1665 /// </remarks>
1666 static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
1668 method_params.Add (mb, ip);
1671 static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
1673 method_params.Add (pb, p);
1676 static public AParametersCollection GetParameterData (MethodBase mb)
1678 AParametersCollection pd = (AParametersCollection) method_params [mb];
1679 if (pd == null) {
1680 #if MS_COMPATIBLE
1681 if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
1682 MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
1683 pd = GetParameterData (mi);
1685 if (mi.IsGenericMethod)
1686 pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
1687 else
1688 pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
1690 method_params.Add (mb, pd);
1691 return pd;
1694 if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
1695 throw new InternalErrorException ("Parameters are not registered for method `{0}'",
1696 TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
1699 pd = ParametersImported.Create (mb);
1700 #else
1701 MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
1702 if (generic != mb) {
1703 pd = TypeManager.GetParameterData (generic);
1704 pd = ParametersImported.Create (pd, mb);
1705 } else {
1706 pd = ParametersImported.Create (mb);
1708 #endif
1709 method_params.Add (mb, pd);
1711 return pd;
1714 public static AParametersCollection GetParameterData (PropertyInfo pi)
1716 AParametersCollection pd = (AParametersCollection)method_params [pi];
1717 if (pd == null) {
1718 if (pi is PropertyBuilder)
1719 return ParametersCompiled.EmptyReadOnlyParameters;
1721 ParameterInfo [] p = pi.GetIndexParameters ();
1722 if (p == null)
1723 return ParametersCompiled.EmptyReadOnlyParameters;
1725 pd = ParametersImported.Create (p, null);
1726 method_params.Add (pi, pd);
1729 return pd;
1732 public static AParametersCollection GetDelegateParameters (Type t)
1734 Delegate d = builder_to_declspace [t] as Delegate;
1735 if (d != null)
1736 return d.Parameters;
1738 MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t);
1739 return GetParameterData (invoke_mb);
1742 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1744 if (!method_overrides.Contains (override_method))
1745 method_overrides [override_method] = base_method;
1746 if (method_overrides [override_method] != base_method)
1747 throw new InternalErrorException ("Override mismatch: " + override_method);
1750 static public bool IsOverride (MethodBase m)
1752 m = DropGenericMethodArguments (m);
1754 return m.IsVirtual &&
1755 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1756 (m is MethodBuilder || method_overrides.Contains (m));
1759 static public MethodBase TryGetBaseDefinition (MethodBase m)
1761 m = DropGenericMethodArguments (m);
1763 return (MethodBase) method_overrides [m];
1766 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1768 fields.Add (fb, ic);
1771 public static IConstant GetConstant (FieldInfo fb)
1773 if (fb == null)
1774 return null;
1776 return (IConstant)fields [fb];
1779 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1781 propertybuilder_to_property.Add (pi, pb);
1784 public static PropertyBase GetProperty (PropertyInfo pi)
1786 return (PropertyBase)propertybuilder_to_property [pi];
1789 static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
1791 fieldbuilders_to_fields.Add (fb, f);
1795 // The return value can be null; This will be the case for
1796 // auxiliary FieldBuilders created by the compiler that have no
1797 // real field being declared on the source code
1799 static public FieldBase GetField (FieldInfo fb)
1801 #if GMCS_SOURCE
1802 fb = GetGenericFieldDefinition (fb);
1803 #endif
1804 return (FieldBase) fieldbuilders_to_fields [fb];
1807 static public MethodInfo GetAddMethod (EventInfo ei)
1809 if (ei is MyEventBuilder) {
1810 return ((MyEventBuilder)ei).GetAddMethod (true);
1812 return ei.GetAddMethod (true);
1815 static public MethodInfo GetRemoveMethod (EventInfo ei)
1817 if (ei is MyEventBuilder) {
1818 return ((MyEventBuilder)ei).GetRemoveMethod (true);
1820 return ei.GetRemoveMethod (true);
1823 static public void RegisterEventField (EventInfo einfo, EventField e)
1825 if (events == null)
1826 events = new Hashtable ();
1828 events.Add (einfo, e);
1831 static public EventField GetEventField (EventInfo ei)
1833 if (events == null)
1834 return null;
1836 return (EventField) events [ei];
1839 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1841 Hashtable hash = new Hashtable ();
1842 return CheckStructCycles (tc, seen, hash);
1845 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1846 Hashtable hash)
1848 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
1849 return true;
1852 // `seen' contains all types we've already visited.
1854 if (seen.Contains (tc))
1855 return true;
1856 seen.Add (tc, null);
1858 if (tc.Fields == null)
1859 return true;
1861 foreach (FieldBase field in tc.Fields) {
1862 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1863 continue;
1865 Type ftype = field.FieldBuilder.FieldType;
1866 TypeContainer ftc = LookupTypeContainer (ftype);
1867 if (ftc == null)
1868 continue;
1870 if (hash.Contains (ftc)) {
1871 Report.Error (523, tc.Location,
1872 "Struct member `{0}.{1}' of type `{2}' " +
1873 "causes a cycle in the struct layout",
1874 tc.Name, field.Name, ftc.Name);
1875 return false;
1879 // `hash' contains all types in the current path.
1881 hash.Add (tc, null);
1883 bool ok = CheckStructCycles (ftc, seen, hash);
1885 hash.Remove (tc);
1887 if (!ok)
1888 return false;
1890 if (!seen.Contains (ftc))
1891 seen.Add (ftc, null);
1894 return true;
1897 /// <summary>
1898 /// Given an array of interface types, expand and eliminate repeated ocurrences
1899 /// of an interface.
1900 /// </summary>
1902 /// <remarks>
1903 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1904 /// be IA, IB, IC.
1905 /// </remarks>
1906 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
1908 ArrayList new_ifaces = new ArrayList ();
1910 foreach (TypeExpr iface in base_interfaces){
1911 Type itype = iface.Type;
1913 if (new_ifaces.Contains (itype))
1914 continue;
1916 new_ifaces.Add (itype);
1918 Type [] implementing = GetInterfaces (itype);
1920 foreach (Type imp in implementing){
1921 if (!new_ifaces.Contains (imp))
1922 new_ifaces.Add (imp);
1925 Type [] ret = new Type [new_ifaces.Count];
1926 new_ifaces.CopyTo (ret, 0);
1927 return ret;
1930 public static Type[] ExpandInterfaces (Type [] base_interfaces)
1932 ArrayList new_ifaces = new ArrayList ();
1934 foreach (Type itype in base_interfaces){
1935 if (new_ifaces.Contains (itype))
1936 continue;
1938 new_ifaces.Add (itype);
1940 Type [] implementing = GetInterfaces (itype);
1942 foreach (Type imp in implementing){
1943 if (!new_ifaces.Contains (imp))
1944 new_ifaces.Add (imp);
1947 Type [] ret = new Type [new_ifaces.Count];
1948 new_ifaces.CopyTo (ret, 0);
1949 return ret;
1952 static PtrHashtable iface_cache;
1954 /// <summary>
1955 /// This function returns the interfaces in the type `t'. Works with
1956 /// both types and TypeBuilders.
1957 /// </summary>
1958 public static Type [] GetInterfaces (Type t)
1960 Type [] cached = iface_cache [t] as Type [];
1961 if (cached != null)
1962 return cached;
1965 // The reason for catching the Array case is that Reflection.Emit
1966 // will not return a TypeBuilder for Array types of TypeBuilder types,
1967 // but will still throw an exception if we try to call GetInterfaces
1968 // on the type.
1970 // Since the array interfaces are always constant, we return those for
1971 // the System.Array
1974 if (t.IsArray)
1975 t = TypeManager.array_type;
1977 if ((t is TypeBuilder) || IsGenericType (t)) {
1978 Type [] base_ifaces;
1980 if (t.BaseType == null)
1981 base_ifaces = Type.EmptyTypes;
1982 else
1983 base_ifaces = GetInterfaces (t.BaseType);
1984 Type[] type_ifaces;
1985 if (IsGenericType (t))
1986 #if MS_COMPATIBLE && GMCS_SOURCE
1987 type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
1988 #else
1989 type_ifaces = t.GetInterfaces ();
1990 #endif
1991 else
1992 type_ifaces = (Type []) builder_to_ifaces [t];
1993 if (type_ifaces == null || type_ifaces.Length == 0)
1994 type_ifaces = Type.EmptyTypes;
1996 int base_count = base_ifaces.Length;
1997 Type [] result = new Type [base_count + type_ifaces.Length];
1998 base_ifaces.CopyTo (result, 0);
1999 type_ifaces.CopyTo (result, base_count);
2001 iface_cache [t] = result;
2002 return result;
2003 } else if (t is GenericTypeParameterBuilder){
2004 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2005 if (type_ifaces == null || type_ifaces.Length == 0)
2006 type_ifaces = Type.EmptyTypes;
2008 iface_cache [t] = type_ifaces;
2009 return type_ifaces;
2010 } else {
2011 Type[] ifaces = t.GetInterfaces ();
2012 iface_cache [t] = ifaces;
2013 return ifaces;
2018 // gets the interfaces that are declared explicitly on t
2020 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2022 return (Type []) builder_to_ifaces [t];
2025 /// <remarks>
2026 /// The following is used to check if a given type implements an interface.
2027 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2028 /// </remarks>
2029 public static bool ImplementsInterface (Type t, Type iface)
2031 Type [] interfaces;
2034 // FIXME OPTIMIZATION:
2035 // as soon as we hit a non-TypeBuiler in the interface
2036 // chain, we could return, as the `Type.GetInterfaces'
2037 // will return all the interfaces implement by the type
2038 // or its bases.
2040 do {
2041 interfaces = GetInterfaces (t);
2043 if (interfaces != null){
2044 foreach (Type i in interfaces){
2045 if (i == iface || IsVariantOf (i, iface))
2046 return true;
2050 t = t.BaseType;
2051 } while (t != null);
2053 return false;
2056 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2058 // This is a custom version of Convert.ChangeType() which works
2059 // with the TypeBuilder defined types when compiling corlib.
2060 public static object ChangeType (object value, Type conversionType, out bool error)
2062 IConvertible convert_value = value as IConvertible;
2064 if (convert_value == null){
2065 error = true;
2066 return null;
2070 // NOTE 1:
2071 // We must use Type.Equals() here since `conversionType' is
2072 // the TypeBuilder created version of a system type and not
2073 // the system type itself. You cannot use Type.GetTypeCode()
2074 // on such a type - it'd always return TypeCode.Object.
2076 // NOTE 2:
2077 // We cannot rely on build-in type conversions as they are
2078 // more limited than what C# supports.
2079 // See char -> float/decimal/double conversion
2082 error = false;
2083 try {
2084 if (conversionType.Equals (typeof (Boolean)))
2085 return (object)(convert_value.ToBoolean (nf_provider));
2086 if (conversionType.Equals (typeof (Byte)))
2087 return (object)(convert_value.ToByte (nf_provider));
2088 if (conversionType.Equals (typeof (Char)))
2089 return (object)(convert_value.ToChar (nf_provider));
2090 if (conversionType.Equals (typeof (DateTime)))
2091 return (object)(convert_value.ToDateTime (nf_provider));
2093 if (conversionType.Equals (decimal_type)) {
2094 if (convert_value.GetType () == TypeManager.char_type)
2095 return (decimal)convert_value.ToInt32 (nf_provider);
2096 return convert_value.ToDecimal (nf_provider);
2099 if (conversionType.Equals (typeof (Double))) {
2100 if (convert_value.GetType () == TypeManager.char_type)
2101 return (double)convert_value.ToInt32 (nf_provider);
2102 return convert_value.ToDouble (nf_provider);
2105 if (conversionType.Equals (typeof (Int16)))
2106 return (object)(convert_value.ToInt16 (nf_provider));
2107 if (conversionType.Equals (int32_type))
2108 return (object)(convert_value.ToInt32 (nf_provider));
2109 if (conversionType.Equals (int64_type))
2110 return (object)(convert_value.ToInt64 (nf_provider));
2111 if (conversionType.Equals (typeof (SByte)))
2112 return (object)(convert_value.ToSByte (nf_provider));
2114 if (conversionType.Equals (typeof (Single))) {
2115 if (convert_value.GetType () == TypeManager.char_type)
2116 return (float)convert_value.ToInt32 (nf_provider);
2117 return convert_value.ToSingle (nf_provider);
2120 if (conversionType.Equals (typeof (String)))
2121 return (object)(convert_value.ToString (nf_provider));
2122 if (conversionType.Equals (typeof (UInt16)))
2123 return (object)(convert_value.ToUInt16 (nf_provider));
2124 if (conversionType.Equals (typeof (UInt32)))
2125 return (object)(convert_value.ToUInt32 (nf_provider));
2126 if (conversionType.Equals (typeof (UInt64)))
2127 return (object)(convert_value.ToUInt64 (nf_provider));
2128 if (conversionType.Equals (typeof (Object)))
2129 return (object)(value);
2130 else
2131 error = true;
2132 } catch {
2133 error = true;
2135 return null;
2139 // When compiling with -nostdlib and the type is imported from an external assembly
2140 // SRE uses "wrong" type and we have to convert it to the right compiler instance.
2142 public static Type TypeToCoreType (Type t)
2144 if (RootContext.StdLib || t.Module != typeof (object).Module)
2145 return t;
2147 TypeCode tc = Type.GetTypeCode (t);
2149 switch (tc){
2150 case TypeCode.Boolean:
2151 return TypeManager.bool_type;
2152 case TypeCode.Byte:
2153 return TypeManager.byte_type;
2154 case TypeCode.SByte:
2155 return TypeManager.sbyte_type;
2156 case TypeCode.Char:
2157 return TypeManager.char_type;
2158 case TypeCode.Int16:
2159 return TypeManager.short_type;
2160 case TypeCode.UInt16:
2161 return TypeManager.ushort_type;
2162 case TypeCode.Int32:
2163 return TypeManager.int32_type;
2164 case TypeCode.UInt32:
2165 return TypeManager.uint32_type;
2166 case TypeCode.Int64:
2167 return TypeManager.int64_type;
2168 case TypeCode.UInt64:
2169 return TypeManager.uint64_type;
2170 case TypeCode.Single:
2171 return TypeManager.float_type;
2172 case TypeCode.Double:
2173 return TypeManager.double_type;
2174 case TypeCode.String:
2175 return TypeManager.string_type;
2176 case TypeCode.Decimal:
2177 return TypeManager.decimal_type;
2180 if (t == typeof (void))
2181 return TypeManager.void_type;
2182 if (t == typeof (object))
2183 return TypeManager.object_type;
2184 if (t == typeof (System.Type))
2185 return TypeManager.type_type;
2186 if (t == typeof (System.IntPtr))
2187 return TypeManager.intptr_type;
2188 if (t == typeof (System.UIntPtr))
2189 return TypeManager.uintptr_type;
2190 #if GMCS_SOURCE
2191 if (t.IsArray) {
2192 int dim = t.GetArrayRank ();
2193 t = GetElementType (t);
2194 return t.MakeArrayType (dim);
2196 if (t.IsByRef) {
2197 t = GetElementType (t);
2198 return t.MakeByRefType ();
2200 if (t.IsPointer) {
2201 t = GetElementType (t);
2202 return t.MakePointerType ();
2204 #endif
2205 return t;
2209 // Converts any type to reflection supported type
2211 public static Type TypeToReflectionType (Type type)
2213 // TODO: Very lame and painful, GetReference () is enough for mcs-cecil
2214 return IsDynamicType (type) ? object_type : type;
2217 /// <summary>
2218 /// Utility function that can be used to probe whether a type
2219 /// is managed or not.
2220 /// </summary>
2221 public static bool VerifyUnManaged (Type t, Location loc)
2223 if (IsUnmanagedType (t))
2224 return true;
2226 while (t.IsPointer)
2227 t = GetElementType (t);
2229 Report.SymbolRelatedToPreviousError (t);
2230 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2231 CSharpName (t));
2233 return false;
2236 /// <summary>
2237 /// Returns the name of the indexer in a given type.
2238 /// </summary>
2239 /// <remarks>
2240 /// The default is not always `Item'. The user can change this behaviour by
2241 /// using the IndexerNameAttribute in the container.
2242 /// For example, the String class indexer is named `Chars' not `Item'
2243 /// </remarks>
2244 public static string IndexerPropertyName (Type t)
2246 t = DropGenericTypeArguments (t);
2247 if (t is TypeBuilder) {
2248 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2249 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2252 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
2253 if (pa.IsDefined) {
2254 System.Attribute attr = System.Attribute.GetCustomAttribute (
2255 t, pa.Type);
2256 if (attr != null) {
2257 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2258 return dma.MemberName;
2262 return TypeContainer.DefaultIndexerName;
2265 static MethodInfo declare_local_method = null;
2267 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2269 if (declare_local_method == null){
2270 declare_local_method = typeof (ILGenerator).GetMethod (
2271 "DeclareLocal",
2272 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2273 null,
2274 new Type [] { typeof (Type), typeof (bool)},
2275 null);
2276 if (declare_local_method == null){
2277 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2278 return ig.DeclareLocal (t);
2281 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2284 private static bool IsSignatureEqual (Type a, Type b)
2287 /// Consider the following example (bug #77674):
2289 /// public abstract class A
2290 /// {
2291 /// public abstract T Foo<T> ();
2292 /// }
2294 /// public abstract class B : A
2295 /// {
2296 /// public override U Foo<T> ()
2297 /// { return default (U); }
2298 /// }
2300 /// Here, `T' and `U' are method type parameters from different methods
2301 /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
2303 /// However, since we're determining whether B.Foo() overrides A.Foo(),
2304 /// we need to do a signature based comparision and consider them equal.
2306 if (a == b)
2307 return true;
2309 #if GMCS_SOURCE
2310 if (a.IsGenericParameter && b.IsGenericParameter &&
2311 (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
2312 return a.GenericParameterPosition == b.GenericParameterPosition;
2314 #endif
2316 if (a.IsArray && b.IsArray) {
2317 if (a.GetArrayRank () != b.GetArrayRank ())
2318 return false;
2320 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2323 if (a.IsByRef && b.IsByRef)
2324 return IsSignatureEqual (GetElementType (a), GetElementType (b));
2326 if (IsGenericType (a) && IsGenericType (b)) {
2327 if (DropGenericTypeArguments (a) != DropGenericTypeArguments (b))
2328 return false;
2330 Type[] aargs = GetTypeArguments (a);
2331 Type[] bargs = GetTypeArguments (b);
2333 if (aargs.Length != bargs.Length)
2334 return false;
2336 for (int i = 0; i < aargs.Length; i++) {
2337 if (!IsSignatureEqual (aargs [i], bargs [i]))
2338 return false;
2341 return true;
2344 return false;
2348 // Returns whether the array of memberinfos contains the given method
2350 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
2352 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2354 foreach (MethodBase method in array) {
2355 if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
2356 continue;
2358 if (method.Name != new_method.Name)
2359 continue;
2361 if (method is MethodInfo && new_method is MethodInfo &&
2362 !IsSignatureEqual (
2363 TypeToCoreType (((MethodInfo) method).ReturnType),
2364 TypeToCoreType (((MethodInfo) new_method).ReturnType)))
2365 continue;
2367 Type [] old_args = TypeManager.GetParameterData (method).Types;
2368 int old_count = old_args.Length;
2369 int i;
2371 if (new_args.Length != old_count)
2372 continue;
2374 for (i = 0; i < old_count; i++){
2375 if (!IsSignatureEqual (old_args [i], new_args [i]))
2376 break;
2378 if (i != old_count)
2379 continue;
2381 return true;
2384 return false;
2388 // We copy methods from `new_members' into `target_list' if the signature
2389 // for the method from in the new list does not exist in the target_list
2391 // The name is assumed to be the same.
2393 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2395 if (target_list == null){
2396 target_list = new ArrayList ();
2398 foreach (MemberInfo mi in new_members){
2399 if (mi is MethodBase)
2400 target_list.Add (mi);
2402 return target_list;
2405 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2406 target_list.CopyTo (target_array, 0);
2408 foreach (MemberInfo mi in new_members){
2409 MethodBase new_method = (MethodBase) mi;
2411 if (!ArrayContainsMethod (target_array, new_method, true))
2412 target_list.Add (new_method);
2414 return target_list;
2417 #region Generics
2418 // <remarks>
2419 // Tracks the generic parameters.
2420 // </remarks>
2421 static PtrHashtable builder_to_type_param;
2423 public static void AddTypeParameter (Type t, TypeParameter tparam)
2425 if (!builder_to_type_param.Contains (t))
2426 builder_to_type_param.Add (t, tparam);
2429 public static TypeParameter LookupTypeParameter (Type t)
2431 return (TypeParameter) builder_to_type_param [t];
2434 // This method always return false for non-generic compiler,
2435 // while Type.IsGenericParameter is returned if it is supported.
2436 public static bool IsGenericParameter (Type type)
2438 #if GMCS_SOURCE
2439 return type.IsGenericParameter;
2440 #else
2441 return false;
2442 #endif
2445 public static int GenericParameterPosition (Type type)
2447 #if GMCS_SOURCE
2448 return type.GenericParameterPosition;
2449 #else
2450 throw new InternalErrorException ("should not be called");
2451 #endif
2454 public static bool IsGenericType (Type type)
2456 #if GMCS_SOURCE
2457 return type.IsGenericType;
2458 #else
2459 return false;
2460 #endif
2463 public static bool IsGenericTypeDefinition (Type type)
2465 #if GMCS_SOURCE
2466 return type.IsGenericTypeDefinition;
2467 #else
2468 return false;
2469 #endif
2472 public static bool ContainsGenericParameters (Type type)
2474 #if GMCS_SOURCE
2475 return type.ContainsGenericParameters;
2476 #else
2477 return false;
2478 #endif
2481 public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
2483 #if GMCS_SOURCE
2484 if (fi.DeclaringType.IsGenericTypeDefinition ||
2485 !fi.DeclaringType.IsGenericType)
2486 return fi;
2488 Type t = fi.DeclaringType.GetGenericTypeDefinition ();
2489 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2490 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2492 // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
2493 foreach (FieldInfo f in t.GetFields (bf))
2494 if (f.MetadataToken == fi.MetadataToken)
2495 return f;
2496 #endif
2498 return fi;
2501 public static bool IsEqual (Type a, Type b)
2503 if (a.Equals (b)) {
2504 // MS BCL returns true even if enum types are different
2505 if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
2506 return a.FullName == b.FullName;
2508 // Some types are never equal
2509 if (a == TypeManager.null_type || a == InternalType.AnonymousMethod)
2510 return false;
2512 return true;
2515 if (IsGenericParameter (a) && IsGenericParameter (b)) {
2516 // TODO: needs more testing before cleaning up
2517 //if (a.DeclaringMethod != b.DeclaringMethod &&
2518 // (a.DeclaringMethod == null || b.DeclaringMethod == null))
2519 // return false;
2520 #if GMCS_SOURCE
2521 return a.GenericParameterPosition == b.GenericParameterPosition;
2522 #else
2523 throw new NotSupportedException ();
2524 #endif
2527 if (a.IsArray && b.IsArray) {
2528 if (a.GetArrayRank () != b.GetArrayRank ())
2529 return false;
2530 return IsEqual (GetElementType (a), GetElementType (b));
2533 if (a.IsByRef && b.IsByRef)
2534 return IsEqual (a.GetElementType (), b.GetElementType ());
2536 if (IsGenericType (a) && IsGenericType (b)) {
2537 Type adef = DropGenericTypeArguments (a);
2538 Type bdef = DropGenericTypeArguments (b);
2540 if (adef != bdef)
2541 return false;
2543 if (adef.IsEnum && bdef.IsEnum)
2544 return true;
2546 Type[] aargs = GetTypeArguments (a);
2547 Type[] bargs = GetTypeArguments (b);
2549 if (aargs.Length != bargs.Length)
2550 return false;
2552 for (int i = 0; i < aargs.Length; i++) {
2553 if (!IsEqual (aargs [i], bargs [i]))
2554 return false;
2557 return true;
2560 return false;
2563 public static bool IsEqual (Type[] a, Type[] b)
2565 if (a == null || b == null || a.Length != b.Length)
2566 return false;
2568 for (int i = 0; i < a.Length; ++i) {
2569 if (a [i] == null || b [i] == null) {
2570 if (a [i] == b [i])
2571 continue;
2573 return false;
2576 if (!IsEqual (a [i], b [i]))
2577 return false;
2580 return true;
2583 public static Type DropGenericTypeArguments (Type t)
2585 #if GMCS_SOURCE
2586 if (!t.IsGenericType)
2587 return t;
2588 // Micro-optimization: a generic typebuilder is always a generic type definition
2589 if (t is TypeBuilder)
2590 return t;
2591 return t.GetGenericTypeDefinition ();
2592 #else
2593 return t;
2594 #endif
2597 public static MethodBase DropGenericMethodArguments (MethodBase m)
2599 #if GMCS_SOURCE
2600 if (m.IsGenericMethod)
2601 m = ((MethodInfo) m).GetGenericMethodDefinition ();
2603 Type t = m.DeclaringType;
2604 if (!t.IsGenericType || t.IsGenericTypeDefinition)
2605 return m;
2607 t = t.GetGenericTypeDefinition ();
2608 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
2609 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
2611 #if MS_COMPATIBLE
2612 // TODO: use CodeGen.Module.Builder.ResolveMethod ()
2613 return m;
2614 #endif
2616 if (m is ConstructorInfo) {
2617 foreach (ConstructorInfo c in t.GetConstructors (bf))
2618 if (c.MetadataToken == m.MetadataToken)
2619 return c;
2620 } else {
2621 foreach (MethodBase mb in t.GetMethods (bf))
2622 if (mb.MetadataToken == m.MetadataToken)
2623 return mb;
2625 #endif
2627 return m;
2630 public static Type[] GetGenericArguments (MethodBase mi)
2632 #if GMCS_SOURCE
2633 return mi.GetGenericArguments ();
2634 #else
2635 return Type.EmptyTypes;
2636 #endif
2639 public static Type[] GetTypeArguments (Type t)
2641 #if GMCS_SOURCE
2642 DeclSpace tc = LookupDeclSpace (t);
2643 if (tc != null) {
2644 if (!tc.IsGeneric)
2645 return Type.EmptyTypes;
2647 TypeParameter[] tparam = tc.TypeParameters;
2648 Type[] ret = new Type [tparam.Length];
2649 for (int i = 0; i < tparam.Length; i++) {
2650 ret [i] = tparam [i].Type;
2651 if (ret [i] == null)
2652 throw new InternalErrorException ();
2655 return ret;
2656 } else
2657 return t.GetGenericArguments ();
2658 #else
2659 throw new InternalErrorException ();
2660 #endif
2663 public static GenericConstraints GetTypeParameterConstraints (Type t)
2665 #if GMCS_SOURCE
2666 if (!t.IsGenericParameter)
2667 throw new InvalidOperationException ();
2669 TypeParameter tparam = LookupTypeParameter (t);
2670 if (tparam != null)
2671 return tparam.GenericConstraints;
2673 return ReflectionConstraints.GetConstraints (t);
2674 #else
2675 throw new InternalErrorException ();
2676 #endif
2679 public static bool HasGenericArguments (Type t)
2681 return GetNumberOfTypeArguments (t) > 0;
2684 public static int GetNumberOfTypeArguments (Type t)
2686 #if GMCS_SOURCE
2687 if (t.IsGenericParameter)
2688 return 0;
2689 DeclSpace tc = LookupDeclSpace (t);
2690 if (tc != null)
2691 return tc.IsGeneric ? tc.CountTypeParameters : 0;
2692 else
2693 return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
2694 #else
2695 return 0;
2696 #endif
2699 /// <summary>
2700 /// Check whether `type' and `parent' are both instantiations of the same
2701 /// generic type. Note that we do not check the type parameters here.
2702 /// </summary>
2703 public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
2705 int tcount = GetNumberOfTypeArguments (type);
2706 int pcount = GetNumberOfTypeArguments (parent);
2708 if (tcount != pcount)
2709 return false;
2711 type = DropGenericTypeArguments (type);
2712 parent = DropGenericTypeArguments (parent);
2714 return type.Equals (parent);
2717 /// <summary>
2718 /// Whether `mb' is a generic method definition.
2719 /// </summary>
2720 public static bool IsGenericMethodDefinition (MethodBase mb)
2722 #if GMCS_SOURCE
2723 if (mb.DeclaringType is TypeBuilder) {
2724 IMethodData method = (IMethodData) builder_to_method [mb];
2725 if (method == null)
2726 return false;
2728 return method.GenericMethod != null;
2731 return mb.IsGenericMethodDefinition;
2732 #else
2733 return false;
2734 #endif
2737 /// <summary>
2738 /// Whether `mb' is a generic method.
2739 /// </summary>
2740 public static bool IsGenericMethod (MethodBase mb)
2742 #if GMCS_SOURCE
2743 return mb.IsGenericMethod;
2744 #else
2745 return false;
2746 #endif
2749 public static bool IsNullableType (Type t)
2751 #if GMCS_SOURCE
2752 return generic_nullable_type == DropGenericTypeArguments (t);
2753 #else
2754 return false;
2755 #endif
2757 #endregion
2759 #region MemberLookup implementation
2762 // Whether we allow private members in the result (since FindMembers
2763 // uses NonPublic for both protected and private), we need to distinguish.
2766 internal class Closure {
2767 internal bool private_ok;
2769 // Who is invoking us and which type is being queried currently.
2770 internal Type invocation_type;
2771 internal Type qualifier_type;
2773 // The assembly that defines the type is that is calling us
2774 internal Assembly invocation_assembly;
2775 internal IList almost_match;
2777 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2779 if (invocation_type == null)
2780 return false;
2782 if (is_static && qualifier_type == null)
2783 // It resolved from a simple name, so it should be visible.
2784 return true;
2786 if (IsNestedChildOf (invocation_type, m.DeclaringType))
2787 return true;
2789 for (Type t = invocation_type; t != null; t = t.DeclaringType) {
2790 if (!IsFamilyAccessible (t, m.DeclaringType))
2791 continue;
2793 // Although a derived class can access protected members of its base class
2794 // it cannot do so through an instance of the base class (CS1540).
2795 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2796 if (is_static || qualifier_type == null ||
2797 IsInstantiationOfSameGenericType (t, qualifier_type) ||
2798 IsFamilyAccessible (qualifier_type, t))
2799 return true;
2802 if (almost_match != null)
2803 almost_match.Add (m);
2805 return false;
2809 // This filter filters by name + whether it is ok to include private
2810 // members in the search
2812 internal bool Filter (MemberInfo m, object filter_criteria)
2815 // Hack: we know that the filter criteria will always be in the
2816 // `closure' // fields.
2819 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2820 return false;
2822 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2823 (invocation_type != null) &&
2824 IsPrivateAccessible (m.DeclaringType, invocation_type))
2825 return true;
2828 // Ugly: we need to find out the type of `m', and depending
2829 // on this, tell whether we accept or not
2831 if (m is MethodBase){
2832 MethodBase mb = (MethodBase) m;
2833 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2835 if (ma == MethodAttributes.Public)
2836 return true;
2838 if (ma == MethodAttributes.PrivateScope)
2839 return false;
2841 if (ma == MethodAttributes.Private)
2842 return private_ok ||
2843 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2844 IsNestedChildOf (invocation_type, m.DeclaringType);
2846 if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) {
2847 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2848 return true;
2849 } else {
2850 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2851 return false;
2854 // Family, FamORAssem or FamANDAssem
2855 return CheckValidFamilyAccess (mb.IsStatic, m);
2858 if (m is FieldInfo){
2859 FieldInfo fi = (FieldInfo) m;
2860 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2862 if (fa == FieldAttributes.Public)
2863 return true;
2865 if (fa == FieldAttributes.PrivateScope)
2866 return false;
2868 if (fa == FieldAttributes.Private)
2869 return private_ok ||
2870 IsPrivateAccessible (invocation_type, m.DeclaringType) ||
2871 IsNestedChildOf (invocation_type, m.DeclaringType);
2873 if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) {
2874 if ((fa == FieldAttributes.Assembly) ||
2875 (fa == FieldAttributes.FamORAssem))
2876 return true;
2877 } else {
2878 if ((fa == FieldAttributes.Assembly) ||
2879 (fa == FieldAttributes.FamANDAssem))
2880 return false;
2883 // Family, FamORAssem or FamANDAssem
2884 return CheckValidFamilyAccess (fi.IsStatic, m);
2888 // EventInfos and PropertyInfos, return true because they lack
2889 // permission information, so we need to check later on the methods.
2891 return true;
2895 static Closure closure;
2896 static MemberFilter FilterWithClosure_delegate;
2899 // Looks up a member called `name' in the `queried_type'. This lookup
2900 // is done by code that is contained in the definition for `invocation_type'
2901 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2903 // `invocation_type' is used to check whether we're allowed to access the requested
2904 // member wrt its protection level.
2906 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2907 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2908 // is B and qualifier_type is A). This is used to do the CS1540 check.
2910 // When resolving a SimpleName, `qualifier_type' is null.
2912 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2913 // the same than `queried_type' - except when we're being called from BaseAccess;
2914 // in this case, `invocation_type' is the current type and `queried_type' the base
2915 // type, so this'd normally trigger a CS1540.
2917 // The binding flags are `bf' and the kind of members being looked up are `mt'
2919 // The return value always includes private members which code in `invocation_type'
2920 // is allowed to access (using the specified `qualifier_type' if given); only use
2921 // BindingFlags.NonPublic to bypass the permission check.
2923 // The 'almost_match' argument is used for reporting error CS1540.
2925 // Returns an array of a single element for everything but Methods/Constructors
2926 // that might return multiple matches.
2928 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2929 Type queried_type, MemberTypes mt,
2930 BindingFlags original_bf, string name, IList almost_match)
2932 Timer.StartTimer (TimerType.MemberLookup);
2934 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2935 queried_type, mt, original_bf, name, almost_match);
2937 Timer.StopTimer (TimerType.MemberLookup);
2939 return retval;
2942 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2943 Type queried_type, MemberTypes mt,
2944 BindingFlags original_bf, string name, IList almost_match)
2946 BindingFlags bf = original_bf;
2948 ArrayList method_list = null;
2949 Type current_type = queried_type;
2950 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2951 bool skip_iface_check = true, used_cache = false;
2952 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
2954 closure.invocation_type = invocation_type;
2955 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2956 closure.qualifier_type = qualifier_type;
2957 closure.almost_match = almost_match;
2959 // This is from the first time we find a method
2960 // in most cases, we do not actually find a method in the base class
2961 // so we can just ignore it, and save the arraylist allocation
2962 MemberInfo [] first_members_list = null;
2963 bool use_first_members_list = false;
2965 do {
2966 MemberInfo [] list;
2969 // `NonPublic' is lame, because it includes both protected and
2970 // private methods, so we need to control this behavior by
2971 // explicitly tracking if a private method is ok or not.
2973 // The possible cases are:
2974 // public, private and protected (internal does not come into the
2975 // equation)
2977 if ((invocation_type != null) &&
2978 ((invocation_type == current_type) ||
2979 IsNestedChildOf (invocation_type, current_type)) ||
2980 always_ok_flag)
2981 bf = original_bf | BindingFlags.NonPublic;
2982 else
2983 bf = original_bf;
2985 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2987 Timer.StopTimer (TimerType.MemberLookup);
2989 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2991 Timer.StartTimer (TimerType.MemberLookup);
2994 // When queried for an interface type, the cache will automatically check all
2995 // inherited members, so we don't need to do this here. However, this only
2996 // works if we already used the cache in the first iteration of this loop.
2998 // If we used the cache in any further iteration, we can still terminate the
2999 // loop since the cache always looks in all base classes.
3002 if (used_cache)
3003 searching = false;
3004 else
3005 skip_iface_check = false;
3007 if (current_type == TypeManager.object_type)
3008 searching = false;
3009 else {
3010 current_type = current_type.BaseType;
3013 // This happens with interfaces, they have a null
3014 // basetype. Look members up in the Object class.
3016 if (current_type == null) {
3017 current_type = TypeManager.object_type;
3018 searching = true;
3022 if (list.Length == 0)
3023 continue;
3026 // Events and types are returned by both `static' and `instance'
3027 // searches, which means that our above FindMembers will
3028 // return two copies of the same.
3030 if (list.Length == 1 && !(list [0] is MethodBase)){
3031 return list;
3035 // Multiple properties: we query those just to find out the indexer
3036 // name
3038 if (list [0] is PropertyInfo)
3039 return list;
3042 // We found an event: the cache lookup returns both the event and
3043 // its private field.
3045 if (list [0] is EventInfo) {
3046 if ((list.Length == 2) && (list [1] is FieldInfo))
3047 return new MemberInfo [] { list [0] };
3049 return list;
3053 // We found methods, turn the search into "method scan"
3054 // mode.
3057 if (first_members_list != null) {
3058 if (use_first_members_list) {
3059 method_list = CopyNewMethods (method_list, first_members_list);
3060 use_first_members_list = false;
3063 method_list = CopyNewMethods (method_list, list);
3064 } else {
3065 first_members_list = list;
3066 use_first_members_list = true;
3067 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3069 } while (searching);
3071 if (use_first_members_list)
3072 return first_members_list;
3074 if (method_list != null && method_list.Count > 0) {
3075 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3078 // This happens if we already used the cache in the first iteration, in this case
3079 // the cache already looked in all interfaces.
3081 if (skip_iface_check)
3082 return null;
3085 // Interfaces do not list members they inherit, so we have to
3086 // scan those.
3088 if (!queried_type.IsInterface)
3089 return null;
3091 if (queried_type.IsArray)
3092 queried_type = TypeManager.array_type;
3094 Type [] ifaces = GetInterfaces (queried_type);
3095 if (ifaces == null)
3096 return null;
3098 foreach (Type itype in ifaces){
3099 MemberInfo [] x;
3101 x = MemberLookup (null, null, itype, mt, bf, name, null);
3102 if (x != null)
3103 return x;
3106 return null;
3109 public const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
3110 BindingFlags.Static | BindingFlags.Instance |
3111 BindingFlags.DeclaredOnly;
3113 // Currently is designed to work with external types only
3114 public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
3116 if (!mb.IsSpecialName)
3117 return null;
3119 string name = mb.Name;
3120 if (name.Length < 5)
3121 return null;
3123 if (name [3] != '_')
3124 return null;
3126 if (name.StartsWith ("get") || name.StartsWith ("set")) {
3127 MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
3128 Type.FilterName, name.Substring (4));
3130 if (pi == null)
3131 return null;
3133 // This can happen when property is indexer (it can have same name but different parameters)
3134 foreach (PropertyInfo p in pi) {
3135 foreach (MethodInfo p_mi in p.GetAccessors (true)) {
3136 if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
3137 return p;
3142 return null;
3145 // Currently is designed to work with external types only
3146 public static MemberInfo GetEventFromAccessor (MethodBase mb)
3148 if (!mb.IsSpecialName)
3149 return null;
3151 string name = mb.Name;
3152 if (name.Length < 5)
3153 return null;
3155 if (name.StartsWith ("add_"))
3156 return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
3158 if (name.StartsWith ("remove_"))
3159 return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
3161 return null;
3164 // Tests whether external method is really special
3165 public static bool IsSpecialMethod (MethodBase mb)
3167 if (!mb.IsSpecialName)
3168 return false;
3170 IMethodData md = TypeManager.GetMethod (mb);
3171 if (md != null)
3172 return (md is AbstractPropertyEventMethod || md is Operator);
3174 PropertyInfo pi = GetPropertyFromAccessor (mb);
3175 if (pi != null)
3176 return IsValidProperty (pi);
3178 if (GetEventFromAccessor (mb) != null)
3179 return true;
3181 string name = mb.Name;
3182 if (name.StartsWith ("op_"))
3183 return Operator.GetName (name) != null;
3185 return false;
3188 // Tests whether imported property is valid C# property.
3189 // TODO: It seems to me that we should do a lot of sanity tests before
3190 // we accept property as C# property
3191 static bool IsValidProperty (PropertyInfo pi)
3193 MethodInfo get_method = pi.GetGetMethod (true);
3194 MethodInfo set_method = pi.GetSetMethod (true);
3195 int g_count = 0;
3196 int s_count = 0;
3197 if (get_method != null && set_method != null) {
3198 g_count = get_method.GetParameters ().Length;
3199 s_count = set_method.GetParameters ().Length;
3200 if (g_count + 1 != s_count)
3201 return false;
3202 } else if (get_method != null) {
3203 g_count = get_method.GetParameters ().Length;
3204 } else if (set_method != null) {
3205 s_count = set_method.GetParameters ().Length;
3209 // DefaultMemberName and indexer name has to match to identify valid C# indexer
3211 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
3212 if ((s_count > 1 || g_count > 0) && pa.IsDefined) {
3213 object[] o = pi.DeclaringType.GetCustomAttributes (pa.Type, false);
3214 if (o.Length == 0)
3215 return false;
3217 DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
3218 if (dma.MemberName != pi.Name)
3219 return false;
3220 if (get_method != null && "get_" + dma.MemberName != get_method.Name)
3221 return false;
3222 if (set_method != null && "set_" + dma.MemberName != set_method.Name)
3223 return false;
3226 return true;
3229 #endregion
3233 class InternalType
3235 public static readonly Type AnonymousMethod = typeof (AnonymousMethodBody);
3236 public static readonly Type Arglist = typeof (ArglistAccess);
3237 public static readonly Type Dynamic = new DynamicType ();
3238 public static readonly Type MethodGroup = typeof (MethodGroupExpr);
3241 /// <summary>
3242 /// There is exactly one instance of this class per type.
3243 /// </summary>
3244 public sealed class TypeHandle : IMemberContainer {
3245 public readonly IMemberContainer BaseType;
3247 readonly int id = ++next_id;
3248 static int next_id = 0;
3250 static TypeHandle ()
3252 Reset ();
3255 /// <summary>
3256 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3257 /// a TypeHandle yet, a new instance of it is created. This static method
3258 /// ensures that we'll only have one TypeHandle instance per type.
3259 /// </summary>
3260 private static TypeHandle GetTypeHandle (Type t)
3262 TypeHandle handle = (TypeHandle) type_hash [t];
3263 if (handle != null)
3264 return handle;
3266 handle = new TypeHandle (t);
3267 type_hash.Add (t, handle);
3268 return handle;
3271 public static MemberCache GetMemberCache (Type t)
3273 return GetTypeHandle (t).MemberCache;
3276 public static void CleanUp ()
3278 type_hash = null;
3281 public static void Reset ()
3283 type_hash = new PtrHashtable ();
3286 /// <summary>
3287 /// Returns the TypeHandle for TypeManager.object_type.
3288 /// </summary>
3289 public static IMemberContainer ObjectType {
3290 get {
3291 if (object_type != null)
3292 return object_type;
3294 object_type = GetTypeHandle (TypeManager.object_type);
3296 return object_type;
3300 /// <summary>
3301 /// Returns the TypeHandle for TypeManager.array_type.
3302 /// </summary>
3303 public static TypeHandle ArrayType {
3304 get {
3305 if (array_type != null)
3306 return array_type;
3308 array_type = GetTypeHandle (TypeManager.array_type);
3310 return array_type;
3314 private static PtrHashtable type_hash;
3316 private static TypeHandle object_type = null;
3317 private static TypeHandle array_type = null;
3319 private Type type;
3320 private string full_name;
3321 private bool is_interface;
3322 private MemberCache member_cache;
3323 private MemberCache base_cache;
3325 private TypeHandle (Type type)
3327 this.type = type;
3328 full_name = type.FullName != null ? type.FullName : type.Name;
3329 if (type.BaseType != null) {
3330 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3331 BaseType = base_cache.Container;
3332 } else if (type.IsInterface)
3333 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3334 this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
3335 this.member_cache = new MemberCache (this);
3338 // IMemberContainer methods
3340 public string Name {
3341 get {
3342 return full_name;
3346 public Type Type {
3347 get {
3348 return type;
3352 public MemberCache BaseCache {
3353 get {
3354 return base_cache;
3358 public bool IsInterface {
3359 get {
3360 return is_interface;
3364 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3366 MemberInfo [] members;
3368 if (type is GenericTypeParameterBuilder)
3369 return MemberList.Empty;
3371 #if MS_COMPATIBLE
3372 type = TypeManager.DropGenericTypeArguments (type);
3373 #endif
3374 if (mt == MemberTypes.Event)
3375 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3376 else
3377 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3378 null, null);
3380 if (members.Length == 0)
3381 return MemberList.Empty;
3383 Array.Reverse (members);
3384 return new MemberList (members);
3387 // IMemberFinder methods
3389 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3390 MemberFilter filter, object criteria)
3392 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3395 public MemberCache MemberCache {
3396 get {
3397 return member_cache;
3401 public override string ToString ()
3403 if (BaseType != null)
3404 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3405 else
3406 return "TypeHandle (" + id + "," + Name + ")";