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 iconvertible_type;
67 static public Type default_member_type;
68 static public Type iasyncresult_type;
69 static public Type asynccallback_type;
70 static public Type intptr_type;
71 static public Type monitor_type;
72 static public Type runtime_field_handle_type;
73 static public Type attribute_type;
74 static public Type attribute_usage_type;
75 static public Type dllimport_type;
76 static public Type unverifiable_code_type;
77 static public Type methodimpl_attr_type;
78 static public Type marshal_as_attr_type;
79 static public Type new_constraint_attr_type;
80 static public Type param_array_type;
81 static public Type guid_attr_type;
82 static public Type void_ptr_type;
83 static public Type indexer_name_type;
84 static public Type exception_type;
85 static public Type activator_type;
86 static public Type invalid_operation_exception_type;
87 static public Type obsolete_attribute_type;
88 static public object conditional_attribute_type;
89 static public Type in_attribute_type;
90 static public Type cls_compliant_attribute_type;
91 static public Type typed_reference_type;
92 static public Type arg_iterator_type;
93 static public Type mbr_type;
94 static public Type struct_layout_attribute_type;
95 static public Type field_offset_attribute_type;
98 // An empty array of types
100 static public Type [] NoTypes;
101 static public TypeExpr [] NoTypeExprs;
105 // Expressions representing the internal types. Used during declaration
108 static public TypeExpr system_object_expr, system_string_expr;
109 static public TypeExpr system_boolean_expr, system_decimal_expr;
110 static public TypeExpr system_single_expr, system_double_expr;
111 static public TypeExpr system_sbyte_expr, system_byte_expr;
112 static public TypeExpr system_int16_expr, system_uint16_expr;
113 static public TypeExpr system_int32_expr, system_uint32_expr;
114 static public TypeExpr system_int64_expr, system_uint64_expr;
115 static public TypeExpr system_char_expr, system_void_expr;
116 static public TypeExpr system_asynccallback_expr;
117 static public TypeExpr system_iasyncresult_expr;
118 static public TypeExpr system_valuetype_expr;
121 // This is only used when compiling corlib
123 static public Type system_int32_type;
124 static public Type system_array_type;
125 static public Type system_type_type;
126 static public Type system_assemblybuilder_type;
127 static public MethodInfo system_int_array_get_length;
128 static public MethodInfo system_int_array_get_rank;
129 static public MethodInfo system_object_array_clone;
130 static public MethodInfo system_int_array_get_length_int;
131 static public MethodInfo system_int_array_get_lower_bound_int;
132 static public MethodInfo system_int_array_get_upper_bound_int;
133 static public MethodInfo system_void_array_copyto_array_int;
137 // Internal, not really used outside
139 static Type runtime_helpers_type;
142 // These methods are called by code generated by the compiler
144 static public MethodInfo string_concat_string_string;
145 static public MethodInfo string_concat_string_string_string;
146 static public MethodInfo string_concat_string_string_string_string;
147 static public MethodInfo string_concat_string_dot_dot_dot;
148 static public MethodInfo string_concat_object_object;
149 static public MethodInfo string_concat_object_object_object;
150 static public MethodInfo string_concat_object_dot_dot_dot;
151 static public MethodInfo string_isinterneted_string;
152 static public MethodInfo system_type_get_type_from_handle;
153 static public MethodInfo object_getcurrent_void;
154 static public MethodInfo bool_movenext_void;
155 static public MethodInfo ienumerable_getenumerator_void;
156 static public MethodInfo void_reset_void;
157 static public MethodInfo void_dispose_void;
158 static public MethodInfo void_monitor_enter_object;
159 static public MethodInfo void_monitor_exit_object;
160 static public MethodInfo void_initializearray_array_fieldhandle;
161 static public MethodInfo int_getlength_int;
162 static public MethodInfo delegate_combine_delegate_delegate;
163 static public MethodInfo delegate_remove_delegate_delegate;
164 static public MethodInfo int_get_offset_to_string_data;
165 static public MethodInfo int_array_get_length;
166 static public MethodInfo int_array_get_rank;
167 static public MethodInfo object_array_clone;
168 static public MethodInfo int_array_get_length_int;
169 static public MethodInfo int_array_get_lower_bound_int;
170 static public MethodInfo int_array_get_upper_bound_int;
171 static public MethodInfo void_array_copyto_array_int;
172 static public MethodInfo activator_create_instance;
175 // The attribute constructors.
177 static public ConstructorInfo object_ctor;
178 static public ConstructorInfo cons_param_array_attribute;
179 static public ConstructorInfo void_decimal_ctor_five_args;
180 static public ConstructorInfo unverifiable_code_ctor;
181 static public ConstructorInfo invalid_operation_ctor;
184 // Holds the Array of Assemblies that have been loaded
185 // (either because it is the default or the user used the
186 // -r command line option)
188 static Assembly [] assemblies;
191 // Keeps a list of modules. We used this to do lookups
192 // on the module using GetType -- needed for arrays
194 static Module [] modules;
197 // This is the type_cache from the assemblies to avoid
198 // hitting System.Reflection on every lookup.
200 static Hashtable types;
203 // This is used to hotld the corresponding TypeContainer objects
204 // since we need this in FindMembers
206 static Hashtable typecontainers;
209 // Keeps track of those types that are defined by the
212 static ArrayList user_types;
214 static PtrHashtable builder_to_declspace;
217 // Tracks the interfaces implemented by typebuilders. We only
218 // enter those who do implement or or more interfaces
220 static PtrHashtable builder_to_ifaces;
223 // Tracks the generic parameters.
225 static PtrHashtable builder_to_type_param;
228 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
229 // the arguments to the method
231 static Hashtable method_arguments;
234 // Maps PropertyBuilder to a Type array that contains
235 // the arguments to the indexer
237 static Hashtable indexer_arguments;
240 // Maybe `method_arguments' should be replaced and only
241 // method_internal_params should be kept?
243 static Hashtable method_internal_params;
246 // Keeps track of methods
249 static Hashtable builder_to_method;
252 // Contains all public types from referenced assemblies.
253 // This member is used only if CLS Compliance verification is required.
255 public static Hashtable all_imported_types;
262 public static void CleanUp ()
264 // Lets get everything clean so that we can collect before generating code
268 typecontainers = null;
270 builder_to_declspace = null;
271 builder_to_ifaces = null;
272 method_arguments = null;
273 indexer_arguments = null;
274 method_internal_params = null;
275 builder_to_method = null;
276 builder_to_type_param = null;
280 negative_hits = null;
281 builder_to_constant = null;
282 fieldbuilders_to_fields = null;
284 priv_fields_events = null;
287 TypeHandle.CleanUp ();
291 /// A filter for Findmembers that uses the Signature object to
294 static bool SignatureFilter (MemberInfo mi, object criteria)
296 Signature sig = (Signature) criteria;
298 if (!(mi is MethodBase))
301 if (mi.Name != sig.name)
304 int count = sig.args.Length;
306 if (mi is MethodBuilder || mi is ConstructorBuilder){
307 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
309 if (candidate_args.Length != count)
312 for (int i = 0; i < count; i++)
313 if (candidate_args [i] != sig.args [i])
318 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
320 if (pars.Length != count)
323 for (int i = 0; i < count; i++)
324 if (pars [i].ParameterType != sig.args [i])
330 // A delegate that points to the filter above.
331 static MemberFilter signature_filter;
334 // These are expressions that represent some of the internal data types, used
337 static void InitExpressionTypes ()
339 system_object_expr = new TypeLookupExpression ("System.Object");
340 system_string_expr = new TypeLookupExpression ("System.String");
341 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
342 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
343 system_single_expr = new TypeLookupExpression ("System.Single");
344 system_double_expr = new TypeLookupExpression ("System.Double");
345 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
346 system_byte_expr = new TypeLookupExpression ("System.Byte");
347 system_int16_expr = new TypeLookupExpression ("System.Int16");
348 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
349 system_int32_expr = new TypeLookupExpression ("System.Int32");
350 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
351 system_int64_expr = new TypeLookupExpression ("System.Int64");
352 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
353 system_char_expr = new TypeLookupExpression ("System.Char");
354 system_void_expr = new TypeLookupExpression ("System.Void");
355 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
356 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
357 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
360 static TypeManager ()
362 assemblies = new Assembly [0];
364 user_types = new ArrayList ();
366 types = new Hashtable ();
367 typecontainers = new Hashtable ();
369 builder_to_declspace = new PtrHashtable ();
370 builder_to_method = new PtrHashtable ();
371 method_arguments = new PtrHashtable ();
372 method_internal_params = new PtrHashtable ();
373 indexer_arguments = new PtrHashtable ();
374 builder_to_ifaces = new PtrHashtable ();
375 builder_to_type_param = new PtrHashtable ();
377 NoTypes = new Type [0];
378 NoTypeExprs = new TypeExpr [0];
380 signature_filter = new MemberFilter (SignatureFilter);
381 InitExpressionTypes ();
384 public static void HandleDuplicate (string name, Type t)
386 Type prev = (Type) types [name];
387 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
391 // This probably never happens, as we catch this before
393 Report.Error (-17, "The type `" + name + "' has already been defined.");
397 tc = builder_to_declspace [t] as TypeContainer;
400 1595, "The type `" + name + "' is defined in an existing assembly;"+
401 " Using the new definition from: " + tc.Location);
404 1595, "The type `" + name + "' is defined in an existing assembly;");
407 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
413 public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
418 HandleDuplicate (name, t);
423 builder_to_ifaces [t] = ifaces;
427 // This entry point is used by types that we define under the covers
429 public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
432 builder_to_ifaces [tb] = ifaces;
435 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
437 builder_to_declspace.Add (t, tc);
438 typecontainers.Add (name, tc);
439 AddUserType (name, t, ifaces);
442 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
447 HandleDuplicate (name, t);
450 builder_to_declspace.Add (t, del);
453 public static void AddEnumType (string name, TypeBuilder t, Enum en)
458 HandleDuplicate (name, t);
460 builder_to_declspace.Add (t, en);
463 public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
465 AddUserType (name, t, ifaces);
466 builder_to_declspace.Add (t, i);
469 public static void AddMethod (MethodBase builder, IMethodData method)
471 builder_to_method.Add (builder, method);
474 public static IMethodData GetMethod (MethodBase builder)
476 return (IMethodData) builder_to_method [builder];
479 public static void AddTypeParameter (Type t, TypeParameter tparam, TypeExpr[] ifaces)
481 if (!builder_to_type_param.Contains (t)) {
482 builder_to_type_param.Add (t, tparam);
485 builder_to_ifaces [t] = ifaces;
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 IMemberContainer LookupMemberContainer (Type t)
509 if (t is TypeBuilder) {
510 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
511 if (container != null)
515 if (t is GenericTypeParameterBuilder) {
516 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
518 if (container != null)
522 return TypeHandle.GetTypeHandle (t);
525 public static Interface LookupInterface (Type t)
527 return builder_to_declspace [t] as Interface;
530 public static Delegate LookupDelegate (Type t)
532 return builder_to_declspace [t] as Delegate;
535 public static Enum LookupEnum (Type t)
537 return builder_to_declspace [t] as Enum;
540 public static Class LookupClass (Type t)
542 return (Class) builder_to_declspace [t];
545 public static TypeParameter LookupTypeParameter (Type t)
547 return (TypeParameter) builder_to_type_param [t];
550 public static bool HasConstructorConstraint (Type t)
552 if (!t.IsGenericParameter)
553 throw new InvalidOperationException ();
555 TypeParameter tparam = LookupTypeParameter (t);
557 return tparam.HasConstructorConstraint;
559 object[] attrs = t.GetCustomAttributes (
560 TypeManager.new_constraint_attr_type, false);
562 return attrs.Length > 0;
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);
586 /// Registers a module builder to lookup types from
588 public static void AddModule (Module mb)
590 int top = modules != null ? modules.Length : 0;
591 Module [] n = new Module [top + 1];
594 modules.CopyTo (n, 0);
599 public static Module[] Modules {
605 static Hashtable references = new Hashtable ();
608 // Gets the reference to T version of the Type (T&)
610 public static Type GetReferenceType (Type t)
612 return t.MakeByRefType ();
615 static Hashtable pointers = new Hashtable ();
618 // Gets the pointer to T version of the Type (T*)
620 public static Type GetPointerType (Type t)
622 string tname = t.FullName + "*";
624 Type ret = t.Assembly.GetType (tname);
627 // If the type comes from the assembly we are building
628 // We need the Hashtable, because .NET 1.1 will return different instance types
629 // every time we call ModuleBuilder.GetType.
632 if (pointers [t] == null)
633 pointers [t] = CodeGen.Module.Builder.GetType (tname);
635 ret = (Type) pointers [t];
642 // Low-level lookup, cache-less
644 static Type LookupTypeReflection (string name)
648 foreach (Assembly a in assemblies){
649 t = a.GetType (name);
654 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
655 if (ta == TypeAttributes.NotPublic ||
656 ta == TypeAttributes.NestedPrivate ||
657 ta == TypeAttributes.NestedAssembly ||
658 ta == TypeAttributes.NestedFamANDAssem){
661 // In .NET pointers turn out to be private, even if their
662 // element type is not
665 t = t.GetElementType ();
675 foreach (Module mb in modules) {
676 t = mb.GetType (name);
684 static Hashtable negative_hits = new Hashtable ();
687 // This function is used when you want to avoid the lookups, and want to go
688 // directly to the source. This will use the cache.
690 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
691 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
692 // way to test things other than doing a fullname compare
694 public static Type LookupTypeDirect (string name)
696 Type t = (Type) types [name];
700 t = LookupTypeReflection (name);
708 static readonly char [] dot_array = { '.' };
711 /// Returns the Type associated with @name, takes care of the fact that
712 /// reflection expects nested types to be separated from the main type
713 /// with a "+" instead of a "."
715 public static Type LookupType (string name)
720 // First lookup in user defined and cached values
723 t = (Type) types [name];
727 // Two thirds of the failures are caught here.
728 if (negative_hits.Contains (name))
731 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
732 string [] elements = name.Split (dot_array);
733 int count = elements.Length;
735 for (int n = 1; n <= count; n++){
736 string top_level_type = String.Join (".", elements, 0, n);
738 // One third of the failures are caught here.
739 if (negative_hits.Contains (top_level_type))
742 t = (Type) types [top_level_type];
744 t = LookupTypeReflection (top_level_type);
746 negative_hits [top_level_type] = null;
757 // We know that System.Object does not have children, and since its the parent of
758 // all the objects, it always gets probbed for inner classes.
760 if (top_level_type == "System.Object")
763 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
764 //Console.WriteLine ("Looking up: " + newt + " " + name);
765 t = LookupTypeReflection (newt);
767 negative_hits [name] = null;
772 negative_hits [name] = null;
777 /// Computes the namespaces that we import from the assemblies we reference.
779 public static void ComputeNamespaces ()
781 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
784 // First add the assembly namespaces
786 if (assembly_get_namespaces != null){
787 int count = assemblies.Length;
789 for (int i = 0; i < count; i++){
790 Assembly a = assemblies [i];
791 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
792 foreach (string ns in namespaces){
795 Namespace.LookupNamespace (ns, true);
799 Hashtable cache = new Hashtable ();
800 cache.Add ("", null);
801 foreach (Assembly a in assemblies) {
802 foreach (Type t in a.GetExportedTypes ()) {
803 string ns = t.Namespace;
804 if (ns == null || cache.Contains (ns))
807 Namespace.LookupNamespace (ns, true);
808 cache.Add (ns, null);
815 /// Fills static table with exported types from all referenced assemblies.
816 /// This information is required for CLS Compliance tests.
818 public static void LoadAllImportedTypes ()
820 if (!CodeGen.Assembly.IsClsCompliant)
823 all_imported_types = new Hashtable ();
824 foreach (Assembly a in assemblies) {
825 foreach (Type t in a.GetExportedTypes ()) {
826 all_imported_types [t.FullName] = t;
831 public static bool NamespaceClash (string name, Location loc)
833 if (Namespace.LookupNamespace (name, false) == null)
836 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
841 /// Returns the C# name of a type if possible, or the full type name otherwise
843 static public string CSharpName (Type t)
845 if (t.FullName == null)
848 return Regex.Replace (t.FullName,
850 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
851 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
852 @"Boolean|String|Void)" +
854 new MatchEvaluator (CSharpNameMatch));
857 static String CSharpNameMatch (Match match)
859 string s = match.Groups [1].Captures [0].Value;
861 Replace ("int32", "int").
862 Replace ("uint32", "uint").
863 Replace ("int16", "short").
864 Replace ("uint16", "ushort").
865 Replace ("int64", "long").
866 Replace ("uint64", "ulong").
867 Replace ("single", "float").
868 Replace ("boolean", "bool")
869 + match.Groups [2].Captures [0].Value;
873 /// Returns the signature of the method with full namespace classification
875 static public string GetFullNameSignature (MemberInfo mi)
879 n = mi.DeclaringType.Name;
881 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n;
884 static public string GetFullName (Type t)
886 if (t.FullName == null)
889 string name = t.FullName.Replace ('+', '.');
891 DeclSpace tc = LookupDeclSpace (t);
892 if ((tc != null) && tc.IsGeneric) {
893 TypeParameter[] tparam = tc.TypeParameters;
895 StringBuilder sb = new StringBuilder (name);
897 for (int i = 0; i < tparam.Length; i++) {
900 sb.Append (tparam [i].Name);
903 return sb.ToString ();
904 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
905 Type[] tparam = t.GetGenericArguments ();
907 StringBuilder sb = new StringBuilder (name);
909 for (int i = 0; i < tparam.Length; i++) {
912 sb.Append (tparam [i].Name);
915 return sb.ToString ();
922 /// Returns the signature of the property and indexer
924 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
927 return GetFullNameSignature (pb);
930 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
931 string signature = GetFullNameSignature (mb);
932 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
933 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
937 /// Returns the signature of the method
939 static public string CSharpSignature (MethodBase mb)
944 // FIXME: We should really have a single function to do
945 // everything instead of the following 5 line pattern
947 ParameterData iparams = LookupParametersByBuilder (mb);
950 iparams = new ReflectionParameters (mb);
952 for (int i = 0; i < iparams.Count; i++) {
956 sig += iparams.ParameterDesc(i);
960 return GetFullNameSignature (mb) + sig;
964 /// Looks up a type, and aborts if it is not found. This is used
965 /// by types required by the compiler
967 static Type CoreLookupType (string name)
969 Type t = LookupTypeDirect (name);
972 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
973 Environment.Exit (1);
980 /// Returns the MethodInfo for a method named `name' defined
981 /// in type `t' which takes arguments of types `args'
983 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
987 BindingFlags flags = instance_and_static | BindingFlags.Public;
993 flags |= BindingFlags.NonPublic;
995 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
996 if (list.Count == 0) {
998 Report.Error (-19, "Can not find the core function `" + name + "'");
1002 MethodInfo mi = list [0] as MethodInfo;
1005 Report.Error (-19, "Can not find the core function `" + name + "'");
1012 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1014 return GetMethod (t, name, args, false, report_errors);
1017 static MethodInfo GetMethod (Type t, string name, Type [] args)
1019 return GetMethod (t, name, args, true);
1024 /// Returns the ConstructorInfo for "args"
1026 static ConstructorInfo GetConstructor (Type t, Type [] args)
1034 list = FindMembers (t, MemberTypes.Constructor,
1035 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1036 signature_filter, sig);
1037 if (list.Count == 0){
1038 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1042 ConstructorInfo ci = list [0] as ConstructorInfo;
1044 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1051 public static void InitEnumUnderlyingTypes ()
1054 int32_type = CoreLookupType ("System.Int32");
1055 int64_type = CoreLookupType ("System.Int64");
1056 uint32_type = CoreLookupType ("System.UInt32");
1057 uint64_type = CoreLookupType ("System.UInt64");
1058 byte_type = CoreLookupType ("System.Byte");
1059 sbyte_type = CoreLookupType ("System.SByte");
1060 short_type = CoreLookupType ("System.Int16");
1061 ushort_type = CoreLookupType ("System.UInt16");
1065 /// The types have to be initialized after the initial
1066 /// population of the type has happened (for example, to
1067 /// bootstrap the corlib.dll
1069 public static void InitCoreTypes ()
1071 object_type = CoreLookupType ("System.Object");
1072 value_type = CoreLookupType ("System.ValueType");
1074 InitEnumUnderlyingTypes ();
1076 char_type = CoreLookupType ("System.Char");
1077 string_type = CoreLookupType ("System.String");
1078 float_type = CoreLookupType ("System.Single");
1079 double_type = CoreLookupType ("System.Double");
1080 char_ptr_type = CoreLookupType ("System.Char*");
1081 decimal_type = CoreLookupType ("System.Decimal");
1082 bool_type = CoreLookupType ("System.Boolean");
1083 enum_type = CoreLookupType ("System.Enum");
1085 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1086 delegate_type = CoreLookupType ("System.Delegate");
1088 array_type = CoreLookupType ("System.Array");
1089 void_type = CoreLookupType ("System.Void");
1090 type_type = CoreLookupType ("System.Type");
1092 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1093 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1094 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1095 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1096 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1097 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1098 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1099 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1100 idisposable_type = CoreLookupType ("System.IDisposable");
1101 icloneable_type = CoreLookupType ("System.ICloneable");
1102 iconvertible_type = CoreLookupType ("System.IConvertible");
1103 monitor_type = CoreLookupType ("System.Threading.Monitor");
1104 intptr_type = CoreLookupType ("System.IntPtr");
1106 attribute_type = CoreLookupType ("System.Attribute");
1107 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1108 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1109 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1110 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1111 new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
1112 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1113 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1114 typed_reference_type = CoreLookupType ("System.TypedReference");
1115 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1116 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1119 // Sigh. Remove this before the release. Wonder what versions of Mono
1120 // people are running.
1122 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1124 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1126 void_ptr_type = CoreLookupType ("System.Void*");
1128 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1130 exception_type = CoreLookupType ("System.Exception");
1131 activator_type = CoreLookupType ("System.Activator");
1132 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1137 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1138 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1139 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1140 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1141 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1144 // When compiling corlib, store the "real" types here.
1146 if (!RootContext.StdLib) {
1147 system_int32_type = typeof (System.Int32);
1148 system_array_type = typeof (System.Array);
1149 system_type_type = typeof (System.Type);
1150 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1152 Type [] void_arg = { };
1153 system_int_array_get_length = GetMethod (
1154 system_array_type, "get_Length", void_arg);
1155 system_int_array_get_rank = GetMethod (
1156 system_array_type, "get_Rank", void_arg);
1157 system_object_array_clone = GetMethod (
1158 system_array_type, "Clone", void_arg);
1160 Type [] system_int_arg = { system_int32_type };
1161 system_int_array_get_length_int = GetMethod (
1162 system_array_type, "GetLength", system_int_arg);
1163 system_int_array_get_upper_bound_int = GetMethod (
1164 system_array_type, "GetUpperBound", system_int_arg);
1165 system_int_array_get_lower_bound_int = GetMethod (
1166 system_array_type, "GetLowerBound", system_int_arg);
1168 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1169 system_void_array_copyto_array_int = GetMethod (
1170 system_array_type, "CopyTo", system_array_int_arg);
1172 Type [] system_3_type_arg = {
1173 system_type_type, system_type_type, system_type_type };
1174 Type [] system_4_type_arg = {
1175 system_type_type, system_type_type, system_type_type, system_type_type };
1177 MethodInfo set_corlib_type_builders = GetMethod (
1178 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1179 system_4_type_arg, true, false);
1181 if (set_corlib_type_builders != null) {
1182 object[] args = new object [4];
1183 args [0] = object_type;
1184 args [1] = value_type;
1185 args [2] = enum_type;
1186 args [3] = void_type;
1188 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1190 // Compatibility for an older version of the class libs.
1191 set_corlib_type_builders = GetMethod (
1192 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1193 system_3_type_arg, true, true);
1195 if (set_corlib_type_builders == null) {
1196 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1200 object[] args = new object [3];
1201 args [0] = object_type;
1202 args [1] = value_type;
1203 args [2] = enum_type;
1205 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1209 system_object_expr.Type = object_type;
1210 system_string_expr.Type = string_type;
1211 system_boolean_expr.Type = bool_type;
1212 system_decimal_expr.Type = decimal_type;
1213 system_single_expr.Type = float_type;
1214 system_double_expr.Type = double_type;
1215 system_sbyte_expr.Type = sbyte_type;
1216 system_byte_expr.Type = byte_type;
1217 system_int16_expr.Type = short_type;
1218 system_uint16_expr.Type = ushort_type;
1219 system_int32_expr.Type = int32_type;
1220 system_uint32_expr.Type = uint32_type;
1221 system_int64_expr.Type = int64_type;
1222 system_uint64_expr.Type = uint64_type;
1223 system_char_expr.Type = char_type;
1224 system_void_expr.Type = void_type;
1225 system_asynccallback_expr.Type = asynccallback_type;
1226 system_iasyncresult_expr.Type = iasyncresult_type;
1227 system_valuetype_expr.Type = value_type;
1231 // The helper methods that are used by the compiler
1233 public static void InitCodeHelpers ()
1236 // Now load the default methods that we use.
1238 Type [] string_string = { string_type, string_type };
1239 string_concat_string_string = GetMethod (
1240 string_type, "Concat", string_string);
1241 Type [] string_string_string = { string_type, string_type, string_type };
1242 string_concat_string_string_string = GetMethod (
1243 string_type, "Concat", string_string_string);
1244 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1245 string_concat_string_string_string_string = GetMethod (
1246 string_type, "Concat", string_string_string_string);
1247 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1248 string_concat_string_dot_dot_dot = GetMethod (
1249 string_type, "Concat", params_string);
1251 Type [] object_object = { object_type, object_type };
1252 string_concat_object_object = GetMethod (
1253 string_type, "Concat", object_object);
1254 Type [] object_object_object = { object_type, object_type, object_type };
1255 string_concat_object_object_object = GetMethod (
1256 string_type, "Concat", object_object_object);
1257 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1258 string_concat_object_dot_dot_dot = GetMethod (
1259 string_type, "Concat", params_object);
1261 Type [] string_ = { string_type };
1262 string_isinterneted_string = GetMethod (
1263 string_type, "IsInterned", string_);
1265 Type [] runtime_type_handle = { runtime_handle_type };
1266 system_type_get_type_from_handle = GetMethod (
1267 type_type, "GetTypeFromHandle", runtime_type_handle);
1269 Type [] delegate_delegate = { delegate_type, delegate_type };
1270 delegate_combine_delegate_delegate = GetMethod (
1271 delegate_type, "Combine", delegate_delegate);
1273 delegate_remove_delegate_delegate = GetMethod (
1274 delegate_type, "Remove", delegate_delegate);
1279 Type [] void_arg = { };
1280 object_getcurrent_void = GetMethod (
1281 ienumerator_type, "get_Current", void_arg);
1282 bool_movenext_void = GetMethod (
1283 ienumerator_type, "MoveNext", void_arg);
1284 void_reset_void = GetMethod (
1285 ienumerator_type, "Reset", void_arg);
1286 void_dispose_void = GetMethod (
1287 idisposable_type, "Dispose", void_arg);
1288 int_get_offset_to_string_data = GetMethod (
1289 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1290 int_array_get_length = GetMethod (
1291 array_type, "get_Length", void_arg);
1292 int_array_get_rank = GetMethod (
1293 array_type, "get_Rank", void_arg);
1294 ienumerable_getenumerator_void = GetMethod (
1295 ienumerable_type, "GetEnumerator", void_arg);
1300 Type [] int_arg = { int32_type };
1301 int_array_get_length_int = GetMethod (
1302 array_type, "GetLength", int_arg);
1303 int_array_get_upper_bound_int = GetMethod (
1304 array_type, "GetUpperBound", int_arg);
1305 int_array_get_lower_bound_int = GetMethod (
1306 array_type, "GetLowerBound", int_arg);
1309 // System.Array methods
1311 object_array_clone = GetMethod (
1312 array_type, "Clone", void_arg);
1313 Type [] array_int_arg = { array_type, int32_type };
1314 void_array_copyto_array_int = GetMethod (
1315 array_type, "CopyTo", array_int_arg);
1320 Type [] object_arg = { object_type };
1321 void_monitor_enter_object = GetMethod (
1322 monitor_type, "Enter", object_arg);
1323 void_monitor_exit_object = GetMethod (
1324 monitor_type, "Exit", object_arg);
1326 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1328 void_initializearray_array_fieldhandle = GetMethod (
1329 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1334 int_getlength_int = GetMethod (
1335 array_type, "GetLength", int_arg);
1338 // Decimal constructors
1340 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1341 void_decimal_ctor_five_args = GetConstructor (
1342 decimal_type, dec_arg);
1347 cons_param_array_attribute = GetConstructor (
1348 param_array_type, void_arg);
1350 unverifiable_code_ctor = GetConstructor (
1351 unverifiable_code_type, void_arg);
1354 // InvalidOperationException
1356 invalid_operation_ctor = GetConstructor (
1357 invalid_operation_exception_type, void_arg);
1361 object_ctor = GetConstructor (object_type, void_arg);
1364 Type [] type_arg = { type_type };
1365 activator_create_instance = GetMethod (
1366 activator_type, "CreateInstance", type_arg);
1369 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1372 /// This is the "old", non-cache based FindMembers() function. We cannot use
1373 /// the cache here because there is no member name argument.
1375 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1376 MemberFilter filter, object criteria)
1378 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1381 // `builder_to_declspace' contains all dynamic types.
1385 Timer.StartTimer (TimerType.FindMembers);
1386 list = decl.FindMembers (mt, bf, filter, criteria);
1387 Timer.StopTimer (TimerType.FindMembers);
1392 // We have to take care of arrays specially, because GetType on
1393 // a TypeBuilder array will return a Type, not a TypeBuilder,
1394 // and we can not call FindMembers on this type.
1396 if (t.IsSubclassOf (TypeManager.array_type))
1397 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1400 // Since FindMembers will not lookup both static and instance
1401 // members, we emulate this behaviour here.
1403 if ((bf & instance_and_static) == instance_and_static){
1404 MemberInfo [] i_members = t.FindMembers (
1405 mt, bf & ~BindingFlags.Static, filter, criteria);
1407 int i_len = i_members.Length;
1409 MemberInfo one = i_members [0];
1412 // If any of these are present, we are done!
1414 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1415 return new MemberList (i_members);
1418 MemberInfo [] s_members = t.FindMembers (
1419 mt, bf & ~BindingFlags.Instance, filter, criteria);
1421 int s_len = s_members.Length;
1422 if (i_len > 0 || s_len > 0)
1423 return new MemberList (i_members, s_members);
1426 return new MemberList (i_members);
1428 return new MemberList (s_members);
1432 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1437 /// This method is only called from within MemberLookup. It tries to use the member
1438 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1439 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1440 /// our return value will already contain all inherited members and the caller don't need
1441 /// to check base classes and interfaces anymore.
1443 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1444 string name, out bool used_cache)
1447 // We have to take care of arrays specially, because GetType on
1448 // a TypeBuilder array will return a Type, not a TypeBuilder,
1449 // and we can not call FindMembers on this type.
1451 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1453 return TypeHandle.ArrayType.MemberCache.FindMembers (
1454 mt, bf, name, FilterWithClosure_delegate, null);
1458 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1459 // and we can ask the DeclSpace for the MemberCache.
1461 if (t is TypeBuilder) {
1462 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1463 MemberCache cache = decl.MemberCache;
1466 // If this DeclSpace has a MemberCache, use it.
1469 if (cache != null) {
1471 return cache.FindMembers (
1472 mt, bf, name, FilterWithClosure_delegate, null);
1475 // If there is no MemberCache, we need to use the "normal" FindMembers.
1476 // Note, this is a VERY uncommon route!
1479 Timer.StartTimer (TimerType.FindMembers);
1480 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1481 FilterWithClosure_delegate, name);
1482 Timer.StopTimer (TimerType.FindMembers);
1484 return (MemberInfo []) list;
1487 if (t is GenericTypeParameterBuilder) {
1488 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1491 Timer.StartTimer (TimerType.FindMembers);
1492 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1493 FilterWithClosure_delegate, name);
1494 Timer.StopTimer (TimerType.FindMembers);
1496 return (MemberInfo []) list;
1500 // This call will always succeed. There is exactly one TypeHandle instance per
1501 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1502 // if it didn't already exist.
1504 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1507 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1510 public static bool IsBuiltinType (Type t)
1512 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1513 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1514 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1515 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1521 public static bool IsBuiltinType (TypeContainer tc)
1523 return IsBuiltinType (tc.TypeBuilder);
1527 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1528 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1530 public static bool IsCLRType (Type t)
1532 if (t == object_type || t == int32_type || t == uint32_type ||
1533 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1534 t == char_type || t == short_type || t == bool_type ||
1535 t == sbyte_type || t == byte_type || t == ushort_type)
1541 public static bool IsDelegateType (Type t)
1543 if (t.IsGenericInstance)
1544 t = t.GetGenericTypeDefinition ();
1546 if (t.IsSubclassOf (TypeManager.delegate_type))
1552 public static bool IsEnumType (Type t)
1554 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1559 public static bool IsBuiltinOrEnum (Type t)
1561 if (IsBuiltinType (t))
1571 // Only a quick hack to get things moving, while real runtime support appears
1573 public static bool IsGeneric (Type t)
1575 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1577 return ds.IsGeneric;
1580 public static bool HasGenericArguments (Type t)
1582 return GetNumberOfTypeArguments (t) > 0;
1585 public static int GetNumberOfTypeArguments (Type t)
1587 DeclSpace tc = LookupDeclSpace (t);
1589 return tc.IsGeneric ? tc.CountTypeParameters : 0;
1591 return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1594 public static Type[] GetTypeArguments (Type t)
1596 DeclSpace tc = LookupDeclSpace (t);
1599 throw new InvalidOperationException ();
1601 TypeParameter[] tparam = tc.TypeParameters;
1602 Type[] ret = new Type [tparam.Length];
1603 for (int i = 0; i < tparam.Length; i++) {
1604 ret [i] = tparam [i].Type;
1605 if (ret [i] == null)
1606 throw new InternalErrorException ();
1611 return t.GetGenericArguments ();
1615 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1617 public static bool IsUnmanagedType (Type t)
1619 if (IsBuiltinType (t) && t != TypeManager.string_type)
1628 if (IsValueType (t)){
1629 if (t is TypeBuilder){
1630 TypeContainer tc = LookupTypeContainer (t);
1632 if (tc.Fields != null){
1633 foreach (Field f in tc.Fields){
1634 if (f.FieldBuilder.IsStatic)
1636 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1642 FieldInfo [] fields = t.GetFields ();
1644 foreach (FieldInfo f in fields){
1647 if (!IsUnmanagedType (f.FieldType))
1657 public static bool IsValueType (Type t)
1659 return t.IsGenericParameter || t.IsValueType;
1662 public static bool IsInterfaceType (Type t)
1664 Interface iface = builder_to_declspace [t] as Interface;
1672 public static bool IsEqualGenericType (Type a, Type b)
1674 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1676 // `a' is a generic type definition's TypeBuilder and `b' is a
1677 // generic instance of the same type.
1683 // void Test (Stack<T> stack) { }
1686 // The first argument of `Test' will be the generic instance
1687 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1689 if (a != b.GetGenericTypeDefinition ())
1692 Type[] aparams = a.GetGenericArguments ();
1693 Type[] bparams = b.GetGenericArguments ();
1695 if (aparams.Length != bparams.Length)
1698 for (int i = 0; i < aparams.Length; i++)
1699 if (!aparams [i].Equals (bparams [i]))
1708 public static bool IsEqual (Type a, Type b)
1713 return IsEqualGenericType (a, b);
1716 public static bool MayBecomeEqualGenericTypes (Type a, Type b)
1718 if (a.IsGenericParameter) {
1720 // If a is an array of a's type, they may never
1724 b = b.GetElementType ();
1730 // If b is a generic parameter or an actual type,
1731 // they may become equal:
1733 // class X<T,U> : I<T>, I<U>
1734 // class X<T> : I<T>, I<float>
1736 if (b.IsGenericParameter || !b.IsGenericInstance)
1740 // We're now comparing a type parameter with a
1741 // generic instance. They may become equal unless
1742 // the type parameter appears anywhere in the
1743 // generic instance:
1745 // class X<T,U> : I<T>, I<X<U>>
1746 // -> error because you could instanciate it as
1749 // class X<T> : I<T>, I<X<T>> -> ok
1752 Type[] bargs = GetTypeArguments (b);
1753 for (int i = 0; i < bargs.Length; i++) {
1754 if (a.Equals (bargs [i]))
1761 if (b.IsGenericParameter)
1762 return MayBecomeEqualGenericTypes (b, a);
1765 // At this point, neither a nor b are a type parameter.
1767 // If one of them is a generic instance, let
1768 // MayBecomeEqualGenericInstances() compare them (if the
1769 // other one is not a generic instance, they can never
1773 if (a.IsGenericInstance || b.IsGenericInstance)
1774 return MayBecomeEqualGenericInstances (a, b);
1777 // If both of them are arrays.
1780 if (a.IsArray && b.IsArray) {
1781 if (a.GetArrayRank () != b.GetArrayRank ())
1784 a = a.GetElementType ();
1785 b = b.GetElementType ();
1787 return MayBecomeEqualGenericTypes (a, b);
1791 // Ok, two ordinary types.
1794 return a.Equals (b);
1798 // Checks whether two generic instances may become equal for some
1799 // particular instantiation (26.3.1).
1801 public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1803 if (!a.IsGenericInstance || !b.IsGenericInstance)
1805 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1808 Type[] aargs = GetTypeArguments (a);
1809 Type[] bargs = GetTypeArguments (b);
1811 if (aargs.Length != bargs.Length)
1814 for (int i = 0; i < aargs.Length; i++) {
1815 if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1822 public static bool IsSubclassOf (Type type, Type parent)
1824 if (type.IsGenericInstance && !parent.IsGenericInstance)
1825 type = type.GetGenericTypeDefinition ();
1827 return type.IsSubclassOf (parent);
1831 // Checks whether `type' is a subclass or nested child of `parent'.
1833 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1836 if ((type == parent) || type.IsSubclassOf (parent) ||
1837 IsEqualGenericType (type, parent))
1840 // Handle nested types.
1841 type = type.DeclaringType;
1842 } while (type != null);
1848 // Checks whether `type' is a nested child of `parent'.
1850 public static bool IsNestedChildOf (Type type, Type parent)
1855 type = type.DeclaringType;
1856 while (type != null) {
1860 type = type.DeclaringType;
1867 // Do the right thing when returning the element type of an
1868 // array type based on whether we are compiling corlib or not
1870 public static Type GetElementType (Type t)
1872 if (RootContext.StdLib)
1873 return t.GetElementType ();
1875 return TypeToCoreType (t.GetElementType ());
1879 /// Returns the User Defined Types
1881 public static ArrayList UserTypes {
1887 public static Hashtable TypeContainers {
1889 return typecontainers;
1893 static Hashtable builder_to_constant;
1895 public static void RegisterConstant (FieldBuilder fb, Const c)
1897 if (builder_to_constant == null)
1898 builder_to_constant = new PtrHashtable ();
1900 if (builder_to_constant.Contains (fb))
1903 builder_to_constant.Add (fb, c);
1906 public static Const LookupConstant (FieldBuilder fb)
1908 if (builder_to_constant == null)
1911 return (Const) builder_to_constant [fb];
1915 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1919 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1920 /// for anything which is dynamic, and we need this in a number of places,
1921 /// we register this information here, and use it afterwards.
1923 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1928 method_arguments.Add (mb, args);
1929 method_internal_params.Add (mb, ip);
1934 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1936 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1939 if (method_internal_params.Contains (mb))
1940 return (InternalParameters) method_internal_params [mb];
1942 throw new Exception ("Argument for Method not registered" + mb);
1946 /// Returns the argument types for a method based on its methodbase
1948 /// For dynamic methods, we use the compiler provided types, for
1949 /// methods from existing assemblies we load them from GetParameters,
1950 /// and insert them into the cache
1952 static public Type [] GetArgumentTypes (MethodBase mb)
1954 if (method_arguments.Contains (mb))
1955 return (Type []) method_arguments [mb];
1957 ParameterInfo [] pi = mb.GetParameters ();
1959 Type [] types = new Type [c];
1961 for (int i = 0; i < c; i++)
1962 types [i] = pi [i].ParameterType;
1964 method_arguments.Add (mb, types);
1970 /// Returns the argument types for an indexer based on its PropertyInfo
1972 /// For dynamic indexers, we use the compiler provided types, for
1973 /// indexers from existing assemblies we load them from GetParameters,
1974 /// and insert them into the cache
1976 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1978 if (indexer_arguments.Contains (indexer))
1979 return (Type []) indexer_arguments [indexer];
1980 else if (indexer is PropertyBuilder)
1981 // If we're a PropertyBuilder and not in the
1982 // `indexer_arguments' hash, then we're a property and
1986 ParameterInfo [] pi = indexer.GetIndexParameters ();
1987 // Property, not an indexer.
1991 Type [] types = new Type [c];
1993 for (int i = 0; i < c; i++)
1994 types [i] = pi [i].ParameterType;
1996 indexer_arguments.Add (indexer, types);
2002 // This is a workaround the fact that GetValue is not
2003 // supported for dynamic types
2005 static Hashtable fields = new Hashtable ();
2006 static public bool RegisterFieldValue (FieldBuilder fb, object value)
2008 if (fields.Contains (fb))
2011 fields.Add (fb, value);
2016 static public object GetValue (FieldBuilder fb)
2021 static Hashtable fieldbuilders_to_fields = new Hashtable ();
2022 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2024 if (fieldbuilders_to_fields.Contains (fb))
2027 fieldbuilders_to_fields.Add (fb, f);
2032 // The return value can be null; This will be the case for
2033 // auxiliary FieldBuilders created by the compiler that have no
2034 // real field being declared on the source code
2036 static public FieldBase GetField (FieldInfo fb)
2038 return (FieldBase) fieldbuilders_to_fields [fb];
2041 static Hashtable events;
2043 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2046 events = new Hashtable ();
2048 if (events.Contains (eb))
2051 events.Add (eb, new Pair (add, remove));
2056 static public MethodInfo GetAddMethod (EventInfo ei)
2058 if (ei is MyEventBuilder) {
2059 Pair pair = (Pair) events [ei];
2061 return (MethodInfo) pair.First;
2063 return ei.GetAddMethod ();
2066 static public MethodInfo GetRemoveMethod (EventInfo ei)
2068 if (ei is MyEventBuilder) {
2069 Pair pair = (Pair) events [ei];
2071 return (MethodInfo) pair.Second;
2073 return ei.GetRemoveMethod ();
2076 static Hashtable priv_fields_events;
2078 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2080 if (priv_fields_events == null)
2081 priv_fields_events = new Hashtable ();
2083 if (priv_fields_events.Contains (einfo))
2086 priv_fields_events.Add (einfo, builder);
2091 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2093 if (priv_fields_events == null)
2096 return (MemberInfo) priv_fields_events [ei];
2099 static Hashtable properties;
2101 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2103 if (properties == null)
2104 properties = new Hashtable ();
2106 if (properties.Contains (pb))
2109 properties.Add (pb, new Pair (get, set));
2114 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2115 MethodBase set, Type[] args)
2117 if (!RegisterProperty (pb, get,set))
2120 indexer_arguments.Add (pb, args);
2125 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2127 Hashtable hash = new Hashtable ();
2128 return CheckStructCycles (tc, seen, hash);
2131 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2134 if (!(tc is Struct) || IsBuiltinType (tc))
2138 // `seen' contains all types we've already visited.
2140 if (seen.Contains (tc))
2142 seen.Add (tc, null);
2144 if (tc.Fields == null)
2147 foreach (Field field in tc.Fields) {
2148 if (field.FieldBuilder.IsStatic)
2151 Type ftype = field.FieldBuilder.FieldType;
2152 TypeContainer ftc = LookupTypeContainer (ftype);
2156 if (hash.Contains (ftc)) {
2157 Report.Error (523, tc.Location,
2158 "Struct member `{0}.{1}' of type `{2}' " +
2159 "causes a cycle in the struct layout",
2160 tc.Name, field.Name, ftc.Name);
2165 // `hash' contains all types in the current path.
2167 hash.Add (tc, null);
2169 bool ok = CheckStructCycles (ftc, seen, hash);
2176 if (!seen.Contains (ftc))
2177 seen.Add (ftc, null);
2184 /// Given an array of interface types, expand and eliminate repeated ocurrences
2185 /// of an interface.
2189 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2192 public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
2194 ArrayList new_ifaces = new ArrayList ();
2196 foreach (TypeExpr iface in base_interfaces){
2197 if (!new_ifaces.Contains (iface))
2198 new_ifaces.Add (iface);
2200 TypeExpr [] implementing = iface.GetInterfaces ();
2202 foreach (TypeExpr imp in implementing){
2203 if (!new_ifaces.Contains (imp))
2204 new_ifaces.Add (imp);
2207 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
2208 new_ifaces.CopyTo (ret, 0);
2212 static PtrHashtable iface_cache = new PtrHashtable ();
2215 /// This function returns the interfaces in the type `t'. Works with
2216 /// both types and TypeBuilders.
2218 public static TypeExpr [] GetInterfaces (Type t)
2221 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
2226 // The reason for catching the Array case is that Reflection.Emit
2227 // will not return a TypeBuilder for Array types of TypeBuilder types,
2228 // but will still throw an exception if we try to call GetInterfaces
2231 // Since the array interfaces are always constant, we return those for
2236 t = TypeManager.array_type;
2238 if (t is TypeBuilder){
2239 TypeExpr [] parent_ifaces;
2241 if (t.BaseType == null)
2242 parent_ifaces = NoTypeExprs;
2244 parent_ifaces = GetInterfaces (t.BaseType);
2245 TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2246 if (type_ifaces == null)
2247 type_ifaces = NoTypeExprs;
2249 int parent_count = parent_ifaces.Length;
2250 TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2251 parent_ifaces.CopyTo (result, 0);
2252 type_ifaces.CopyTo (result, parent_count);
2254 iface_cache [t] = result;
2256 } else if (t is GenericTypeParameterBuilder){
2257 TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2258 if (type_ifaces == null)
2259 type_ifaces = NoTypeExprs;
2261 iface_cache [t] = type_ifaces;
2264 Type [] ifaces = t.GetInterfaces ();
2265 if (ifaces.Length == 0)
2268 TypeExpr [] result = new TypeExpr [ifaces.Length];
2269 for (int i = 0; i < ifaces.Length; i++)
2270 result [i] = new TypeExpression (ifaces [i], Location.Null);
2272 iface_cache [t] = result;
2278 // gets the interfaces that are declared explicitly on t
2280 public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2282 return (TypeExpr []) builder_to_ifaces [t];
2286 /// The following is used to check if a given type implements an interface.
2287 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2289 public static bool ImplementsInterface (Type t, Type iface)
2291 TypeExpr [] interfaces;
2294 // FIXME OPTIMIZATION:
2295 // as soon as we hit a non-TypeBuiler in the interface
2296 // chain, we could return, as the `Type.GetInterfaces'
2297 // will return all the interfaces implement by the type
2301 interfaces = GetInterfaces (t);
2303 if (interfaces != null){
2304 foreach (TypeExpr i in interfaces){
2305 if (i.Type == iface)
2311 } while (t != null);
2316 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2318 // This is a custom version of Convert.ChangeType() which works
2319 // with the TypeBuilder defined types when compiling corlib.
2320 public static object ChangeType (object value, Type conversionType, out bool error)
2322 IConvertible convert_value = value as IConvertible;
2324 if (convert_value == null){
2330 // We must use Type.Equals() here since `conversionType' is
2331 // the TypeBuilder created version of a system type and not
2332 // the system type itself. You cannot use Type.GetTypeCode()
2333 // on such a type - it'd always return TypeCode.Object.
2337 if (conversionType.Equals (typeof (Boolean)))
2338 return (object)(convert_value.ToBoolean (nf_provider));
2339 else if (conversionType.Equals (typeof (Byte)))
2340 return (object)(convert_value.ToByte (nf_provider));
2341 else if (conversionType.Equals (typeof (Char)))
2342 return (object)(convert_value.ToChar (nf_provider));
2343 else if (conversionType.Equals (typeof (DateTime)))
2344 return (object)(convert_value.ToDateTime (nf_provider));
2345 else if (conversionType.Equals (typeof (Decimal)))
2346 return (object)(convert_value.ToDecimal (nf_provider));
2347 else if (conversionType.Equals (typeof (Double)))
2348 return (object)(convert_value.ToDouble (nf_provider));
2349 else if (conversionType.Equals (typeof (Int16)))
2350 return (object)(convert_value.ToInt16 (nf_provider));
2351 else if (conversionType.Equals (typeof (Int32)))
2352 return (object)(convert_value.ToInt32 (nf_provider));
2353 else if (conversionType.Equals (typeof (Int64)))
2354 return (object)(convert_value.ToInt64 (nf_provider));
2355 else if (conversionType.Equals (typeof (SByte)))
2356 return (object)(convert_value.ToSByte (nf_provider));
2357 else if (conversionType.Equals (typeof (Single)))
2358 return (object)(convert_value.ToSingle (nf_provider));
2359 else if (conversionType.Equals (typeof (String)))
2360 return (object)(convert_value.ToString (nf_provider));
2361 else if (conversionType.Equals (typeof (UInt16)))
2362 return (object)(convert_value.ToUInt16 (nf_provider));
2363 else if (conversionType.Equals (typeof (UInt32)))
2364 return (object)(convert_value.ToUInt32 (nf_provider));
2365 else if (conversionType.Equals (typeof (UInt64)))
2366 return (object)(convert_value.ToUInt64 (nf_provider));
2367 else if (conversionType.Equals (typeof (Object)))
2368 return (object)(value);
2378 // This is needed, because enumerations from assemblies
2379 // do not report their underlyingtype, but they report
2382 public static Type EnumToUnderlying (Type t)
2384 if (t == TypeManager.enum_type)
2387 t = t.UnderlyingSystemType;
2388 if (!TypeManager.IsEnumType (t))
2391 if (t is TypeBuilder) {
2392 // slow path needed to compile corlib
2393 if (t == TypeManager.bool_type ||
2394 t == TypeManager.byte_type ||
2395 t == TypeManager.sbyte_type ||
2396 t == TypeManager.char_type ||
2397 t == TypeManager.short_type ||
2398 t == TypeManager.ushort_type ||
2399 t == TypeManager.int32_type ||
2400 t == TypeManager.uint32_type ||
2401 t == TypeManager.int64_type ||
2402 t == TypeManager.uint64_type)
2404 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2406 TypeCode tc = Type.GetTypeCode (t);
2409 case TypeCode.Boolean:
2410 return TypeManager.bool_type;
2412 return TypeManager.byte_type;
2413 case TypeCode.SByte:
2414 return TypeManager.sbyte_type;
2416 return TypeManager.char_type;
2417 case TypeCode.Int16:
2418 return TypeManager.short_type;
2419 case TypeCode.UInt16:
2420 return TypeManager.ushort_type;
2421 case TypeCode.Int32:
2422 return TypeManager.int32_type;
2423 case TypeCode.UInt32:
2424 return TypeManager.uint32_type;
2425 case TypeCode.Int64:
2426 return TypeManager.int64_type;
2427 case TypeCode.UInt64:
2428 return TypeManager.uint64_type;
2430 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2434 // When compiling corlib and called with one of the core types, return
2435 // the corresponding typebuilder for that type.
2437 public static Type TypeToCoreType (Type t)
2439 if (RootContext.StdLib || (t is TypeBuilder))
2442 TypeCode tc = Type.GetTypeCode (t);
2445 case TypeCode.Boolean:
2446 return TypeManager.bool_type;
2448 return TypeManager.byte_type;
2449 case TypeCode.SByte:
2450 return TypeManager.sbyte_type;
2452 return TypeManager.char_type;
2453 case TypeCode.Int16:
2454 return TypeManager.short_type;
2455 case TypeCode.UInt16:
2456 return TypeManager.ushort_type;
2457 case TypeCode.Int32:
2458 return TypeManager.int32_type;
2459 case TypeCode.UInt32:
2460 return TypeManager.uint32_type;
2461 case TypeCode.Int64:
2462 return TypeManager.int64_type;
2463 case TypeCode.UInt64:
2464 return TypeManager.uint64_type;
2465 case TypeCode.Single:
2466 return TypeManager.float_type;
2467 case TypeCode.Double:
2468 return TypeManager.double_type;
2469 case TypeCode.String:
2470 return TypeManager.string_type;
2472 if (t == typeof (void))
2473 return TypeManager.void_type;
2474 if (t == typeof (object))
2475 return TypeManager.object_type;
2476 if (t == typeof (System.Type))
2477 return TypeManager.type_type;
2478 if (t == typeof (System.IntPtr))
2479 return TypeManager.intptr_type;
2485 /// Utility function that can be used to probe whether a type
2486 /// is managed or not.
2488 public static bool VerifyUnManaged (Type t, Location loc)
2490 if (t.IsValueType || t.IsPointer){
2492 // FIXME: this is more complex, we actually need to
2493 // make sure that the type does not contain any
2499 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2500 // We need this explicit check here to make it work when
2501 // compiling corlib.
2506 "Cannot take the address or size of a variable of a managed type ('" +
2507 CSharpName (t) + "')");
2512 /// Returns the name of the indexer in a given type.
2515 /// The default is not always `Item'. The user can change this behaviour by
2516 /// using the DefaultMemberAttribute in the class.
2518 /// For example, the String class indexer is named `Chars' not `Item'
2520 public static string IndexerPropertyName (Type t)
2522 if (t.IsGenericInstance)
2523 t = t.GetGenericTypeDefinition ();
2525 if (t is TypeBuilder) {
2526 if (t.IsInterface) {
2527 Interface i = LookupInterface (t);
2529 if ((i == null) || (i.IndexerName == null))
2532 return i.IndexerName;
2534 TypeContainer tc = LookupTypeContainer (t);
2536 if ((tc == null) || (tc.IndexerName == null))
2539 return tc.IndexerName;
2543 System.Attribute attr = System.Attribute.GetCustomAttribute (
2544 t, TypeManager.default_member_type);
2546 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2547 return dma.MemberName;
2553 static MethodInfo pinned_method = null;
2554 public static void MakePinned (LocalBuilder builder)
2556 if (pinned_method == null) {
2557 pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
2558 if (pinned_method == null) {
2559 Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
2560 "This code may cause errors on a runtime with a moving GC");
2566 pinned_method.Invoke (builder, null);
2571 // Returns whether the array of memberinfos contains the given method
2573 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2575 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2577 foreach (MethodBase method in array) {
2578 if (method.Name != new_method.Name)
2581 if (method is MethodInfo && new_method is MethodInfo)
2582 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2586 Type [] old_args = TypeManager.GetArgumentTypes (method);
2587 int old_count = old_args.Length;
2590 if (new_args.Length != old_count)
2593 for (i = 0; i < old_count; i++){
2594 if (old_args [i] != new_args [i])
2607 // We copy methods from `new_members' into `target_list' if the signature
2608 // for the method from in the new list does not exist in the target_list
2610 // The name is assumed to be the same.
2612 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2614 if (target_list == null){
2615 target_list = new ArrayList ();
2617 foreach (MemberInfo mi in new_members){
2618 if (mi is MethodBase)
2619 target_list.Add (mi);
2624 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2625 target_list.CopyTo (target_array, 0);
2627 foreach (MemberInfo mi in new_members){
2628 MethodBase new_method = (MethodBase) mi;
2630 if (!ArrayContainsMethod (target_array, new_method))
2631 target_list.Add (new_method);
2637 public enum MethodFlags {
2638 ShouldIgnore = 1 << 2
2641 static public bool IsGenericMethod (MethodBase mb)
2643 if (mb.DeclaringType is TypeBuilder) {
2644 MethodData method = (MethodData) builder_to_method [mb];
2648 return method.GenericMethod != null;
2651 return mb.IsGenericMethodDefinition;
2655 // Returns the TypeManager.MethodFlags for this method.
2656 // This emits an error 619 / warning 618 if the method is obsolete.
2657 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2659 static public MethodFlags GetMethodFlags (MethodBase mb)
2661 MethodFlags flags = 0;
2663 if (mb.Mono_IsInflatedMethod)
2664 mb = mb.GetGenericMethodDefinition ();
2666 if (mb.DeclaringType is TypeBuilder){
2667 IMethodData method = (IMethodData) builder_to_method [mb];
2668 if (method == null) {
2669 // FIXME: implement Obsolete attribute on Property,
2670 // Indexer and Event.
2674 if (method.ShouldIgnore ())
2675 flags |= MethodFlags.ShouldIgnore;
2680 object [] attrs = mb.GetCustomAttributes (true);
2681 foreach (object ta in attrs){
2682 if (!(ta is System.Attribute)){
2683 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2686 System.Attribute a = (System.Attribute) ta;
2689 // Skip over conditional code.
2691 if (a.TypeId == TypeManager.conditional_attribute_type){
2692 ConditionalAttribute ca = (ConditionalAttribute) a;
2694 if (RootContext.AllDefines [ca.ConditionString] == null)
2695 flags |= MethodFlags.ShouldIgnore;
2702 #region MemberLookup implementation
2705 // Whether we allow private members in the result (since FindMembers
2706 // uses NonPublic for both protected and private), we need to distinguish.
2708 static bool closure_private_ok;
2711 // Who is invoking us and which type is being queried currently.
2713 static Type closure_invocation_type;
2714 static Type closure_qualifier_type;
2717 // The assembly that defines the type is that is calling us
2719 static Assembly closure_invocation_assembly;
2721 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2727 // This filter filters by name + whether it is ok to include private
2728 // members in the search
2730 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2733 // Hack: we know that the filter criteria will always be in the `closure'
2737 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2740 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2741 (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
2745 // Ugly: we need to find out the type of `m', and depending
2746 // on this, tell whether we accept or not
2748 if (m is MethodBase){
2749 MethodBase mb = (MethodBase) m;
2750 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2752 if (ma == MethodAttributes.Private)
2753 return closure_private_ok ||
2754 IsEqual (closure_invocation_type, m.DeclaringType) ||
2755 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2758 // FamAndAssem requires that we not only derivate, but we are on the
2761 if (ma == MethodAttributes.FamANDAssem){
2762 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2766 // Assembly and FamORAssem succeed if we're in the same assembly.
2767 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2768 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2772 // We already know that we aren't in the same assembly.
2773 if (ma == MethodAttributes.Assembly)
2776 // Family and FamANDAssem require that we derive.
2777 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2778 if (closure_invocation_type == null)
2781 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2784 // Although a derived class can access protected members of its base class
2785 // it cannot do so through an instance of the base class (CS1540).
2786 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2787 (closure_qualifier_type != null) &&
2788 closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2789 !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2799 if (m is FieldInfo){
2800 FieldInfo fi = (FieldInfo) m;
2801 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2803 if (fa == FieldAttributes.Private)
2804 return closure_private_ok ||
2805 IsEqual (closure_invocation_type, m.DeclaringType) ||
2806 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2809 // FamAndAssem requires that we not only derivate, but we are on the
2812 if (fa == FieldAttributes.FamANDAssem){
2813 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2817 // Assembly and FamORAssem succeed if we're in the same assembly.
2818 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2819 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2823 // We already know that we aren't in the same assembly.
2824 if (fa == FieldAttributes.Assembly)
2827 // Family and FamANDAssem require that we derive.
2828 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2829 if (closure_invocation_type == null)
2832 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2835 // Although a derived class can access protected members of its base class
2836 // it cannot do so through an instance of the base class (CS1540).
2837 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2838 (closure_qualifier_type != null) &&
2839 closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
2840 !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
2851 // EventInfos and PropertyInfos, return true because they lack permission
2852 // informaiton, so we need to check later on the methods.
2857 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2858 static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2861 // Looks up a member called `name' in the `queried_type'. This lookup
2862 // is done by code that is contained in the definition for `invocation_type'
2863 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2865 // `invocation_type' is used to check whether we're allowed to access the requested
2866 // member wrt its protection level.
2868 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2869 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2870 // is B and qualifier_type is A). This is used to do the CS1540 check.
2872 // When resolving a SimpleName, `qualifier_type' is null.
2874 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2875 // the same than `queried_type' - except when we're being called from BaseAccess;
2876 // in this case, `invocation_type' is the current type and `queried_type' the base
2877 // type, so this'd normally trigger a CS1540.
2879 // The binding flags are `bf' and the kind of members being looked up are `mt'
2881 // The return value always includes private members which code in `invocation_type'
2882 // is allowed to access (using the specified `qualifier_type' if given); only use
2883 // BindingFlags.NonPublic to bypass the permission check.
2885 // Returns an array of a single element for everything but Methods/Constructors
2886 // that might return multiple matches.
2888 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2889 Type queried_type, MemberTypes mt,
2890 BindingFlags original_bf, string name)
2892 Timer.StartTimer (TimerType.MemberLookup);
2894 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2895 queried_type, mt, original_bf, name);
2897 Timer.StopTimer (TimerType.MemberLookup);
2902 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2903 Type queried_type, MemberTypes mt,
2904 BindingFlags original_bf, string name)
2906 BindingFlags bf = original_bf;
2908 ArrayList method_list = null;
2909 Type current_type = queried_type;
2910 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2911 bool skip_iface_check = true, used_cache = false;
2912 bool always_ok_flag = false;
2914 closure_invocation_type = invocation_type;
2915 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2916 closure_qualifier_type = qualifier_type;
2919 // If we are a nested class, we always have access to our container
2922 if (invocation_type != null){
2923 string invocation_name = invocation_type.FullName;
2924 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
2925 string container = queried_type.FullName + "+";
2926 int container_length = container.Length;
2928 if (invocation_name.Length > container_length){
2929 string shared = invocation_name.Substring (0, container_length);
2931 if (shared == container)
2932 always_ok_flag = true;
2937 // This is from the first time we find a method
2938 // in most cases, we do not actually find a method in the base class
2939 // so we can just ignore it, and save the arraylist allocation
2940 MemberInfo [] first_members_list = null;
2941 bool use_first_members_list = false;
2947 // `NonPublic' is lame, because it includes both protected and
2948 // private methods, so we need to control this behavior by
2949 // explicitly tracking if a private method is ok or not.
2951 // The possible cases are:
2952 // public, private and protected (internal does not come into the
2955 if ((invocation_type != null) &&
2956 ((invocation_type == current_type) ||
2957 IsNestedChildOf (invocation_type, current_type)) ||
2959 bf = original_bf | BindingFlags.NonPublic;
2963 closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2965 Timer.StopTimer (TimerType.MemberLookup);
2967 list = MemberLookup_FindMembers (
2968 current_type, mt, bf, name, out used_cache);
2970 Timer.StartTimer (TimerType.MemberLookup);
2973 // When queried for an interface type, the cache will automatically check all
2974 // inherited members, so we don't need to do this here. However, this only
2975 // works if we already used the cache in the first iteration of this loop.
2977 // If we used the cache in any further iteration, we can still terminate the
2978 // loop since the cache always looks in all parent classes.
2984 skip_iface_check = false;
2986 if (current_type == TypeManager.object_type)
2989 current_type = current_type.BaseType;
2992 // This happens with interfaces, they have a null
2993 // basetype. Look members up in the Object class.
2995 if (current_type == null)
2996 current_type = TypeManager.object_type;
2999 if (list.Length == 0)
3003 // Events and types are returned by both `static' and `instance'
3004 // searches, which means that our above FindMembers will
3005 // return two copies of the same.
3007 if (list.Length == 1 && !(list [0] is MethodBase)){
3012 // Multiple properties: we query those just to find out the indexer
3015 if (list [0] is PropertyInfo)
3019 // We found an event: the cache lookup returns both the event and
3020 // its private field.
3022 if (list [0] is EventInfo) {
3023 if ((list.Length == 2) && (list [1] is FieldInfo))
3024 return new MemberInfo [] { list [0] };
3031 // We found methods, turn the search into "method scan"
3035 if (first_members_list != null) {
3036 if (use_first_members_list) {
3037 method_list = CopyNewMethods (method_list, first_members_list);
3038 use_first_members_list = false;
3041 method_list = CopyNewMethods (method_list, list);
3043 first_members_list = list;
3044 use_first_members_list = true;
3046 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3048 } while (searching);
3050 if (use_first_members_list) {
3051 foreach (MemberInfo mi in first_members_list) {
3052 if (! (mi is MethodBase)) {
3053 method_list = CopyNewMethods (method_list, first_members_list);
3054 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3057 return (MemberInfo []) first_members_list;
3060 if (method_list != null && method_list.Count > 0) {
3061 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3064 // This happens if we already used the cache in the first iteration, in this case
3065 // the cache already looked in all interfaces.
3067 if (skip_iface_check)
3071 // Interfaces do not list members they inherit, so we have to
3074 if (!queried_type.IsInterface)
3077 if (queried_type.IsArray)
3078 queried_type = TypeManager.array_type;
3080 TypeExpr [] ifaces = GetInterfaces (queried_type);
3084 foreach (TypeExpr itype in ifaces){
3087 x = MemberLookup (null, null, itype.Type, mt, bf, name);
3096 // This is used to extract properties and event declarations from a type
3098 static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
3100 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
3102 bf |= BindingFlags.Public | BindingFlags.NonPublic;
3104 if (t is TypeBuilder) {
3105 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
3107 return (MemberInfo []) decl.FindMembers (
3108 MemberTypes.Property | MemberTypes.Event,
3109 bf, FilterNone_delegate, null);
3111 return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
3112 bf, FilterNone_delegate, null);
3117 public static bool IsSpecialMethod (MethodBase mb)
3119 Type t = mb.DeclaringType;
3121 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
3122 if (matches == null)
3125 foreach (MemberInfo mi in matches){
3126 if (mi is PropertyBuilder){
3127 Pair p = (Pair) properties [mi];
3129 if (p.First == mb || p.Second == mb)
3131 } else if (mi is PropertyInfo){
3132 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
3134 foreach (MethodInfo m in methods){
3138 } else if (mi is MyEventBuilder){
3139 Pair p = (Pair) events [mi];
3141 if (p.First == mb || p.Second == mb)
3143 } else if (mi is EventInfo){
3144 EventInfo ei = ((EventInfo) mi);
3146 if (ei.GetAddMethod (true) == mb)
3149 if (ei.GetRemoveMethod (true) == mb)
3152 if (ei.GetRaiseMethod (true) == mb)
3158 // Now check if it is an operator method
3162 if (s.StartsWith ("op_")){
3163 foreach (string name in Unary.oper_names){
3168 foreach (string name in Binary.oper_names){
3182 /// There is exactly one instance of this class per type.
3184 public sealed class TypeHandle : IMemberContainer {
3185 public readonly TypeHandle BaseType;
3187 readonly int id = ++next_id;
3188 static int next_id = 0;
3191 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3192 /// a TypeHandle yet, a new instance of it is created. This static method
3193 /// ensures that we'll only have one TypeHandle instance per type.
3195 public static TypeHandle GetTypeHandle (Type t)
3197 TypeHandle handle = (TypeHandle) type_hash [t];
3201 handle = new TypeHandle (t);
3202 type_hash.Add (t, handle);
3206 public static void CleanUp ()
3212 /// Returns the TypeHandle for TypeManager.object_type.
3214 public static IMemberContainer ObjectType {
3216 if (object_type != null)
3219 object_type = GetTypeHandle (TypeManager.object_type);
3226 /// Returns the TypeHandle for TypeManager.array_type.
3228 public static IMemberContainer ArrayType {
3230 if (array_type != null)
3233 array_type = GetTypeHandle (TypeManager.array_type);
3239 private static PtrHashtable type_hash = new PtrHashtable ();
3241 private static TypeHandle object_type = null;
3242 private static TypeHandle array_type = null;
3245 private string full_name;
3246 private bool is_interface;
3247 private MemberCache member_cache;
3249 private TypeHandle (Type type)
3252 full_name = type.FullName != null ? type.FullName : type.Name;
3253 if (type.BaseType != null)
3254 BaseType = GetTypeHandle (type.BaseType);
3255 this.is_interface = type.IsInterface || type.IsGenericParameter;
3256 this.member_cache = new MemberCache (this);
3259 // IMemberContainer methods
3261 public string Name {
3273 public IMemberContainer Parent {
3279 public bool IsInterface {
3281 return is_interface;
3285 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3287 MemberInfo [] members;
3288 if (type is GenericTypeParameterBuilder)
3289 return MemberList.Empty;
3290 if (mt == MemberTypes.Event)
3291 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3293 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3295 Array.Reverse (members);
3297 return new MemberList (members);
3300 // IMemberFinder methods
3302 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3303 MemberFilter filter, object criteria)
3305 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3308 public MemberCache MemberCache {
3310 return member_cache;
3314 public override string ToString ()
3316 if (BaseType != null)
3317 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3319 return "TypeHandle (" + id + "," + Name + ")";