2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public 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 char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type sbyte_type;
52 static public Type byte_type;
53 static public Type ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type null_type;
59 static public Type enumeration_type;
60 static public Type array_type;
61 static public Type runtime_handle_type;
62 static public Type icloneable_type;
63 static public Type type_type;
64 static public Type ienumerator_type;
65 static public Type ienumerable_type;
66 static public Type idisposable_type;
67 static public Type iconvertible_type;
68 static public Type default_member_type;
69 static public Type iasyncresult_type;
70 static public Type asynccallback_type;
71 static public Type intptr_type;
72 static public Type monitor_type;
73 static public Type runtime_field_handle_type;
74 static public Type runtime_argument_handle_type;
75 static public Type attribute_type;
76 static public Type attribute_usage_type;
77 static public Type decimal_constant_attribute_type;
78 static public Type dllimport_type;
79 static public Type unverifiable_code_type;
80 static public Type methodimpl_attr_type;
81 static public Type marshal_as_attr_type;
82 static public Type param_array_type;
83 static public Type void_ptr_type;
84 static public Type indexer_name_type;
85 static public Type exception_type;
86 static public Type invalid_operation_exception_type;
87 static public Type not_supported_exception_type;
88 static public Type obsolete_attribute_type;
89 static public Type conditional_attribute_type;
90 static public Type in_attribute_type;
91 static public Type out_attribute_type;
92 static public Type anonymous_method_type;
93 static public Type cls_compliant_attribute_type;
94 static public Type typed_reference_type;
95 static public Type arg_iterator_type;
96 static public Type mbr_type;
97 static public Type struct_layout_attribute_type;
98 static public Type field_offset_attribute_type;
99 static public Type security_attr_type;
100 static public Type required_attr_type;
101 static public Type guid_attr_type;
107 static internal Type compiler_generated_attr_type;
108 static internal Type fixed_buffer_attr_type;
109 static internal Type default_charset_type;
113 // An empty array of types
115 static public Type [] NoTypes;
116 static public TypeExpr [] NoTypeExprs;
120 // Expressions representing the internal types. Used during declaration
123 static public TypeExpr system_object_expr, system_string_expr;
124 static public TypeExpr system_boolean_expr, system_decimal_expr;
125 static public TypeExpr system_single_expr, system_double_expr;
126 static public TypeExpr system_sbyte_expr, system_byte_expr;
127 static public TypeExpr system_int16_expr, system_uint16_expr;
128 static public TypeExpr system_int32_expr, system_uint32_expr;
129 static public TypeExpr system_int64_expr, system_uint64_expr;
130 static public TypeExpr system_char_expr, system_void_expr;
131 static public TypeExpr system_asynccallback_expr;
132 static public TypeExpr system_iasyncresult_expr;
133 static public TypeExpr system_valuetype_expr;
134 static public TypeExpr system_intptr_expr;
137 // This is only used when compiling corlib
139 static public Type system_int32_type;
140 static public Type system_array_type;
141 static public Type system_type_type;
142 static public Type system_assemblybuilder_type;
143 static public MethodInfo system_int_array_get_length;
144 static public MethodInfo system_int_array_get_rank;
145 static public MethodInfo system_object_array_clone;
146 static public MethodInfo system_int_array_get_length_int;
147 static public MethodInfo system_int_array_get_lower_bound_int;
148 static public MethodInfo system_int_array_get_upper_bound_int;
149 static public MethodInfo system_void_array_copyto_array_int;
153 // Internal, not really used outside
155 static Type runtime_helpers_type;
158 // These methods are called by code generated by the compiler
160 static public MethodInfo string_concat_string_string;
161 static public MethodInfo string_concat_string_string_string;
162 static public MethodInfo string_concat_string_string_string_string;
163 static public MethodInfo string_concat_string_dot_dot_dot;
164 static public MethodInfo string_concat_object_object;
165 static public MethodInfo string_concat_object_object_object;
166 static public MethodInfo string_concat_object_dot_dot_dot;
167 static public MethodInfo string_isinterneted_string;
168 static public MethodInfo system_type_get_type_from_handle;
169 static public MethodInfo object_getcurrent_void;
170 static public MethodInfo bool_movenext_void;
171 static public MethodInfo ienumerable_getenumerator_void;
172 static public MethodInfo void_reset_void;
173 static public MethodInfo void_dispose_void;
174 static public MethodInfo void_monitor_enter_object;
175 static public MethodInfo void_monitor_exit_object;
176 static public MethodInfo void_initializearray_array_fieldhandle;
177 static public MethodInfo int_getlength_int;
178 static public MethodInfo delegate_combine_delegate_delegate;
179 static public MethodInfo delegate_remove_delegate_delegate;
180 static public MethodInfo int_get_offset_to_string_data;
181 static public MethodInfo int_array_get_length;
182 static public MethodInfo int_array_get_rank;
183 static public MethodInfo object_array_clone;
184 static public MethodInfo int_array_get_length_int;
185 static public MethodInfo int_array_get_lower_bound_int;
186 static public MethodInfo int_array_get_upper_bound_int;
187 static public MethodInfo void_array_copyto_array_int;
190 // The attribute constructors.
192 static public ConstructorInfo object_ctor;
193 static public ConstructorInfo cons_param_array_attribute;
194 static public ConstructorInfo void_decimal_ctor_five_args;
195 static public ConstructorInfo void_decimal_ctor_int_arg;
196 static public ConstructorInfo unverifiable_code_ctor;
197 static public ConstructorInfo default_member_ctor;
198 static public ConstructorInfo decimal_constant_attribute_ctor;
199 static internal ConstructorInfo struct_layout_attribute_ctor;
200 static public ConstructorInfo field_offset_attribute_ctor;
206 static internal CustomAttributeBuilder compiler_generated_attr;
207 static internal ConstructorInfo fixed_buffer_attr_ctor;
211 // Holds the Array of Assemblies that have been loaded
212 // (either because it is the default or the user used the
213 // -r command line option)
215 static Assembly [] assemblies;
218 // Keeps a list of modules. We used this to do lookups
219 // on the module using GetType -- needed for arrays
221 static Module [] modules;
224 // This is the type_cache from the assemblies to avoid
225 // hitting System.Reflection on every lookup.
227 static Hashtable types;
230 // This is used to hotld the corresponding TypeContainer objects
231 // since we need this in FindMembers
233 static Hashtable typecontainers;
236 // Keeps track of those types that are defined by the
239 static ArrayList user_types;
241 static PtrHashtable builder_to_declspace;
243 static PtrHashtable builder_to_member_cache;
246 // Tracks the interfaces implemented by typebuilders. We only
247 // enter those who do implement or or more interfaces
249 static PtrHashtable builder_to_ifaces;
252 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
253 // the arguments to the method
255 static Hashtable method_arguments;
258 // Maps PropertyBuilder to a Type array that contains
259 // the arguments to the indexer
261 static Hashtable indexer_arguments;
264 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
266 static Hashtable method_params;
269 // A hash table from override methods to their base virtual method.
271 static Hashtable method_overrides;
274 // Keeps track of methods
277 static Hashtable builder_to_method;
280 // Contains all public types from referenced assemblies.
281 // This member is used only if CLS Compliance verification is required.
283 public static Hashtable all_imported_types;
285 static Hashtable fieldbuilders_to_fields;
286 static Hashtable fields;
293 public static void CleanUp ()
295 // Lets get everything clean so that we can collect before generating code
299 typecontainers = null;
301 builder_to_declspace = null;
302 builder_to_member_cache = null;
303 builder_to_ifaces = null;
304 method_arguments = null;
305 indexer_arguments = null;
306 method_params = null;
307 builder_to_method = null;
310 builder_to_constant = null;
311 fieldbuilders_to_fields = null;
313 priv_fields_events = null;
317 TypeHandle.CleanUp ();
321 /// A filter for Findmembers that uses the Signature object to
324 static bool SignatureFilter (MemberInfo mi, object criteria)
326 Signature sig = (Signature) criteria;
328 if (!(mi is MethodBase))
331 if (mi.Name != sig.name)
334 int count = sig.args.Length;
336 if (mi is MethodBuilder || mi is ConstructorBuilder){
337 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
339 if (candidate_args.Length != count)
342 for (int i = 0; i < count; i++)
343 if (candidate_args [i] != sig.args [i])
348 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
350 if (pars.Length != count)
353 for (int i = 0; i < count; i++)
354 if (pars [i].ParameterType != sig.args [i])
360 // A delegate that points to the filter above.
361 static MemberFilter signature_filter;
364 // These are expressions that represent some of the internal data types, used
367 static void InitExpressionTypes ()
369 system_object_expr = new TypeLookupExpression ("System.Object");
370 system_string_expr = new TypeLookupExpression ("System.String");
371 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
372 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
373 system_single_expr = new TypeLookupExpression ("System.Single");
374 system_double_expr = new TypeLookupExpression ("System.Double");
375 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
376 system_byte_expr = new TypeLookupExpression ("System.Byte");
377 system_int16_expr = new TypeLookupExpression ("System.Int16");
378 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
379 system_int32_expr = new TypeLookupExpression ("System.Int32");
380 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
381 system_int64_expr = new TypeLookupExpression ("System.Int64");
382 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
383 system_char_expr = new TypeLookupExpression ("System.Char");
384 system_void_expr = new TypeLookupExpression ("System.Void");
385 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
386 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
387 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
388 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
391 static TypeManager ()
395 signature_filter = new MemberFilter (SignatureFilter);
396 InitExpressionTypes ();
399 static public void Reset ()
401 assemblies = new Assembly [0];
403 user_types = new ArrayList ();
405 types = new Hashtable ();
406 typecontainers = new Hashtable ();
408 builder_to_declspace = new PtrHashtable ();
409 builder_to_member_cache = new PtrHashtable ();
410 builder_to_method = new PtrHashtable ();
411 method_arguments = new PtrHashtable ();
412 method_params = new PtrHashtable ();
413 method_overrides = new PtrHashtable ();
414 indexer_arguments = new PtrHashtable ();
415 builder_to_ifaces = new PtrHashtable ();
417 NoTypes = new Type [0];
418 NoTypeExprs = new TypeExpr [0];
420 fieldbuilders_to_fields = new Hashtable ();
421 fields = new Hashtable ();
422 type_hash = new DoubleHash ();
425 public static void HandleDuplicate (string name, Type t)
427 Type prev = (Type) types [name];
428 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
432 // This probably never happens, as we catch this before
434 Report.Error (-17, "The type `" + name + "' has already been defined.");
438 tc = builder_to_declspace [t] as TypeContainer;
441 1595, "The type `" + name + "' is defined in an existing assembly;"+
442 " Using the new definition from: " + tc.Location);
445 1595, "The type `" + name + "' is defined in an existing assembly;");
448 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
454 public static void AddUserType (string name, TypeBuilder t)
459 HandleDuplicate (name, t);
466 // This entry point is used by types that we define under the covers
468 public static void RegisterBuilder (Type tb, Type [] ifaces)
471 builder_to_ifaces [tb] = ifaces;
474 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
476 builder_to_declspace.Add (t, tc);
477 typecontainers.Add (name, tc);
478 AddUserType (name, t);
481 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
486 HandleDuplicate (name, t);
489 builder_to_declspace.Add (t, del);
492 public static void AddEnumType (string name, TypeBuilder t, Enum en)
497 HandleDuplicate (name, t);
499 builder_to_declspace.Add (t, en);
502 public static void AddMethod (MethodBase builder, IMethodData method)
504 builder_to_method.Add (builder, method);
507 public static IMethodData GetMethod (MethodBase builder)
509 return (IMethodData) builder_to_method [builder];
513 /// Returns the DeclSpace whose Type is `t' or null if there is no
514 /// DeclSpace for `t' (ie, the Type comes from a library)
516 public static DeclSpace LookupDeclSpace (Type t)
518 return builder_to_declspace [t] as DeclSpace;
522 /// Returns the TypeContainer whose Type is `t' or null if there is no
523 /// TypeContainer for `t' (ie, the Type comes from a library)
525 public static TypeContainer LookupTypeContainer (Type t)
527 return builder_to_declspace [t] as TypeContainer;
530 public static MemberCache LookupMemberCache (Type t)
532 if (t is TypeBuilder) {
533 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
534 if (container != null)
535 return container.MemberCache;
538 return TypeHandle.GetMemberCache (t);
541 public static MemberCache LookupBaseInterfacesCache (Type t)
543 Type [] ifaces = t.GetInterfaces ();
545 if (ifaces != null && ifaces.Length == 1)
546 return LookupMemberCache (ifaces [0]);
548 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
549 MemberCache cache = builder_to_member_cache [t] as MemberCache;
553 cache = new MemberCache (ifaces);
554 builder_to_member_cache.Add (t, cache);
558 public static TypeContainer LookupInterface (Type t)
560 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
561 if ((tc == null) || (tc.Kind != Kind.Interface))
567 public static Delegate LookupDelegate (Type t)
569 return builder_to_declspace [t] as Delegate;
572 public static Enum LookupEnum (Type t)
574 return builder_to_declspace [t] as Enum;
577 public static Class LookupClass (Type t)
579 return (Class) builder_to_declspace [t];
583 /// Registers an assembly to load types from.
585 public static void AddAssembly (Assembly a)
587 foreach (Assembly assembly in assemblies) {
592 int top = assemblies.Length;
593 Assembly [] n = new Assembly [top + 1];
595 assemblies.CopyTo (n, 0);
601 public static Assembly [] GetAssemblies ()
607 /// Registers a module builder to lookup types from
609 public static void AddModule (Module mb)
611 int top = modules != null ? modules.Length : 0;
612 Module [] n = new Module [top + 1];
615 modules.CopyTo (n, 0);
620 public static Module[] Modules {
627 // We use this hash for multiple kinds of constructed types:
629 // (T, "&") Given T, get T &
630 // (T, "*") Given T, get T *
631 // (T, "[]") Given T and a array dimension, get T []
632 // (T, X) Given a type T and a simple name X, get the type T+X
634 // Accessibility tests, if necessary, should be done by the user
636 static DoubleHash type_hash = new DoubleHash ();
639 // Gets the reference to T version of the Type (T&)
641 public static Type GetReferenceType (Type t)
643 return GetConstructedType (t, "&");
647 // Gets the pointer to T version of the Type (T*)
649 public static Type GetPointerType (Type t)
651 return GetConstructedType (t, "*");
654 public static Type GetConstructedType (Type t, string dim)
657 if (!type_hash.Lookup (t, dim, out ret)) {
658 ret = t.Module.GetType (t.ToString () + dim);
659 type_hash.Insert (t, dim, ret);
664 public static Type GetNestedType (Type t, string name)
667 if (!type_hash.Lookup (t, name, out ret)) {
668 string lookup = t.ToString () + "+" + name;
669 ret = t.Module.GetType (lookup);
670 type_hash.Insert (t, name, ret);
676 // Low-level lookup, cache-less
678 public static Type LookupTypeReflection (string name)
682 foreach (Assembly a in assemblies){
683 t = a.GetType (name);
688 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
689 if (ta == TypeAttributes.NotPublic ||
690 ta == TypeAttributes.NestedPrivate ||
691 ta == TypeAttributes.NestedAssembly ||
692 ta == TypeAttributes.NestedFamANDAssem){
695 // In .NET pointers turn out to be private, even if their
696 // element type is not
699 t = t.GetElementType ();
709 foreach (Module mb in modules) {
710 t = mb.GetType (name);
719 /// Computes the namespaces that we import from the assemblies we reference.
721 public static void ComputeNamespaces ()
723 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
725 Hashtable cache = null;
728 // First add the assembly namespaces
730 if (assembly_get_namespaces != null){
731 int count = assemblies.Length;
733 for (int i = 0; i < count; i++){
734 Assembly a = assemblies [i];
735 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
736 foreach (string ns in namespaces){
739 Namespace.LookupNamespace (ns, true);
743 cache = new Hashtable ();
744 cache.Add ("", null);
745 foreach (Assembly a in assemblies) {
746 foreach (Type t in a.GetExportedTypes ()) {
747 string ns = t.Namespace;
748 if (ns == null || cache.Contains (ns))
751 Namespace.LookupNamespace (ns, true);
752 cache.Add (ns, null);
758 // Then add module namespaces
760 foreach (Module m in modules) {
761 if (m == CodeGen.Module.Builder)
764 cache = new Hashtable ();
765 cache.Add ("", null);
767 foreach (Type t in m.GetTypes ()) {
768 string ns = t.Namespace;
769 if (ns == null || cache.Contains (ns))
771 Namespace.LookupNamespace (ns, true);
772 cache.Add (ns, null);
778 /// Fills static table with exported types from all referenced assemblies.
779 /// This information is required for CLS Compliance tests.
781 public static void LoadAllImportedTypes ()
783 all_imported_types = new Hashtable ();
784 foreach (Assembly a in assemblies) {
785 foreach (Type t in a.GetExportedTypes ()) {
786 all_imported_types [t.FullName] = t;
791 public static bool NamespaceClash (string name, Location loc)
793 if (Namespace.LookupNamespace (name, false) == null)
796 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
801 /// Returns the C# name of a type if possible, or the full type name otherwise
803 static public string CSharpName (Type t)
805 return Regex.Replace (t.FullName,
807 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
808 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
809 @"Boolean|String|Void|Null)" +
811 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
814 static public string CSharpName (Type[] types)
816 StringBuilder sb = new StringBuilder ();
817 foreach (Type t in types) {
818 sb.Append (CSharpName (t));
821 sb.Remove (sb.Length - 1, 1);
822 return sb.ToString ();
825 static String CSharpNameMatch (Match match)
827 string s = match.Groups [1].Captures [0].Value;
829 Replace ("int32", "int").
830 Replace ("uint32", "uint").
831 Replace ("int16", "short").
832 Replace ("uint16", "ushort").
833 Replace ("int64", "long").
834 Replace ("uint64", "ulong").
835 Replace ("single", "float").
836 Replace ("boolean", "bool")
837 + match.Groups [2].Captures [0].Value;
841 /// Returns the signature of the method with full namespace classification
843 static public string GetFullNameSignature (MemberInfo mi)
845 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
846 return (mi is MethodBase)
847 ? GetFullNameSignature (mi as MethodBase)
848 : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
851 static public string GetFullNameSignature (MethodBase mb)
853 string name = mb.Name;
855 name = mb.DeclaringType.Name;
857 if (mb.IsSpecialName) {
858 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
859 name = name.Remove (0, 4);
866 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
870 /// Returns the signature of the property and indexer
872 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
875 return GetFullNameSignature (pb);
878 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
879 string signature = GetFullNameSignature (mb);
880 string arg = GetParameterData (mb).ParameterDesc (0);
881 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
885 /// Returns the signature of the method
887 static public string CSharpSignature (MethodBase mb)
889 StringBuilder sig = new StringBuilder ("(");
891 ParameterData iparams = GetParameterData (mb);
894 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
895 return GetFullNameSignature (mb);
897 for (int i = 0; i < iparams.Count; i++) {
901 sig.Append (iparams.ParameterDesc (i));
906 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
907 sig.Replace ('(', '[');
908 sig.Replace (')', ']');
911 return GetFullNameSignature (mb) + sig.ToString ();
915 /// Looks up a type, and aborts if it is not found. This is used
916 /// by types required by the compiler
918 static Type CoreLookupType (string name)
921 if (types.Contains (name))
922 t = (Type) types [name];
924 t = LookupTypeReflection (name);
927 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
934 /// Returns the MethodInfo for a method named `name' defined
935 /// in type `t' which takes arguments of types `args'
937 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
941 BindingFlags flags = instance_and_static | BindingFlags.Public;
947 flags |= BindingFlags.NonPublic;
949 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
950 if (list.Count == 0) {
952 Report.Error (-19, "Can not find the core function `" + name + "'");
956 MethodInfo mi = list [0] as MethodInfo;
959 Report.Error (-19, "Can not find the core function `" + name + "'");
966 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
968 return GetMethod (t, name, args, false, report_errors);
971 static MethodInfo GetMethod (Type t, string name, Type [] args)
973 return GetMethod (t, name, args, true);
978 /// Returns the ConstructorInfo for "args"
980 public static ConstructorInfo GetConstructor (Type t, Type [] args)
988 list = FindMembers (t, MemberTypes.Constructor,
989 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
990 signature_filter, sig);
991 if (list.Count == 0){
992 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
996 ConstructorInfo ci = list [0] as ConstructorInfo;
998 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1005 public static void InitEnumUnderlyingTypes ()
1008 int32_type = CoreLookupType ("System.Int32");
1009 int64_type = CoreLookupType ("System.Int64");
1010 uint32_type = CoreLookupType ("System.UInt32");
1011 uint64_type = CoreLookupType ("System.UInt64");
1012 byte_type = CoreLookupType ("System.Byte");
1013 sbyte_type = CoreLookupType ("System.SByte");
1014 short_type = CoreLookupType ("System.Int16");
1015 ushort_type = CoreLookupType ("System.UInt16");
1019 /// The types have to be initialized after the initial
1020 /// population of the type has happened (for example, to
1021 /// bootstrap the corlib.dll
1023 public static void InitCoreTypes ()
1025 object_type = CoreLookupType ("System.Object");
1026 value_type = CoreLookupType ("System.ValueType");
1028 InitEnumUnderlyingTypes ();
1030 char_type = CoreLookupType ("System.Char");
1031 string_type = CoreLookupType ("System.String");
1032 float_type = CoreLookupType ("System.Single");
1033 double_type = CoreLookupType ("System.Double");
1034 char_ptr_type = CoreLookupType ("System.Char*");
1035 decimal_type = CoreLookupType ("System.Decimal");
1036 bool_type = CoreLookupType ("System.Boolean");
1037 enum_type = CoreLookupType ("System.Enum");
1039 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1040 delegate_type = CoreLookupType ("System.Delegate");
1042 array_type = CoreLookupType ("System.Array");
1043 void_type = CoreLookupType ("System.Void");
1044 type_type = CoreLookupType ("System.Type");
1046 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1047 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1048 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1049 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1050 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1051 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1052 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1053 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1054 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1055 idisposable_type = CoreLookupType ("System.IDisposable");
1056 icloneable_type = CoreLookupType ("System.ICloneable");
1057 iconvertible_type = CoreLookupType ("System.IConvertible");
1058 monitor_type = CoreLookupType ("System.Threading.Monitor");
1059 intptr_type = CoreLookupType ("System.IntPtr");
1061 attribute_type = CoreLookupType ("System.Attribute");
1062 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1063 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1064 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1065 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1066 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1067 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1068 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1069 typed_reference_type = CoreLookupType ("System.TypedReference");
1070 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1071 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1072 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1074 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1076 void_ptr_type = CoreLookupType ("System.Void*");
1078 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1080 exception_type = CoreLookupType ("System.Exception");
1081 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1082 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1087 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1088 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1089 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1090 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1091 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1092 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1093 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices.RequiredAttributeAttribute");
1094 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices.GuidAttribute");
1100 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
1101 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices.FixedBufferAttribute");
1102 default_charset_type = CoreLookupType ("System.Runtime.InteropServices.DefaultCharSetAttribute");
1105 // When compiling corlib, store the "real" types here.
1107 if (!RootContext.StdLib) {
1108 system_int32_type = typeof (System.Int32);
1109 system_array_type = typeof (System.Array);
1110 system_type_type = typeof (System.Type);
1111 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1113 Type [] void_arg = { };
1114 system_int_array_get_length = GetMethod (
1115 system_array_type, "get_Length", void_arg);
1116 system_int_array_get_rank = GetMethod (
1117 system_array_type, "get_Rank", void_arg);
1118 system_object_array_clone = GetMethod (
1119 system_array_type, "Clone", void_arg);
1121 Type [] system_int_arg = { system_int32_type };
1122 system_int_array_get_length_int = GetMethod (
1123 system_array_type, "GetLength", system_int_arg);
1124 system_int_array_get_upper_bound_int = GetMethod (
1125 system_array_type, "GetUpperBound", system_int_arg);
1126 system_int_array_get_lower_bound_int = GetMethod (
1127 system_array_type, "GetLowerBound", system_int_arg);
1129 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1130 system_void_array_copyto_array_int = GetMethod (
1131 system_array_type, "CopyTo", system_array_int_arg);
1133 Type [] system_3_type_arg = {
1134 system_type_type, system_type_type, system_type_type };
1135 Type [] system_4_type_arg = {
1136 system_type_type, system_type_type, system_type_type, system_type_type };
1138 MethodInfo set_corlib_type_builders = GetMethod (
1139 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1140 system_4_type_arg, true, false);
1142 if (set_corlib_type_builders != null) {
1143 object[] args = new object [4];
1144 args [0] = object_type;
1145 args [1] = value_type;
1146 args [2] = enum_type;
1147 args [3] = void_type;
1149 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1151 // Compatibility for an older version of the class libs.
1152 set_corlib_type_builders = GetMethod (
1153 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1154 system_3_type_arg, true, true);
1156 if (set_corlib_type_builders == null) {
1157 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1161 object[] args = new object [3];
1162 args [0] = object_type;
1163 args [1] = value_type;
1164 args [2] = enum_type;
1166 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1170 system_object_expr.Type = object_type;
1171 system_string_expr.Type = string_type;
1172 system_boolean_expr.Type = bool_type;
1173 system_decimal_expr.Type = decimal_type;
1174 system_single_expr.Type = float_type;
1175 system_double_expr.Type = double_type;
1176 system_sbyte_expr.Type = sbyte_type;
1177 system_byte_expr.Type = byte_type;
1178 system_int16_expr.Type = short_type;
1179 system_uint16_expr.Type = ushort_type;
1180 system_int32_expr.Type = int32_type;
1181 system_uint32_expr.Type = uint32_type;
1182 system_int64_expr.Type = int64_type;
1183 system_uint64_expr.Type = uint64_type;
1184 system_char_expr.Type = char_type;
1185 system_void_expr.Type = void_type;
1186 system_asynccallback_expr.Type = asynccallback_type;
1187 system_iasyncresult_expr.Type = iasyncresult_type;
1188 system_valuetype_expr.Type = value_type;
1191 // These are only used for compare purposes
1193 anonymous_method_type = typeof (AnonymousMethod);
1194 null_type = typeof (NullType);
1198 // The helper methods that are used by the compiler
1200 public static void InitCodeHelpers ()
1203 // Now load the default methods that we use.
1205 Type [] string_string = { string_type, string_type };
1206 string_concat_string_string = GetMethod (
1207 string_type, "Concat", string_string);
1208 Type [] string_string_string = { string_type, string_type, string_type };
1209 string_concat_string_string_string = GetMethod (
1210 string_type, "Concat", string_string_string);
1211 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1212 string_concat_string_string_string_string = GetMethod (
1213 string_type, "Concat", string_string_string_string);
1214 Type[] params_string = { GetConstructedType (string_type, "[]") };
1215 string_concat_string_dot_dot_dot = GetMethod (
1216 string_type, "Concat", params_string);
1218 Type [] object_object = { object_type, object_type };
1219 string_concat_object_object = GetMethod (
1220 string_type, "Concat", object_object);
1221 Type [] object_object_object = { object_type, object_type, object_type };
1222 string_concat_object_object_object = GetMethod (
1223 string_type, "Concat", object_object_object);
1224 Type[] params_object = { GetConstructedType (object_type, "[]") };
1225 string_concat_object_dot_dot_dot = GetMethod (
1226 string_type, "Concat", params_object);
1228 Type [] string_ = { string_type };
1229 string_isinterneted_string = GetMethod (
1230 string_type, "IsInterned", string_);
1232 Type [] runtime_type_handle = { runtime_handle_type };
1233 system_type_get_type_from_handle = GetMethod (
1234 type_type, "GetTypeFromHandle", runtime_type_handle);
1236 Type [] delegate_delegate = { delegate_type, delegate_type };
1237 delegate_combine_delegate_delegate = GetMethod (
1238 delegate_type, "Combine", delegate_delegate);
1240 delegate_remove_delegate_delegate = GetMethod (
1241 delegate_type, "Remove", delegate_delegate);
1246 Type [] void_arg = { };
1247 object_getcurrent_void = GetMethod (
1248 ienumerator_type, "get_Current", void_arg);
1249 bool_movenext_void = GetMethod (
1250 ienumerator_type, "MoveNext", void_arg);
1251 void_reset_void = GetMethod (
1252 ienumerator_type, "Reset", void_arg);
1253 void_dispose_void = GetMethod (
1254 idisposable_type, "Dispose", void_arg);
1255 int_get_offset_to_string_data = GetMethod (
1256 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1257 int_array_get_length = GetMethod (
1258 array_type, "get_Length", void_arg);
1259 int_array_get_rank = GetMethod (
1260 array_type, "get_Rank", void_arg);
1261 ienumerable_getenumerator_void = GetMethod (
1262 ienumerable_type, "GetEnumerator", void_arg);
1267 Type [] int_arg = { int32_type };
1268 int_array_get_length_int = GetMethod (
1269 array_type, "GetLength", int_arg);
1270 int_array_get_upper_bound_int = GetMethod (
1271 array_type, "GetUpperBound", int_arg);
1272 int_array_get_lower_bound_int = GetMethod (
1273 array_type, "GetLowerBound", int_arg);
1276 // System.Array methods
1278 object_array_clone = GetMethod (
1279 array_type, "Clone", void_arg);
1280 Type [] array_int_arg = { array_type, int32_type };
1281 void_array_copyto_array_int = GetMethod (
1282 array_type, "CopyTo", array_int_arg);
1287 Type [] object_arg = { object_type };
1288 void_monitor_enter_object = GetMethod (
1289 monitor_type, "Enter", object_arg);
1290 void_monitor_exit_object = GetMethod (
1291 monitor_type, "Exit", object_arg);
1293 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1295 void_initializearray_array_fieldhandle = GetMethod (
1296 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1301 int_getlength_int = GetMethod (
1302 array_type, "GetLength", int_arg);
1305 // Decimal constructors
1307 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1308 void_decimal_ctor_five_args = GetConstructor (
1309 decimal_type, dec_arg);
1311 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1316 cons_param_array_attribute = GetConstructor (param_array_type, void_arg);
1317 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg);
1318 default_member_ctor = GetConstructor (default_member_type, string_);
1320 Type[] short_arg = { short_type };
1321 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1323 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1324 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1326 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1333 compiler_generated_attr = new CustomAttributeBuilder (
1334 GetConstructor (compiler_generated_attr_type, void_arg), new object[0]);
1336 Type[] type_int_arg = { type_type, int32_type };
1337 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1341 object_ctor = GetConstructor (object_type, void_arg);
1345 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1348 /// This is the "old", non-cache based FindMembers() function. We cannot use
1349 /// the cache here because there is no member name argument.
1351 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1352 MemberFilter filter, object criteria)
1354 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1357 // `builder_to_declspace' contains all dynamic types.
1361 Timer.StartTimer (TimerType.FindMembers);
1362 list = decl.FindMembers (mt, bf, filter, criteria);
1363 Timer.StopTimer (TimerType.FindMembers);
1368 // We have to take care of arrays specially, because GetType on
1369 // a TypeBuilder array will return a Type, not a TypeBuilder,
1370 // and we can not call FindMembers on this type.
1372 if (t.IsSubclassOf (TypeManager.array_type))
1373 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1376 // Since FindMembers will not lookup both static and instance
1377 // members, we emulate this behaviour here.
1379 if ((bf & instance_and_static) == instance_and_static){
1380 MemberInfo [] i_members = t.FindMembers (
1381 mt, bf & ~BindingFlags.Static, filter, criteria);
1383 int i_len = i_members.Length;
1385 MemberInfo one = i_members [0];
1388 // If any of these are present, we are done!
1390 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1391 return new MemberList (i_members);
1394 MemberInfo [] s_members = t.FindMembers (
1395 mt, bf & ~BindingFlags.Instance, filter, criteria);
1397 int s_len = s_members.Length;
1398 if (i_len > 0 || s_len > 0)
1399 return new MemberList (i_members, s_members);
1402 return new MemberList (i_members);
1404 return new MemberList (s_members);
1408 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1413 /// This method is only called from within MemberLookup. It tries to use the member
1414 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1415 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1416 /// our return value will already contain all inherited members and the caller don't need
1417 /// to check base classes and interfaces anymore.
1419 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1420 string name, out bool used_cache)
1425 // We have to take care of arrays specially, because GetType on
1426 // a TypeBuilder array will return a Type, not a TypeBuilder,
1427 // and we can not call FindMembers on this type.
1429 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1431 return TypeHandle.ArrayType.MemberCache.FindMembers (
1432 mt, bf, name, FilterWithClosure_delegate, null);
1436 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1437 // and we can ask the DeclSpace for the MemberCache.
1439 if (t is TypeBuilder) {
1440 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1441 cache = decl.MemberCache;
1444 // If this DeclSpace has a MemberCache, use it.
1447 if (cache != null) {
1449 return cache.FindMembers (
1450 mt, bf, name, FilterWithClosure_delegate, null);
1453 // If there is no MemberCache, we need to use the "normal" FindMembers.
1454 // Note, this is a VERY uncommon route!
1457 Timer.StartTimer (TimerType.FindMembers);
1458 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1459 FilterWithClosure_delegate, name);
1460 Timer.StopTimer (TimerType.FindMembers);
1463 return (MemberInfo []) list;
1467 // This call will always succeed. There is exactly one TypeHandle instance per
1468 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1469 // the corresponding MemberCache.
1471 cache = TypeHandle.GetMemberCache (t);
1474 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1477 public static bool IsBuiltinType (Type t)
1479 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1480 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1481 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1482 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1488 public static bool IsBuiltinType (TypeContainer tc)
1490 return IsBuiltinType (tc.TypeBuilder);
1494 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1495 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1497 public static bool IsPrimitiveType (Type t)
1499 return (t == int32_type || t == uint32_type ||
1500 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1501 t == char_type || t == short_type || t == bool_type ||
1502 t == sbyte_type || t == byte_type || t == ushort_type);
1505 public static bool IsDelegateType (Type t)
1507 if (t.IsSubclassOf (TypeManager.delegate_type))
1513 public static bool IsEnumType (Type t)
1515 if (t.IsSubclassOf (TypeManager.enum_type))
1520 public static bool IsBuiltinOrEnum (Type t)
1522 if (IsBuiltinType (t))
1531 static Stack unmanaged_enclosing_types = new Stack (4);
1534 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1536 public static bool IsUnmanagedType (Type t)
1538 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1539 if (unmanaged_enclosing_types.Contains (t))
1542 // builtins that are not unmanaged types
1543 if (t == TypeManager.object_type || t == TypeManager.string_type)
1546 if (IsBuiltinOrEnum (t))
1549 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1553 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1557 if (!IsValueType (t))
1560 unmanaged_enclosing_types.Push (t);
1564 if (t is TypeBuilder){
1565 TypeContainer tc = LookupTypeContainer (t);
1566 if (tc.Fields != null){
1567 foreach (Field f in tc.Fields){
1568 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1569 if ((f.ModFlags & Modifiers.STATIC) != 0)
1571 if (f.MemberType == null)
1573 if (!IsUnmanagedType (f.MemberType)){
1574 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1580 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1582 foreach (FieldInfo f in fields){
1583 if (!IsUnmanagedType (f.FieldType)){
1584 Report.SymbolRelatedToPreviousError (f);
1590 unmanaged_enclosing_types.Pop ();
1595 public static bool IsValueType (Type t)
1597 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1603 public static bool IsInterfaceType (Type t)
1605 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1609 return tc.Kind == Kind.Interface;
1612 public static bool IsSubclassOf (Type type, Type base_type)
1615 if (type.Equals (base_type))
1618 type = type.BaseType;
1619 } while (type != null);
1624 public static bool IsFamilyAccessible (Type type, Type base_type)
1626 return IsSubclassOf (type, base_type);
1630 // Checks whether `type' is a subclass or nested child of `base_type'.
1632 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1635 if ((type == base_type) || type.IsSubclassOf (base_type))
1638 // Handle nested types.
1639 type = type.DeclaringType;
1640 } while (type != null);
1646 // Checks whether `type' is a nested child of `parent'.
1648 public static bool IsNestedChildOf (Type type, Type parent)
1653 type = type.DeclaringType;
1654 while (type != null) {
1658 type = type.DeclaringType;
1665 // Do the right thing when returning the element type of an
1666 // array type based on whether we are compiling corlib or not
1668 public static Type GetElementType (Type t)
1670 if (RootContext.StdLib)
1671 return t.GetElementType ();
1673 return TypeToCoreType (t.GetElementType ());
1677 /// This method is not implemented by MS runtime for dynamic types
1679 public static bool HasElementType (Type t)
1681 return t.IsArray || t.IsPointer || t.IsByRef;
1685 /// Returns the User Defined Types
1687 public static ArrayList UserTypes {
1693 public static Hashtable TypeContainers {
1695 return typecontainers;
1699 static Hashtable builder_to_constant;
1701 public static void RegisterConstant (FieldBuilder fb, Const c)
1703 if (builder_to_constant == null)
1704 builder_to_constant = new PtrHashtable ();
1706 if (builder_to_constant.Contains (fb))
1709 builder_to_constant.Add (fb, c);
1712 public static Const LookupConstant (FieldBuilder fb)
1714 if (builder_to_constant == null)
1717 return (Const) builder_to_constant [fb];
1721 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1725 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1726 /// for anything which is dynamic, and we need this in a number of places,
1727 /// we register this information here, and use it afterwards.
1729 static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1734 method_arguments.Add (mb, args);
1735 method_params.Add (mb, ip);
1738 static public ParameterData GetParameterData (MethodBase mb)
1740 object pd = method_params [mb];
1742 if (mb is MethodBuilder || mb is ConstructorBuilder)
1743 throw new InternalErrorException ("Argument for Method not registered" + mb);
1745 method_params [mb] = pd = new ReflectionParameters (mb);
1748 return (ParameterData) pd;
1751 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1753 if (method_overrides.Contains (override_method)) {
1754 if (method_overrides [override_method] != base_method)
1755 throw new InternalErrorException ("Override mismatch: " + override_method);
1758 method_overrides [override_method] = base_method;
1761 static public bool IsOverride (MethodBase m)
1763 return m.IsVirtual &&
1764 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1765 (m is MethodBuilder || method_overrides.Contains (m));
1769 /// Returns the argument types for a method based on its methodbase
1771 /// For dynamic methods, we use the compiler provided types, for
1772 /// methods from existing assemblies we load them from GetParameters,
1773 /// and insert them into the cache
1775 static public Type [] GetArgumentTypes (MethodBase mb)
1777 object t = method_arguments [mb];
1781 ParameterInfo [] pi = mb.GetParameters ();
1788 types = new Type [c];
1789 for (int i = 0; i < c; i++)
1790 types [i] = pi [i].ParameterType;
1792 method_arguments.Add (mb, types);
1797 /// Returns the argument types for an indexer based on its PropertyInfo
1799 /// For dynamic indexers, we use the compiler provided types, for
1800 /// indexers from existing assemblies we load them from GetParameters,
1801 /// and insert them into the cache
1803 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1805 if (indexer_arguments.Contains (indexer))
1806 return (Type []) indexer_arguments [indexer];
1807 else if (indexer is PropertyBuilder)
1808 // If we're a PropertyBuilder and not in the
1809 // `indexer_arguments' hash, then we're a property and
1813 ParameterInfo [] pi = indexer.GetIndexParameters ();
1814 // Property, not an indexer.
1818 Type [] types = new Type [c];
1820 for (int i = 0; i < c; i++)
1821 types [i] = pi [i].ParameterType;
1823 indexer_arguments.Add (indexer, types);
1829 // This is a workaround the fact that GetValue is not
1830 // supported for dynamic types
1832 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1834 if (fields.Contains (fb))
1837 fields.Add (fb, value);
1842 static public object GetValue (FieldBuilder fb)
1847 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1849 if (fieldbuilders_to_fields.Contains (fb))
1852 fieldbuilders_to_fields.Add (fb, f);
1857 // The return value can be null; This will be the case for
1858 // auxiliary FieldBuilders created by the compiler that have no
1859 // real field being declared on the source code
1861 static public FieldBase GetField (FieldInfo fb)
1863 return (FieldBase) fieldbuilders_to_fields [fb];
1866 static Hashtable events;
1868 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1871 events = new Hashtable ();
1873 if (!events.Contains (eb)) {
1874 events.Add (eb, new Pair (add, remove));
1878 static public MethodInfo GetAddMethod (EventInfo ei)
1880 if (ei is MyEventBuilder) {
1881 Pair pair = (Pair) events [ei];
1883 return (MethodInfo) pair.First;
1885 return ei.GetAddMethod (true);
1888 static public MethodInfo GetRemoveMethod (EventInfo ei)
1890 if (ei is MyEventBuilder) {
1891 Pair pair = (Pair) events [ei];
1893 return (MethodInfo) pair.Second;
1895 return ei.GetRemoveMethod (true);
1898 static Hashtable priv_fields_events;
1900 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1902 if (priv_fields_events == null)
1903 priv_fields_events = new Hashtable ();
1905 if (priv_fields_events.Contains (einfo))
1908 priv_fields_events.Add (einfo, builder);
1913 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1915 if (priv_fields_events == null)
1918 return (MemberInfo) priv_fields_events [ei];
1921 static Hashtable properties;
1923 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1925 if (properties == null)
1926 properties = new Hashtable ();
1928 if (properties.Contains (pb))
1931 properties.Add (pb, new Pair (get, set));
1936 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1937 MethodBase set, Type[] args)
1939 if (!RegisterProperty (pb, get,set))
1942 indexer_arguments.Add (pb, args);
1947 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1949 Hashtable hash = new Hashtable ();
1950 return CheckStructCycles (tc, seen, hash);
1953 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1956 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
1960 // `seen' contains all types we've already visited.
1962 if (seen.Contains (tc))
1964 seen.Add (tc, null);
1966 if (tc.Fields == null)
1969 foreach (FieldMember field in tc.Fields) {
1970 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1973 Type ftype = field.FieldBuilder.FieldType;
1974 TypeContainer ftc = LookupTypeContainer (ftype);
1978 if (hash.Contains (ftc)) {
1979 Report.Error (523, tc.Location,
1980 "Struct member `{0}.{1}' of type `{2}' " +
1981 "causes a cycle in the struct layout",
1982 tc.Name, field.Name, ftc.Name);
1987 // `hash' contains all types in the current path.
1989 hash.Add (tc, null);
1991 bool ok = CheckStructCycles (ftc, seen, hash);
1998 if (!seen.Contains (ftc))
1999 seen.Add (ftc, null);
2006 /// Given an array of interface types, expand and eliminate repeated ocurrences
2007 /// of an interface.
2011 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2014 public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2016 ArrayList new_ifaces = new ArrayList ();
2018 foreach (TypeExpr iface in base_interfaces){
2019 Type itype = iface.ResolveType (ec);
2023 if (!new_ifaces.Contains (itype))
2024 new_ifaces.Add (itype);
2026 Type [] implementing = itype.GetInterfaces ();
2028 foreach (Type imp in implementing){
2029 if (!new_ifaces.Contains (imp))
2030 new_ifaces.Add (imp);
2033 Type [] ret = new Type [new_ifaces.Count];
2034 new_ifaces.CopyTo (ret, 0);
2038 static PtrHashtable iface_cache = new PtrHashtable ();
2041 /// This function returns the interfaces in the type `t'. Works with
2042 /// both types and TypeBuilders.
2044 public static Type [] GetInterfaces (Type t)
2047 Type [] cached = iface_cache [t] as Type [];
2052 // The reason for catching the Array case is that Reflection.Emit
2053 // will not return a TypeBuilder for Array types of TypeBuilder types,
2054 // but will still throw an exception if we try to call GetInterfaces
2057 // Since the array interfaces are always constant, we return those for
2062 t = TypeManager.array_type;
2064 if (t is TypeBuilder){
2065 Type [] base_ifaces;
2067 if (t.BaseType == null)
2068 base_ifaces = NoTypes;
2070 base_ifaces = GetInterfaces (t.BaseType);
2071 Type [] type_ifaces = (Type []) builder_to_ifaces [t];
2072 if (type_ifaces == null)
2073 type_ifaces = NoTypes;
2075 int base_count = base_ifaces.Length;
2076 Type [] result = new Type [base_count + type_ifaces.Length];
2077 base_ifaces.CopyTo (result, 0);
2078 type_ifaces.CopyTo (result, base_count);
2080 iface_cache [t] = result;
2083 Type[] ifaces = t.GetInterfaces ();
2084 iface_cache [t] = ifaces;
2090 // gets the interfaces that are declared explicitly on t
2092 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2094 return (Type []) builder_to_ifaces [t];
2098 /// The following is used to check if a given type implements an interface.
2099 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2101 public static bool ImplementsInterface (Type t, Type iface)
2106 // FIXME OPTIMIZATION:
2107 // as soon as we hit a non-TypeBuiler in the interface
2108 // chain, we could return, as the `Type.GetInterfaces'
2109 // will return all the interfaces implement by the type
2113 interfaces = GetInterfaces (t);
2115 if (interfaces != null){
2116 foreach (Type i in interfaces){
2123 } while (t != null);
2128 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2130 // This is a custom version of Convert.ChangeType() which works
2131 // with the TypeBuilder defined types when compiling corlib.
2132 public static object ChangeType (object value, Type conversionType, out bool error)
2134 IConvertible convert_value = value as IConvertible;
2136 if (convert_value == null){
2142 // We must use Type.Equals() here since `conversionType' is
2143 // the TypeBuilder created version of a system type and not
2144 // the system type itself. You cannot use Type.GetTypeCode()
2145 // on such a type - it'd always return TypeCode.Object.
2149 if (conversionType.Equals (typeof (Boolean)))
2150 return (object)(convert_value.ToBoolean (nf_provider));
2151 else if (conversionType.Equals (typeof (Byte)))
2152 return (object)(convert_value.ToByte (nf_provider));
2153 else if (conversionType.Equals (typeof (Char)))
2154 return (object)(convert_value.ToChar (nf_provider));
2155 else if (conversionType.Equals (typeof (DateTime)))
2156 return (object)(convert_value.ToDateTime (nf_provider));
2157 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2158 return (object)(convert_value.ToDecimal (nf_provider));
2159 else if (conversionType.Equals (typeof (Double)))
2160 return (object)(convert_value.ToDouble (nf_provider));
2161 else if (conversionType.Equals (typeof (Int16)))
2162 return (object)(convert_value.ToInt16 (nf_provider));
2163 else if (conversionType.Equals (typeof (Int32)))
2164 return (object)(convert_value.ToInt32 (nf_provider));
2165 else if (conversionType.Equals (typeof (Int64)))
2166 return (object)(convert_value.ToInt64 (nf_provider));
2167 else if (conversionType.Equals (typeof (SByte)))
2168 return (object)(convert_value.ToSByte (nf_provider));
2169 else if (conversionType.Equals (typeof (Single)))
2170 return (object)(convert_value.ToSingle (nf_provider));
2171 else if (conversionType.Equals (typeof (String)))
2172 return (object)(convert_value.ToString (nf_provider));
2173 else if (conversionType.Equals (typeof (UInt16)))
2174 return (object)(convert_value.ToUInt16 (nf_provider));
2175 else if (conversionType.Equals (typeof (UInt32)))
2176 return (object)(convert_value.ToUInt32 (nf_provider));
2177 else if (conversionType.Equals (typeof (UInt64)))
2178 return (object)(convert_value.ToUInt64 (nf_provider));
2179 else if (conversionType.Equals (typeof (Object)))
2180 return (object)(value);
2190 // This is needed, because enumerations from assemblies
2191 // do not report their underlyingtype, but they report
2194 public static Type EnumToUnderlying (Type t)
2196 if (t == TypeManager.enum_type)
2199 t = t.UnderlyingSystemType;
2200 if (!TypeManager.IsEnumType (t))
2203 if (t is TypeBuilder) {
2204 // slow path needed to compile corlib
2205 if (t == TypeManager.bool_type ||
2206 t == TypeManager.byte_type ||
2207 t == TypeManager.sbyte_type ||
2208 t == TypeManager.char_type ||
2209 t == TypeManager.short_type ||
2210 t == TypeManager.ushort_type ||
2211 t == TypeManager.int32_type ||
2212 t == TypeManager.uint32_type ||
2213 t == TypeManager.int64_type ||
2214 t == TypeManager.uint64_type)
2217 TypeCode tc = Type.GetTypeCode (t);
2220 case TypeCode.Boolean:
2221 return TypeManager.bool_type;
2223 return TypeManager.byte_type;
2224 case TypeCode.SByte:
2225 return TypeManager.sbyte_type;
2227 return TypeManager.char_type;
2228 case TypeCode.Int16:
2229 return TypeManager.short_type;
2230 case TypeCode.UInt16:
2231 return TypeManager.ushort_type;
2232 case TypeCode.Int32:
2233 return TypeManager.int32_type;
2234 case TypeCode.UInt32:
2235 return TypeManager.uint32_type;
2236 case TypeCode.Int64:
2237 return TypeManager.int64_type;
2238 case TypeCode.UInt64:
2239 return TypeManager.uint64_type;
2241 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2245 // When compiling corlib and called with one of the core types, return
2246 // the corresponding typebuilder for that type.
2248 public static Type TypeToCoreType (Type t)
2250 if (RootContext.StdLib || (t is TypeBuilder))
2253 TypeCode tc = Type.GetTypeCode (t);
2256 case TypeCode.Boolean:
2257 return TypeManager.bool_type;
2259 return TypeManager.byte_type;
2260 case TypeCode.SByte:
2261 return TypeManager.sbyte_type;
2263 return TypeManager.char_type;
2264 case TypeCode.Int16:
2265 return TypeManager.short_type;
2266 case TypeCode.UInt16:
2267 return TypeManager.ushort_type;
2268 case TypeCode.Int32:
2269 return TypeManager.int32_type;
2270 case TypeCode.UInt32:
2271 return TypeManager.uint32_type;
2272 case TypeCode.Int64:
2273 return TypeManager.int64_type;
2274 case TypeCode.UInt64:
2275 return TypeManager.uint64_type;
2276 case TypeCode.Single:
2277 return TypeManager.float_type;
2278 case TypeCode.Double:
2279 return TypeManager.double_type;
2280 case TypeCode.String:
2281 return TypeManager.string_type;
2282 case TypeCode.Decimal:
2283 return TypeManager.decimal_type;
2285 if (t == typeof (void))
2286 return TypeManager.void_type;
2287 if (t == typeof (object))
2288 return TypeManager.object_type;
2289 if (t == typeof (System.Type))
2290 return TypeManager.type_type;
2291 if (t == typeof (System.IntPtr))
2292 return TypeManager.intptr_type;
2298 /// Utility function that can be used to probe whether a type
2299 /// is managed or not.
2301 public static bool VerifyUnManaged (Type t, Location loc)
2303 if (IsUnmanagedType (t))
2308 "Cannot take the address or size of a variable of a managed type ('" +
2309 CSharpName (t) + "')");
2314 /// Returns the name of the indexer in a given type.
2317 /// The default is not always `Item'. The user can change this behaviour by
2318 /// using the IndexerNameAttribute in the container.
2319 /// For example, the String class indexer is named `Chars' not `Item'
2321 public static string IndexerPropertyName (Type t)
2323 if (t is TypeBuilder) {
2324 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2325 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2328 System.Attribute attr = System.Attribute.GetCustomAttribute (
2329 t, TypeManager.default_member_type);
2331 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2332 return dma.MemberName;
2335 return TypeContainer.DefaultIndexerName;
2338 static MethodInfo declare_local_method = null;
2340 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2342 if (declare_local_method == null){
2343 declare_local_method = typeof (ILGenerator).GetMethod (
2345 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2347 new Type [] { typeof (Type), typeof (bool)},
2349 if (declare_local_method == null){
2350 Report.Warning (-30, new Location (-1),
2351 "This version of the runtime does not support making pinned local variables. " +
2352 "This code may cause errors on a runtime with a moving GC");
2353 return ig.DeclareLocal (t);
2356 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2360 // Returns whether the array of memberinfos contains the given method
2362 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2364 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2366 foreach (MethodBase method in array) {
2367 if (method.Name != new_method.Name)
2370 if (method is MethodInfo && new_method is MethodInfo)
2371 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2375 Type [] old_args = TypeManager.GetArgumentTypes (method);
2376 int old_count = old_args.Length;
2379 if (new_args.Length != old_count)
2382 for (i = 0; i < old_count; i++){
2383 if (old_args [i] != new_args [i])
2396 // We copy methods from `new_members' into `target_list' if the signature
2397 // for the method from in the new list does not exist in the target_list
2399 // The name is assumed to be the same.
2401 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2403 if (target_list == null){
2404 target_list = new ArrayList ();
2406 foreach (MemberInfo mi in new_members){
2407 if (mi is MethodBase)
2408 target_list.Add (mi);
2413 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2414 target_list.CopyTo (target_array, 0);
2416 foreach (MemberInfo mi in new_members){
2417 MethodBase new_method = (MethodBase) mi;
2419 if (!ArrayContainsMethod (target_array, new_method))
2420 target_list.Add (new_method);
2426 #region MemberLookup implementation
2429 // Whether we allow private members in the result (since FindMembers
2430 // uses NonPublic for both protected and private), we need to distinguish.
2433 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2438 internal class Closure {
2439 internal bool private_ok;
2441 // Who is invoking us and which type is being queried currently.
2442 internal Type invocation_type;
2443 internal Type qualifier_type;
2445 // The assembly that defines the type is that is calling us
2446 internal Assembly invocation_assembly;
2447 internal IList almost_match;
2449 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2451 if (invocation_type == null)
2454 if (is_static && qualifier_type == null)
2455 // It resolved from a simple name, so it should be visible.
2458 // A nested class has access to all the protected members visible to its parent.
2459 if (qualifier_type != null && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2462 if (invocation_type == m.DeclaringType || invocation_type.IsSubclassOf (m.DeclaringType)) {
2463 // Although a derived class can access protected members of its base class
2464 // it cannot do so through an instance of the base class (CS1540).
2465 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2467 qualifier_type == null ||
2468 qualifier_type == invocation_type ||
2469 qualifier_type.IsSubclassOf (invocation_type))
2473 if (almost_match != null)
2474 almost_match.Add (m);
2480 // This filter filters by name + whether it is ok to include private
2481 // members in the search
2483 internal bool Filter (MemberInfo m, object filter_criteria)
2486 // Hack: we know that the filter criteria will always be in the `closure'
2490 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2493 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2494 (m.DeclaringType == invocation_type))
2498 // Ugly: we need to find out the type of `m', and depending
2499 // on this, tell whether we accept or not
2501 if (m is MethodBase){
2502 MethodBase mb = (MethodBase) m;
2503 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2505 if (ma == MethodAttributes.Private)
2506 return private_ok || invocation_type == m.DeclaringType ||
2507 IsNestedChildOf (invocation_type, m.DeclaringType);
2509 if (invocation_assembly == mb.DeclaringType.Assembly) {
2510 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2513 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2517 if (ma == MethodAttributes.Family ||
2518 ma == MethodAttributes.FamANDAssem ||
2519 ma == MethodAttributes.FamORAssem)
2520 return CheckValidFamilyAccess (mb.IsStatic, m);
2526 if (m is FieldInfo){
2527 FieldInfo fi = (FieldInfo) m;
2528 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2530 if (fa == FieldAttributes.Private)
2531 return private_ok || (invocation_type == m.DeclaringType) ||
2532 IsNestedChildOf (invocation_type, m.DeclaringType);
2534 if (invocation_assembly == fi.DeclaringType.Assembly) {
2535 if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamORAssem)
2538 if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamANDAssem)
2542 if (fa == FieldAttributes.Family ||
2543 fa == FieldAttributes.FamANDAssem ||
2544 fa == FieldAttributes.FamORAssem)
2545 return CheckValidFamilyAccess (fi.IsStatic, m);
2552 // EventInfos and PropertyInfos, return true because they lack permission
2553 // information, so we need to check later on the methods.
2559 static Closure closure = new Closure ();
2560 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2563 // Looks up a member called `name' in the `queried_type'. This lookup
2564 // is done by code that is contained in the definition for `invocation_type'
2565 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2567 // `invocation_type' is used to check whether we're allowed to access the requested
2568 // member wrt its protection level.
2570 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2571 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2572 // is B and qualifier_type is A). This is used to do the CS1540 check.
2574 // When resolving a SimpleName, `qualifier_type' is null.
2576 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2577 // the same than `queried_type' - except when we're being called from BaseAccess;
2578 // in this case, `invocation_type' is the current type and `queried_type' the base
2579 // type, so this'd normally trigger a CS1540.
2581 // The binding flags are `bf' and the kind of members being looked up are `mt'
2583 // The return value always includes private members which code in `invocation_type'
2584 // is allowed to access (using the specified `qualifier_type' if given); only use
2585 // BindingFlags.NonPublic to bypass the permission check.
2587 // The 'almost_match' argument is used for reporting error CS1540.
2589 // Returns an array of a single element for everything but Methods/Constructors
2590 // that might return multiple matches.
2592 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2593 Type queried_type, MemberTypes mt,
2594 BindingFlags original_bf, string name, IList almost_match)
2596 Timer.StartTimer (TimerType.MemberLookup);
2598 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2599 queried_type, mt, original_bf, name, almost_match);
2601 Timer.StopTimer (TimerType.MemberLookup);
2606 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2607 Type queried_type, MemberTypes mt,
2608 BindingFlags original_bf, string name, IList almost_match)
2610 BindingFlags bf = original_bf;
2612 ArrayList method_list = null;
2613 Type current_type = queried_type;
2614 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2615 bool skip_iface_check = true, used_cache = false;
2616 bool always_ok_flag = false;
2618 closure.invocation_type = invocation_type;
2619 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2620 closure.qualifier_type = qualifier_type;
2621 closure.almost_match = almost_match;
2624 // If we are a nested class, we always have access to our container
2627 if (invocation_type != null){
2628 string invocation_name = invocation_type.FullName;
2629 if (invocation_name.IndexOf ('+') != -1){
2630 string container = queried_type.FullName + "+";
2631 int container_length = container.Length;
2633 if (invocation_name.Length > container_length){
2634 string shared = invocation_name.Substring (0, container_length);
2636 if (shared == container)
2637 always_ok_flag = true;
2642 // This is from the first time we find a method
2643 // in most cases, we do not actually find a method in the base class
2644 // so we can just ignore it, and save the arraylist allocation
2645 MemberInfo [] first_members_list = null;
2646 bool use_first_members_list = false;
2652 // `NonPublic' is lame, because it includes both protected and
2653 // private methods, so we need to control this behavior by
2654 // explicitly tracking if a private method is ok or not.
2656 // The possible cases are:
2657 // public, private and protected (internal does not come into the
2660 if ((invocation_type != null) &&
2661 ((invocation_type == current_type) ||
2662 IsNestedChildOf (invocation_type, current_type)) ||
2664 bf = original_bf | BindingFlags.NonPublic;
2668 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2670 Timer.StopTimer (TimerType.MemberLookup);
2672 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2674 Timer.StartTimer (TimerType.MemberLookup);
2677 // When queried for an interface type, the cache will automatically check all
2678 // inherited members, so we don't need to do this here. However, this only
2679 // works if we already used the cache in the first iteration of this loop.
2681 // If we used the cache in any further iteration, we can still terminate the
2682 // loop since the cache always looks in all base classes.
2688 skip_iface_check = false;
2690 if (current_type == TypeManager.object_type)
2693 current_type = current_type.BaseType;
2696 // This happens with interfaces, they have a null
2697 // basetype. Look members up in the Object class.
2699 if (current_type == null) {
2700 current_type = TypeManager.object_type;
2705 if (list.Length == 0)
2709 // Events and types are returned by both `static' and `instance'
2710 // searches, which means that our above FindMembers will
2711 // return two copies of the same.
2713 if (list.Length == 1 && !(list [0] is MethodBase)){
2718 // Multiple properties: we query those just to find out the indexer
2721 if (list [0] is PropertyInfo)
2725 // We found an event: the cache lookup returns both the event and
2726 // its private field.
2728 if (list [0] is EventInfo) {
2729 if ((list.Length == 2) && (list [1] is FieldInfo))
2730 return new MemberInfo [] { list [0] };
2737 // We found methods, turn the search into "method scan"
2741 if (first_members_list != null) {
2742 if (use_first_members_list) {
2743 method_list = CopyNewMethods (method_list, first_members_list);
2744 use_first_members_list = false;
2747 method_list = CopyNewMethods (method_list, list);
2749 first_members_list = list;
2750 use_first_members_list = true;
2751 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2753 } while (searching);
2755 if (use_first_members_list) {
2756 foreach (MemberInfo mi in first_members_list) {
2757 if (! (mi is MethodBase)) {
2758 method_list = CopyNewMethods (method_list, first_members_list);
2759 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2762 return (MemberInfo []) first_members_list;
2765 if (method_list != null && method_list.Count > 0)
2766 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2769 // This happens if we already used the cache in the first iteration, in this case
2770 // the cache already looked in all interfaces.
2772 if (skip_iface_check)
2776 // Interfaces do not list members they inherit, so we have to
2779 if (!queried_type.IsInterface)
2782 if (queried_type.IsArray)
2783 queried_type = TypeManager.array_type;
2785 Type [] ifaces = GetInterfaces (queried_type);
2789 foreach (Type itype in ifaces){
2792 x = MemberLookup (null, null, itype, mt, bf, name, null);
2800 // Tests whether external method is really special
2801 public static bool IsSpecialMethod (MethodBase mb)
2803 string name = mb.Name;
2804 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
2805 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
2807 if (name.StartsWith ("add_"))
2808 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
2810 if (name.StartsWith ("remove_"))
2811 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
2813 if (name.StartsWith ("op_")){
2814 foreach (string oname in Unary.oper_names) {
2819 foreach (string oname in Binary.oper_names) {
2832 /// There is exactly one instance of this class per type.
2834 public sealed class TypeHandle : IMemberContainer {
2835 public readonly IMemberContainer BaseType;
2837 readonly int id = ++next_id;
2838 static int next_id = 0;
2840 static TypeHandle ()
2846 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
2847 /// a TypeHandle yet, a new instance of it is created. This static method
2848 /// ensures that we'll only have one TypeHandle instance per type.
2850 private static TypeHandle GetTypeHandle (Type t)
2852 TypeHandle handle = (TypeHandle) type_hash [t];
2856 handle = new TypeHandle (t);
2857 type_hash.Add (t, handle);
2861 public static MemberCache GetMemberCache (Type t)
2863 return GetTypeHandle (t).MemberCache;
2866 public static void CleanUp ()
2871 public static void Reset ()
2873 type_hash = new PtrHashtable ();
2877 /// Returns the TypeHandle for TypeManager.object_type.
2879 public static IMemberContainer ObjectType {
2881 if (object_type != null)
2884 object_type = GetTypeHandle (TypeManager.object_type);
2891 /// Returns the TypeHandle for TypeManager.array_type.
2893 public static IMemberContainer ArrayType {
2895 if (array_type != null)
2898 array_type = GetTypeHandle (TypeManager.array_type);
2904 private static PtrHashtable type_hash;
2906 private static TypeHandle object_type = null;
2907 private static TypeHandle array_type = null;
2910 private bool is_interface;
2911 private MemberCache member_cache;
2912 private MemberCache base_cache;
2914 private TypeHandle (Type type)
2917 if (type.BaseType != null) {
2918 base_cache = TypeManager.LookupMemberCache (type.BaseType);
2919 BaseType = base_cache.Container;
2920 } else if (type.IsInterface)
2921 base_cache = TypeManager.LookupBaseInterfacesCache (type);
2922 this.is_interface = type.IsInterface;
2923 this.member_cache = new MemberCache (this);
2926 // IMemberContainer methods
2928 public string Name {
2930 return type.FullName;
2940 public MemberCache BaseCache {
2946 public bool IsInterface {
2948 return is_interface;
2952 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2954 MemberInfo [] members;
2955 if (mt == MemberTypes.Event)
2956 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2958 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2960 Array.Reverse (members);
2962 return new MemberList (members);
2965 // IMemberFinder methods
2967 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2968 MemberFilter filter, object criteria)
2970 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
2973 public MemberCache MemberCache {
2975 return member_cache;
2979 public override string ToString ()
2981 if (BaseType != null)
2982 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2984 return "TypeHandle (" + id + "," + Name + ")";