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 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 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 guid_attr_type;
84 static public Type void_ptr_type;
85 static public Type indexer_name_type;
86 static public Type exception_type;
87 static public Type invalid_operation_exception_type;
88 static public Type not_supported_exception_type;
89 static public Type obsolete_attribute_type;
90 static public Type conditional_attribute_type;
91 static public Type in_attribute_type;
92 static public Type out_attribute_type;
93 static public Type anonymous_method_type;
94 static public Type cls_compliant_attribute_type;
95 static public Type typed_reference_type;
96 static public Type arg_iterator_type;
97 static public Type mbr_type;
98 static public Type struct_layout_attribute_type;
99 static public Type field_offset_attribute_type;
100 static public Type security_attr_type;
105 static internal Type compiler_generated_attr_type;
106 static internal Type fixed_buffer_attr_type;
109 // An empty array of types
111 static public Type [] NoTypes;
112 static public TypeExpr [] NoTypeExprs;
116 // Expressions representing the internal types. Used during declaration
119 static public TypeExpr system_object_expr, system_string_expr;
120 static public TypeExpr system_boolean_expr, system_decimal_expr;
121 static public TypeExpr system_single_expr, system_double_expr;
122 static public TypeExpr system_sbyte_expr, system_byte_expr;
123 static public TypeExpr system_int16_expr, system_uint16_expr;
124 static public TypeExpr system_int32_expr, system_uint32_expr;
125 static public TypeExpr system_int64_expr, system_uint64_expr;
126 static public TypeExpr system_char_expr, system_void_expr;
127 static public TypeExpr system_asynccallback_expr;
128 static public TypeExpr system_iasyncresult_expr;
129 static public TypeExpr system_valuetype_expr;
130 static public TypeExpr system_intptr_expr;
133 // This is only used when compiling corlib
135 static public Type system_int32_type;
136 static public Type system_array_type;
137 static public Type system_type_type;
138 static public Type system_assemblybuilder_type;
139 static public MethodInfo system_int_array_get_length;
140 static public MethodInfo system_int_array_get_rank;
141 static public MethodInfo system_object_array_clone;
142 static public MethodInfo system_int_array_get_length_int;
143 static public MethodInfo system_int_array_get_lower_bound_int;
144 static public MethodInfo system_int_array_get_upper_bound_int;
145 static public MethodInfo system_void_array_copyto_array_int;
149 // Internal, not really used outside
151 static Type runtime_helpers_type;
154 // These methods are called by code generated by the compiler
156 static public MethodInfo string_concat_string_string;
157 static public MethodInfo string_concat_string_string_string;
158 static public MethodInfo string_concat_string_string_string_string;
159 static public MethodInfo string_concat_string_dot_dot_dot;
160 static public MethodInfo string_concat_object_object;
161 static public MethodInfo string_concat_object_object_object;
162 static public MethodInfo string_concat_object_dot_dot_dot;
163 static public MethodInfo string_isinterneted_string;
164 static public MethodInfo system_type_get_type_from_handle;
165 static public MethodInfo object_getcurrent_void;
166 static public MethodInfo bool_movenext_void;
167 static public MethodInfo ienumerable_getenumerator_void;
168 static public MethodInfo void_reset_void;
169 static public MethodInfo void_dispose_void;
170 static public MethodInfo void_monitor_enter_object;
171 static public MethodInfo void_monitor_exit_object;
172 static public MethodInfo void_initializearray_array_fieldhandle;
173 static public MethodInfo int_getlength_int;
174 static public MethodInfo delegate_combine_delegate_delegate;
175 static public MethodInfo delegate_remove_delegate_delegate;
176 static public MethodInfo int_get_offset_to_string_data;
177 static public MethodInfo int_array_get_length;
178 static public MethodInfo int_array_get_rank;
179 static public MethodInfo object_array_clone;
180 static public MethodInfo int_array_get_length_int;
181 static public MethodInfo int_array_get_lower_bound_int;
182 static public MethodInfo int_array_get_upper_bound_int;
183 static public MethodInfo void_array_copyto_array_int;
186 // The attribute constructors.
188 static public ConstructorInfo object_ctor;
189 static public ConstructorInfo cons_param_array_attribute;
190 static public ConstructorInfo void_decimal_ctor_five_args;
191 static public ConstructorInfo void_decimal_ctor_int_arg;
192 static public ConstructorInfo unverifiable_code_ctor;
193 static public ConstructorInfo default_member_ctor;
194 static public ConstructorInfo decimal_constant_attribute_ctor;
195 static internal ConstructorInfo struct_layout_attribute_ctor;
200 static internal CustomAttributeBuilder compiler_generated_attr;
201 static internal ConstructorInfo fixed_buffer_attr_ctor;
204 // Holds the Array of Assemblies that have been loaded
205 // (either because it is the default or the user used the
206 // -r command line option)
208 static Assembly [] assemblies;
211 // Keeps a list of modules. We used this to do lookups
212 // on the module using GetType -- needed for arrays
214 static Module [] modules;
217 // This is the type_cache from the assemblies to avoid
218 // hitting System.Reflection on every lookup.
220 static Hashtable types;
223 // This is used to hotld the corresponding TypeContainer objects
224 // since we need this in FindMembers
226 static Hashtable typecontainers;
229 // Keeps track of those types that are defined by the
232 static ArrayList user_types;
234 static PtrHashtable builder_to_declspace;
236 static PtrHashtable builder_to_member_cache;
239 // Tracks the interfaces implemented by typebuilders. We only
240 // enter those who do implement or or more interfaces
242 static PtrHashtable builder_to_ifaces;
245 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
246 // the arguments to the method
248 static Hashtable method_arguments;
251 // Maps PropertyBuilder to a Type array that contains
252 // the arguments to the indexer
254 static Hashtable indexer_arguments;
257 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
259 static Hashtable method_params;
262 // Keeps track of methods
265 static Hashtable builder_to_method;
268 // Contains all public types from referenced assemblies.
269 // This member is used only if CLS Compliance verification is required.
271 public static Hashtable all_imported_types;
278 public static void CleanUp ()
280 // Lets get everything clean so that we can collect before generating code
284 typecontainers = null;
286 builder_to_declspace = null;
287 builder_to_member_cache = null;
288 builder_to_ifaces = null;
289 method_arguments = null;
290 indexer_arguments = null;
291 method_params = null;
292 builder_to_method = null;
296 negative_hits = null;
297 builder_to_constant = null;
298 fieldbuilders_to_fields = null;
300 priv_fields_events = null;
304 TypeHandle.CleanUp ();
308 /// A filter for Findmembers that uses the Signature object to
311 static bool SignatureFilter (MemberInfo mi, object criteria)
313 Signature sig = (Signature) criteria;
315 if (!(mi is MethodBase))
318 if (mi.Name != sig.name)
321 int count = sig.args.Length;
323 if (mi is MethodBuilder || mi is ConstructorBuilder){
324 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
326 if (candidate_args.Length != count)
329 for (int i = 0; i < count; i++)
330 if (candidate_args [i] != sig.args [i])
335 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
337 if (pars.Length != count)
340 for (int i = 0; i < count; i++)
341 if (pars [i].ParameterType != sig.args [i])
347 // A delegate that points to the filter above.
348 static MemberFilter signature_filter;
351 // These are expressions that represent some of the internal data types, used
354 static void InitExpressionTypes ()
356 system_object_expr = new TypeLookupExpression ("System.Object");
357 system_string_expr = new TypeLookupExpression ("System.String");
358 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
359 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
360 system_single_expr = new TypeLookupExpression ("System.Single");
361 system_double_expr = new TypeLookupExpression ("System.Double");
362 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
363 system_byte_expr = new TypeLookupExpression ("System.Byte");
364 system_int16_expr = new TypeLookupExpression ("System.Int16");
365 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
366 system_int32_expr = new TypeLookupExpression ("System.Int32");
367 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
368 system_int64_expr = new TypeLookupExpression ("System.Int64");
369 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
370 system_char_expr = new TypeLookupExpression ("System.Char");
371 system_void_expr = new TypeLookupExpression ("System.Void");
372 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
373 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
374 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
375 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
378 static TypeManager ()
380 assemblies = new Assembly [0];
382 user_types = new ArrayList ();
384 types = new Hashtable ();
385 typecontainers = new Hashtable ();
387 builder_to_declspace = new PtrHashtable ();
388 builder_to_member_cache = new PtrHashtable ();
389 builder_to_method = new PtrHashtable ();
390 method_arguments = new PtrHashtable ();
391 method_params = new PtrHashtable ();
392 indexer_arguments = new PtrHashtable ();
393 builder_to_ifaces = new PtrHashtable ();
395 NoTypes = new Type [0];
396 NoTypeExprs = new TypeExpr [0];
398 signature_filter = new MemberFilter (SignatureFilter);
400 InitExpressionTypes ();
403 public static void HandleDuplicate (string name, Type t)
405 Type prev = (Type) types [name];
406 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
410 // This probably never happens, as we catch this before
412 Report.Error (-17, "The type `" + name + "' has already been defined.");
416 tc = builder_to_declspace [t] as TypeContainer;
419 1595, "The type `" + name + "' is defined in an existing assembly;"+
420 " Using the new definition from: " + tc.Location);
423 1595, "The type `" + name + "' is defined in an existing assembly;");
426 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
432 public static void AddUserType (string name, TypeBuilder t)
437 HandleDuplicate (name, t);
443 // This entry point is used by types that we define under the covers
445 public static void RegisterBuilder (Type tb, Type [] ifaces)
448 builder_to_ifaces [tb] = ifaces;
451 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
453 builder_to_declspace.Add (t, tc);
454 typecontainers.Add (name, tc);
455 AddUserType (name, t);
458 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
463 HandleDuplicate (name, t);
466 builder_to_declspace.Add (t, del);
469 public static void AddEnumType (string name, TypeBuilder t, Enum en)
474 HandleDuplicate (name, t);
476 builder_to_declspace.Add (t, en);
479 public static void AddMethod (MethodBase builder, IMethodData method)
481 builder_to_method.Add (builder, method);
484 public static IMethodData GetMethod (MethodBase builder)
486 return (IMethodData) builder_to_method [builder];
490 /// Returns the DeclSpace whose Type is `t' or null if there is no
491 /// DeclSpace for `t' (ie, the Type comes from a library)
493 public static DeclSpace LookupDeclSpace (Type t)
495 return builder_to_declspace [t] as DeclSpace;
499 /// Returns the TypeContainer whose Type is `t' or null if there is no
500 /// TypeContainer for `t' (ie, the Type comes from a library)
502 public static TypeContainer LookupTypeContainer (Type t)
504 return builder_to_declspace [t] as TypeContainer;
507 public static MemberCache LookupMemberCache (Type t)
509 if (t is TypeBuilder) {
510 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
511 if (container != null)
512 return container.MemberCache;
515 if (t is GenericTypeParameterBuilder) {
516 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
518 if (container != null)
519 return container.MemberCache;
522 return TypeHandle.GetMemberCache (t);
525 public static MemberCache LookupBaseInterfacesCache (Type t)
527 Type [] ifaces = t.GetInterfaces ();
529 if (ifaces != null && ifaces.Length == 1)
530 return LookupMemberCache (ifaces [0]);
532 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
533 MemberCache cache = builder_to_member_cache [t] as MemberCache;
537 cache = new MemberCache (ifaces);
538 builder_to_member_cache.Add (t, cache);
542 public static TypeContainer LookupInterface (Type t)
544 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
545 if ((tc == null) || (tc.Kind != Kind.Interface))
551 public static Delegate LookupDelegate (Type t)
553 return builder_to_declspace [t] as Delegate;
556 public static Enum LookupEnum (Type t)
558 return builder_to_declspace [t] as Enum;
561 public static Class LookupClass (Type t)
563 return (Class) builder_to_declspace [t];
567 /// Registers an assembly to load types from.
569 public static void AddAssembly (Assembly a)
571 foreach (Assembly assembly in assemblies) {
576 int top = assemblies.Length;
577 Assembly [] n = new Assembly [top + 1];
579 assemblies.CopyTo (n, 0);
585 public static Assembly [] GetAssemblies ()
591 /// Registers a module builder to lookup types from
593 public static void AddModule (Module mb)
595 int top = modules != null ? modules.Length : 0;
596 Module [] n = new Module [top + 1];
599 modules.CopyTo (n, 0);
604 public static Module[] Modules {
610 static Hashtable references = new Hashtable ();
613 // Gets the reference to T version of the Type (T&)
615 public static Type GetReferenceType (Type t)
617 return t.MakeByRefType ();
620 static Hashtable pointers = new Hashtable ();
623 // Gets the pointer to T version of the Type (T*)
625 public static Type GetPointerType (Type t)
627 string tname = t.FullName + "*";
629 Type ret = t.Assembly.GetType (tname);
632 // If the type comes from the assembly we are building
633 // We need the Hashtable, because .NET 1.1 will return different instance types
634 // every time we call ModuleBuilder.GetType.
637 if (pointers [t] == null)
638 pointers [t] = CodeGen.Module.Builder.GetType (tname);
640 ret = (Type) pointers [t];
647 // Low-level lookup, cache-less
649 static Type LookupTypeReflection (string name)
653 foreach (Assembly a in assemblies){
654 t = a.GetType (name);
659 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
660 if (ta == TypeAttributes.NotPublic ||
661 ta == TypeAttributes.NestedPrivate ||
662 ta == TypeAttributes.NestedAssembly ||
663 ta == TypeAttributes.NestedFamANDAssem){
666 // In .NET pointers turn out to be private, even if their
667 // element type is not
670 t = t.GetElementType ();
680 foreach (Module mb in modules) {
681 t = mb.GetType (name);
689 static Hashtable negative_hits = new Hashtable ();
692 // This function is used when you want to avoid the lookups, and want to go
693 // directly to the source. This will use the cache.
695 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
696 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
697 // way to test things other than doing a fullname compare
699 public static Type LookupTypeDirect (string name)
701 Type t = (Type) types [name];
705 t = LookupTypeReflection (name);
713 static readonly char [] dot_array = { '.' };
716 /// Returns the Type associated with @name, takes care of the fact that
717 /// reflection expects nested types to be separated from the main type
718 /// with a "+" instead of a "."
720 public static Type LookupType (string name)
725 // First lookup in user defined and cached values
728 t = (Type) types [name];
732 // Two thirds of the failures are caught here.
733 if (negative_hits.Contains (name))
736 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
737 string [] elements = name.Split (dot_array);
738 int count = elements.Length;
740 for (int n = 1; n <= count; n++){
741 string top_level_type = String.Join (".", elements, 0, n);
743 // One third of the failures are caught here.
744 if (negative_hits.Contains (top_level_type))
747 t = (Type) types [top_level_type];
749 t = LookupTypeReflection (top_level_type);
751 negative_hits [top_level_type] = null;
762 // We know that System.Object does not have children, and since its the base of
763 // all the objects, it always gets probbed for inner classes.
765 if (top_level_type == "System.Object")
768 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
769 //Console.WriteLine ("Looking up: " + newt + " " + name);
770 t = LookupTypeReflection (newt);
772 negative_hits [name] = null;
777 negative_hits [name] = null;
782 /// Computes the namespaces that we import from the assemblies we reference.
784 public static void ComputeNamespaces ()
786 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
789 // First add the assembly namespaces
791 if (assembly_get_namespaces != null){
792 int count = assemblies.Length;
794 for (int i = 0; i < count; i++){
795 Assembly a = assemblies [i];
796 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
797 foreach (string ns in namespaces){
800 Namespace.LookupNamespace (ns, true);
804 Hashtable cache = new Hashtable ();
805 cache.Add ("", null);
806 foreach (Assembly a in assemblies) {
807 foreach (Type t in a.GetExportedTypes ()) {
808 string ns = t.Namespace;
809 if (ns == null || cache.Contains (ns))
812 Namespace.LookupNamespace (ns, true);
813 cache.Add (ns, null);
820 /// Fills static table with exported types from all referenced assemblies.
821 /// This information is required for CLS Compliance tests.
823 public static void LoadAllImportedTypes ()
825 all_imported_types = new Hashtable ();
826 foreach (Assembly a in assemblies) {
827 foreach (Type t in a.GetExportedTypes ()) {
828 all_imported_types [t.FullName] = t;
833 public static bool NamespaceClash (string name, Location loc)
835 if (Namespace.LookupNamespace (name, false) == null)
838 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
843 /// Returns the C# name of a type if possible, or the full type name otherwise
845 static public string CSharpName (Type t)
847 if (t.FullName == null)
850 return Regex.Replace (t.FullName,
852 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
853 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
854 @"Boolean|String|Void|Null)" +
856 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
859 static public string CSharpName (Type[] types)
861 StringBuilder sb = new StringBuilder ();
862 foreach (Type t in types) {
863 sb.Append (CSharpName (t));
866 sb.Remove (sb.Length - 1, 1);
867 return sb.ToString ();
870 static String CSharpNameMatch (Match match)
872 string s = match.Groups [1].Captures [0].Value;
874 Replace ("int32", "int").
875 Replace ("uint32", "uint").
876 Replace ("int16", "short").
877 Replace ("uint16", "ushort").
878 Replace ("int64", "long").
879 Replace ("uint64", "ulong").
880 Replace ("single", "float").
881 Replace ("boolean", "bool")
882 + match.Groups [2].Captures [0].Value;
886 /// Returns the signature of the method with full namespace classification
888 static public string GetFullNameSignature (MemberInfo mi)
890 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
891 return (mi is MethodBase)
892 ? GetFullNameSignature (mi as MethodBase)
893 : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
896 static public string GetFullNameSignature (MethodBase mb)
898 string name = mb.Name;
900 name = mb.DeclaringType.Name;
902 if (mb.IsSpecialName) {
903 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
904 name = name.Remove (0, 4);
911 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
914 static public string GetFullName (Type t)
916 if (t.FullName == null)
919 string name = t.FullName.Replace ('+', '.');
921 DeclSpace tc = LookupDeclSpace (t);
922 if ((tc != null) && tc.IsGeneric) {
923 TypeParameter[] tparam = tc.TypeParameters;
925 StringBuilder sb = new StringBuilder (name);
927 for (int i = 0; i < tparam.Length; i++) {
930 sb.Append (tparam [i].Name);
933 return sb.ToString ();
934 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
935 Type[] tparam = t.GetGenericArguments ();
937 StringBuilder sb = new StringBuilder (name);
939 for (int i = 0; i < tparam.Length; i++) {
942 sb.Append (tparam [i].Name);
945 return sb.ToString ();
952 /// Returns the signature of the property and indexer
954 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
957 return GetFullNameSignature (pb);
960 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
961 string signature = GetFullNameSignature (mb);
962 string arg = GetParameterData (mb).ParameterDesc (0);
963 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
967 /// Returns the signature of the method
969 static public string CSharpSignature (MethodBase mb)
971 StringBuilder sig = new StringBuilder ("(");
973 ParameterData iparams = GetParameterData (mb);
976 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
977 return GetFullNameSignature (mb);
979 for (int i = 0; i < iparams.Count; i++) {
983 sig.Append (iparams.ParameterDesc (i));
988 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
989 sig.Replace ('(', '[');
990 sig.Replace (')', ']');
993 return GetFullNameSignature (mb) + sig.ToString ();
996 public static string GetMethodName (MethodInfo m)
998 if (!IsGenericMethod (m))
1001 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
1005 /// Looks up a type, and aborts if it is not found. This is used
1006 /// by types required by the compiler
1008 static Type CoreLookupType (string name)
1010 Type t = LookupTypeDirect (name);
1013 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1014 Environment.Exit (1);
1021 /// Returns the MethodInfo for a method named `name' defined
1022 /// in type `t' which takes arguments of types `args'
1024 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1028 BindingFlags flags = instance_and_static | BindingFlags.Public;
1034 flags |= BindingFlags.NonPublic;
1036 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1037 if (list.Count == 0) {
1039 Report.Error (-19, "Can not find the core function `" + name + "'");
1043 MethodInfo mi = list [0] as MethodInfo;
1046 Report.Error (-19, "Can not find the core function `" + name + "'");
1053 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1055 return GetMethod (t, name, args, false, report_errors);
1058 static MethodInfo GetMethod (Type t, string name, Type [] args)
1060 return GetMethod (t, name, args, true);
1065 /// Returns the ConstructorInfo for "args"
1067 static ConstructorInfo GetConstructor (Type t, Type [] args)
1075 list = FindMembers (t, MemberTypes.Constructor,
1076 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1077 signature_filter, sig);
1078 if (list.Count == 0){
1079 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1083 ConstructorInfo ci = list [0] as ConstructorInfo;
1085 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1092 public static void InitEnumUnderlyingTypes ()
1095 int32_type = CoreLookupType ("System.Int32");
1096 int64_type = CoreLookupType ("System.Int64");
1097 uint32_type = CoreLookupType ("System.UInt32");
1098 uint64_type = CoreLookupType ("System.UInt64");
1099 byte_type = CoreLookupType ("System.Byte");
1100 sbyte_type = CoreLookupType ("System.SByte");
1101 short_type = CoreLookupType ("System.Int16");
1102 ushort_type = CoreLookupType ("System.UInt16");
1106 /// The types have to be initialized after the initial
1107 /// population of the type has happened (for example, to
1108 /// bootstrap the corlib.dll
1110 public static void InitCoreTypes ()
1112 object_type = CoreLookupType ("System.Object");
1113 value_type = CoreLookupType ("System.ValueType");
1115 InitEnumUnderlyingTypes ();
1117 char_type = CoreLookupType ("System.Char");
1118 string_type = CoreLookupType ("System.String");
1119 float_type = CoreLookupType ("System.Single");
1120 double_type = CoreLookupType ("System.Double");
1121 char_ptr_type = CoreLookupType ("System.Char*");
1122 decimal_type = CoreLookupType ("System.Decimal");
1123 bool_type = CoreLookupType ("System.Boolean");
1124 enum_type = CoreLookupType ("System.Enum");
1126 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1127 delegate_type = CoreLookupType ("System.Delegate");
1129 array_type = CoreLookupType ("System.Array");
1130 void_type = CoreLookupType ("System.Void");
1131 type_type = CoreLookupType ("System.Type");
1133 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1134 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1135 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1136 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1137 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1138 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1139 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1140 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1141 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1142 idisposable_type = CoreLookupType ("System.IDisposable");
1143 icloneable_type = CoreLookupType ("System.ICloneable");
1144 iconvertible_type = CoreLookupType ("System.IConvertible");
1145 monitor_type = CoreLookupType ("System.Threading.Monitor");
1146 intptr_type = CoreLookupType ("System.IntPtr");
1148 attribute_type = CoreLookupType ("System.Attribute");
1149 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1150 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1151 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1152 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1153 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1154 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1155 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1156 typed_reference_type = CoreLookupType ("System.TypedReference");
1157 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1158 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1159 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1162 // Sigh. Remove this before the release. Wonder what versions of Mono
1163 // people are running.
1165 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1167 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1169 void_ptr_type = CoreLookupType ("System.Void*");
1171 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1173 exception_type = CoreLookupType ("System.Exception");
1174 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1175 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1180 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1181 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1182 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1183 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1184 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1185 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1187 InitGenericCoreTypes ();
1192 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
1193 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices.FixedBufferAttribute");
1195 // When compiling corlib, store the "real" types here.
1197 if (!RootContext.StdLib) {
1198 system_int32_type = typeof (System.Int32);
1199 system_array_type = typeof (System.Array);
1200 system_type_type = typeof (System.Type);
1201 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1203 Type [] void_arg = { };
1204 system_int_array_get_length = GetMethod (
1205 system_array_type, "get_Length", void_arg);
1206 system_int_array_get_rank = GetMethod (
1207 system_array_type, "get_Rank", void_arg);
1208 system_object_array_clone = GetMethod (
1209 system_array_type, "Clone", void_arg);
1211 Type [] system_int_arg = { system_int32_type };
1212 system_int_array_get_length_int = GetMethod (
1213 system_array_type, "GetLength", system_int_arg);
1214 system_int_array_get_upper_bound_int = GetMethod (
1215 system_array_type, "GetUpperBound", system_int_arg);
1216 system_int_array_get_lower_bound_int = GetMethod (
1217 system_array_type, "GetLowerBound", system_int_arg);
1219 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1220 system_void_array_copyto_array_int = GetMethod (
1221 system_array_type, "CopyTo", system_array_int_arg);
1223 Type [] system_3_type_arg = {
1224 system_type_type, system_type_type, system_type_type };
1225 Type [] system_4_type_arg = {
1226 system_type_type, system_type_type, system_type_type, system_type_type };
1228 MethodInfo set_corlib_type_builders = GetMethod (
1229 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1230 system_4_type_arg, true, false);
1232 if (set_corlib_type_builders != null) {
1233 object[] args = new object [4];
1234 args [0] = object_type;
1235 args [1] = value_type;
1236 args [2] = enum_type;
1237 args [3] = void_type;
1239 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1241 // Compatibility for an older version of the class libs.
1242 set_corlib_type_builders = GetMethod (
1243 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1244 system_3_type_arg, true, true);
1246 if (set_corlib_type_builders == null) {
1247 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1251 object[] args = new object [3];
1252 args [0] = object_type;
1253 args [1] = value_type;
1254 args [2] = enum_type;
1256 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1260 system_object_expr.Type = object_type;
1261 system_string_expr.Type = string_type;
1262 system_boolean_expr.Type = bool_type;
1263 system_decimal_expr.Type = decimal_type;
1264 system_single_expr.Type = float_type;
1265 system_double_expr.Type = double_type;
1266 system_sbyte_expr.Type = sbyte_type;
1267 system_byte_expr.Type = byte_type;
1268 system_int16_expr.Type = short_type;
1269 system_uint16_expr.Type = ushort_type;
1270 system_int32_expr.Type = int32_type;
1271 system_uint32_expr.Type = uint32_type;
1272 system_int64_expr.Type = int64_type;
1273 system_uint64_expr.Type = uint64_type;
1274 system_char_expr.Type = char_type;
1275 system_void_expr.Type = void_type;
1276 system_asynccallback_expr.Type = asynccallback_type;
1277 system_iasyncresult_expr.Type = iasyncresult_type;
1278 system_valuetype_expr.Type = value_type;
1281 // These are only used for compare purposes
1283 anonymous_method_type = typeof (AnonymousMethod);
1284 null_type = typeof (NullType);
1288 // The helper methods that are used by the compiler
1290 public static void InitCodeHelpers ()
1293 // Now load the default methods that we use.
1295 Type [] string_string = { string_type, string_type };
1296 string_concat_string_string = GetMethod (
1297 string_type, "Concat", string_string);
1298 Type [] string_string_string = { string_type, string_type, string_type };
1299 string_concat_string_string_string = GetMethod (
1300 string_type, "Concat", string_string_string);
1301 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1302 string_concat_string_string_string_string = GetMethod (
1303 string_type, "Concat", string_string_string_string);
1304 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1305 string_concat_string_dot_dot_dot = GetMethod (
1306 string_type, "Concat", params_string);
1308 Type [] object_object = { object_type, object_type };
1309 string_concat_object_object = GetMethod (
1310 string_type, "Concat", object_object);
1311 Type [] object_object_object = { object_type, object_type, object_type };
1312 string_concat_object_object_object = GetMethod (
1313 string_type, "Concat", object_object_object);
1314 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1315 string_concat_object_dot_dot_dot = GetMethod (
1316 string_type, "Concat", params_object);
1318 Type [] string_ = { string_type };
1319 string_isinterneted_string = GetMethod (
1320 string_type, "IsInterned", string_);
1322 Type [] runtime_type_handle = { runtime_handle_type };
1323 system_type_get_type_from_handle = GetMethod (
1324 type_type, "GetTypeFromHandle", runtime_type_handle);
1326 Type [] delegate_delegate = { delegate_type, delegate_type };
1327 delegate_combine_delegate_delegate = GetMethod (
1328 delegate_type, "Combine", delegate_delegate);
1330 delegate_remove_delegate_delegate = GetMethod (
1331 delegate_type, "Remove", delegate_delegate);
1336 Type [] void_arg = { };
1337 object_getcurrent_void = GetMethod (
1338 ienumerator_type, "get_Current", void_arg);
1339 bool_movenext_void = GetMethod (
1340 ienumerator_type, "MoveNext", void_arg);
1341 void_reset_void = GetMethod (
1342 ienumerator_type, "Reset", void_arg);
1343 void_dispose_void = GetMethod (
1344 idisposable_type, "Dispose", void_arg);
1345 int_get_offset_to_string_data = GetMethod (
1346 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1347 int_array_get_length = GetMethod (
1348 array_type, "get_Length", void_arg);
1349 int_array_get_rank = GetMethod (
1350 array_type, "get_Rank", void_arg);
1351 ienumerable_getenumerator_void = GetMethod (
1352 ienumerable_type, "GetEnumerator", void_arg);
1357 Type [] int_arg = { int32_type };
1358 int_array_get_length_int = GetMethod (
1359 array_type, "GetLength", int_arg);
1360 int_array_get_upper_bound_int = GetMethod (
1361 array_type, "GetUpperBound", int_arg);
1362 int_array_get_lower_bound_int = GetMethod (
1363 array_type, "GetLowerBound", int_arg);
1366 // System.Array methods
1368 object_array_clone = GetMethod (
1369 array_type, "Clone", void_arg);
1370 Type [] array_int_arg = { array_type, int32_type };
1371 void_array_copyto_array_int = GetMethod (
1372 array_type, "CopyTo", array_int_arg);
1377 Type [] object_arg = { object_type };
1378 void_monitor_enter_object = GetMethod (
1379 monitor_type, "Enter", object_arg);
1380 void_monitor_exit_object = GetMethod (
1381 monitor_type, "Exit", object_arg);
1383 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1385 void_initializearray_array_fieldhandle = GetMethod (
1386 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1391 int_getlength_int = GetMethod (
1392 array_type, "GetLength", int_arg);
1395 // Decimal constructors
1397 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1398 void_decimal_ctor_five_args = GetConstructor (
1399 decimal_type, dec_arg);
1401 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1406 cons_param_array_attribute = GetConstructor (param_array_type, void_arg);
1407 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg);
1408 default_member_ctor = GetConstructor (default_member_type, string_);
1410 Type[] short_arg = { short_type };
1411 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1413 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1414 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1420 compiler_generated_attr = new CustomAttributeBuilder (
1421 GetConstructor (compiler_generated_attr_type, void_arg), new object[0]);
1423 Type[] type_int_arg = { type_type, int32_type };
1424 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1427 object_ctor = GetConstructor (object_type, void_arg);
1429 InitGenericCodeHelpers ();
1432 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1435 /// This is the "old", non-cache based FindMembers() function. We cannot use
1436 /// the cache here because there is no member name argument.
1438 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1439 MemberFilter filter, object criteria)
1441 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1444 // `builder_to_declspace' contains all dynamic types.
1448 Timer.StartTimer (TimerType.FindMembers);
1449 list = decl.FindMembers (mt, bf, filter, criteria);
1450 Timer.StopTimer (TimerType.FindMembers);
1455 // We have to take care of arrays specially, because GetType on
1456 // a TypeBuilder array will return a Type, not a TypeBuilder,
1457 // and we can not call FindMembers on this type.
1459 if (t.IsSubclassOf (TypeManager.array_type))
1460 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1462 if (t is GenericTypeParameterBuilder) {
1463 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1465 Timer.StartTimer (TimerType.FindMembers);
1466 MemberList list = tparam.FindMembers (
1467 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1468 Timer.StopTimer (TimerType.FindMembers);
1473 // Since FindMembers will not lookup both static and instance
1474 // members, we emulate this behaviour here.
1476 if ((bf & instance_and_static) == instance_and_static){
1477 MemberInfo [] i_members = t.FindMembers (
1478 mt, bf & ~BindingFlags.Static, filter, criteria);
1480 int i_len = i_members.Length;
1482 MemberInfo one = i_members [0];
1485 // If any of these are present, we are done!
1487 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1488 return new MemberList (i_members);
1491 MemberInfo [] s_members = t.FindMembers (
1492 mt, bf & ~BindingFlags.Instance, filter, criteria);
1494 int s_len = s_members.Length;
1495 if (i_len > 0 || s_len > 0)
1496 return new MemberList (i_members, s_members);
1499 return new MemberList (i_members);
1501 return new MemberList (s_members);
1505 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1510 /// This method is only called from within MemberLookup. It tries to use the member
1511 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1512 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1513 /// our return value will already contain all inherited members and the caller don't need
1514 /// to check base classes and interfaces anymore.
1516 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1517 string name, out bool used_cache)
1522 // We have to take care of arrays specially, because GetType on
1523 // a TypeBuilder array will return a Type, not a TypeBuilder,
1524 // and we can not call FindMembers on this type.
1526 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1528 return TypeHandle.ArrayType.MemberCache.FindMembers (
1529 mt, bf, name, FilterWithClosure_delegate, null);
1533 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1534 // and we can ask the DeclSpace for the MemberCache.
1536 if (t is TypeBuilder) {
1537 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1538 cache = decl.MemberCache;
1541 // If this DeclSpace has a MemberCache, use it.
1544 if (cache != null) {
1546 return cache.FindMembers (
1547 mt, bf, name, FilterWithClosure_delegate, null);
1550 // If there is no MemberCache, we need to use the "normal" FindMembers.
1551 // Note, this is a VERY uncommon route!
1554 Timer.StartTimer (TimerType.FindMembers);
1555 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1556 FilterWithClosure_delegate, name);
1557 Timer.StopTimer (TimerType.FindMembers);
1559 return (MemberInfo []) list;
1562 if (t is GenericTypeParameterBuilder) {
1563 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1566 Timer.StartTimer (TimerType.FindMembers);
1567 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1568 FilterWithClosure_delegate, name);
1569 Timer.StopTimer (TimerType.FindMembers);
1571 return (MemberInfo []) list;
1575 // This call will always succeed. There is exactly one TypeHandle instance per
1576 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1577 // the corresponding MemberCache.
1579 cache = TypeHandle.GetMemberCache (t);
1582 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1585 public static bool IsBuiltinType (Type t)
1587 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1588 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1589 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1590 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1596 public static bool IsBuiltinType (TypeContainer tc)
1598 return IsBuiltinType (tc.TypeBuilder);
1602 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1603 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1605 public static bool IsCLRType (Type t)
1607 if (t == object_type || t == int32_type || t == uint32_type ||
1608 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1609 t == char_type || t == short_type || t == bool_type ||
1610 t == sbyte_type || t == byte_type || t == ushort_type)
1616 public static bool IsDelegateType (Type t)
1618 if (t.IsGenericInstance)
1619 t = t.GetGenericTypeDefinition ();
1621 if (t.IsSubclassOf (TypeManager.delegate_type))
1627 public static bool IsEnumType (Type t)
1629 if (t.IsSubclassOf (TypeManager.enum_type))
1634 public static bool IsBuiltinOrEnum (Type t)
1636 if (IsBuiltinType (t))
1645 public static bool IsNullType (Type t)
1647 return t == null_type;
1651 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1653 public static bool IsUnmanagedType (Type t)
1655 if (IsBuiltinType (t) && t != TypeManager.string_type)
1664 if (IsValueType (t)){
1665 if (t is TypeBuilder){
1666 TypeContainer tc = LookupTypeContainer (t);
1668 if (tc.Fields != null){
1669 foreach (Field f in tc.Fields){
1670 if (f.FieldBuilder.IsStatic)
1672 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1678 FieldInfo [] fields = t.GetFields ();
1680 foreach (FieldInfo f in fields){
1683 if (!IsUnmanagedType (f.FieldType))
1693 public static bool IsValueType (Type t)
1695 return t.IsGenericParameter || t.IsValueType;
1698 public static bool IsInterfaceType (Type t)
1700 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1704 return tc.Kind == Kind.Interface;
1707 public static bool IsSubclassOf (Type type, Type base_type)
1709 TypeParameter tparam = LookupTypeParameter (type);
1710 TypeParameter pparam = LookupTypeParameter (base_type);
1712 if ((tparam != null) && (pparam != null)) {
1713 if (tparam == pparam)
1716 return tparam.IsSubclassOf (base_type);
1720 if (type.Equals (base_type))
1723 type = type.BaseType;
1724 } while (type != null);
1729 public static bool IsPrivateAccessible (Type type, Type parent)
1731 if (type.Equals (parent))
1734 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
1736 // `a' is a generic type definition's TypeBuilder and `b' is a
1737 // generic instance of the same type.
1743 // void Test (Stack<T> stack) { }
1746 // The first argument of `Test' will be the generic instance
1747 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1750 // We hit this via Closure.Filter() for gen-82.cs.
1752 if (type != parent.GetGenericTypeDefinition ())
1758 if (type.IsGenericInstance && parent.IsGenericInstance) {
1759 if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
1768 public static bool IsFamilyAccessible (Type type, Type parent)
1770 TypeParameter tparam = LookupTypeParameter (type);
1771 TypeParameter pparam = LookupTypeParameter (parent);
1773 if ((tparam != null) && (pparam != null)) {
1774 if (tparam == pparam)
1777 return tparam.IsSubclassOf (parent);
1781 if (IsEqualGenericInstance (type, parent))
1784 type = type.BaseType;
1785 } while (type != null);
1791 // Checks whether `type' is a subclass or nested child of `base_type'.
1793 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1796 if (IsFamilyAccessible (type, base_type))
1799 // Handle nested types.
1800 type = type.DeclaringType;
1801 } while (type != null);
1807 // Checks whether `type' is a nested child of `parent'.
1809 public static bool IsNestedChildOf (Type type, Type parent)
1811 if (IsEqual (type, parent))
1814 type = type.DeclaringType;
1815 while (type != null) {
1816 if (IsEqual (type, parent))
1819 type = type.DeclaringType;
1826 // Do the right thing when returning the element type of an
1827 // array type based on whether we are compiling corlib or not
1829 public static Type GetElementType (Type t)
1831 if (RootContext.StdLib)
1832 return t.GetElementType ();
1834 return TypeToCoreType (t.GetElementType ());
1838 /// This method is not implemented by MS runtime for dynamic types
1840 public static bool HasElementType (Type t)
1842 return t.IsArray || t.IsPointer || t.IsByRef;
1846 /// Returns the User Defined Types
1848 public static ArrayList UserTypes {
1854 public static Hashtable TypeContainers {
1856 return typecontainers;
1860 static Hashtable builder_to_constant;
1862 public static void RegisterConstant (FieldBuilder fb, Const c)
1864 if (builder_to_constant == null)
1865 builder_to_constant = new PtrHashtable ();
1867 if (builder_to_constant.Contains (fb))
1870 builder_to_constant.Add (fb, c);
1873 public static Const LookupConstant (FieldBuilder fb)
1875 if (builder_to_constant == null)
1878 return (Const) builder_to_constant [fb];
1882 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1886 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1887 /// for anything which is dynamic, and we need this in a number of places,
1888 /// we register this information here, and use it afterwards.
1890 static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1895 method_arguments.Add (mb, args);
1896 method_params.Add (mb, ip);
1899 static public ParameterData GetParameterData (MethodBase mb)
1901 object pd = method_params [mb];
1903 if (mb is MethodBuilder || mb is ConstructorBuilder)
1904 throw new InternalErrorException ("Argument for Method not registered" + mb);
1906 method_params [mb] = pd = new ReflectionParameters (mb);
1909 return (ParameterData) pd;
1913 /// Returns the argument types for a method based on its methodbase
1915 /// For dynamic methods, we use the compiler provided types, for
1916 /// methods from existing assemblies we load them from GetParameters,
1917 /// and insert them into the cache
1919 static public Type [] GetArgumentTypes (MethodBase mb)
1921 object t = method_arguments [mb];
1925 ParameterInfo [] pi = mb.GetParameters ();
1932 types = new Type [c];
1933 for (int i = 0; i < c; i++)
1934 types [i] = pi [i].ParameterType;
1936 method_arguments.Add (mb, types);
1941 /// Returns the argument types for an indexer based on its PropertyInfo
1943 /// For dynamic indexers, we use the compiler provided types, for
1944 /// indexers from existing assemblies we load them from GetParameters,
1945 /// and insert them into the cache
1947 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1949 if (indexer_arguments.Contains (indexer))
1950 return (Type []) indexer_arguments [indexer];
1951 else if (indexer is PropertyBuilder)
1952 // If we're a PropertyBuilder and not in the
1953 // `indexer_arguments' hash, then we're a property and
1957 ParameterInfo [] pi = indexer.GetIndexParameters ();
1958 // Property, not an indexer.
1962 Type [] types = new Type [c];
1964 for (int i = 0; i < c; i++)
1965 types [i] = pi [i].ParameterType;
1967 indexer_arguments.Add (indexer, types);
1973 // This is a workaround the fact that GetValue is not
1974 // supported for dynamic types
1976 static Hashtable fields = new Hashtable ();
1977 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1979 if (fields.Contains (fb))
1982 fields.Add (fb, value);
1987 static public object GetValue (FieldBuilder fb)
1992 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1993 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1995 if (fieldbuilders_to_fields.Contains (fb))
1998 fieldbuilders_to_fields.Add (fb, f);
2003 // The return value can be null; This will be the case for
2004 // auxiliary FieldBuilders created by the compiler that have no
2005 // real field being declared on the source code
2007 static public FieldBase GetField (FieldInfo fb)
2009 if (fb.DeclaringType.IsGenericInstance)
2010 fb = fb.Mono_GetGenericFieldDefinition ();
2012 return (FieldBase) fieldbuilders_to_fields [fb];
2015 static Hashtable events;
2017 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2020 events = new Hashtable ();
2022 if (!events.Contains (eb)) {
2023 events.Add (eb, new Pair (add, remove));
2027 static public MethodInfo GetAddMethod (EventInfo ei)
2029 if (ei is MyEventBuilder) {
2030 Pair pair = (Pair) events [ei];
2032 return (MethodInfo) pair.First;
2034 return ei.GetAddMethod (true);
2037 static public MethodInfo GetRemoveMethod (EventInfo ei)
2039 if (ei is MyEventBuilder) {
2040 Pair pair = (Pair) events [ei];
2042 return (MethodInfo) pair.Second;
2044 return ei.GetRemoveMethod (true);
2047 static Hashtable priv_fields_events;
2049 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2051 if (priv_fields_events == null)
2052 priv_fields_events = new Hashtable ();
2054 if (priv_fields_events.Contains (einfo))
2057 priv_fields_events.Add (einfo, builder);
2062 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2064 if (priv_fields_events == null)
2067 return (MemberInfo) priv_fields_events [ei];
2070 static Hashtable properties;
2072 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2074 if (properties == null)
2075 properties = new Hashtable ();
2077 if (properties.Contains (pb))
2080 properties.Add (pb, new Pair (get, set));
2085 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2086 MethodBase set, Type[] args)
2088 if (!RegisterProperty (pb, get,set))
2091 indexer_arguments.Add (pb, args);
2096 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2098 Hashtable hash = new Hashtable ();
2099 return CheckStructCycles (tc, seen, hash);
2102 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2105 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2109 // `seen' contains all types we've already visited.
2111 if (seen.Contains (tc))
2113 seen.Add (tc, null);
2115 if (tc.Fields == null)
2118 foreach (FieldMember field in tc.Fields) {
2119 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2122 Type ftype = field.FieldBuilder.FieldType;
2123 TypeContainer ftc = LookupTypeContainer (ftype);
2127 if (hash.Contains (ftc)) {
2128 Report.Error (523, tc.Location,
2129 "Struct member `{0}.{1}' of type `{2}' " +
2130 "causes a cycle in the struct layout",
2131 tc.Name, field.Name, ftc.Name);
2136 // `hash' contains all types in the current path.
2138 hash.Add (tc, null);
2140 bool ok = CheckStructCycles (ftc, seen, hash);
2147 if (!seen.Contains (ftc))
2148 seen.Add (ftc, null);
2155 /// Given an array of interface types, expand and eliminate repeated ocurrences
2156 /// of an interface.
2160 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2163 public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2165 ArrayList new_ifaces = new ArrayList ();
2167 foreach (TypeExpr iface in base_interfaces){
2168 TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
2172 if (!new_ifaces.Contains (texpr.Type))
2173 new_ifaces.Add (texpr.Type);
2175 Type [] implementing = texpr.Type.GetInterfaces ();
2177 foreach (Type imp in implementing){
2178 if (!new_ifaces.Contains (imp))
2179 new_ifaces.Add (imp);
2182 Type [] ret = new Type [new_ifaces.Count];
2183 new_ifaces.CopyTo (ret, 0);
2187 static PtrHashtable iface_cache = new PtrHashtable ();
2190 /// This function returns the interfaces in the type `t'. Works with
2191 /// both types and TypeBuilders.
2193 public static Type [] GetInterfaces (Type t)
2196 Type [] cached = iface_cache [t] as Type [];
2201 // The reason for catching the Array case is that Reflection.Emit
2202 // will not return a TypeBuilder for Array types of TypeBuilder types,
2203 // but will still throw an exception if we try to call GetInterfaces
2206 // Since the array interfaces are always constant, we return those for
2211 t = TypeManager.array_type;
2213 if (t is TypeBuilder){
2214 Type [] base_ifaces;
2216 if (t.BaseType == null)
2217 base_ifaces = NoTypes;
2219 base_ifaces = GetInterfaces (t.BaseType);
2220 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2221 if (type_ifaces == null)
2222 type_ifaces = NoTypes;
2224 int base_count = base_ifaces.Length;
2225 Type [] result = new Type [base_count + type_ifaces.Length];
2226 base_ifaces.CopyTo (result, 0);
2227 type_ifaces.CopyTo (result, base_count);
2229 iface_cache [t] = result;
2231 } else if (t is GenericTypeParameterBuilder){
2232 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2233 if (type_ifaces == null)
2234 type_ifaces = NoTypes;
2236 iface_cache [t] = type_ifaces;
2239 Type[] ifaces = t.GetInterfaces ();
2240 iface_cache [t] = ifaces;
2246 // gets the interfaces that are declared explicitly on t
2248 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2250 return (Type []) builder_to_ifaces [t];
2254 /// The following is used to check if a given type implements an interface.
2255 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2257 public static bool ImplementsInterface (Type t, Type iface)
2262 // FIXME OPTIMIZATION:
2263 // as soon as we hit a non-TypeBuiler in the interface
2264 // chain, we could return, as the `Type.GetInterfaces'
2265 // will return all the interfaces implement by the type
2269 interfaces = GetInterfaces (t);
2271 if (interfaces != null){
2272 foreach (Type i in interfaces){
2279 } while (t != null);
2284 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2286 // This is a custom version of Convert.ChangeType() which works
2287 // with the TypeBuilder defined types when compiling corlib.
2288 public static object ChangeType (object value, Type conversionType, out bool error)
2290 IConvertible convert_value = value as IConvertible;
2292 if (convert_value == null){
2298 // We must use Type.Equals() here since `conversionType' is
2299 // the TypeBuilder created version of a system type and not
2300 // the system type itself. You cannot use Type.GetTypeCode()
2301 // on such a type - it'd always return TypeCode.Object.
2305 if (conversionType.Equals (typeof (Boolean)))
2306 return (object)(convert_value.ToBoolean (nf_provider));
2307 else if (conversionType.Equals (typeof (Byte)))
2308 return (object)(convert_value.ToByte (nf_provider));
2309 else if (conversionType.Equals (typeof (Char)))
2310 return (object)(convert_value.ToChar (nf_provider));
2311 else if (conversionType.Equals (typeof (DateTime)))
2312 return (object)(convert_value.ToDateTime (nf_provider));
2313 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2314 return (object)(convert_value.ToDecimal (nf_provider));
2315 else if (conversionType.Equals (typeof (Double)))
2316 return (object)(convert_value.ToDouble (nf_provider));
2317 else if (conversionType.Equals (typeof (Int16)))
2318 return (object)(convert_value.ToInt16 (nf_provider));
2319 else if (conversionType.Equals (typeof (Int32)))
2320 return (object)(convert_value.ToInt32 (nf_provider));
2321 else if (conversionType.Equals (typeof (Int64)))
2322 return (object)(convert_value.ToInt64 (nf_provider));
2323 else if (conversionType.Equals (typeof (SByte)))
2324 return (object)(convert_value.ToSByte (nf_provider));
2325 else if (conversionType.Equals (typeof (Single)))
2326 return (object)(convert_value.ToSingle (nf_provider));
2327 else if (conversionType.Equals (typeof (String)))
2328 return (object)(convert_value.ToString (nf_provider));
2329 else if (conversionType.Equals (typeof (UInt16)))
2330 return (object)(convert_value.ToUInt16 (nf_provider));
2331 else if (conversionType.Equals (typeof (UInt32)))
2332 return (object)(convert_value.ToUInt32 (nf_provider));
2333 else if (conversionType.Equals (typeof (UInt64)))
2334 return (object)(convert_value.ToUInt64 (nf_provider));
2335 else if (conversionType.Equals (typeof (Object)))
2336 return (object)(value);
2346 // This is needed, because enumerations from assemblies
2347 // do not report their underlyingtype, but they report
2350 public static Type EnumToUnderlying (Type t)
2352 if (t == TypeManager.enum_type)
2355 t = t.UnderlyingSystemType;
2356 if (!TypeManager.IsEnumType (t))
2359 if (t is TypeBuilder) {
2360 // slow path needed to compile corlib
2361 if (t == TypeManager.bool_type ||
2362 t == TypeManager.byte_type ||
2363 t == TypeManager.sbyte_type ||
2364 t == TypeManager.char_type ||
2365 t == TypeManager.short_type ||
2366 t == TypeManager.ushort_type ||
2367 t == TypeManager.int32_type ||
2368 t == TypeManager.uint32_type ||
2369 t == TypeManager.int64_type ||
2370 t == TypeManager.uint64_type)
2372 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2374 TypeCode tc = Type.GetTypeCode (t);
2377 case TypeCode.Boolean:
2378 return TypeManager.bool_type;
2380 return TypeManager.byte_type;
2381 case TypeCode.SByte:
2382 return TypeManager.sbyte_type;
2384 return TypeManager.char_type;
2385 case TypeCode.Int16:
2386 return TypeManager.short_type;
2387 case TypeCode.UInt16:
2388 return TypeManager.ushort_type;
2389 case TypeCode.Int32:
2390 return TypeManager.int32_type;
2391 case TypeCode.UInt32:
2392 return TypeManager.uint32_type;
2393 case TypeCode.Int64:
2394 return TypeManager.int64_type;
2395 case TypeCode.UInt64:
2396 return TypeManager.uint64_type;
2398 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2402 // When compiling corlib and called with one of the core types, return
2403 // the corresponding typebuilder for that type.
2405 public static Type TypeToCoreType (Type t)
2407 if (RootContext.StdLib || (t is TypeBuilder))
2410 TypeCode tc = Type.GetTypeCode (t);
2413 case TypeCode.Boolean:
2414 return TypeManager.bool_type;
2416 return TypeManager.byte_type;
2417 case TypeCode.SByte:
2418 return TypeManager.sbyte_type;
2420 return TypeManager.char_type;
2421 case TypeCode.Int16:
2422 return TypeManager.short_type;
2423 case TypeCode.UInt16:
2424 return TypeManager.ushort_type;
2425 case TypeCode.Int32:
2426 return TypeManager.int32_type;
2427 case TypeCode.UInt32:
2428 return TypeManager.uint32_type;
2429 case TypeCode.Int64:
2430 return TypeManager.int64_type;
2431 case TypeCode.UInt64:
2432 return TypeManager.uint64_type;
2433 case TypeCode.Single:
2434 return TypeManager.float_type;
2435 case TypeCode.Double:
2436 return TypeManager.double_type;
2437 case TypeCode.String:
2438 return TypeManager.string_type;
2439 case TypeCode.Decimal:
2440 return TypeManager.decimal_type;
2442 if (t == typeof (void))
2443 return TypeManager.void_type;
2444 if (t == typeof (object))
2445 return TypeManager.object_type;
2446 if (t == typeof (System.Type))
2447 return TypeManager.type_type;
2448 if (t == typeof (System.IntPtr))
2449 return TypeManager.intptr_type;
2455 /// Utility function that can be used to probe whether a type
2456 /// is managed or not.
2458 public static bool VerifyUnManaged (Type t, Location loc)
2460 if (t.IsValueType || t.IsPointer){
2462 // FIXME: this is more complex, we actually need to
2463 // make sure that the type does not contain any
2469 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2470 // We need this explicit check here to make it work when
2471 // compiling corlib.
2476 "Cannot take the address or size of a variable of a managed type ('" +
2477 CSharpName (t) + "')");
2482 /// Returns the name of the indexer in a given type.
2485 /// The default is not always `Item'. The user can change this behaviour by
2486 /// using the IndexerNameAttribute in the container.
2488 /// For example, the String class indexer is named `Chars' not `Item'
2490 public static string IndexerPropertyName (Type t)
2492 if (t.IsGenericInstance)
2493 t = t.GetGenericTypeDefinition ();
2495 if (t is TypeBuilder) {
2496 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2497 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2500 System.Attribute attr = System.Attribute.GetCustomAttribute (
2501 t, TypeManager.default_member_type);
2503 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2504 return dma.MemberName;
2507 return TypeContainer.DefaultIndexerName;
2510 static MethodInfo declare_local_method = null;
2512 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2514 if (declare_local_method == null){
2515 declare_local_method = typeof (ILGenerator).GetMethod (
2517 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2519 new Type [] { typeof (Type), typeof (bool)},
2521 if (declare_local_method == null){
2522 Report.Warning (-24, new Location (-1),
2523 "This version of the runtime does not support making pinned local variables. " +
2524 "This code may cause errors on a runtime with a moving GC");
2525 return ig.DeclareLocal (t);
2528 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2532 // Returns whether the array of memberinfos contains the given method
2534 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2536 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2538 foreach (MethodBase method in array) {
2539 if (method.Name != new_method.Name)
2542 if (method is MethodInfo && new_method is MethodInfo)
2543 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2547 Type [] old_args = TypeManager.GetArgumentTypes (method);
2548 int old_count = old_args.Length;
2551 if (new_args.Length != old_count)
2554 for (i = 0; i < old_count; i++){
2555 if (old_args [i] != new_args [i])
2568 // We copy methods from `new_members' into `target_list' if the signature
2569 // for the method from in the new list does not exist in the target_list
2571 // The name is assumed to be the same.
2573 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2575 if (target_list == null){
2576 target_list = new ArrayList ();
2578 foreach (MemberInfo mi in new_members){
2579 if (mi is MethodBase)
2580 target_list.Add (mi);
2585 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2586 target_list.CopyTo (target_array, 0);
2588 foreach (MemberInfo mi in new_members){
2589 MethodBase new_method = (MethodBase) mi;
2591 if (!ArrayContainsMethod (target_array, new_method))
2592 target_list.Add (new_method);
2597 #region MemberLookup implementation
2600 // Whether we allow private members in the result (since FindMembers
2601 // uses NonPublic for both protected and private), we need to distinguish.
2604 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2609 internal class Closure {
2610 internal bool private_ok;
2612 // Who is invoking us and which type is being queried currently.
2613 internal Type invocation_type;
2614 internal Type qualifier_type;
2616 // The assembly that defines the type is that is calling us
2617 internal Assembly invocation_assembly;
2618 internal IList almost_match;
2620 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2622 if (invocation_type == null)
2625 Debug.Assert (IsNestedFamilyAccessible (invocation_type, m.DeclaringType));
2630 // A nested class has access to all the protected members visible
2632 if (qualifier_type != null
2633 && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2636 if (invocation_type == m.DeclaringType
2637 || invocation_type.IsSubclassOf (m.DeclaringType)) {
2638 // Although a derived class can access protected members of
2639 // its base class it cannot do so through an instance of the
2640 // base class (CS1540).
2641 // => Ancestry should be: declaring_type ->* invocation_type
2642 // ->* qualified_type
2643 if (qualifier_type == null
2644 || qualifier_type == invocation_type
2645 || qualifier_type.IsSubclassOf (invocation_type))
2649 if (almost_match != null)
2650 almost_match.Add (m);
2654 bool Filter (MethodBase mb, object filter_criteria)
2656 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2658 if (ma == MethodAttributes.Private)
2659 return private_ok ||
2660 IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
2661 IsNestedChildOf (invocation_type, mb.DeclaringType);
2664 // FamAndAssem requires that we not only derivate, but we are on the
2667 if (ma == MethodAttributes.FamANDAssem){
2668 if (invocation_assembly != mb.DeclaringType.Assembly)
2672 // Assembly and FamORAssem succeed if we're in the same assembly.
2673 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2674 if (invocation_assembly == mb.DeclaringType.Assembly)
2678 // We already know that we aren't in the same assembly.
2679 if (ma == MethodAttributes.Assembly)
2682 // Family and FamANDAssem require that we derive.
2683 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2684 if (invocation_type == null)
2687 if (!IsNestedFamilyAccessible (invocation_type, mb.DeclaringType))
2690 // Although a derived class can access protected members of its base class
2691 // it cannot do so through an instance of the base class (CS1540).
2692 if (!mb.IsStatic && (qualifier_type != null) &&
2693 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
2694 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
2695 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2705 bool Filter (FieldInfo fi, object filter_criteria)
2707 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2709 if (fa == FieldAttributes.Private)
2710 return private_ok ||
2711 IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
2712 IsNestedChildOf (invocation_type, fi.DeclaringType);
2715 // FamAndAssem requires that we not only derivate, but we are on the
2718 if (fa == FieldAttributes.FamANDAssem){
2719 if (invocation_assembly != fi.DeclaringType.Assembly)
2723 // Assembly and FamORAssem succeed if we're in the same assembly.
2724 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2725 if (invocation_assembly == fi.DeclaringType.Assembly)
2729 // We already know that we aren't in the same assembly.
2730 if (fa == FieldAttributes.Assembly)
2733 // Family and FamANDAssem require that we derive.
2734 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2735 if (invocation_type == null)
2738 if (!IsNestedFamilyAccessible (invocation_type, fi.DeclaringType))
2741 // Although a derived class can access protected members of its base class
2742 // it cannot do so through an instance of the base class (CS1540).
2743 if (!fi.IsStatic && (qualifier_type != null) &&
2744 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
2745 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
2746 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2757 // This filter filters by name + whether it is ok to include private
2758 // members in the search
2760 internal bool Filter (MemberInfo m, object filter_criteria)
2763 // Hack: we know that the filter criteria will always be in the
2764 // `closure' // fields.
2767 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2770 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2771 (invocation_type != null) &&
2772 IsPrivateAccessible (m.DeclaringType, invocation_type))
2776 // Ugly: we need to find out the type of `m', and depending
2777 // on this, tell whether we accept or not
2779 if (m is MethodBase)
2780 return Filter ((MethodBase) m, filter_criteria);
2783 return Filter ((FieldInfo) m, filter_criteria);
2786 // EventInfos and PropertyInfos, return true because they lack
2787 // permission information, so we need to check later on the methods.
2793 static Closure closure = new Closure ();
2794 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2797 // Looks up a member called `name' in the `queried_type'. This lookup
2798 // is done by code that is contained in the definition for `invocation_type'
2799 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2801 // `invocation_type' is used to check whether we're allowed to access the requested
2802 // member wrt its protection level.
2804 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2805 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2806 // is B and qualifier_type is A). This is used to do the CS1540 check.
2808 // When resolving a SimpleName, `qualifier_type' is null.
2810 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2811 // the same than `queried_type' - except when we're being called from BaseAccess;
2812 // in this case, `invocation_type' is the current type and `queried_type' the base
2813 // type, so this'd normally trigger a CS1540.
2815 // The binding flags are `bf' and the kind of members being looked up are `mt'
2817 // The return value always includes private members which code in `invocation_type'
2818 // is allowed to access (using the specified `qualifier_type' if given); only use
2819 // BindingFlags.NonPublic to bypass the permission check.
2821 // The 'almost_match' argument is used for reporting error CS1540.
2823 // Returns an array of a single element for everything but Methods/Constructors
2824 // that might return multiple matches.
2826 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2827 Type queried_type, MemberTypes mt,
2828 BindingFlags original_bf, string name, IList almost_match)
2830 Timer.StartTimer (TimerType.MemberLookup);
2832 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2833 queried_type, mt, original_bf, name, almost_match);
2835 Timer.StopTimer (TimerType.MemberLookup);
2840 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2841 Type queried_type, MemberTypes mt,
2842 BindingFlags original_bf, string name, IList almost_match)
2844 BindingFlags bf = original_bf;
2846 ArrayList method_list = null;
2847 Type current_type = queried_type;
2848 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2849 bool skip_iface_check = true, used_cache = false;
2850 bool always_ok_flag = false;
2852 closure.invocation_type = invocation_type;
2853 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2854 closure.qualifier_type = qualifier_type;
2855 closure.almost_match = almost_match;
2858 // If we are a nested class, we always have access to our container
2861 if (invocation_type != null){
2862 string invocation_name = invocation_type.FullName;
2863 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
2864 string container = queried_type.FullName + "+";
2865 int container_length = container.Length;
2867 if (invocation_name.Length > container_length){
2868 string shared = invocation_name.Substring (0, container_length);
2870 if (shared == container)
2871 always_ok_flag = true;
2876 // This is from the first time we find a method
2877 // in most cases, we do not actually find a method in the base class
2878 // so we can just ignore it, and save the arraylist allocation
2879 MemberInfo [] first_members_list = null;
2880 bool use_first_members_list = false;
2886 // `NonPublic' is lame, because it includes both protected and
2887 // private methods, so we need to control this behavior by
2888 // explicitly tracking if a private method is ok or not.
2890 // The possible cases are:
2891 // public, private and protected (internal does not come into the
2894 if ((invocation_type != null) &&
2895 ((invocation_type == current_type) ||
2896 IsNestedChildOf (invocation_type, current_type)) ||
2898 bf = original_bf | BindingFlags.NonPublic;
2902 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2904 Timer.StopTimer (TimerType.MemberLookup);
2906 list = MemberLookup_FindMembers (
2907 current_type, mt, bf, name, out used_cache);
2909 Timer.StartTimer (TimerType.MemberLookup);
2912 // When queried for an interface type, the cache will automatically check all
2913 // inherited members, so we don't need to do this here. However, this only
2914 // works if we already used the cache in the first iteration of this loop.
2916 // If we used the cache in any further iteration, we can still terminate the
2917 // loop since the cache always looks in all base classes.
2923 skip_iface_check = false;
2925 if (current_type == TypeManager.object_type)
2928 current_type = current_type.BaseType;
2931 // This happens with interfaces, they have a null
2932 // basetype. Look members up in the Object class.
2934 if (current_type == null) {
2935 current_type = TypeManager.object_type;
2940 if (list.Length == 0)
2944 // Events and types are returned by both `static' and `instance'
2945 // searches, which means that our above FindMembers will
2946 // return two copies of the same.
2948 if (list.Length == 1 && !(list [0] is MethodBase)){
2953 // Multiple properties: we query those just to find out the indexer
2956 if (list [0] is PropertyInfo)
2960 // We found an event: the cache lookup returns both the event and
2961 // its private field.
2963 if (list [0] is EventInfo) {
2964 if ((list.Length == 2) && (list [1] is FieldInfo))
2965 return new MemberInfo [] { list [0] };
2972 // We found methods, turn the search into "method scan"
2976 if (first_members_list != null) {
2977 if (use_first_members_list) {
2978 method_list = CopyNewMethods (method_list, first_members_list);
2979 use_first_members_list = false;
2982 method_list = CopyNewMethods (method_list, list);
2984 first_members_list = list;
2985 use_first_members_list = true;
2987 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2989 } while (searching);
2991 if (use_first_members_list) {
2992 foreach (MemberInfo mi in first_members_list) {
2993 if (! (mi is MethodBase)) {
2994 method_list = CopyNewMethods (method_list, first_members_list);
2995 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2998 return (MemberInfo []) first_members_list;
3001 if (method_list != null && method_list.Count > 0) {
3002 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3005 // This happens if we already used the cache in the first iteration, in this case
3006 // the cache already looked in all interfaces.
3008 if (skip_iface_check)
3012 // Interfaces do not list members they inherit, so we have to
3015 if (!queried_type.IsInterface)
3018 if (queried_type.IsArray)
3019 queried_type = TypeManager.array_type;
3021 Type [] ifaces = GetInterfaces (queried_type);
3025 foreach (Type itype in ifaces){
3028 x = MemberLookup (null, null, itype, mt, bf, name, null);
3036 // Tests whether external method is really special
3037 public static bool IsSpecialMethod (MethodBase mb)
3039 string name = mb.Name;
3040 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3041 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3043 if (name.StartsWith ("add_"))
3044 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3046 if (name.StartsWith ("remove_"))
3047 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3049 if (name.StartsWith ("op_")){
3050 foreach (string oname in Unary.oper_names) {
3055 foreach (string oname in Binary.oper_names) {
3068 /// There is exactly one instance of this class per type.
3070 public sealed class TypeHandle : IMemberContainer {
3071 public readonly IMemberContainer BaseType;
3073 readonly int id = ++next_id;
3074 static int next_id = 0;
3077 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3078 /// a TypeHandle yet, a new instance of it is created. This static method
3079 /// ensures that we'll only have one TypeHandle instance per type.
3081 private static TypeHandle GetTypeHandle (Type t)
3083 TypeHandle handle = (TypeHandle) type_hash [t];
3087 handle = new TypeHandle (t);
3088 type_hash.Add (t, handle);
3092 public static MemberCache GetMemberCache (Type t)
3094 return GetTypeHandle (t).MemberCache;
3097 public static void CleanUp ()
3103 /// Returns the TypeHandle for TypeManager.object_type.
3105 public static IMemberContainer ObjectType {
3107 if (object_type != null)
3110 object_type = GetTypeHandle (TypeManager.object_type);
3117 /// Returns the TypeHandle for TypeManager.array_type.
3119 public static IMemberContainer ArrayType {
3121 if (array_type != null)
3124 array_type = GetTypeHandle (TypeManager.array_type);
3130 private static PtrHashtable type_hash = new PtrHashtable ();
3132 private static TypeHandle object_type = null;
3133 private static TypeHandle array_type = null;
3136 private string full_name;
3137 private bool is_interface;
3138 private MemberCache member_cache;
3139 private MemberCache base_cache;
3141 private TypeHandle (Type type)
3144 full_name = type.FullName != null ? type.FullName : type.Name;
3145 if (type.BaseType != null) {
3146 base_cache = TypeManager.LookupMemberCache (type.BaseType);
3147 BaseType = base_cache.Container;
3148 } else if (type.IsInterface)
3149 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3150 this.is_interface = type.IsInterface || type.IsGenericParameter;
3151 this.member_cache = new MemberCache (this);
3154 // IMemberContainer methods
3156 public string Name {
3168 public MemberCache BaseCache {
3174 public bool IsInterface {
3176 return is_interface;
3180 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3182 MemberInfo [] members;
3183 if (type is GenericTypeParameterBuilder)
3184 return MemberList.Empty;
3185 if (mt == MemberTypes.Event)
3186 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3188 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3190 Array.Reverse (members);
3192 return new MemberList (members);
3195 // IMemberFinder methods
3197 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3198 MemberFilter filter, object criteria)
3200 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3203 public MemberCache MemberCache {
3205 return member_cache;
3209 public override string ToString ()
3211 if (BaseType != null)
3212 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3214 return "TypeHandle (" + id + "," + Name + ")";