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 enumeration_type;
59 static public Type array_type;
60 static public Type runtime_handle_type;
61 static public Type icloneable_type;
62 static public Type type_type;
63 static public Type ienumerator_type;
64 static public Type ienumerable_type;
65 static public Type idisposable_type;
66 static public Type default_member_type;
67 static public Type iasyncresult_type;
68 static public Type asynccallback_type;
69 static public Type intptr_type;
70 static public Type monitor_type;
71 static public Type runtime_field_handle_type;
72 static public Type attribute_type;
73 static public Type attribute_usage_type;
74 static public Type dllimport_type;
75 static public Type unverifiable_code_type;
76 static public Type methodimpl_attr_type;
77 static public Type marshal_as_attr_type;
78 static public Type new_constraint_attr_type;
79 static public Type param_array_type;
80 static public Type guid_attr_type;
81 static public Type void_ptr_type;
82 static public Type indexer_name_type;
83 static public Type exception_type;
84 static public Type activator_type;
85 static public Type invalid_operation_exception_type;
86 static public object obsolete_attribute_type;
87 static public object conditional_attribute_type;
88 static public Type in_attribute_type;
89 static public Type cls_compliant_attribute_type;
90 static public Type typed_reference_type;
91 static public Type arg_iterator_type;
92 static public Type mbr_type;
93 static public Type struct_layout_attribute_type;
94 static public Type field_offset_attribute_type;
97 // An empty array of types
99 static public Type [] NoTypes;
100 static public TypeExpr [] NoTypeExprs;
104 // Expressions representing the internal types. Used during declaration
107 static public TypeExpr system_object_expr, system_string_expr;
108 static public TypeExpr system_boolean_expr, system_decimal_expr;
109 static public TypeExpr system_single_expr, system_double_expr;
110 static public TypeExpr system_sbyte_expr, system_byte_expr;
111 static public TypeExpr system_int16_expr, system_uint16_expr;
112 static public TypeExpr system_int32_expr, system_uint32_expr;
113 static public TypeExpr system_int64_expr, system_uint64_expr;
114 static public TypeExpr system_char_expr, system_void_expr;
115 static public TypeExpr system_asynccallback_expr;
116 static public TypeExpr system_iasyncresult_expr;
117 static public TypeExpr system_valuetype_expr;
120 // This is only used when compiling corlib
122 static public Type system_int32_type;
123 static public Type system_array_type;
124 static public Type system_type_type;
125 static public Type system_assemblybuilder_type;
126 static public MethodInfo system_int_array_get_length;
127 static public MethodInfo system_int_array_get_rank;
128 static public MethodInfo system_object_array_clone;
129 static public MethodInfo system_int_array_get_length_int;
130 static public MethodInfo system_int_array_get_lower_bound_int;
131 static public MethodInfo system_int_array_get_upper_bound_int;
132 static public MethodInfo system_void_array_copyto_array_int;
136 // Internal, not really used outside
138 static Type runtime_helpers_type;
141 // These methods are called by code generated by the compiler
143 static public MethodInfo string_concat_string_string;
144 static public MethodInfo string_concat_string_string_string;
145 static public MethodInfo string_concat_string_string_string_string;
146 static public MethodInfo string_concat_string_dot_dot_dot;
147 static public MethodInfo string_concat_object_object;
148 static public MethodInfo string_concat_object_object_object;
149 static public MethodInfo string_concat_object_dot_dot_dot;
150 static public MethodInfo string_isinterneted_string;
151 static public MethodInfo system_type_get_type_from_handle;
152 static public MethodInfo object_getcurrent_void;
153 static public MethodInfo bool_movenext_void;
154 static public MethodInfo ienumerable_getenumerator_void;
155 static public MethodInfo void_reset_void;
156 static public MethodInfo void_dispose_void;
157 static public MethodInfo void_monitor_enter_object;
158 static public MethodInfo void_monitor_exit_object;
159 static public MethodInfo void_initializearray_array_fieldhandle;
160 static public MethodInfo int_getlength_int;
161 static public MethodInfo delegate_combine_delegate_delegate;
162 static public MethodInfo delegate_remove_delegate_delegate;
163 static public MethodInfo int_get_offset_to_string_data;
164 static public MethodInfo int_array_get_length;
165 static public MethodInfo int_array_get_rank;
166 static public MethodInfo object_array_clone;
167 static public MethodInfo int_array_get_length_int;
168 static public MethodInfo int_array_get_lower_bound_int;
169 static public MethodInfo int_array_get_upper_bound_int;
170 static public MethodInfo void_array_copyto_array_int;
171 static public MethodInfo activator_create_instance;
174 // The attribute constructors.
176 static public ConstructorInfo object_ctor;
177 static public ConstructorInfo cons_param_array_attribute;
178 static public ConstructorInfo void_decimal_ctor_five_args;
179 static public ConstructorInfo unverifiable_code_ctor;
180 static public ConstructorInfo invalid_operation_ctor;
183 // Holds the Array of Assemblies that have been loaded
184 // (either because it is the default or the user used the
185 // -r command line option)
187 static Assembly [] assemblies;
190 // Keeps a list of modules. We used this to do lookups
191 // on the module using GetType -- needed for arrays
193 static Module [] modules;
196 // This is the type_cache from the assemblies to avoid
197 // hitting System.Reflection on every lookup.
199 static Hashtable types;
202 // This is used to hotld the corresponding TypeContainer objects
203 // since we need this in FindMembers
205 static Hashtable typecontainers;
208 // Keeps track of those types that are defined by the
211 static ArrayList user_types;
213 static PtrHashtable builder_to_declspace;
216 // Tracks the interfaces implemented by typebuilders. We only
217 // enter those who do implement or or more interfaces
219 static PtrHashtable builder_to_ifaces;
222 // Tracks the generic parameters.
224 static PtrHashtable builder_to_type_param;
227 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
228 // the arguments to the method
230 static Hashtable method_arguments;
233 // Maps PropertyBuilder to a Type array that contains
234 // the arguments to the indexer
236 static Hashtable indexer_arguments;
239 // Maybe `method_arguments' should be replaced and only
240 // method_internal_params should be kept?
242 static Hashtable method_internal_params;
245 // Keeps track of methods
248 static Hashtable builder_to_method;
251 // Contains all public types from referenced assemblies.
252 // This member is used only if CLS Compliance verification is required.
254 public static Hashtable all_imported_types;
261 public static void CleanUp ()
263 // Lets get everything clean so that we can collect before generating code
267 typecontainers = null;
269 builder_to_declspace = null;
270 builder_to_ifaces = null;
271 method_arguments = null;
272 indexer_arguments = null;
273 method_internal_params = null;
274 builder_to_method = null;
275 builder_to_type_param = null;
279 negative_hits = null;
280 builder_to_constant = null;
281 fieldbuilders_to_fields = null;
283 priv_fields_events = null;
286 TypeHandle.CleanUp ();
290 /// A filter for Findmembers that uses the Signature object to
293 static bool SignatureFilter (MemberInfo mi, object criteria)
295 Signature sig = (Signature) criteria;
297 if (!(mi is MethodBase))
300 if (mi.Name != sig.name)
303 int count = sig.args.Length;
305 if (mi is MethodBuilder || mi is ConstructorBuilder){
306 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
308 if (candidate_args.Length != count)
311 for (int i = 0; i < count; i++)
312 if (candidate_args [i] != sig.args [i])
317 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
319 if (pars.Length != count)
322 for (int i = 0; i < count; i++)
323 if (pars [i].ParameterType != sig.args [i])
329 // A delegate that points to the filter above.
330 static MemberFilter signature_filter;
333 // These are expressions that represent some of the internal data types, used
336 static void InitExpressionTypes ()
338 system_object_expr = new TypeLookupExpression ("System.Object");
339 system_string_expr = new TypeLookupExpression ("System.String");
340 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
341 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
342 system_single_expr = new TypeLookupExpression ("System.Single");
343 system_double_expr = new TypeLookupExpression ("System.Double");
344 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
345 system_byte_expr = new TypeLookupExpression ("System.Byte");
346 system_int16_expr = new TypeLookupExpression ("System.Int16");
347 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
348 system_int32_expr = new TypeLookupExpression ("System.Int32");
349 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
350 system_int64_expr = new TypeLookupExpression ("System.Int64");
351 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
352 system_char_expr = new TypeLookupExpression ("System.Char");
353 system_void_expr = new TypeLookupExpression ("System.Void");
354 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
355 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
356 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
359 static TypeManager ()
361 assemblies = new Assembly [0];
363 user_types = new ArrayList ();
365 types = new Hashtable ();
366 typecontainers = new Hashtable ();
368 builder_to_declspace = new PtrHashtable ();
369 builder_to_method = new PtrHashtable ();
370 method_arguments = new PtrHashtable ();
371 method_internal_params = new PtrHashtable ();
372 indexer_arguments = new PtrHashtable ();
373 builder_to_ifaces = new PtrHashtable ();
374 builder_to_type_param = new PtrHashtable ();
376 NoTypes = new Type [0];
377 NoTypeExprs = new TypeExpr [0];
379 signature_filter = new MemberFilter (SignatureFilter);
380 InitExpressionTypes ();
383 public static void HandleDuplicate (string name, Type t)
385 Type prev = (Type) types [name];
386 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
390 // This probably never happens, as we catch this before
392 Report.Error (-17, "The type `" + name + "' has already been defined.");
396 tc = builder_to_declspace [t] as TypeContainer;
399 1595, "The type `" + name + "' is defined in an existing assembly;"+
400 " Using the new definition from: " + tc.Location);
403 1595, "The type `" + name + "' is defined in an existing assembly;");
406 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
412 public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
417 HandleDuplicate (name, t);
422 builder_to_ifaces [t] = ifaces;
426 // This entry point is used by types that we define under the covers
428 public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
431 builder_to_ifaces [tb] = ifaces;
434 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
436 builder_to_declspace.Add (t, tc);
437 typecontainers.Add (name, tc);
438 AddUserType (name, t, ifaces);
441 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
446 HandleDuplicate (name, t);
449 builder_to_declspace.Add (t, del);
452 public static void AddEnumType (string name, TypeBuilder t, Enum en)
457 HandleDuplicate (name, t);
459 builder_to_declspace.Add (t, en);
462 public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
464 AddUserType (name, t, ifaces);
465 builder_to_declspace.Add (t, i);
468 public static void AddMethod (MethodBuilder builder, MethodData method)
470 builder_to_method.Add (builder, method);
473 public static void AddTypeParameter (Type t, TypeParameter tparam, TypeExpr[] ifaces)
475 if (!builder_to_type_param.Contains (t)) {
476 builder_to_type_param.Add (t, tparam);
479 builder_to_ifaces [t] = ifaces;
484 /// Returns the DeclSpace whose Type is `t' or null if there is no
485 /// DeclSpace for `t' (ie, the Type comes from a library)
487 public static DeclSpace LookupDeclSpace (Type t)
489 return builder_to_declspace [t] as DeclSpace;
493 /// Returns the TypeContainer whose Type is `t' or null if there is no
494 /// TypeContainer for `t' (ie, the Type comes from a library)
496 public static TypeContainer LookupTypeContainer (Type t)
498 return builder_to_declspace [t] as TypeContainer;
501 public static IMemberContainer LookupMemberContainer (Type t)
503 if (t is TypeBuilder) {
504 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
505 if (container != null)
509 if (t is GenericTypeParameterBuilder) {
510 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
512 if (container != null)
516 return TypeHandle.GetTypeHandle (t);
519 public static Interface LookupInterface (Type t)
521 return builder_to_declspace [t] as Interface;
524 public static Delegate LookupDelegate (Type t)
526 return builder_to_declspace [t] as Delegate;
529 public static Enum LookupEnum (Type t)
531 return builder_to_declspace [t] as Enum;
534 public static Class LookupClass (Type t)
536 return (Class) builder_to_declspace [t];
539 public static TypeParameter LookupTypeParameter (Type t)
541 return (TypeParameter) builder_to_type_param [t];
544 public static bool HasConstructorConstraint (Type t)
546 if (!t.IsGenericParameter)
547 throw new InvalidOperationException ();
549 TypeParameter tparam = LookupTypeParameter (t);
551 return tparam.HasConstructorConstraint;
553 object[] attrs = t.GetCustomAttributes (
554 TypeManager.new_constraint_attr_type, false);
556 return attrs.Length > 0;
561 /// Registers an assembly to load types from.
563 public static void AddAssembly (Assembly a)
565 foreach (Assembly assembly in assemblies) {
570 int top = assemblies.Length;
571 Assembly [] n = new Assembly [top + 1];
573 assemblies.CopyTo (n, 0);
580 /// Registers a module builder to lookup types from
582 public static void AddModule (Module mb)
584 int top = modules != null ? modules.Length : 0;
585 Module [] n = new Module [top + 1];
588 modules.CopyTo (n, 0);
593 public static Module[] Modules {
599 static Hashtable references = new Hashtable ();
602 // Gets the reference to T version of the Type (T&)
604 public static Type GetReferenceType (Type t)
606 return t.MakeByRefType ();
609 static Hashtable pointers = new Hashtable ();
612 // Gets the pointer to T version of the Type (T*)
614 public static Type GetPointerType (Type t)
616 string tname = t.FullName + "*";
618 Type ret = t.Assembly.GetType (tname);
621 // If the type comes from the assembly we are building
622 // We need the Hashtable, because .NET 1.1 will return different instance types
623 // every time we call ModuleBuilder.GetType.
626 if (pointers [t] == null)
627 pointers [t] = CodeGen.Module.Builder.GetType (tname);
629 ret = (Type) pointers [t];
636 // Low-level lookup, cache-less
638 static Type LookupTypeReflection (string name)
642 foreach (Assembly a in assemblies){
643 t = a.GetType (name);
648 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
649 if (ta == TypeAttributes.NotPublic ||
650 ta == TypeAttributes.NestedPrivate ||
651 ta == TypeAttributes.NestedAssembly ||
652 ta == TypeAttributes.NestedFamANDAssem){
655 // In .NET pointers turn out to be private, even if their
656 // element type is not
659 t = t.GetElementType ();
669 foreach (Module mb in modules) {
670 t = mb.GetType (name);
678 static Hashtable negative_hits = new Hashtable ();
681 // This function is used when you want to avoid the lookups, and want to go
682 // directly to the source. This will use the cache.
684 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
685 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
686 // way to test things other than doing a fullname compare
688 public static Type LookupTypeDirect (string name)
690 Type t = (Type) types [name];
694 t = LookupTypeReflection (name);
702 static readonly char [] dot_array = { '.' };
705 /// Returns the Type associated with @name, takes care of the fact that
706 /// reflection expects nested types to be separated from the main type
707 /// with a "+" instead of a "."
709 public static Type LookupType (string name)
714 // First lookup in user defined and cached values
717 t = (Type) types [name];
721 // Two thirds of the failures are caught here.
722 if (negative_hits.Contains (name))
725 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
726 string [] elements = name.Split (dot_array);
727 int count = elements.Length;
729 for (int n = 1; n <= count; n++){
730 string top_level_type = String.Join (".", elements, 0, n);
732 // One third of the failures are caught here.
733 if (negative_hits.Contains (top_level_type))
736 t = (Type) types [top_level_type];
738 t = LookupTypeReflection (top_level_type);
740 negative_hits [top_level_type] = null;
751 // We know that System.Object does not have children, and since its the parent of
752 // all the objects, it always gets probbed for inner classes.
754 if (top_level_type == "System.Object")
757 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
758 //Console.WriteLine ("Looking up: " + newt + " " + name);
759 t = LookupTypeReflection (newt);
761 negative_hits [name] = null;
766 negative_hits [name] = null;
771 /// Computes the namespaces that we import from the assemblies we reference.
773 public static void ComputeNamespaces ()
775 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
778 // First add the assembly namespaces
780 if (assembly_get_namespaces != null){
781 int count = assemblies.Length;
783 for (int i = 0; i < count; i++){
784 Assembly a = assemblies [i];
785 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
786 foreach (string ns in namespaces){
789 Namespace.LookupNamespace (ns, true);
793 Hashtable cache = new Hashtable ();
794 cache.Add ("", null);
795 foreach (Assembly a in assemblies) {
796 foreach (Type t in a.GetExportedTypes ()) {
797 string ns = t.Namespace;
798 if (ns == null || cache.Contains (ns))
801 Namespace.LookupNamespace (ns, true);
802 cache.Add (ns, null);
809 /// Fills static table with exported types from all referenced assemblies.
810 /// This information is required for CLS Compliance tests.
812 public static void LoadAllImportedTypes ()
814 if (!CodeGen.Assembly.IsClsCompliant)
817 all_imported_types = new Hashtable ();
818 foreach (Assembly a in assemblies) {
819 foreach (Type t in a.GetExportedTypes ()) {
820 all_imported_types [t.FullName] = t;
825 public static bool NamespaceClash (string name, Location loc)
827 if (Namespace.LookupNamespace (name, false) == null)
830 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
835 /// Returns the C# name of a type if possible, or the full type name otherwise
837 static public string CSharpName (Type t)
839 if (t.FullName == null)
842 return Regex.Replace (t.FullName,
844 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
845 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
846 @"Boolean|String|Void)" +
848 new MatchEvaluator (CSharpNameMatch));
851 static String CSharpNameMatch (Match match)
853 string s = match.Groups [1].Captures [0].Value;
855 Replace ("int32", "int").
856 Replace ("uint32", "uint").
857 Replace ("int16", "short").
858 Replace ("uint16", "ushort").
859 Replace ("int64", "long").
860 Replace ("uint64", "ulong").
861 Replace ("single", "float").
862 Replace ("boolean", "bool")
863 + match.Groups [2].Captures [0].Value;
867 /// Returns the signature of the method with full namespace classification
869 static public string GetFullNameSignature (MemberInfo mi)
873 n = mi.DeclaringType.Name;
875 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n;
878 static public string GetFullName (Type t)
880 if (t.FullName == null)
883 string name = t.FullName.Replace ('+', '.');
885 DeclSpace tc = LookupDeclSpace (t);
886 if ((tc != null) && tc.IsGeneric) {
887 TypeParameter[] tparam = tc.TypeParameters;
889 StringBuilder sb = new StringBuilder (name);
891 for (int i = 0; i < tparam.Length; i++) {
894 sb.Append (tparam [i].Name);
897 return sb.ToString ();
898 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
899 Type[] tparam = t.GetGenericArguments ();
901 StringBuilder sb = new StringBuilder (name);
903 for (int i = 0; i < tparam.Length; i++) {
906 sb.Append (tparam [i].Name);
909 return sb.ToString ();
916 /// Returns the signature of the property and indexer
918 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
921 return GetFullNameSignature (pb);
924 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
925 string signature = GetFullNameSignature (mb);
926 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
927 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
931 /// Returns the signature of the method
933 static public string CSharpSignature (MethodBase mb)
938 // FIXME: We should really have a single function to do
939 // everything instead of the following 5 line pattern
941 ParameterData iparams = LookupParametersByBuilder (mb);
944 iparams = new ReflectionParameters (mb);
946 for (int i = 0; i < iparams.Count; i++) {
950 sig += iparams.ParameterDesc(i);
954 return GetFullNameSignature (mb) + sig;
958 /// Looks up a type, and aborts if it is not found. This is used
959 /// by types required by the compiler
961 static Type CoreLookupType (string name)
963 Type t = LookupTypeDirect (name);
966 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
967 Environment.Exit (1);
974 /// Returns the MethodInfo for a method named `name' defined
975 /// in type `t' which takes arguments of types `args'
977 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
981 BindingFlags flags = instance_and_static | BindingFlags.Public;
987 flags |= BindingFlags.NonPublic;
989 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
990 if (list.Count == 0) {
992 Report.Error (-19, "Can not find the core function `" + name + "'");
996 MethodInfo mi = list [0] as MethodInfo;
999 Report.Error (-19, "Can not find the core function `" + name + "'");
1006 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1008 return GetMethod (t, name, args, false, report_errors);
1011 static MethodInfo GetMethod (Type t, string name, Type [] args)
1013 return GetMethod (t, name, args, true);
1018 /// Returns the ConstructorInfo for "args"
1020 static ConstructorInfo GetConstructor (Type t, Type [] args)
1028 list = FindMembers (t, MemberTypes.Constructor,
1029 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1030 signature_filter, sig);
1031 if (list.Count == 0){
1032 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1036 ConstructorInfo ci = list [0] as ConstructorInfo;
1038 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1045 public static void InitEnumUnderlyingTypes ()
1048 int32_type = CoreLookupType ("System.Int32");
1049 int64_type = CoreLookupType ("System.Int64");
1050 uint32_type = CoreLookupType ("System.UInt32");
1051 uint64_type = CoreLookupType ("System.UInt64");
1052 byte_type = CoreLookupType ("System.Byte");
1053 sbyte_type = CoreLookupType ("System.SByte");
1054 short_type = CoreLookupType ("System.Int16");
1055 ushort_type = CoreLookupType ("System.UInt16");
1059 /// The types have to be initialized after the initial
1060 /// population of the type has happened (for example, to
1061 /// bootstrap the corlib.dll
1063 public static void InitCoreTypes ()
1065 object_type = CoreLookupType ("System.Object");
1066 value_type = CoreLookupType ("System.ValueType");
1068 InitEnumUnderlyingTypes ();
1070 char_type = CoreLookupType ("System.Char");
1071 string_type = CoreLookupType ("System.String");
1072 float_type = CoreLookupType ("System.Single");
1073 double_type = CoreLookupType ("System.Double");
1074 char_ptr_type = CoreLookupType ("System.Char*");
1075 decimal_type = CoreLookupType ("System.Decimal");
1076 bool_type = CoreLookupType ("System.Boolean");
1077 enum_type = CoreLookupType ("System.Enum");
1079 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1080 delegate_type = CoreLookupType ("System.Delegate");
1082 array_type = CoreLookupType ("System.Array");
1083 void_type = CoreLookupType ("System.Void");
1084 type_type = CoreLookupType ("System.Type");
1086 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1087 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1088 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1089 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1090 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1091 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1092 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1093 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1094 idisposable_type = CoreLookupType ("System.IDisposable");
1095 icloneable_type = CoreLookupType ("System.ICloneable");
1096 monitor_type = CoreLookupType ("System.Threading.Monitor");
1097 intptr_type = CoreLookupType ("System.IntPtr");
1099 attribute_type = CoreLookupType ("System.Attribute");
1100 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1101 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1102 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1103 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1104 new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
1105 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1106 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1107 typed_reference_type = CoreLookupType ("System.TypedReference");
1108 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1109 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1112 // Sigh. Remove this before the release. Wonder what versions of Mono
1113 // people are running.
1115 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1117 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1119 void_ptr_type = CoreLookupType ("System.Void*");
1121 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1123 exception_type = CoreLookupType ("System.Exception");
1124 activator_type = CoreLookupType ("System.Activator");
1125 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1130 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1131 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1132 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1133 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1134 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1137 // When compiling corlib, store the "real" types here.
1139 if (!RootContext.StdLib) {
1140 system_int32_type = typeof (System.Int32);
1141 system_array_type = typeof (System.Array);
1142 system_type_type = typeof (System.Type);
1143 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1145 Type [] void_arg = { };
1146 system_int_array_get_length = GetMethod (
1147 system_array_type, "get_Length", void_arg);
1148 system_int_array_get_rank = GetMethod (
1149 system_array_type, "get_Rank", void_arg);
1150 system_object_array_clone = GetMethod (
1151 system_array_type, "Clone", void_arg);
1153 Type [] system_int_arg = { system_int32_type };
1154 system_int_array_get_length_int = GetMethod (
1155 system_array_type, "GetLength", system_int_arg);
1156 system_int_array_get_upper_bound_int = GetMethod (
1157 system_array_type, "GetUpperBound", system_int_arg);
1158 system_int_array_get_lower_bound_int = GetMethod (
1159 system_array_type, "GetLowerBound", system_int_arg);
1161 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1162 system_void_array_copyto_array_int = GetMethod (
1163 system_array_type, "CopyTo", system_array_int_arg);
1165 Type [] system_3_type_arg = {
1166 system_type_type, system_type_type, system_type_type };
1167 Type [] system_4_type_arg = {
1168 system_type_type, system_type_type, system_type_type, system_type_type };
1170 MethodInfo set_corlib_type_builders = GetMethod (
1171 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1172 system_4_type_arg, true, false);
1174 if (set_corlib_type_builders != null) {
1175 object[] args = new object [4];
1176 args [0] = object_type;
1177 args [1] = value_type;
1178 args [2] = enum_type;
1179 args [3] = void_type;
1181 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1183 // Compatibility for an older version of the class libs.
1184 set_corlib_type_builders = GetMethod (
1185 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1186 system_3_type_arg, true, true);
1188 if (set_corlib_type_builders == null) {
1189 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1193 object[] args = new object [3];
1194 args [0] = object_type;
1195 args [1] = value_type;
1196 args [2] = enum_type;
1198 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1202 system_object_expr.Type = object_type;
1203 system_string_expr.Type = string_type;
1204 system_boolean_expr.Type = bool_type;
1205 system_decimal_expr.Type = decimal_type;
1206 system_single_expr.Type = float_type;
1207 system_double_expr.Type = double_type;
1208 system_sbyte_expr.Type = sbyte_type;
1209 system_byte_expr.Type = byte_type;
1210 system_int16_expr.Type = short_type;
1211 system_uint16_expr.Type = ushort_type;
1212 system_int32_expr.Type = int32_type;
1213 system_uint32_expr.Type = uint32_type;
1214 system_int64_expr.Type = int64_type;
1215 system_uint64_expr.Type = uint64_type;
1216 system_char_expr.Type = char_type;
1217 system_void_expr.Type = void_type;
1218 system_asynccallback_expr.Type = asynccallback_type;
1219 system_iasyncresult_expr.Type = iasyncresult_type;
1220 system_valuetype_expr.Type = value_type;
1224 // The helper methods that are used by the compiler
1226 public static void InitCodeHelpers ()
1229 // Now load the default methods that we use.
1231 Type [] string_string = { string_type, string_type };
1232 string_concat_string_string = GetMethod (
1233 string_type, "Concat", string_string);
1234 Type [] string_string_string = { string_type, string_type, string_type };
1235 string_concat_string_string_string = GetMethod (
1236 string_type, "Concat", string_string_string);
1237 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1238 string_concat_string_string_string_string = GetMethod (
1239 string_type, "Concat", string_string_string_string);
1240 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1241 string_concat_string_dot_dot_dot = GetMethod (
1242 string_type, "Concat", params_string);
1244 Type [] object_object = { object_type, object_type };
1245 string_concat_object_object = GetMethod (
1246 string_type, "Concat", object_object);
1247 Type [] object_object_object = { object_type, object_type, object_type };
1248 string_concat_object_object_object = GetMethod (
1249 string_type, "Concat", object_object_object);
1250 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1251 string_concat_object_dot_dot_dot = GetMethod (
1252 string_type, "Concat", params_object);
1254 Type [] string_ = { string_type };
1255 string_isinterneted_string = GetMethod (
1256 string_type, "IsInterned", string_);
1258 Type [] runtime_type_handle = { runtime_handle_type };
1259 system_type_get_type_from_handle = GetMethod (
1260 type_type, "GetTypeFromHandle", runtime_type_handle);
1262 Type [] delegate_delegate = { delegate_type, delegate_type };
1263 delegate_combine_delegate_delegate = GetMethod (
1264 delegate_type, "Combine", delegate_delegate);
1266 delegate_remove_delegate_delegate = GetMethod (
1267 delegate_type, "Remove", delegate_delegate);
1272 Type [] void_arg = { };
1273 object_getcurrent_void = GetMethod (
1274 ienumerator_type, "get_Current", void_arg);
1275 bool_movenext_void = GetMethod (
1276 ienumerator_type, "MoveNext", void_arg);
1277 void_reset_void = GetMethod (
1278 ienumerator_type, "Reset", void_arg);
1279 void_dispose_void = GetMethod (
1280 idisposable_type, "Dispose", void_arg);
1281 int_get_offset_to_string_data = GetMethod (
1282 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1283 int_array_get_length = GetMethod (
1284 array_type, "get_Length", void_arg);
1285 int_array_get_rank = GetMethod (
1286 array_type, "get_Rank", void_arg);
1287 ienumerable_getenumerator_void = GetMethod (
1288 ienumerable_type, "GetEnumerator", void_arg);
1293 Type [] int_arg = { int32_type };
1294 int_array_get_length_int = GetMethod (
1295 array_type, "GetLength", int_arg);
1296 int_array_get_upper_bound_int = GetMethod (
1297 array_type, "GetUpperBound", int_arg);
1298 int_array_get_lower_bound_int = GetMethod (
1299 array_type, "GetLowerBound", int_arg);
1302 // System.Array methods
1304 object_array_clone = GetMethod (
1305 array_type, "Clone", void_arg);
1306 Type [] array_int_arg = { array_type, int32_type };
1307 void_array_copyto_array_int = GetMethod (
1308 array_type, "CopyTo", array_int_arg);
1313 Type [] object_arg = { object_type };
1314 void_monitor_enter_object = GetMethod (
1315 monitor_type, "Enter", object_arg);
1316 void_monitor_exit_object = GetMethod (
1317 monitor_type, "Exit", object_arg);
1319 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1321 void_initializearray_array_fieldhandle = GetMethod (
1322 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1327 int_getlength_int = GetMethod (
1328 array_type, "GetLength", int_arg);
1331 // Decimal constructors
1333 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1334 void_decimal_ctor_five_args = GetConstructor (
1335 decimal_type, dec_arg);
1340 cons_param_array_attribute = GetConstructor (
1341 param_array_type, void_arg);
1343 unverifiable_code_ctor = GetConstructor (
1344 unverifiable_code_type, void_arg);
1347 // InvalidOperationException
1349 invalid_operation_ctor = GetConstructor (
1350 invalid_operation_exception_type, void_arg);
1354 object_ctor = GetConstructor (object_type, void_arg);
1357 Type [] type_arg = { type_type };
1358 activator_create_instance = GetMethod (
1359 activator_type, "CreateInstance", type_arg);
1362 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1365 /// This is the "old", non-cache based FindMembers() function. We cannot use
1366 /// the cache here because there is no member name argument.
1368 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1369 MemberFilter filter, object criteria)
1371 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1374 // `builder_to_declspace' contains all dynamic types.
1378 Timer.StartTimer (TimerType.FindMembers);
1379 list = decl.FindMembers (mt, bf, filter, criteria);
1380 Timer.StopTimer (TimerType.FindMembers);
1385 // We have to take care of arrays specially, because GetType on
1386 // a TypeBuilder array will return a Type, not a TypeBuilder,
1387 // and we can not call FindMembers on this type.
1389 if (t.IsSubclassOf (TypeManager.array_type))
1390 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1393 // Since FindMembers will not lookup both static and instance
1394 // members, we emulate this behaviour here.
1396 if ((bf & instance_and_static) == instance_and_static){
1397 MemberInfo [] i_members = t.FindMembers (
1398 mt, bf & ~BindingFlags.Static, filter, criteria);
1400 int i_len = i_members.Length;
1402 MemberInfo one = i_members [0];
1405 // If any of these are present, we are done!
1407 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1408 return new MemberList (i_members);
1411 MemberInfo [] s_members = t.FindMembers (
1412 mt, bf & ~BindingFlags.Instance, filter, criteria);
1414 int s_len = s_members.Length;
1415 if (i_len > 0 || s_len > 0)
1416 return new MemberList (i_members, s_members);
1419 return new MemberList (i_members);
1421 return new MemberList (s_members);
1425 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1430 /// This method is only called from within MemberLookup. It tries to use the member
1431 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1432 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1433 /// our return value will already contain all inherited members and the caller don't need
1434 /// to check base classes and interfaces anymore.
1436 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1437 string name, out bool used_cache)
1440 // We have to take care of arrays specially, because GetType on
1441 // a TypeBuilder array will return a Type, not a TypeBuilder,
1442 // and we can not call FindMembers on this type.
1444 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1446 return TypeHandle.ArrayType.MemberCache.FindMembers (
1447 mt, bf, name, FilterWithClosure_delegate, null);
1451 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1452 // and we can ask the DeclSpace for the MemberCache.
1454 if (t is TypeBuilder) {
1455 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1456 MemberCache cache = decl.MemberCache;
1459 // If this DeclSpace has a MemberCache, use it.
1462 if (cache != null) {
1464 return cache.FindMembers (
1465 mt, bf, name, FilterWithClosure_delegate, null);
1468 // If there is no MemberCache, we need to use the "normal" FindMembers.
1469 // Note, this is a VERY uncommon route!
1472 Timer.StartTimer (TimerType.FindMembers);
1473 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1474 FilterWithClosure_delegate, name);
1475 Timer.StopTimer (TimerType.FindMembers);
1477 return (MemberInfo []) list;
1480 if (t is GenericTypeParameterBuilder) {
1481 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1484 Timer.StartTimer (TimerType.FindMembers);
1485 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1486 FilterWithClosure_delegate, name);
1487 Timer.StopTimer (TimerType.FindMembers);
1489 return (MemberInfo []) list;
1493 // This call will always succeed. There is exactly one TypeHandle instance per
1494 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1495 // if it didn't already exist.
1497 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1500 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1503 public static bool IsBuiltinType (Type t)
1505 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1506 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1507 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1508 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1514 public static bool IsBuiltinType (TypeContainer tc)
1516 return IsBuiltinType (tc.TypeBuilder);
1520 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1521 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1523 public static bool IsCLRType (Type t)
1525 if (t == object_type || t == int32_type || t == uint32_type ||
1526 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1527 t == char_type || t == short_type || t == bool_type ||
1528 t == sbyte_type || t == byte_type || t == ushort_type)
1534 public static bool IsDelegateType (Type t)
1536 if (t.IsGenericInstance)
1537 t = t.GetGenericTypeDefinition ();
1539 if (t.IsSubclassOf (TypeManager.delegate_type))
1545 public static bool IsEnumType (Type t)
1547 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1552 public static bool IsBuiltinOrEnum (Type t)
1554 if (IsBuiltinType (t))
1564 // Only a quick hack to get things moving, while real runtime support appears
1566 public static bool IsGeneric (Type t)
1568 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1570 return ds.IsGeneric;
1573 public static bool HasGenericArguments (Type t)
1575 return GetNumberOfTypeArguments (t) > 0;
1578 public static int GetNumberOfTypeArguments (Type t)
1580 DeclSpace tc = LookupDeclSpace (t);
1582 return tc.IsGeneric ? tc.CountTypeParameters : 0;
1584 return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1587 public static Type[] GetTypeArguments (Type t)
1589 DeclSpace tc = LookupDeclSpace (t);
1592 throw new InvalidOperationException ();
1594 TypeParameter[] tparam = tc.TypeParameters;
1595 Type[] ret = new Type [tparam.Length];
1596 for (int i = 0; i < tparam.Length; i++) {
1597 ret [i] = tparam [i].Type;
1598 if (ret [i] == null)
1599 throw new InternalErrorException ();
1604 return t.GetGenericArguments ();
1608 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1610 public static bool IsUnmanagedType (Type t)
1612 if (IsBuiltinType (t) && t != TypeManager.string_type)
1621 if (IsValueType (t)){
1622 if (t is TypeBuilder){
1623 TypeContainer tc = LookupTypeContainer (t);
1625 if (tc.Fields != null){
1626 foreach (Field f in tc.Fields){
1627 if (f.FieldBuilder.IsStatic)
1629 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1635 FieldInfo [] fields = t.GetFields ();
1637 foreach (FieldInfo f in fields){
1640 if (!IsUnmanagedType (f.FieldType))
1650 public static bool IsValueType (Type t)
1652 return t.IsGenericParameter || t.IsValueType;
1655 public static bool IsInterfaceType (Type t)
1657 Interface iface = builder_to_declspace [t] as Interface;
1665 public static bool IsEqualGenericType (Type a, Type b)
1667 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1669 // `a' is a generic type definition's TypeBuilder and `b' is a
1670 // generic instance of the same type.
1676 // void Test (Stack<T> stack) { }
1679 // The first argument of `Test' will be the generic instance
1680 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1682 if (a != b.GetGenericTypeDefinition ())
1685 Type[] aparams = a.GetGenericArguments ();
1686 Type[] bparams = b.GetGenericArguments ();
1688 if (aparams.Length != bparams.Length)
1691 for (int i = 0; i < aparams.Length; i++)
1692 if (!aparams [i].Equals (bparams [i]))
1701 public static bool IsEqual (Type a, Type b)
1706 return IsEqualGenericType (a, b);
1709 public static bool MayBecomeEqualGenericTypes (Type a, Type b)
1711 if (a.IsGenericParameter) {
1713 // If a is an array of a's type, they may never
1717 b = b.GetElementType ();
1723 // If b is a generic parameter or an actual type,
1724 // they may become equal:
1726 // class X<T,U> : I<T>, I<U>
1727 // class X<T> : I<T>, I<float>
1729 if (b.IsGenericParameter || !b.IsGenericInstance)
1733 // We're now comparing a type parameter with a
1734 // generic instance. They may become equal unless
1735 // the type parameter appears anywhere in the
1736 // generic instance:
1738 // class X<T,U> : I<T>, I<X<U>>
1739 // -> error because you could instanciate it as
1742 // class X<T> : I<T>, I<X<T>> -> ok
1745 Type[] bargs = GetTypeArguments (b);
1746 for (int i = 0; i < bargs.Length; i++) {
1747 if (a.Equals (bargs [i]))
1754 if (b.IsGenericParameter)
1755 return MayBecomeEqualGenericTypes (b, a);
1758 // At this point, neither a nor b are a type parameter.
1760 // If one of them is a generic instance, let
1761 // MayBecomeEqualGenericInstances() compare them (if the
1762 // other one is not a generic instance, they can never
1766 if (a.IsGenericInstance || b.IsGenericInstance)
1767 return MayBecomeEqualGenericInstances (a, b);
1770 // If both of them are arrays.
1773 if (a.IsArray && b.IsArray) {
1774 if (a.GetArrayRank () != b.GetArrayRank ())
1777 a = a.GetElementType ();
1778 b = b.GetElementType ();
1780 return MayBecomeEqualGenericTypes (a, b);
1784 // Ok, two ordinary types.
1787 return a.Equals (b);
1791 // Checks whether two generic instances may become equal for some
1792 // particular instantiation (26.3.1).
1794 public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1796 if (!a.IsGenericInstance || !b.IsGenericInstance)
1798 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1801 Type[] aargs = GetTypeArguments (a);
1802 Type[] bargs = GetTypeArguments (b);
1804 if (aargs.Length != bargs.Length)
1807 for (int i = 0; i < aargs.Length; i++) {
1808 if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1815 public static bool IsSubclassOf (Type type, Type parent)
1817 if (type.IsGenericInstance && !parent.IsGenericInstance)
1818 type = type.GetGenericTypeDefinition ();
1820 return type.IsSubclassOf (parent);
1824 // Checks whether `type' is a subclass or nested child of `parent'.
1826 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1829 if ((type == parent) || type.IsSubclassOf (parent) ||
1830 IsEqualGenericType (type, parent))
1833 // Handle nested types.
1834 type = type.DeclaringType;
1835 } while (type != null);
1841 // Checks whether `type' is a nested child of `parent'.
1843 public static bool IsNestedChildOf (Type type, Type parent)
1848 type = type.DeclaringType;
1849 while (type != null) {
1853 type = type.DeclaringType;
1860 // Do the right thing when returning the element type of an
1861 // array type based on whether we are compiling corlib or not
1863 public static Type GetElementType (Type t)
1865 if (RootContext.StdLib)
1866 return t.GetElementType ();
1868 return TypeToCoreType (t.GetElementType ());
1872 /// Returns the User Defined Types
1874 public static ArrayList UserTypes {
1880 public static Hashtable TypeContainers {
1882 return typecontainers;
1886 static Hashtable builder_to_constant;
1888 public static void RegisterConstant (FieldBuilder fb, Const c)
1890 if (builder_to_constant == null)
1891 builder_to_constant = new PtrHashtable ();
1893 if (builder_to_constant.Contains (fb))
1896 builder_to_constant.Add (fb, c);
1899 public static Const LookupConstant (FieldBuilder fb)
1901 if (builder_to_constant == null)
1904 return (Const) builder_to_constant [fb];
1908 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1912 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1913 /// for anything which is dynamic, and we need this in a number of places,
1914 /// we register this information here, and use it afterwards.
1916 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1921 method_arguments.Add (mb, args);
1922 method_internal_params.Add (mb, ip);
1927 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1929 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1932 if (method_internal_params.Contains (mb))
1933 return (InternalParameters) method_internal_params [mb];
1935 throw new Exception ("Argument for Method not registered" + mb);
1939 /// Returns the argument types for a method based on its methodbase
1941 /// For dynamic methods, we use the compiler provided types, for
1942 /// methods from existing assemblies we load them from GetParameters,
1943 /// and insert them into the cache
1945 static public Type [] GetArgumentTypes (MethodBase mb)
1947 if (method_arguments.Contains (mb))
1948 return (Type []) method_arguments [mb];
1950 ParameterInfo [] pi = mb.GetParameters ();
1952 Type [] types = new Type [c];
1954 for (int i = 0; i < c; i++)
1955 types [i] = pi [i].ParameterType;
1957 method_arguments.Add (mb, types);
1963 /// Returns the argument types for an indexer based on its PropertyInfo
1965 /// For dynamic indexers, we use the compiler provided types, for
1966 /// indexers from existing assemblies we load them from GetParameters,
1967 /// and insert them into the cache
1969 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1971 if (indexer_arguments.Contains (indexer))
1972 return (Type []) indexer_arguments [indexer];
1973 else if (indexer is PropertyBuilder)
1974 // If we're a PropertyBuilder and not in the
1975 // `indexer_arguments' hash, then we're a property and
1979 ParameterInfo [] pi = indexer.GetIndexParameters ();
1980 // Property, not an indexer.
1984 Type [] types = new Type [c];
1986 for (int i = 0; i < c; i++)
1987 types [i] = pi [i].ParameterType;
1989 indexer_arguments.Add (indexer, types);
1995 // This is a workaround the fact that GetValue is not
1996 // supported for dynamic types
1998 static Hashtable fields = new Hashtable ();
1999 static public bool RegisterFieldValue (FieldBuilder fb, object value)
2001 if (fields.Contains (fb))
2004 fields.Add (fb, value);
2009 static public object GetValue (FieldBuilder fb)
2014 static Hashtable fieldbuilders_to_fields = new Hashtable ();
2015 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2017 if (fieldbuilders_to_fields.Contains (fb))
2020 fieldbuilders_to_fields.Add (fb, f);
2025 // The return value can be null; This will be the case for
2026 // auxiliary FieldBuilders created by the compiler that have no
2027 // real field being declared on the source code
2029 static public FieldBase GetField (FieldInfo fb)
2031 return (FieldBase) fieldbuilders_to_fields [fb];
2034 static Hashtable events;
2036 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2039 events = new Hashtable ();
2041 if (events.Contains (eb))
2044 events.Add (eb, new Pair (add, remove));
2049 static public MethodInfo GetAddMethod (EventInfo ei)
2051 if (ei is MyEventBuilder) {
2052 Pair pair = (Pair) events [ei];
2054 return (MethodInfo) pair.First;
2056 return ei.GetAddMethod ();
2059 static public MethodInfo GetRemoveMethod (EventInfo ei)
2061 if (ei is MyEventBuilder) {
2062 Pair pair = (Pair) events [ei];
2064 return (MethodInfo) pair.Second;
2066 return ei.GetRemoveMethod ();
2069 static Hashtable priv_fields_events;
2071 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2073 if (priv_fields_events == null)
2074 priv_fields_events = new Hashtable ();
2076 if (priv_fields_events.Contains (einfo))
2079 priv_fields_events.Add (einfo, builder);
2084 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2086 if (priv_fields_events == null)
2089 return (MemberInfo) priv_fields_events [ei];
2092 static Hashtable properties;
2094 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2096 if (properties == null)
2097 properties = new Hashtable ();
2099 if (properties.Contains (pb))
2102 properties.Add (pb, new Pair (get, set));
2107 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2108 MethodBase set, Type[] args)
2110 if (!RegisterProperty (pb, get,set))
2113 indexer_arguments.Add (pb, args);
2118 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2120 Hashtable hash = new Hashtable ();
2121 return CheckStructCycles (tc, seen, hash);
2124 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2127 if (!(tc is Struct) || IsBuiltinType (tc))
2131 // `seen' contains all types we've already visited.
2133 if (seen.Contains (tc))
2135 seen.Add (tc, null);
2137 if (tc.Fields == null)
2140 foreach (Field field in tc.Fields) {
2141 if (field.FieldBuilder.IsStatic)
2144 Type ftype = field.FieldBuilder.FieldType;
2145 TypeContainer ftc = LookupTypeContainer (ftype);
2149 if (hash.Contains (ftc)) {
2150 Report.Error (523, tc.Location,
2151 "Struct member `{0}.{1}' of type `{2}' " +
2152 "causes a cycle in the struct layout",
2153 tc.Name, field.Name, ftc.Name);
2158 // `hash' contains all types in the current path.
2160 hash.Add (tc, null);
2162 bool ok = CheckStructCycles (ftc, seen, hash);
2169 if (!seen.Contains (ftc))
2170 seen.Add (ftc, null);
2177 /// Given an array of interface types, expand and eliminate repeated ocurrences
2178 /// of an interface.
2182 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2185 public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
2187 ArrayList new_ifaces = new ArrayList ();
2189 foreach (TypeExpr iface in base_interfaces){
2190 if (!new_ifaces.Contains (iface))
2191 new_ifaces.Add (iface);
2193 TypeExpr [] implementing = iface.GetInterfaces ();
2195 foreach (TypeExpr imp in implementing){
2196 if (!new_ifaces.Contains (imp))
2197 new_ifaces.Add (imp);
2200 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
2201 new_ifaces.CopyTo (ret, 0);
2205 static PtrHashtable iface_cache = new PtrHashtable ();
2208 /// This function returns the interfaces in the type `t'. Works with
2209 /// both types and TypeBuilders.
2211 public static TypeExpr [] GetInterfaces (Type t)
2214 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
2219 // The reason for catching the Array case is that Reflection.Emit
2220 // will not return a TypeBuilder for Array types of TypeBuilder types,
2221 // but will still throw an exception if we try to call GetInterfaces
2224 // Since the array interfaces are always constant, we return those for
2229 t = TypeManager.array_type;
2231 if (t is TypeBuilder){
2232 TypeExpr [] parent_ifaces;
2234 if (t.BaseType == null)
2235 parent_ifaces = NoTypeExprs;
2237 parent_ifaces = GetInterfaces (t.BaseType);
2238 TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2239 if (type_ifaces == null)
2240 type_ifaces = NoTypeExprs;
2242 int parent_count = parent_ifaces.Length;
2243 TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2244 parent_ifaces.CopyTo (result, 0);
2245 type_ifaces.CopyTo (result, parent_count);
2247 iface_cache [t] = result;
2249 } else if (t is GenericTypeParameterBuilder){
2250 TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2251 if (type_ifaces == null)
2252 type_ifaces = NoTypeExprs;
2254 iface_cache [t] = type_ifaces;
2257 Type [] ifaces = t.GetInterfaces ();
2258 if (ifaces.Length == 0)
2261 TypeExpr [] result = new TypeExpr [ifaces.Length];
2262 for (int i = 0; i < ifaces.Length; i++)
2263 result [i] = new TypeExpression (ifaces [i], Location.Null);
2265 iface_cache [t] = result;
2271 // gets the interfaces that are declared explicitly on t
2273 public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2275 return (TypeExpr []) builder_to_ifaces [t];
2279 /// The following is used to check if a given type implements an interface.
2280 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2282 public static bool ImplementsInterface (Type t, Type iface)
2284 TypeExpr [] interfaces;
2287 // FIXME OPTIMIZATION:
2288 // as soon as we hit a non-TypeBuiler in the interface
2289 // chain, we could return, as the `Type.GetInterfaces'
2290 // will return all the interfaces implement by the type
2294 interfaces = GetInterfaces (t);
2296 if (interfaces != null){
2297 foreach (TypeExpr i in interfaces){
2298 if (i.Type == iface)
2304 } while (t != null);
2309 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2311 // This is a custom version of Convert.ChangeType() which works
2312 // with the TypeBuilder defined types when compiling corlib.
2313 public static object ChangeType (object value, Type conversionType, out bool error)
2315 IConvertible convert_value = value as IConvertible;
2317 if (convert_value == null){
2323 // We must use Type.Equals() here since `conversionType' is
2324 // the TypeBuilder created version of a system type and not
2325 // the system type itself. You cannot use Type.GetTypeCode()
2326 // on such a type - it'd always return TypeCode.Object.
2330 if (conversionType.Equals (typeof (Boolean)))
2331 return (object)(convert_value.ToBoolean (nf_provider));
2332 else if (conversionType.Equals (typeof (Byte)))
2333 return (object)(convert_value.ToByte (nf_provider));
2334 else if (conversionType.Equals (typeof (Char)))
2335 return (object)(convert_value.ToChar (nf_provider));
2336 else if (conversionType.Equals (typeof (DateTime)))
2337 return (object)(convert_value.ToDateTime (nf_provider));
2338 else if (conversionType.Equals (typeof (Decimal)))
2339 return (object)(convert_value.ToDecimal (nf_provider));
2340 else if (conversionType.Equals (typeof (Double)))
2341 return (object)(convert_value.ToDouble (nf_provider));
2342 else if (conversionType.Equals (typeof (Int16)))
2343 return (object)(convert_value.ToInt16 (nf_provider));
2344 else if (conversionType.Equals (typeof (Int32)))
2345 return (object)(convert_value.ToInt32 (nf_provider));
2346 else if (conversionType.Equals (typeof (Int64)))
2347 return (object)(convert_value.ToInt64 (nf_provider));
2348 else if (conversionType.Equals (typeof (SByte)))
2349 return (object)(convert_value.ToSByte (nf_provider));
2350 else if (conversionType.Equals (typeof (Single)))
2351 return (object)(convert_value.ToSingle (nf_provider));
2352 else if (conversionType.Equals (typeof (String)))
2353 return (object)(convert_value.ToString (nf_provider));
2354 else if (conversionType.Equals (typeof (UInt16)))
2355 return (object)(convert_value.ToUInt16 (nf_provider));
2356 else if (conversionType.Equals (typeof (UInt32)))
2357 return (object)(convert_value.ToUInt32 (nf_provider));
2358 else if (conversionType.Equals (typeof (UInt64)))
2359 return (object)(convert_value.ToUInt64 (nf_provider));
2360 else if (conversionType.Equals (typeof (Object)))
2361 return (object)(value);
2371 // This is needed, because enumerations from assemblies
2372 // do not report their underlyingtype, but they report
2375 public static Type EnumToUnderlying (Type t)
2377 if (t == TypeManager.enum_type)
2380 t = t.UnderlyingSystemType;
2381 if (!TypeManager.IsEnumType (t))
2384 if (t is TypeBuilder) {
2385 // slow path needed to compile corlib
2386 if (t == TypeManager.bool_type ||
2387 t == TypeManager.byte_type ||
2388 t == TypeManager.sbyte_type ||
2389 t == TypeManager.char_type ||
2390 t == TypeManager.short_type ||
2391 t == TypeManager.ushort_type ||
2392 t == TypeManager.int32_type ||
2393 t == TypeManager.uint32_type ||
2394 t == TypeManager.int64_type ||
2395 t == TypeManager.uint64_type)
2397 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2399 TypeCode tc = Type.GetTypeCode (t);
2402 case TypeCode.Boolean:
2403 return TypeManager.bool_type;
2405 return TypeManager.byte_type;
2406 case TypeCode.SByte:
2407 return TypeManager.sbyte_type;
2409 return TypeManager.char_type;
2410 case TypeCode.Int16:
2411 return TypeManager.short_type;
2412 case TypeCode.UInt16:
2413 return TypeManager.ushort_type;
2414 case TypeCode.Int32:
2415 return TypeManager.int32_type;
2416 case TypeCode.UInt32:
2417 return TypeManager.uint32_type;
2418 case TypeCode.Int64:
2419 return TypeManager.int64_type;
2420 case TypeCode.UInt64:
2421 return TypeManager.uint64_type;
2423 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2427 // When compiling corlib and called with one of the core types, return
2428 // the corresponding typebuilder for that type.
2430 public static Type TypeToCoreType (Type t)
2432 if (RootContext.StdLib || (t is TypeBuilder))
2435 TypeCode tc = Type.GetTypeCode (t);
2438 case TypeCode.Boolean:
2439 return TypeManager.bool_type;
2441 return TypeManager.byte_type;
2442 case TypeCode.SByte:
2443 return TypeManager.sbyte_type;
2445 return TypeManager.char_type;
2446 case TypeCode.Int16:
2447 return TypeManager.short_type;
2448 case TypeCode.UInt16:
2449 return TypeManager.ushort_type;
2450 case TypeCode.Int32:
2451 return TypeManager.int32_type;
2452 case TypeCode.UInt32:
2453 return TypeManager.uint32_type;
2454 case TypeCode.Int64:
2455 return TypeManager.int64_type;
2456 case TypeCode.UInt64:
2457 return TypeManager.uint64_type;
2458 case TypeCode.Single:
2459 return TypeManager.float_type;
2460 case TypeCode.Double:
2461 return TypeManager.double_type;
2462 case TypeCode.String:
2463 return TypeManager.string_type;
2465 if (t == typeof (void))
2466 return TypeManager.void_type;
2467 if (t == typeof (object))
2468 return TypeManager.object_type;
2469 if (t == typeof (System.Type))
2470 return TypeManager.type_type;
2471 if (t == typeof (System.IntPtr))
2472 return TypeManager.intptr_type;
2478 /// Utility function that can be used to probe whether a type
2479 /// is managed or not.
2481 public static bool VerifyUnManaged (Type t, Location loc)
2483 if (t.IsValueType || t.IsPointer){
2485 // FIXME: this is more complex, we actually need to
2486 // make sure that the type does not contain any
2492 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2493 // We need this explicit check here to make it work when
2494 // compiling corlib.
2499 "Cannot take the address or size of a variable of a managed type ('" +
2500 CSharpName (t) + "')");
2505 /// Returns the name of the indexer in a given type.
2508 /// The default is not always `Item'. The user can change this behaviour by
2509 /// using the DefaultMemberAttribute in the class.
2511 /// For example, the String class indexer is named `Chars' not `Item'
2513 public static string IndexerPropertyName (Type t)
2515 if (t.IsGenericInstance)
2516 t = t.GetGenericTypeDefinition ();
2518 if (t is TypeBuilder) {
2519 if (t.IsInterface) {
2520 Interface i = LookupInterface (t);
2522 if ((i == null) || (i.IndexerName == null))
2525 return i.IndexerName;
2527 TypeContainer tc = LookupTypeContainer (t);
2529 if ((tc == null) || (tc.IndexerName == null))
2532 return tc.IndexerName;
2536 System.Attribute attr = System.Attribute.GetCustomAttribute (
2537 t, TypeManager.default_member_type);
2539 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2540 return dma.MemberName;
2546 static MethodInfo pinned_method = null;
2547 public static void MakePinned (LocalBuilder builder)
2549 if (pinned_method == null) {
2550 pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
2551 if (pinned_method == null) {
2552 Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
2553 "This code may cause errors on a runtime with a moving GC");
2559 pinned_method.Invoke (builder, null);
2564 // Returns whether the array of memberinfos contains the given method
2566 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2568 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2570 foreach (MethodBase method in array) {
2571 if (method.Name != new_method.Name)
2574 if (method is MethodInfo && new_method is MethodInfo)
2575 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2579 Type [] old_args = TypeManager.GetArgumentTypes (method);
2580 int old_count = old_args.Length;
2583 if (new_args.Length != old_count)
2586 for (i = 0; i < old_count; i++){
2587 if (old_args [i] != new_args [i])
2600 // We copy methods from `new_members' into `target_list' if the signature
2601 // for the method from in the new list does not exist in the target_list
2603 // The name is assumed to be the same.
2605 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2607 if (target_list == null){
2608 target_list = new ArrayList ();
2610 foreach (MemberInfo mi in new_members){
2611 if (mi is MethodBase)
2612 target_list.Add (mi);
2617 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2618 target_list.CopyTo (target_array, 0);
2620 foreach (MemberInfo mi in new_members){
2621 MethodBase new_method = (MethodBase) mi;
2623 if (!ArrayContainsMethod (target_array, new_method))
2624 target_list.Add (new_method);
2630 public enum MethodFlags {
2632 IsObsoleteError = 1 << 1,
2633 ShouldIgnore = 1 << 2
2636 static public bool IsGenericMethod (MethodBase mb)
2638 if (mb.DeclaringType is TypeBuilder) {
2639 MethodData method = (MethodData) builder_to_method [mb];
2643 return method.GenericMethod != null;
2646 return mb.IsGenericMethodDefinition;
2650 // Returns the TypeManager.MethodFlags for this method.
2651 // This emits an error 619 / warning 618 if the method is obsolete.
2652 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2654 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2656 MethodFlags flags = 0;
2658 if (mb.Mono_IsInflatedMethod)
2659 mb = mb.GetGenericMethodDefinition ();
2661 if (mb.DeclaringType is TypeBuilder){
2662 MethodData method = (MethodData) builder_to_method [mb];
2663 if (method == null) {
2664 // FIXME: implement Obsolete attribute on Property,
2665 // Indexer and Event.
2669 return method.GetMethodFlags (loc);
2672 object [] attrs = mb.GetCustomAttributes (true);
2673 foreach (object ta in attrs){
2674 if (!(ta is System.Attribute)){
2675 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2678 System.Attribute a = (System.Attribute) ta;
2679 if (a.TypeId == TypeManager.obsolete_attribute_type){
2680 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2682 string method_desc = TypeManager.CSharpSignature (mb);
2685 Report.Error (619, loc, "Method `" + method_desc +
2686 "' is obsolete: `" + oa.Message + "'");
2687 return MethodFlags.IsObsoleteError;
2689 Report.Warning (618, loc, "Method `" + method_desc +
2690 "' is obsolete: `" + oa.Message + "'");
2692 flags |= MethodFlags.IsObsolete;
2698 // Skip over conditional code.
2700 if (a.TypeId == TypeManager.conditional_attribute_type){
2701 ConditionalAttribute ca = (ConditionalAttribute) a;
2703 if (RootContext.AllDefines [ca.ConditionString] == null)
2704 flags |= MethodFlags.ShouldIgnore;
2711 #region MemberLookup implementation
2714 // Whether we allow private members in the result (since FindMembers
2715 // uses NonPublic for both protected and private), we need to distinguish.
2717 static bool closure_private_ok;
2720 // Who is invoking us and which type is being queried currently.
2722 static Type closure_invocation_type;
2723 static Type closure_qualifier_type;
2726 // The assembly that defines the type is that is calling us
2728 static Assembly closure_invocation_assembly;
2730 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2736 // This filter filters by name + whether it is ok to include private
2737 // members in the search
2739 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2742 // Hack: we know that the filter criteria will always be in the `closure'
2746 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2749 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2750 (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
2754 // Ugly: we need to find out the type of `m', and depending
2755 // on this, tell whether we accept or not
2757 if (m is MethodBase){
2758 MethodBase mb = (MethodBase) m;
2759 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2761 if (ma == MethodAttributes.Private)
2762 return closure_private_ok ||
2763 IsEqual (closure_invocation_type, m.DeclaringType) ||
2764 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2767 // FamAndAssem requires that we not only derivate, but we are on the
2770 if (ma == MethodAttributes.FamANDAssem){
2771 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2775 // Assembly and FamORAssem succeed if we're in the same assembly.
2776 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2777 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2781 // We already know that we aren't in the same assembly.
2782 if (ma == MethodAttributes.Assembly)
2785 // Family and FamANDAssem require that we derive.
2786 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2787 if (closure_invocation_type == null)
2790 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2793 // Although a derived class can access protected members of its base class
2794 // it cannot do so through an instance of the base class (CS1540).
2795 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2796 (closure_qualifier_type != null) &&
2797 closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2798 !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2808 if (m is FieldInfo){
2809 FieldInfo fi = (FieldInfo) m;
2810 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2812 if (fa == FieldAttributes.Private)
2813 return closure_private_ok ||
2814 IsEqual (closure_invocation_type, m.DeclaringType) ||
2815 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2818 // FamAndAssem requires that we not only derivate, but we are on the
2821 if (fa == FieldAttributes.FamANDAssem){
2822 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2826 // Assembly and FamORAssem succeed if we're in the same assembly.
2827 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2828 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2832 // We already know that we aren't in the same assembly.
2833 if (fa == FieldAttributes.Assembly)
2836 // Family and FamANDAssem require that we derive.
2837 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2838 if (closure_invocation_type == null)
2841 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2844 // Although a derived class can access protected members of its base class
2845 // it cannot do so through an instance of the base class (CS1540).
2846 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2847 (closure_qualifier_type != null) &&
2848 closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2849 !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2860 // EventInfos and PropertyInfos, return true because they lack permission
2861 // informaiton, so we need to check later on the methods.
2866 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2867 static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2870 // Looks up a member called `name' in the `queried_type'. This lookup
2871 // is done by code that is contained in the definition for `invocation_type'
2872 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2874 // `invocation_type' is used to check whether we're allowed to access the requested
2875 // member wrt its protection level.
2877 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2878 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2879 // is B and qualifier_type is A). This is used to do the CS1540 check.
2881 // When resolving a SimpleName, `qualifier_type' is null.
2883 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2884 // the same than `queried_type' - except when we're being called from BaseAccess;
2885 // in this case, `invocation_type' is the current type and `queried_type' the base
2886 // type, so this'd normally trigger a CS1540.
2888 // The binding flags are `bf' and the kind of members being looked up are `mt'
2890 // The return value always includes private members which code in `invocation_type'
2891 // is allowed to access (using the specified `qualifier_type' if given); only use
2892 // BindingFlags.NonPublic to bypass the permission check.
2894 // Returns an array of a single element for everything but Methods/Constructors
2895 // that might return multiple matches.
2897 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2898 Type queried_type, MemberTypes mt,
2899 BindingFlags original_bf, string name)
2901 Timer.StartTimer (TimerType.MemberLookup);
2903 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2904 queried_type, mt, original_bf, name);
2906 Timer.StopTimer (TimerType.MemberLookup);
2911 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2912 Type queried_type, MemberTypes mt,
2913 BindingFlags original_bf, string name)
2915 BindingFlags bf = original_bf;
2917 ArrayList method_list = null;
2918 Type current_type = queried_type;
2919 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2920 bool skip_iface_check = true, used_cache = false;
2921 bool always_ok_flag = false;
2923 closure_invocation_type = invocation_type;
2924 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2925 closure_qualifier_type = qualifier_type;
2928 // If we are a nested class, we always have access to our container
2931 if (invocation_type != null){
2932 string invocation_name = invocation_type.FullName;
2933 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
2934 string container = queried_type.FullName + "+";
2935 int container_length = container.Length;
2937 if (invocation_name.Length > container_length){
2938 string shared = invocation_name.Substring (0, container_length);
2940 if (shared == container)
2941 always_ok_flag = true;
2946 // This is from the first time we find a method
2947 // in most cases, we do not actually find a method in the base class
2948 // so we can just ignore it, and save the arraylist allocation
2949 MemberInfo [] first_members_list = null;
2950 bool use_first_members_list = false;
2956 // `NonPublic' is lame, because it includes both protected and
2957 // private methods, so we need to control this behavior by
2958 // explicitly tracking if a private method is ok or not.
2960 // The possible cases are:
2961 // public, private and protected (internal does not come into the
2964 if ((invocation_type != null) &&
2965 ((invocation_type == current_type) ||
2966 IsNestedChildOf (invocation_type, current_type)) ||
2968 bf = original_bf | BindingFlags.NonPublic;
2972 closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2974 Timer.StopTimer (TimerType.MemberLookup);
2976 list = MemberLookup_FindMembers (
2977 current_type, mt, bf, name, out used_cache);
2979 Timer.StartTimer (TimerType.MemberLookup);
2982 // When queried for an interface type, the cache will automatically check all
2983 // inherited members, so we don't need to do this here. However, this only
2984 // works if we already used the cache in the first iteration of this loop.
2986 // If we used the cache in any further iteration, we can still terminate the
2987 // loop since the cache always looks in all parent classes.
2993 skip_iface_check = false;
2995 if (current_type == TypeManager.object_type)
2998 current_type = current_type.BaseType;
3001 // This happens with interfaces, they have a null
3002 // basetype. Look members up in the Object class.
3004 if (current_type == null)
3005 current_type = TypeManager.object_type;
3008 if (list.Length == 0)
3012 // Events and types are returned by both `static' and `instance'
3013 // searches, which means that our above FindMembers will
3014 // return two copies of the same.
3016 if (list.Length == 1 && !(list [0] is MethodBase)){
3021 // Multiple properties: we query those just to find out the indexer
3024 if (list [0] is PropertyInfo)
3028 // We found an event: the cache lookup returns both the event and
3029 // its private field.
3031 if (list [0] is EventInfo) {
3032 if ((list.Length == 2) && (list [1] is FieldInfo))
3033 return new MemberInfo [] { list [0] };
3040 // We found methods, turn the search into "method scan"
3044 if (first_members_list != null) {
3045 if (use_first_members_list) {
3046 method_list = CopyNewMethods (method_list, first_members_list);
3047 use_first_members_list = false;
3050 method_list = CopyNewMethods (method_list, list);
3052 first_members_list = list;
3053 use_first_members_list = true;
3055 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3057 } while (searching);
3059 if (use_first_members_list) {
3060 foreach (MemberInfo mi in first_members_list) {
3061 if (! (mi is MethodBase)) {
3062 method_list = CopyNewMethods (method_list, first_members_list);
3063 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3066 return (MemberInfo []) first_members_list;
3069 if (method_list != null && method_list.Count > 0) {
3070 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3073 // This happens if we already used the cache in the first iteration, in this case
3074 // the cache already looked in all interfaces.
3076 if (skip_iface_check)
3080 // Interfaces do not list members they inherit, so we have to
3083 if (!queried_type.IsInterface)
3086 if (queried_type.IsArray)
3087 queried_type = TypeManager.array_type;
3089 TypeExpr [] ifaces = GetInterfaces (queried_type);
3093 foreach (TypeExpr itype in ifaces){
3096 x = MemberLookup (null, null, itype.Type, mt, bf, name);
3105 // This is used to extract properties and event declarations from a type
3107 static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
3109 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
3111 bf |= BindingFlags.Public | BindingFlags.NonPublic;
3113 if (t is TypeBuilder) {
3114 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
3116 return (MemberInfo []) decl.FindMembers (
3117 MemberTypes.Property | MemberTypes.Event,
3118 bf, FilterNone_delegate, null);
3120 return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
3121 bf, FilterNone_delegate, null);
3126 public static bool IsSpecialMethod (MethodBase mb)
3128 Type t = mb.DeclaringType;
3130 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
3131 if (matches == null)
3134 foreach (MemberInfo mi in matches){
3135 if (mi is PropertyBuilder){
3136 Pair p = (Pair) properties [mi];
3138 if (p.First == mb || p.Second == mb)
3140 } else if (mi is PropertyInfo){
3141 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
3143 foreach (MethodInfo m in methods){
3147 } else if (mi is MyEventBuilder){
3148 Pair p = (Pair) events [mi];
3150 if (p.First == mb || p.Second == mb)
3152 } else if (mi is EventInfo){
3153 EventInfo ei = ((EventInfo) mi);
3155 if (ei.GetAddMethod (true) == mb)
3158 if (ei.GetRemoveMethod (true) == mb)
3161 if (ei.GetRaiseMethod (true) == mb)
3167 // Now check if it is an operator method
3171 if (s.StartsWith ("op_")){
3172 foreach (string name in Unary.oper_names){
3177 foreach (string name in Binary.oper_names){
3191 /// There is exactly one instance of this class per type.
3193 public sealed class TypeHandle : IMemberContainer {
3194 public readonly TypeHandle BaseType;
3196 readonly int id = ++next_id;
3197 static int next_id = 0;
3200 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3201 /// a TypeHandle yet, a new instance of it is created. This static method
3202 /// ensures that we'll only have one TypeHandle instance per type.
3204 public static TypeHandle GetTypeHandle (Type t)
3206 TypeHandle handle = (TypeHandle) type_hash [t];
3210 handle = new TypeHandle (t);
3211 type_hash.Add (t, handle);
3215 public static void CleanUp ()
3221 /// Returns the TypeHandle for TypeManager.object_type.
3223 public static IMemberContainer ObjectType {
3225 if (object_type != null)
3228 object_type = GetTypeHandle (TypeManager.object_type);
3235 /// Returns the TypeHandle for TypeManager.array_type.
3237 public static IMemberContainer ArrayType {
3239 if (array_type != null)
3242 array_type = GetTypeHandle (TypeManager.array_type);
3248 private static PtrHashtable type_hash = new PtrHashtable ();
3250 private static TypeHandle object_type = null;
3251 private static TypeHandle array_type = null;
3254 private string full_name;
3255 private bool is_interface;
3256 private MemberCache member_cache;
3258 private TypeHandle (Type type)
3261 full_name = type.FullName != null ? type.FullName : type.Name;
3262 if (type.BaseType != null)
3263 BaseType = GetTypeHandle (type.BaseType);
3264 this.is_interface = type.IsInterface || type.IsGenericParameter;
3265 this.member_cache = new MemberCache (this);
3268 // IMemberContainer methods
3270 public string Name {
3282 public IMemberContainer Parent {
3288 public bool IsInterface {
3290 return is_interface;
3294 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3296 MemberInfo [] members;
3297 if (type is GenericTypeParameterBuilder)
3298 return MemberList.Empty;
3299 if (mt == MemberTypes.Event)
3300 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3302 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3304 Array.Reverse (members);
3306 return new MemberList (members);
3309 // IMemberFinder methods
3311 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3312 MemberFilter filter, object criteria)
3314 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3317 public MemberCache MemberCache {
3319 return member_cache;
3323 public override string ToString ()
3325 if (BaseType != null)
3326 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3328 return "TypeHandle (" + id + "," + Name + ")";