2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static public Type uint32_type;
42 static public Type int64_type;
43 static public Type uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type sbyte_type;
52 static public Type byte_type;
53 static public Type ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type null_type;
59 static public Type enumeration_type;
60 static public Type array_type;
61 static public Type runtime_handle_type;
62 static public Type icloneable_type;
63 static public Type type_type;
64 static public Type ienumerator_type;
65 static public Type ienumerable_type;
66 static public Type idisposable_type;
67 static public Type iconvertible_type;
68 static public Type default_member_type;
69 static public Type iasyncresult_type;
70 static public Type asynccallback_type;
71 static public Type intptr_type;
72 static public Type monitor_type;
73 static public Type runtime_field_handle_type;
74 static public Type runtime_argument_handle_type;
75 static public Type attribute_type;
76 static public Type attribute_usage_type;
77 static public Type decimal_constant_attribute_type;
78 static public Type dllimport_type;
79 static public Type unverifiable_code_type;
80 static public Type methodimpl_attr_type;
81 static public Type marshal_as_attr_type;
82 static public Type new_constraint_attr_type;
83 static public Type param_array_type;
84 static public Type guid_attr_type;
85 static public Type void_ptr_type;
86 static public Type indexer_name_type;
87 static public Type exception_type;
88 static public Type activator_type;
89 static public Type invalid_operation_exception_type;
90 static public Type not_supported_exception_type;
91 static public Type obsolete_attribute_type;
92 static public Type conditional_attribute_type;
93 static public Type in_attribute_type;
94 static public Type anonymous_method_type;
95 static public Type cls_compliant_attribute_type;
96 static public Type typed_reference_type;
97 static public Type arg_iterator_type;
98 static public Type mbr_type;
99 static public Type struct_layout_attribute_type;
100 static public Type field_offset_attribute_type;
101 static public Type security_attr_type;
103 static public Type generic_ienumerator_type;
104 static public Type generic_ienumerable_type;
107 // An empty array of types
109 static public Type [] NoTypes;
110 static public TypeExpr [] NoTypeExprs;
114 // Expressions representing the internal types. Used during declaration
117 static public TypeExpr system_object_expr, system_string_expr;
118 static public TypeExpr system_boolean_expr, system_decimal_expr;
119 static public TypeExpr system_single_expr, system_double_expr;
120 static public TypeExpr system_sbyte_expr, system_byte_expr;
121 static public TypeExpr system_int16_expr, system_uint16_expr;
122 static public TypeExpr system_int32_expr, system_uint32_expr;
123 static public TypeExpr system_int64_expr, system_uint64_expr;
124 static public TypeExpr system_char_expr, system_void_expr;
125 static public TypeExpr system_asynccallback_expr;
126 static public TypeExpr system_iasyncresult_expr;
127 static public TypeExpr system_valuetype_expr;
128 static public TypeExpr system_intptr_expr;
131 // This is only used when compiling corlib
133 static public Type system_int32_type;
134 static public Type system_array_type;
135 static public Type system_type_type;
136 static public Type system_assemblybuilder_type;
137 static public MethodInfo system_int_array_get_length;
138 static public MethodInfo system_int_array_get_rank;
139 static public MethodInfo system_object_array_clone;
140 static public MethodInfo system_int_array_get_length_int;
141 static public MethodInfo system_int_array_get_lower_bound_int;
142 static public MethodInfo system_int_array_get_upper_bound_int;
143 static public MethodInfo system_void_array_copyto_array_int;
147 // Internal, not really used outside
149 static Type runtime_helpers_type;
152 // These methods are called by code generated by the compiler
154 static public MethodInfo string_concat_string_string;
155 static public MethodInfo string_concat_string_string_string;
156 static public MethodInfo string_concat_string_string_string_string;
157 static public MethodInfo string_concat_string_dot_dot_dot;
158 static public MethodInfo string_concat_object_object;
159 static public MethodInfo string_concat_object_object_object;
160 static public MethodInfo string_concat_object_dot_dot_dot;
161 static public MethodInfo string_isinterneted_string;
162 static public MethodInfo system_type_get_type_from_handle;
163 static public MethodInfo object_getcurrent_void;
164 static public MethodInfo bool_movenext_void;
165 static public MethodInfo ienumerable_getenumerator_void;
166 static public MethodInfo void_reset_void;
167 static public MethodInfo void_dispose_void;
168 static public MethodInfo void_monitor_enter_object;
169 static public MethodInfo void_monitor_exit_object;
170 static public MethodInfo void_initializearray_array_fieldhandle;
171 static public MethodInfo int_getlength_int;
172 static public MethodInfo delegate_combine_delegate_delegate;
173 static public MethodInfo delegate_remove_delegate_delegate;
174 static public MethodInfo int_get_offset_to_string_data;
175 static public MethodInfo int_array_get_length;
176 static public MethodInfo int_array_get_rank;
177 static public MethodInfo object_array_clone;
178 static public MethodInfo int_array_get_length_int;
179 static public MethodInfo int_array_get_lower_bound_int;
180 static public MethodInfo int_array_get_upper_bound_int;
181 static public MethodInfo void_array_copyto_array_int;
182 static public MethodInfo activator_create_instance;
185 // The attribute constructors.
187 static public ConstructorInfo object_ctor;
188 static public ConstructorInfo cons_param_array_attribute;
189 static public ConstructorInfo void_decimal_ctor_five_args;
190 static public ConstructorInfo void_decimal_ctor_int_arg;
191 static public ConstructorInfo unverifiable_code_ctor;
192 static public ConstructorInfo invalid_operation_ctor;
193 static public ConstructorInfo default_member_ctor;
194 static public ConstructorInfo decimal_constant_attribute_ctor;
197 // Holds the Array of Assemblies that have been loaded
198 // (either because it is the default or the user used the
199 // -r command line option)
201 static Assembly [] assemblies;
204 // Keeps a list of modules. We used this to do lookups
205 // on the module using GetType -- needed for arrays
207 static Module [] modules;
210 // This is the type_cache from the assemblies to avoid
211 // hitting System.Reflection on every lookup.
213 static Hashtable types;
216 // This is used to hotld the corresponding TypeContainer objects
217 // since we need this in FindMembers
219 static Hashtable typecontainers;
222 // Keeps track of those types that are defined by the
225 static ArrayList user_types;
227 static PtrHashtable builder_to_declspace;
229 static PtrHashtable builder_to_member_cache;
232 // Tracks the interfaces implemented by typebuilders. We only
233 // enter those who do implement or or more interfaces
235 static PtrHashtable builder_to_ifaces;
238 // Tracks the generic parameters.
240 static PtrHashtable builder_to_type_param;
243 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
244 // the arguments to the method
246 static Hashtable method_arguments;
249 // Maps PropertyBuilder to a Type array that contains
250 // the arguments to the indexer
252 static Hashtable indexer_arguments;
255 // Maybe `method_arguments' should be replaced and only
256 // method_internal_params should be kept?
258 static Hashtable method_internal_params;
261 // Keeps track of methods
264 static Hashtable builder_to_method;
267 // Contains all public types from referenced assemblies.
268 // This member is used only if CLS Compliance verification is required.
270 public static Hashtable all_imported_types;
277 public static void CleanUp ()
279 // Lets get everything clean so that we can collect before generating code
283 typecontainers = null;
285 builder_to_declspace = null;
286 builder_to_member_cache = null;
287 builder_to_ifaces = null;
288 method_arguments = null;
289 indexer_arguments = null;
290 method_internal_params = null;
291 builder_to_method = null;
292 builder_to_type_param = null;
296 negative_hits = null;
297 builder_to_constant = null;
298 fieldbuilders_to_fields = null;
300 priv_fields_events = null;
303 TypeHandle.CleanUp ();
307 /// A filter for Findmembers that uses the Signature object to
310 static bool SignatureFilter (MemberInfo mi, object criteria)
312 Signature sig = (Signature) criteria;
314 if (!(mi is MethodBase))
317 if (mi.Name != sig.name)
320 int count = sig.args.Length;
322 if (mi is MethodBuilder || mi is ConstructorBuilder){
323 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
325 if (candidate_args.Length != count)
328 for (int i = 0; i < count; i++)
329 if (candidate_args [i] != sig.args [i])
334 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
336 if (pars.Length != count)
339 for (int i = 0; i < count; i++)
340 if (pars [i].ParameterType != sig.args [i])
346 // A delegate that points to the filter above.
347 static MemberFilter signature_filter;
350 // These are expressions that represent some of the internal data types, used
353 static void InitExpressionTypes ()
355 system_object_expr = new TypeLookupExpression ("System.Object");
356 system_string_expr = new TypeLookupExpression ("System.String");
357 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
358 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
359 system_single_expr = new TypeLookupExpression ("System.Single");
360 system_double_expr = new TypeLookupExpression ("System.Double");
361 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
362 system_byte_expr = new TypeLookupExpression ("System.Byte");
363 system_int16_expr = new TypeLookupExpression ("System.Int16");
364 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
365 system_int32_expr = new TypeLookupExpression ("System.Int32");
366 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
367 system_int64_expr = new TypeLookupExpression ("System.Int64");
368 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
369 system_char_expr = new TypeLookupExpression ("System.Char");
370 system_void_expr = new TypeLookupExpression ("System.Void");
371 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
372 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
373 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
374 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
377 static TypeManager ()
379 assemblies = new Assembly [0];
381 user_types = new ArrayList ();
383 types = new Hashtable ();
384 typecontainers = new Hashtable ();
386 builder_to_declspace = new PtrHashtable ();
387 builder_to_member_cache = new PtrHashtable ();
388 builder_to_method = new PtrHashtable ();
389 method_arguments = new PtrHashtable ();
390 method_internal_params = new PtrHashtable ();
391 indexer_arguments = new PtrHashtable ();
392 builder_to_ifaces = new PtrHashtable ();
393 builder_to_type_param = new PtrHashtable ();
395 NoTypes = new Type [0];
396 NoTypeExprs = new TypeExpr [0];
398 signature_filter = new MemberFilter (SignatureFilter);
399 InitExpressionTypes ();
402 public static void HandleDuplicate (string name, Type t)
404 Type prev = (Type) types [name];
405 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
409 // This probably never happens, as we catch this before
411 Report.Error (-17, "The type `" + name + "' has already been defined.");
415 tc = builder_to_declspace [t] as TypeContainer;
418 1595, "The type `" + name + "' is defined in an existing assembly;"+
419 " Using the new definition from: " + tc.Location);
422 1595, "The type `" + name + "' is defined in an existing assembly;");
425 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
431 public static void AddUserType (string name, TypeBuilder t)
436 HandleDuplicate (name, t);
442 // This entry point is used by types that we define under the covers
444 public static void RegisterBuilder (Type tb, Type [] ifaces)
447 builder_to_ifaces [tb] = ifaces;
450 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
452 builder_to_declspace.Add (t, tc);
453 typecontainers.Add (name, tc);
454 AddUserType (name, t);
457 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
462 HandleDuplicate (name, t);
465 builder_to_declspace.Add (t, del);
468 public static void AddEnumType (string name, TypeBuilder t, Enum en)
473 HandleDuplicate (name, t);
475 builder_to_declspace.Add (t, en);
478 public static void AddMethod (MethodBase builder, IMethodData method)
480 builder_to_method.Add (builder, method);
483 public static IMethodData GetMethod (MethodBase builder)
485 return (IMethodData) builder_to_method [builder];
488 public static void AddTypeParameter (Type t, TypeParameter tparam)
490 if (!builder_to_type_param.Contains (t))
491 builder_to_type_param.Add (t, tparam);
495 /// Returns the DeclSpace whose Type is `t' or null if there is no
496 /// DeclSpace for `t' (ie, the Type comes from a library)
498 public static DeclSpace LookupDeclSpace (Type t)
500 return builder_to_declspace [t] as DeclSpace;
504 /// Returns the TypeContainer whose Type is `t' or null if there is no
505 /// TypeContainer for `t' (ie, the Type comes from a library)
507 public static TypeContainer LookupTypeContainer (Type t)
509 return builder_to_declspace [t] as TypeContainer;
512 public static TypeContainer LookupGenericTypeContainer (Type t)
514 while (t.IsGenericInstance)
515 t = t.GetGenericTypeDefinition ();
517 return LookupTypeContainer (t);
520 public static MemberCache LookupMemberCache (Type t)
522 if (t is TypeBuilder) {
523 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
524 if (container != null)
525 return container.MemberCache;
528 if (t is GenericTypeParameterBuilder) {
529 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
531 if (container != null)
532 return container.MemberCache;
535 return TypeHandle.GetMemberCache (t);
538 public static MemberCache LookupParentInterfacesCache (Type t)
540 Type [] ifaces = t.GetInterfaces ();
542 if (ifaces != null && ifaces.Length == 1)
543 return LookupMemberCache (ifaces [0]);
545 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
546 MemberCache cache = builder_to_member_cache [t] as MemberCache;
550 cache = new MemberCache (ifaces);
551 builder_to_member_cache.Add (t, cache);
555 public static TypeContainer LookupInterface (Type t)
557 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
558 if ((tc == null) || (tc.Kind != Kind.Interface))
564 public static Delegate LookupDelegate (Type t)
566 return builder_to_declspace [t] as Delegate;
569 public static Enum LookupEnum (Type t)
571 return builder_to_declspace [t] as Enum;
574 public static Class LookupClass (Type t)
576 return (Class) builder_to_declspace [t];
579 public static TypeParameter LookupTypeParameter (Type t)
581 return (TypeParameter) builder_to_type_param [t];
584 public static bool HasConstructorConstraint (Type t)
586 GenericConstraints gc = GetTypeParameterConstraints (t);
590 return (gc.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
593 public static GenericConstraints GetTypeParameterConstraints (Type t)
595 if (!t.IsGenericParameter)
596 throw new InvalidOperationException ();
598 TypeParameter tparam = LookupTypeParameter (t);
600 return tparam.GenericConstraints;
602 return new ReflectionConstraints (t);
606 /// Registers an assembly to load types from.
608 public static void AddAssembly (Assembly a)
610 foreach (Assembly assembly in assemblies) {
615 int top = assemblies.Length;
616 Assembly [] n = new Assembly [top + 1];
618 assemblies.CopyTo (n, 0);
624 public static Assembly [] GetAssemblies ()
630 /// Registers a module builder to lookup types from
632 public static void AddModule (Module mb)
634 int top = modules != null ? modules.Length : 0;
635 Module [] n = new Module [top + 1];
638 modules.CopyTo (n, 0);
643 public static Module[] Modules {
649 static Hashtable references = new Hashtable ();
652 // Gets the reference to T version of the Type (T&)
654 public static Type GetReferenceType (Type t)
656 return t.MakeByRefType ();
659 static Hashtable pointers = new Hashtable ();
662 // Gets the pointer to T version of the Type (T*)
664 public static Type GetPointerType (Type t)
666 string tname = t.FullName + "*";
668 Type ret = t.Assembly.GetType (tname);
671 // If the type comes from the assembly we are building
672 // We need the Hashtable, because .NET 1.1 will return different instance types
673 // every time we call ModuleBuilder.GetType.
676 if (pointers [t] == null)
677 pointers [t] = CodeGen.Module.Builder.GetType (tname);
679 ret = (Type) pointers [t];
686 // Low-level lookup, cache-less
688 static Type LookupTypeReflection (string name)
692 foreach (Assembly a in assemblies){
693 t = a.GetType (name);
698 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
699 if (ta == TypeAttributes.NotPublic ||
700 ta == TypeAttributes.NestedPrivate ||
701 ta == TypeAttributes.NestedAssembly ||
702 ta == TypeAttributes.NestedFamANDAssem){
705 // In .NET pointers turn out to be private, even if their
706 // element type is not
709 t = t.GetElementType ();
719 foreach (Module mb in modules) {
720 t = mb.GetType (name);
728 static Hashtable negative_hits = new Hashtable ();
731 // This function is used when you want to avoid the lookups, and want to go
732 // directly to the source. This will use the cache.
734 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
735 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
736 // way to test things other than doing a fullname compare
738 public static Type LookupTypeDirect (string name)
740 Type t = (Type) types [name];
744 t = LookupTypeReflection (name);
752 static readonly char [] dot_array = { '.' };
755 /// Returns the Type associated with @name, takes care of the fact that
756 /// reflection expects nested types to be separated from the main type
757 /// with a "+" instead of a "."
759 public static Type LookupType (string name)
764 // First lookup in user defined and cached values
767 t = (Type) types [name];
771 // Two thirds of the failures are caught here.
772 if (negative_hits.Contains (name))
775 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
776 string [] elements = name.Split (dot_array);
777 int count = elements.Length;
779 for (int n = 1; n <= count; n++){
780 string top_level_type = String.Join (".", elements, 0, n);
782 // One third of the failures are caught here.
783 if (negative_hits.Contains (top_level_type))
786 t = (Type) types [top_level_type];
788 t = LookupTypeReflection (top_level_type);
790 negative_hits [top_level_type] = null;
801 // We know that System.Object does not have children, and since its the parent of
802 // all the objects, it always gets probbed for inner classes.
804 if (top_level_type == "System.Object")
807 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
808 //Console.WriteLine ("Looking up: " + newt + " " + name);
809 t = LookupTypeReflection (newt);
811 negative_hits [name] = null;
816 negative_hits [name] = null;
821 /// Computes the namespaces that we import from the assemblies we reference.
823 public static void ComputeNamespaces ()
825 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
828 // First add the assembly namespaces
830 if (assembly_get_namespaces != null){
831 int count = assemblies.Length;
833 for (int i = 0; i < count; i++){
834 Assembly a = assemblies [i];
835 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
836 foreach (string ns in namespaces){
839 Namespace.LookupNamespace (ns, true);
843 Hashtable cache = new Hashtable ();
844 cache.Add ("", null);
845 foreach (Assembly a in assemblies) {
846 foreach (Type t in a.GetExportedTypes ()) {
847 string ns = t.Namespace;
848 if (ns == null || cache.Contains (ns))
851 Namespace.LookupNamespace (ns, true);
852 cache.Add (ns, null);
859 /// Fills static table with exported types from all referenced assemblies.
860 /// This information is required for CLS Compliance tests.
862 public static void LoadAllImportedTypes ()
864 all_imported_types = new Hashtable ();
865 foreach (Assembly a in assemblies) {
866 foreach (Type t in a.GetExportedTypes ()) {
867 all_imported_types [t.FullName] = t;
872 public static bool NamespaceClash (string name, Location loc)
874 if (Namespace.LookupNamespace (name, false) == null)
877 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
882 /// Returns the C# name of a type if possible, or the full type name otherwise
884 static public string CSharpName (Type t)
886 if (t.FullName == null)
889 return Regex.Replace (t.FullName,
891 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
892 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
893 @"Boolean|String|Void|Null)" +
895 new MatchEvaluator (CSharpNameMatch));
898 static String CSharpNameMatch (Match match)
900 string s = match.Groups [1].Captures [0].Value;
902 Replace ("int32", "int").
903 Replace ("uint32", "uint").
904 Replace ("int16", "short").
905 Replace ("uint16", "ushort").
906 Replace ("int64", "long").
907 Replace ("uint64", "ulong").
908 Replace ("single", "float").
909 Replace ("boolean", "bool")
910 + match.Groups [2].Captures [0].Value;
914 /// Returns the signature of the method with full namespace classification
916 static public string GetFullNameSignature (MemberInfo mi)
918 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
921 static public string GetFullNameSignature (MethodBase mb)
923 string name = mb.Name;
925 name = mb.DeclaringType.Name;
927 if (mb.IsSpecialName) {
928 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
929 name = name.Remove (0, 4);
936 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
939 static public string GetFullName (Type t)
941 if (t.FullName == null)
944 string name = t.FullName.Replace ('+', '.');
946 DeclSpace tc = LookupDeclSpace (t);
947 if ((tc != null) && tc.IsGeneric) {
948 TypeParameter[] tparam = tc.TypeParameters;
950 StringBuilder sb = new StringBuilder (name);
952 for (int i = 0; i < tparam.Length; i++) {
955 sb.Append (tparam [i].Name);
958 return sb.ToString ();
959 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
960 Type[] tparam = t.GetGenericArguments ();
962 StringBuilder sb = new StringBuilder (name);
964 for (int i = 0; i < tparam.Length; i++) {
967 sb.Append (tparam [i].Name);
970 return sb.ToString ();
977 /// Returns the signature of the property and indexer
979 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
982 return GetFullNameSignature (pb);
985 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
986 string signature = GetFullNameSignature (mb);
987 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
988 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
992 /// Returns the signature of the method
994 static public string CSharpSignature (MethodBase mb)
996 StringBuilder sig = new StringBuilder ("(");
999 // FIXME: We should really have a single function to do
1000 // everything instead of the following 5 line pattern
1002 ParameterData iparams = LookupParametersByBuilder (mb);
1004 if (iparams == null)
1005 iparams = new ReflectionParameters (mb);
1008 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
1009 return GetFullNameSignature (mb);
1011 for (int i = 0; i < iparams.Count; i++) {
1015 sig.Append (iparams.ParameterDesc (i));
1020 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
1021 sig.Replace ('(', '[');
1022 sig.Replace (')', ']');
1025 return GetFullNameSignature (mb) + sig.ToString ();
1028 public static string GetMethodName (MethodInfo m)
1030 if (!IsGenericMethod (m))
1033 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
1037 /// Looks up a type, and aborts if it is not found. This is used
1038 /// by types required by the compiler
1040 static Type CoreLookupType (string name)
1042 Type t = LookupTypeDirect (name);
1045 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1046 Environment.Exit (1);
1053 /// Returns the MethodInfo for a method named `name' defined
1054 /// in type `t' which takes arguments of types `args'
1056 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1060 BindingFlags flags = instance_and_static | BindingFlags.Public;
1066 flags |= BindingFlags.NonPublic;
1068 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1069 if (list.Count == 0) {
1071 Report.Error (-19, "Can not find the core function `" + name + "'");
1075 MethodInfo mi = list [0] as MethodInfo;
1078 Report.Error (-19, "Can not find the core function `" + name + "'");
1085 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1087 return GetMethod (t, name, args, false, report_errors);
1090 static MethodInfo GetMethod (Type t, string name, Type [] args)
1092 return GetMethod (t, name, args, true);
1097 /// Returns the ConstructorInfo for "args"
1099 static ConstructorInfo GetConstructor (Type t, Type [] args)
1107 list = FindMembers (t, MemberTypes.Constructor,
1108 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1109 signature_filter, sig);
1110 if (list.Count == 0){
1111 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1115 ConstructorInfo ci = list [0] as ConstructorInfo;
1117 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1124 public static void InitEnumUnderlyingTypes ()
1127 int32_type = CoreLookupType ("System.Int32");
1128 int64_type = CoreLookupType ("System.Int64");
1129 uint32_type = CoreLookupType ("System.UInt32");
1130 uint64_type = CoreLookupType ("System.UInt64");
1131 byte_type = CoreLookupType ("System.Byte");
1132 sbyte_type = CoreLookupType ("System.SByte");
1133 short_type = CoreLookupType ("System.Int16");
1134 ushort_type = CoreLookupType ("System.UInt16");
1138 /// The types have to be initialized after the initial
1139 /// population of the type has happened (for example, to
1140 /// bootstrap the corlib.dll
1142 public static void InitCoreTypes ()
1144 object_type = CoreLookupType ("System.Object");
1145 value_type = CoreLookupType ("System.ValueType");
1147 InitEnumUnderlyingTypes ();
1149 char_type = CoreLookupType ("System.Char");
1150 string_type = CoreLookupType ("System.String");
1151 float_type = CoreLookupType ("System.Single");
1152 double_type = CoreLookupType ("System.Double");
1153 char_ptr_type = CoreLookupType ("System.Char*");
1154 decimal_type = CoreLookupType ("System.Decimal");
1155 bool_type = CoreLookupType ("System.Boolean");
1156 enum_type = CoreLookupType ("System.Enum");
1158 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1159 delegate_type = CoreLookupType ("System.Delegate");
1161 array_type = CoreLookupType ("System.Array");
1162 void_type = CoreLookupType ("System.Void");
1163 type_type = CoreLookupType ("System.Type");
1165 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1166 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1167 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1168 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1169 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1170 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1171 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1172 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1173 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1174 idisposable_type = CoreLookupType ("System.IDisposable");
1175 icloneable_type = CoreLookupType ("System.ICloneable");
1176 iconvertible_type = CoreLookupType ("System.IConvertible");
1177 monitor_type = CoreLookupType ("System.Threading.Monitor");
1178 intptr_type = CoreLookupType ("System.IntPtr");
1180 attribute_type = CoreLookupType ("System.Attribute");
1181 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1182 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1183 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1184 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1185 new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
1186 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1187 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1188 typed_reference_type = CoreLookupType ("System.TypedReference");
1189 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1190 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1191 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1194 // Sigh. Remove this before the release. Wonder what versions of Mono
1195 // people are running.
1197 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1199 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1201 void_ptr_type = CoreLookupType ("System.Void*");
1203 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1205 exception_type = CoreLookupType ("System.Exception");
1206 activator_type = CoreLookupType ("System.Activator");
1207 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1208 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1213 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1214 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1215 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1216 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1217 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1218 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1223 generic_ienumerator_type = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerator", 1));
1224 generic_ienumerable_type = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerable", 1));
1228 // When compiling corlib, store the "real" types here.
1230 if (!RootContext.StdLib) {
1231 system_int32_type = typeof (System.Int32);
1232 system_array_type = typeof (System.Array);
1233 system_type_type = typeof (System.Type);
1234 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1236 Type [] void_arg = { };
1237 system_int_array_get_length = GetMethod (
1238 system_array_type, "get_Length", void_arg);
1239 system_int_array_get_rank = GetMethod (
1240 system_array_type, "get_Rank", void_arg);
1241 system_object_array_clone = GetMethod (
1242 system_array_type, "Clone", void_arg);
1244 Type [] system_int_arg = { system_int32_type };
1245 system_int_array_get_length_int = GetMethod (
1246 system_array_type, "GetLength", system_int_arg);
1247 system_int_array_get_upper_bound_int = GetMethod (
1248 system_array_type, "GetUpperBound", system_int_arg);
1249 system_int_array_get_lower_bound_int = GetMethod (
1250 system_array_type, "GetLowerBound", system_int_arg);
1252 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1253 system_void_array_copyto_array_int = GetMethod (
1254 system_array_type, "CopyTo", system_array_int_arg);
1256 Type [] system_3_type_arg = {
1257 system_type_type, system_type_type, system_type_type };
1258 Type [] system_4_type_arg = {
1259 system_type_type, system_type_type, system_type_type, system_type_type };
1261 MethodInfo set_corlib_type_builders = GetMethod (
1262 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1263 system_4_type_arg, true, false);
1265 if (set_corlib_type_builders != null) {
1266 object[] args = new object [4];
1267 args [0] = object_type;
1268 args [1] = value_type;
1269 args [2] = enum_type;
1270 args [3] = void_type;
1272 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1274 // Compatibility for an older version of the class libs.
1275 set_corlib_type_builders = GetMethod (
1276 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1277 system_3_type_arg, true, true);
1279 if (set_corlib_type_builders == null) {
1280 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1284 object[] args = new object [3];
1285 args [0] = object_type;
1286 args [1] = value_type;
1287 args [2] = enum_type;
1289 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1293 system_object_expr.Type = object_type;
1294 system_string_expr.Type = string_type;
1295 system_boolean_expr.Type = bool_type;
1296 system_decimal_expr.Type = decimal_type;
1297 system_single_expr.Type = float_type;
1298 system_double_expr.Type = double_type;
1299 system_sbyte_expr.Type = sbyte_type;
1300 system_byte_expr.Type = byte_type;
1301 system_int16_expr.Type = short_type;
1302 system_uint16_expr.Type = ushort_type;
1303 system_int32_expr.Type = int32_type;
1304 system_uint32_expr.Type = uint32_type;
1305 system_int64_expr.Type = int64_type;
1306 system_uint64_expr.Type = uint64_type;
1307 system_char_expr.Type = char_type;
1308 system_void_expr.Type = void_type;
1309 system_asynccallback_expr.Type = asynccallback_type;
1310 system_iasyncresult_expr.Type = iasyncresult_type;
1311 system_valuetype_expr.Type = value_type;
1314 // These are only used for compare purposes
1316 anonymous_method_type = typeof (AnonymousMethod);
1317 null_type = typeof (NullType);
1321 // The helper methods that are used by the compiler
1323 public static void InitCodeHelpers ()
1326 // Now load the default methods that we use.
1328 Type [] string_string = { string_type, string_type };
1329 string_concat_string_string = GetMethod (
1330 string_type, "Concat", string_string);
1331 Type [] string_string_string = { string_type, string_type, string_type };
1332 string_concat_string_string_string = GetMethod (
1333 string_type, "Concat", string_string_string);
1334 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1335 string_concat_string_string_string_string = GetMethod (
1336 string_type, "Concat", string_string_string_string);
1337 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1338 string_concat_string_dot_dot_dot = GetMethod (
1339 string_type, "Concat", params_string);
1341 Type [] object_object = { object_type, object_type };
1342 string_concat_object_object = GetMethod (
1343 string_type, "Concat", object_object);
1344 Type [] object_object_object = { object_type, object_type, object_type };
1345 string_concat_object_object_object = GetMethod (
1346 string_type, "Concat", object_object_object);
1347 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1348 string_concat_object_dot_dot_dot = GetMethod (
1349 string_type, "Concat", params_object);
1351 Type [] string_ = { string_type };
1352 string_isinterneted_string = GetMethod (
1353 string_type, "IsInterned", string_);
1355 Type [] runtime_type_handle = { runtime_handle_type };
1356 system_type_get_type_from_handle = GetMethod (
1357 type_type, "GetTypeFromHandle", runtime_type_handle);
1359 Type [] delegate_delegate = { delegate_type, delegate_type };
1360 delegate_combine_delegate_delegate = GetMethod (
1361 delegate_type, "Combine", delegate_delegate);
1363 delegate_remove_delegate_delegate = GetMethod (
1364 delegate_type, "Remove", delegate_delegate);
1369 Type [] void_arg = { };
1370 object_getcurrent_void = GetMethod (
1371 ienumerator_type, "get_Current", void_arg);
1372 bool_movenext_void = GetMethod (
1373 ienumerator_type, "MoveNext", void_arg);
1374 void_reset_void = GetMethod (
1375 ienumerator_type, "Reset", void_arg);
1376 void_dispose_void = GetMethod (
1377 idisposable_type, "Dispose", void_arg);
1378 int_get_offset_to_string_data = GetMethod (
1379 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1380 int_array_get_length = GetMethod (
1381 array_type, "get_Length", void_arg);
1382 int_array_get_rank = GetMethod (
1383 array_type, "get_Rank", void_arg);
1384 ienumerable_getenumerator_void = GetMethod (
1385 ienumerable_type, "GetEnumerator", void_arg);
1390 Type [] int_arg = { int32_type };
1391 int_array_get_length_int = GetMethod (
1392 array_type, "GetLength", int_arg);
1393 int_array_get_upper_bound_int = GetMethod (
1394 array_type, "GetUpperBound", int_arg);
1395 int_array_get_lower_bound_int = GetMethod (
1396 array_type, "GetLowerBound", int_arg);
1399 // System.Array methods
1401 object_array_clone = GetMethod (
1402 array_type, "Clone", void_arg);
1403 Type [] array_int_arg = { array_type, int32_type };
1404 void_array_copyto_array_int = GetMethod (
1405 array_type, "CopyTo", array_int_arg);
1410 Type [] object_arg = { object_type };
1411 void_monitor_enter_object = GetMethod (
1412 monitor_type, "Enter", object_arg);
1413 void_monitor_exit_object = GetMethod (
1414 monitor_type, "Exit", object_arg);
1416 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1418 void_initializearray_array_fieldhandle = GetMethod (
1419 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1424 int_getlength_int = GetMethod (
1425 array_type, "GetLength", int_arg);
1428 // Decimal constructors
1430 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1431 void_decimal_ctor_five_args = GetConstructor (
1432 decimal_type, dec_arg);
1434 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1439 cons_param_array_attribute = GetConstructor (
1440 param_array_type, void_arg);
1442 unverifiable_code_ctor = GetConstructor (
1443 unverifiable_code_type, void_arg);
1445 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1446 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1448 default_member_ctor = GetConstructor (default_member_type, string_);
1451 // InvalidOperationException
1453 invalid_operation_ctor = GetConstructor (
1454 invalid_operation_exception_type, void_arg);
1458 object_ctor = GetConstructor (object_type, void_arg);
1461 Type [] type_arg = { type_type };
1462 activator_create_instance = GetMethod (
1463 activator_type, "CreateInstance", type_arg);
1466 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1469 /// This is the "old", non-cache based FindMembers() function. We cannot use
1470 /// the cache here because there is no member name argument.
1472 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1473 MemberFilter filter, object criteria)
1475 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1478 // `builder_to_declspace' contains all dynamic types.
1482 Timer.StartTimer (TimerType.FindMembers);
1483 list = decl.FindMembers (mt, bf, filter, criteria);
1484 Timer.StopTimer (TimerType.FindMembers);
1489 // We have to take care of arrays specially, because GetType on
1490 // a TypeBuilder array will return a Type, not a TypeBuilder,
1491 // and we can not call FindMembers on this type.
1493 if (t.IsSubclassOf (TypeManager.array_type))
1494 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1496 if (t is GenericTypeParameterBuilder) {
1497 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1499 Timer.StartTimer (TimerType.FindMembers);
1500 MemberList list = tparam.FindMembers (
1501 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1502 Timer.StopTimer (TimerType.FindMembers);
1507 // Since FindMembers will not lookup both static and instance
1508 // members, we emulate this behaviour here.
1510 if ((bf & instance_and_static) == instance_and_static){
1511 MemberInfo [] i_members = t.FindMembers (
1512 mt, bf & ~BindingFlags.Static, filter, criteria);
1514 int i_len = i_members.Length;
1516 MemberInfo one = i_members [0];
1519 // If any of these are present, we are done!
1521 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1522 return new MemberList (i_members);
1525 MemberInfo [] s_members = t.FindMembers (
1526 mt, bf & ~BindingFlags.Instance, filter, criteria);
1528 int s_len = s_members.Length;
1529 if (i_len > 0 || s_len > 0)
1530 return new MemberList (i_members, s_members);
1533 return new MemberList (i_members);
1535 return new MemberList (s_members);
1539 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1544 /// This method is only called from within MemberLookup. It tries to use the member
1545 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1546 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1547 /// our return value will already contain all inherited members and the caller don't need
1548 /// to check base classes and interfaces anymore.
1550 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1551 string name, out bool used_cache)
1556 // We have to take care of arrays specially, because GetType on
1557 // a TypeBuilder array will return a Type, not a TypeBuilder,
1558 // and we can not call FindMembers on this type.
1560 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1562 return TypeHandle.ArrayType.MemberCache.FindMembers (
1563 mt, bf, name, FilterWithClosure_delegate, null);
1567 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1568 // and we can ask the DeclSpace for the MemberCache.
1570 if (t is TypeBuilder) {
1571 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1572 cache = decl.MemberCache;
1575 // If this DeclSpace has a MemberCache, use it.
1578 if (cache != null) {
1580 return cache.FindMembers (
1581 mt, bf, name, FilterWithClosure_delegate, null);
1584 // If there is no MemberCache, we need to use the "normal" FindMembers.
1585 // Note, this is a VERY uncommon route!
1588 Timer.StartTimer (TimerType.FindMembers);
1589 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1590 FilterWithClosure_delegate, name);
1591 Timer.StopTimer (TimerType.FindMembers);
1593 return (MemberInfo []) list;
1596 if (t is GenericTypeParameterBuilder) {
1597 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1600 Timer.StartTimer (TimerType.FindMembers);
1601 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1602 FilterWithClosure_delegate, name);
1603 Timer.StopTimer (TimerType.FindMembers);
1605 return (MemberInfo []) list;
1609 // This call will always succeed. There is exactly one TypeHandle instance per
1610 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1611 // the corresponding MemberCache.
1613 cache = TypeHandle.GetMemberCache (t);
1616 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1619 public static bool IsBuiltinType (Type t)
1621 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1622 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1623 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1624 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1630 public static bool IsBuiltinType (TypeContainer tc)
1632 return IsBuiltinType (tc.TypeBuilder);
1636 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1637 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1639 public static bool IsCLRType (Type t)
1641 if (t == object_type || t == int32_type || t == uint32_type ||
1642 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1643 t == char_type || t == short_type || t == bool_type ||
1644 t == sbyte_type || t == byte_type || t == ushort_type)
1650 public static bool IsDelegateType (Type t)
1652 if (t.IsGenericInstance)
1653 t = t.GetGenericTypeDefinition ();
1655 if (t.IsSubclassOf (TypeManager.delegate_type))
1661 public static bool IsEnumType (Type t)
1663 if (t.IsSubclassOf (TypeManager.enum_type))
1668 public static bool IsBuiltinOrEnum (Type t)
1670 if (IsBuiltinType (t))
1679 public static bool IsNullType (Type t)
1681 return t == null_type;
1685 // Only a quick hack to get things moving, while real runtime support appears
1687 public static bool IsGeneric (Type t)
1689 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1691 return ds.IsGeneric;
1694 public static bool HasGenericArguments (Type t)
1696 return GetNumberOfTypeArguments (t) > 0;
1699 public static int GetNumberOfTypeArguments (Type t)
1701 DeclSpace tc = LookupDeclSpace (t);
1703 return tc.IsGeneric ? tc.CountTypeParameters : 0;
1705 return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1708 public static Type[] GetTypeArguments (Type t)
1710 DeclSpace tc = LookupDeclSpace (t);
1713 return Type.EmptyTypes;
1715 TypeParameter[] tparam = tc.TypeParameters;
1716 Type[] ret = new Type [tparam.Length];
1717 for (int i = 0; i < tparam.Length; i++) {
1718 ret [i] = tparam [i].Type;
1719 if (ret [i] == null)
1720 throw new InternalErrorException ();
1725 return t.GetGenericArguments ();
1729 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1731 public static bool IsUnmanagedType (Type t)
1733 if (IsBuiltinType (t) && t != TypeManager.string_type)
1742 if (IsValueType (t)){
1743 if (t is TypeBuilder){
1744 TypeContainer tc = LookupTypeContainer (t);
1746 if (tc.Fields != null){
1747 foreach (Field f in tc.Fields){
1748 if (f.FieldBuilder.IsStatic)
1750 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1756 FieldInfo [] fields = t.GetFields ();
1758 foreach (FieldInfo f in fields){
1761 if (!IsUnmanagedType (f.FieldType))
1771 public static bool IsValueType (Type t)
1773 return t.IsGenericParameter || t.IsValueType;
1776 public static bool IsInterfaceType (Type t)
1778 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1782 return tc.Kind == Kind.Interface;
1785 public static bool IsEqual (Type a, Type b)
1790 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1792 // `a' is a generic type definition's TypeBuilder and `b' is a
1793 // generic instance of the same type.
1799 // void Test (Stack<T> stack) { }
1802 // The first argument of `Test' will be the generic instance
1803 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1806 // We hit this via Closure.Filter() for gen-82.cs.
1808 if (a != b.GetGenericTypeDefinition ())
1811 Type[] aparams = a.GetGenericArguments ();
1812 Type[] bparams = b.GetGenericArguments ();
1814 if (aparams.Length != bparams.Length)
1817 for (int i = 0; i < aparams.Length; i++)
1818 if (!IsEqual (aparams [i], bparams [i]))
1824 if (a.IsGenericParameter && b.IsGenericParameter) {
1825 if ((a.DeclaringMethod == null) || (b.DeclaringMethod == null))
1827 return a.GenericParameterPosition == b.GenericParameterPosition;
1830 if (a.IsArray && b.IsArray) {
1831 if (a.GetArrayRank () != b.GetArrayRank ())
1833 return IsEqual (a.GetElementType (), b.GetElementType ());
1836 if (a.IsGenericInstance && b.IsGenericInstance) {
1837 Type at = a.GetGenericTypeDefinition ();
1838 Type bt = b.GetGenericTypeDefinition ();
1840 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1843 Type[] aargs = a.GetGenericArguments ();
1844 Type[] bargs = b.GetGenericArguments ();
1846 if (aargs.Length != bargs.Length)
1849 for (int i = 0; i < aargs.Length; i++) {
1850 if (!IsEqual (aargs [i], bargs [i]))
1860 public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_infered, Type[] method_infered)
1862 if (a.IsGenericParameter) {
1864 // If a is an array of a's type, they may never
1868 b = b.GetElementType ();
1874 // If b is a generic parameter or an actual type,
1875 // they may become equal:
1877 // class X<T,U> : I<T>, I<U>
1878 // class X<T> : I<T>, I<float>
1880 if (b.IsGenericParameter || !b.IsGenericInstance) {
1881 int pos = a.GenericParameterPosition;
1882 Type[] args = a.DeclaringMethod != null ? method_infered : class_infered;
1883 if (args [pos] == null) {
1888 return args [pos] == a;
1892 // We're now comparing a type parameter with a
1893 // generic instance. They may become equal unless
1894 // the type parameter appears anywhere in the
1895 // generic instance:
1897 // class X<T,U> : I<T>, I<X<U>>
1898 // -> error because you could instanciate it as
1901 // class X<T> : I<T>, I<X<T>> -> ok
1904 Type[] bargs = GetTypeArguments (b);
1905 for (int i = 0; i < bargs.Length; i++) {
1906 if (a.Equals (bargs [i]))
1913 if (b.IsGenericParameter)
1914 return MayBecomeEqualGenericTypes (b, a, class_infered, method_infered);
1917 // At this point, neither a nor b are a type parameter.
1919 // If one of them is a generic instance, let
1920 // MayBecomeEqualGenericInstances() compare them (if the
1921 // other one is not a generic instance, they can never
1925 if (a.IsGenericInstance || b.IsGenericInstance)
1926 return MayBecomeEqualGenericInstances (a, b, class_infered, method_infered);
1929 // If both of them are arrays.
1932 if (a.IsArray && b.IsArray) {
1933 if (a.GetArrayRank () != b.GetArrayRank ())
1936 a = a.GetElementType ();
1937 b = b.GetElementType ();
1939 return MayBecomeEqualGenericTypes (a, b, class_infered, method_infered);
1943 // Ok, two ordinary types.
1946 return a.Equals (b);
1950 // Checks whether two generic instances may become equal for some
1951 // particular instantiation (26.3.1).
1953 public static bool MayBecomeEqualGenericInstances (Type a, Type b,
1954 Type[] class_infered, Type[] method_infered)
1956 if (!a.IsGenericInstance || !b.IsGenericInstance)
1958 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1961 Type[] aargs = GetTypeArguments (a);
1962 Type[] bargs = GetTypeArguments (b);
1964 return MayBecomeEqualGenericInstances (
1965 GetTypeArguments (a), GetTypeArguments (b), class_infered, method_infered);
1968 public static bool MayBecomeEqualGenericInstances (Type[] aargs, Type[] bargs,
1969 Type[] class_infered, Type[] method_infered)
1971 if (aargs.Length != bargs.Length)
1974 Type[] args = new Type [aargs.Length];
1975 for (int i = 0; i < aargs.Length; i++) {
1976 if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_infered, method_infered))
1983 public static bool IsEqualGenericInstance (Type type, Type parent)
1985 int tcount = GetNumberOfTypeArguments (type);
1986 int pcount = GetNumberOfTypeArguments (parent);
1988 if (type.IsGenericInstance)
1989 type = type.GetGenericTypeDefinition ();
1990 if (parent.IsGenericInstance)
1991 parent = parent.GetGenericTypeDefinition ();
1993 if (tcount != pcount)
1996 return type.Equals (parent);
1999 public static bool IsSubclassOf (Type type, Type parent)
2001 TypeParameter tparam = LookupTypeParameter (type);
2002 TypeParameter pparam = LookupTypeParameter (parent);
2004 if ((tparam != null) && (pparam != null)) {
2005 if (tparam == pparam)
2008 return tparam.IsSubclassOf (parent);
2012 if (type.Equals (parent))
2015 type = type.BaseType;
2016 } while (type != null);
2021 public static bool IsPrivateAccessible (Type type, Type parent)
2023 if (type.Equals (parent))
2026 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
2028 // `a' is a generic type definition's TypeBuilder and `b' is a
2029 // generic instance of the same type.
2035 // void Test (Stack<T> stack) { }
2038 // The first argument of `Test' will be the generic instance
2039 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
2042 // We hit this via Closure.Filter() for gen-82.cs.
2044 if (type != parent.GetGenericTypeDefinition ())
2050 if (type.IsGenericInstance && parent.IsGenericInstance) {
2051 Type tdef = type.GetGenericTypeDefinition ();
2052 Type pdef = parent.GetGenericTypeDefinition ();
2054 if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
2063 public static bool IsFamilyAccessible (Type type, Type parent)
2065 TypeParameter tparam = LookupTypeParameter (type);
2066 TypeParameter pparam = LookupTypeParameter (parent);
2068 if ((tparam != null) && (pparam != null)) {
2069 if (tparam == pparam)
2072 return tparam.IsSubclassOf (parent);
2076 if (IsEqualGenericInstance (type, parent))
2079 type = type.BaseType;
2080 } while (type != null);
2086 // Checks whether `type' is a subclass or nested child of `parent'.
2088 public static bool IsNestedFamilyAccessible (Type type, Type parent)
2091 if (IsFamilyAccessible (type, parent))
2094 // Handle nested types.
2095 type = type.DeclaringType;
2096 } while (type != null);
2102 // Checks whether `type' is a nested child of `parent'.
2104 public static bool IsNestedChildOf (Type type, Type parent)
2106 if (IsEqual (type, parent))
2109 type = type.DeclaringType;
2110 while (type != null) {
2111 if (IsEqual (type, parent))
2114 type = type.DeclaringType;
2121 // Do the right thing when returning the element type of an
2122 // array type based on whether we are compiling corlib or not
2124 public static Type GetElementType (Type t)
2126 if (RootContext.StdLib)
2127 return t.GetElementType ();
2129 return TypeToCoreType (t.GetElementType ());
2133 /// Returns the User Defined Types
2135 public static ArrayList UserTypes {
2141 public static Hashtable TypeContainers {
2143 return typecontainers;
2147 static Hashtable builder_to_constant;
2149 public static void RegisterConstant (FieldBuilder fb, Const c)
2151 if (builder_to_constant == null)
2152 builder_to_constant = new PtrHashtable ();
2154 if (builder_to_constant.Contains (fb))
2157 builder_to_constant.Add (fb, c);
2160 public static Const LookupConstant (FieldBuilder fb)
2162 if (builder_to_constant == null)
2165 return (Const) builder_to_constant [fb];
2169 /// Gigantic work around for missing features in System.Reflection.Emit follows.
2173 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
2174 /// for anything which is dynamic, and we need this in a number of places,
2175 /// we register this information here, and use it afterwards.
2177 static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
2182 method_arguments.Add (mb, args);
2183 method_internal_params.Add (mb, ip);
2186 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
2188 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
2191 if (method_internal_params.Contains (mb))
2192 return (InternalParameters) method_internal_params [mb];
2194 throw new Exception ("Argument for Method not registered" + mb);
2198 /// Returns the argument types for a method based on its methodbase
2200 /// For dynamic methods, we use the compiler provided types, for
2201 /// methods from existing assemblies we load them from GetParameters,
2202 /// and insert them into the cache
2204 static public Type [] GetArgumentTypes (MethodBase mb)
2206 object t = method_arguments [mb];
2210 ParameterInfo [] pi = mb.GetParameters ();
2217 types = new Type [c];
2218 for (int i = 0; i < c; i++)
2219 types [i] = pi [i].ParameterType;
2221 method_arguments.Add (mb, types);
2226 /// Returns the argument types for an indexer based on its PropertyInfo
2228 /// For dynamic indexers, we use the compiler provided types, for
2229 /// indexers from existing assemblies we load them from GetParameters,
2230 /// and insert them into the cache
2232 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2234 if (indexer_arguments.Contains (indexer))
2235 return (Type []) indexer_arguments [indexer];
2236 else if (indexer is PropertyBuilder)
2237 // If we're a PropertyBuilder and not in the
2238 // `indexer_arguments' hash, then we're a property and
2242 ParameterInfo [] pi = indexer.GetIndexParameters ();
2243 // Property, not an indexer.
2247 Type [] types = new Type [c];
2249 for (int i = 0; i < c; i++)
2250 types [i] = pi [i].ParameterType;
2252 indexer_arguments.Add (indexer, types);
2258 // This is a workaround the fact that GetValue is not
2259 // supported for dynamic types
2261 static Hashtable fields = new Hashtable ();
2262 static public bool RegisterFieldValue (FieldBuilder fb, object value)
2264 if (fields.Contains (fb))
2267 fields.Add (fb, value);
2272 static public object GetValue (FieldBuilder fb)
2277 static Hashtable fieldbuilders_to_fields = new Hashtable ();
2278 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2280 if (fieldbuilders_to_fields.Contains (fb))
2283 fieldbuilders_to_fields.Add (fb, f);
2288 // The return value can be null; This will be the case for
2289 // auxiliary FieldBuilders created by the compiler that have no
2290 // real field being declared on the source code
2292 static public FieldBase GetField (FieldInfo fb)
2294 return (FieldBase) fieldbuilders_to_fields [fb];
2297 static Hashtable events;
2299 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2302 events = new Hashtable ();
2304 if (!events.Contains (eb)) {
2305 events.Add (eb, new Pair (add, remove));
2309 static public MethodInfo GetAddMethod (EventInfo ei)
2311 if (ei is MyEventBuilder) {
2312 Pair pair = (Pair) events [ei];
2314 return (MethodInfo) pair.First;
2316 return ei.GetAddMethod (true);
2319 static public MethodInfo GetRemoveMethod (EventInfo ei)
2321 if (ei is MyEventBuilder) {
2322 Pair pair = (Pair) events [ei];
2324 return (MethodInfo) pair.Second;
2326 return ei.GetRemoveMethod (true);
2329 static Hashtable priv_fields_events;
2331 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2333 if (priv_fields_events == null)
2334 priv_fields_events = new Hashtable ();
2336 if (priv_fields_events.Contains (einfo))
2339 priv_fields_events.Add (einfo, builder);
2344 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2346 if (priv_fields_events == null)
2349 return (MemberInfo) priv_fields_events [ei];
2352 static Hashtable properties;
2354 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2356 if (properties == null)
2357 properties = new Hashtable ();
2359 if (properties.Contains (pb))
2362 properties.Add (pb, new Pair (get, set));
2367 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2368 MethodBase set, Type[] args)
2370 if (!RegisterProperty (pb, get,set))
2373 indexer_arguments.Add (pb, args);
2378 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2380 Hashtable hash = new Hashtable ();
2381 return CheckStructCycles (tc, seen, hash);
2384 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2387 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2391 // `seen' contains all types we've already visited.
2393 if (seen.Contains (tc))
2395 seen.Add (tc, null);
2397 if (tc.Fields == null)
2400 foreach (Field field in tc.Fields) {
2401 if (field.FieldBuilder.IsStatic)
2404 Type ftype = field.FieldBuilder.FieldType;
2405 TypeContainer ftc = LookupTypeContainer (ftype);
2409 if (hash.Contains (ftc)) {
2410 Report.Error (523, tc.Location,
2411 "Struct member `{0}.{1}' of type `{2}' " +
2412 "causes a cycle in the struct layout",
2413 tc.Name, field.Name, ftc.Name);
2418 // `hash' contains all types in the current path.
2420 hash.Add (tc, null);
2422 bool ok = CheckStructCycles (ftc, seen, hash);
2429 if (!seen.Contains (ftc))
2430 seen.Add (ftc, null);
2437 /// Given an array of interface types, expand and eliminate repeated ocurrences
2438 /// of an interface.
2442 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2445 public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2447 ArrayList new_ifaces = new ArrayList ();
2449 foreach (TypeExpr iface in base_interfaces){
2450 TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
2454 if (!new_ifaces.Contains (texpr.Type))
2455 new_ifaces.Add (texpr.Type);
2457 Type [] implementing = texpr.Type.GetInterfaces ();
2459 foreach (Type imp in implementing){
2460 if (!new_ifaces.Contains (imp))
2461 new_ifaces.Add (imp);
2464 Type [] ret = new Type [new_ifaces.Count];
2465 new_ifaces.CopyTo (ret, 0);
2469 static PtrHashtable iface_cache = new PtrHashtable ();
2472 /// This function returns the interfaces in the type `t'. Works with
2473 /// both types and TypeBuilders.
2475 public static Type [] GetInterfaces (Type t)
2478 Type [] cached = iface_cache [t] as Type [];
2483 // The reason for catching the Array case is that Reflection.Emit
2484 // will not return a TypeBuilder for Array types of TypeBuilder types,
2485 // but will still throw an exception if we try to call GetInterfaces
2488 // Since the array interfaces are always constant, we return those for
2493 t = TypeManager.array_type;
2495 if (t is TypeBuilder){
2496 Type[] parent_ifaces;
2498 if (t.BaseType == null)
2499 parent_ifaces = NoTypes;
2501 parent_ifaces = GetInterfaces (t.BaseType);
2502 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2503 if (type_ifaces == null)
2504 type_ifaces = NoTypes;
2506 int parent_count = parent_ifaces.Length;
2507 Type[] result = new Type [parent_count + type_ifaces.Length];
2508 parent_ifaces.CopyTo (result, 0);
2509 type_ifaces.CopyTo (result, parent_count);
2511 iface_cache [t] = result;
2513 } else if (t is GenericTypeParameterBuilder){
2514 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2515 if (type_ifaces == null)
2516 type_ifaces = NoTypes;
2518 iface_cache [t] = type_ifaces;
2521 Type[] ifaces = t.GetInterfaces ();
2522 iface_cache [t] = ifaces;
2528 // gets the interfaces that are declared explicitly on t
2530 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2532 return (Type []) builder_to_ifaces [t];
2536 /// The following is used to check if a given type implements an interface.
2537 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2539 public static bool ImplementsInterface (Type t, Type iface)
2544 // FIXME OPTIMIZATION:
2545 // as soon as we hit a non-TypeBuiler in the interface
2546 // chain, we could return, as the `Type.GetInterfaces'
2547 // will return all the interfaces implement by the type
2551 interfaces = GetInterfaces (t);
2553 if (interfaces != null){
2554 foreach (Type i in interfaces){
2561 } while (t != null);
2566 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2568 // This is a custom version of Convert.ChangeType() which works
2569 // with the TypeBuilder defined types when compiling corlib.
2570 public static object ChangeType (object value, Type conversionType, out bool error)
2572 IConvertible convert_value = value as IConvertible;
2574 if (convert_value == null){
2580 // We must use Type.Equals() here since `conversionType' is
2581 // the TypeBuilder created version of a system type and not
2582 // the system type itself. You cannot use Type.GetTypeCode()
2583 // on such a type - it'd always return TypeCode.Object.
2587 if (conversionType.Equals (typeof (Boolean)))
2588 return (object)(convert_value.ToBoolean (nf_provider));
2589 else if (conversionType.Equals (typeof (Byte)))
2590 return (object)(convert_value.ToByte (nf_provider));
2591 else if (conversionType.Equals (typeof (Char)))
2592 return (object)(convert_value.ToChar (nf_provider));
2593 else if (conversionType.Equals (typeof (DateTime)))
2594 return (object)(convert_value.ToDateTime (nf_provider));
2595 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2596 return (object)(convert_value.ToDecimal (nf_provider));
2597 else if (conversionType.Equals (typeof (Double)))
2598 return (object)(convert_value.ToDouble (nf_provider));
2599 else if (conversionType.Equals (typeof (Int16)))
2600 return (object)(convert_value.ToInt16 (nf_provider));
2601 else if (conversionType.Equals (typeof (Int32)))
2602 return (object)(convert_value.ToInt32 (nf_provider));
2603 else if (conversionType.Equals (typeof (Int64)))
2604 return (object)(convert_value.ToInt64 (nf_provider));
2605 else if (conversionType.Equals (typeof (SByte)))
2606 return (object)(convert_value.ToSByte (nf_provider));
2607 else if (conversionType.Equals (typeof (Single)))
2608 return (object)(convert_value.ToSingle (nf_provider));
2609 else if (conversionType.Equals (typeof (String)))
2610 return (object)(convert_value.ToString (nf_provider));
2611 else if (conversionType.Equals (typeof (UInt16)))
2612 return (object)(convert_value.ToUInt16 (nf_provider));
2613 else if (conversionType.Equals (typeof (UInt32)))
2614 return (object)(convert_value.ToUInt32 (nf_provider));
2615 else if (conversionType.Equals (typeof (UInt64)))
2616 return (object)(convert_value.ToUInt64 (nf_provider));
2617 else if (conversionType.Equals (typeof (Object)))
2618 return (object)(value);
2628 // This is needed, because enumerations from assemblies
2629 // do not report their underlyingtype, but they report
2632 public static Type EnumToUnderlying (Type t)
2634 if (t == TypeManager.enum_type)
2637 t = t.UnderlyingSystemType;
2638 if (!TypeManager.IsEnumType (t))
2641 if (t is TypeBuilder) {
2642 // slow path needed to compile corlib
2643 if (t == TypeManager.bool_type ||
2644 t == TypeManager.byte_type ||
2645 t == TypeManager.sbyte_type ||
2646 t == TypeManager.char_type ||
2647 t == TypeManager.short_type ||
2648 t == TypeManager.ushort_type ||
2649 t == TypeManager.int32_type ||
2650 t == TypeManager.uint32_type ||
2651 t == TypeManager.int64_type ||
2652 t == TypeManager.uint64_type)
2654 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2656 TypeCode tc = Type.GetTypeCode (t);
2659 case TypeCode.Boolean:
2660 return TypeManager.bool_type;
2662 return TypeManager.byte_type;
2663 case TypeCode.SByte:
2664 return TypeManager.sbyte_type;
2666 return TypeManager.char_type;
2667 case TypeCode.Int16:
2668 return TypeManager.short_type;
2669 case TypeCode.UInt16:
2670 return TypeManager.ushort_type;
2671 case TypeCode.Int32:
2672 return TypeManager.int32_type;
2673 case TypeCode.UInt32:
2674 return TypeManager.uint32_type;
2675 case TypeCode.Int64:
2676 return TypeManager.int64_type;
2677 case TypeCode.UInt64:
2678 return TypeManager.uint64_type;
2680 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2684 // When compiling corlib and called with one of the core types, return
2685 // the corresponding typebuilder for that type.
2687 public static Type TypeToCoreType (Type t)
2689 if (RootContext.StdLib || (t is TypeBuilder))
2692 TypeCode tc = Type.GetTypeCode (t);
2695 case TypeCode.Boolean:
2696 return TypeManager.bool_type;
2698 return TypeManager.byte_type;
2699 case TypeCode.SByte:
2700 return TypeManager.sbyte_type;
2702 return TypeManager.char_type;
2703 case TypeCode.Int16:
2704 return TypeManager.short_type;
2705 case TypeCode.UInt16:
2706 return TypeManager.ushort_type;
2707 case TypeCode.Int32:
2708 return TypeManager.int32_type;
2709 case TypeCode.UInt32:
2710 return TypeManager.uint32_type;
2711 case TypeCode.Int64:
2712 return TypeManager.int64_type;
2713 case TypeCode.UInt64:
2714 return TypeManager.uint64_type;
2715 case TypeCode.Single:
2716 return TypeManager.float_type;
2717 case TypeCode.Double:
2718 return TypeManager.double_type;
2719 case TypeCode.String:
2720 return TypeManager.string_type;
2721 case TypeCode.Decimal:
2722 return TypeManager.decimal_type;
2724 if (t == typeof (void))
2725 return TypeManager.void_type;
2726 if (t == typeof (object))
2727 return TypeManager.object_type;
2728 if (t == typeof (System.Type))
2729 return TypeManager.type_type;
2730 if (t == typeof (System.IntPtr))
2731 return TypeManager.intptr_type;
2737 /// Utility function that can be used to probe whether a type
2738 /// is managed or not.
2740 public static bool VerifyUnManaged (Type t, Location loc)
2742 if (t.IsValueType || t.IsPointer){
2744 // FIXME: this is more complex, we actually need to
2745 // make sure that the type does not contain any
2751 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2752 // We need this explicit check here to make it work when
2753 // compiling corlib.
2758 "Cannot take the address or size of a variable of a managed type ('" +
2759 CSharpName (t) + "')");
2764 /// Returns the name of the indexer in a given type.
2767 /// The default is not always `Item'. The user can change this behaviour by
2768 /// using the IndexerNameAttribute in the container.
2770 /// For example, the String class indexer is named `Chars' not `Item'
2772 public static string IndexerPropertyName (Type t)
2774 if (t.IsGenericInstance)
2775 t = t.GetGenericTypeDefinition ();
2777 if (t is TypeBuilder) {
2778 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2779 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2782 System.Attribute attr = System.Attribute.GetCustomAttribute (
2783 t, TypeManager.default_member_type);
2785 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2786 return dma.MemberName;
2789 return TypeContainer.DefaultIndexerName;
2792 static MethodInfo declare_local_method = null;
2794 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2796 if (declare_local_method == null){
2797 declare_local_method = typeof (ILGenerator).GetMethod (
2799 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2801 new Type [] { typeof (Type), typeof (bool)},
2803 if (declare_local_method == null){
2804 Report.Warning (-24, new Location (-1),
2805 "This version of the runtime does not support making pinned local variables. " +
2806 "This code may cause errors on a runtime with a moving GC");
2807 return ig.DeclareLocal (t);
2810 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2814 // Returns whether the array of memberinfos contains the given method
2816 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2818 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2820 foreach (MethodBase method in array) {
2821 if (method.Name != new_method.Name)
2824 if (method is MethodInfo && new_method is MethodInfo)
2825 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2829 Type [] old_args = TypeManager.GetArgumentTypes (method);
2830 int old_count = old_args.Length;
2833 if (new_args.Length != old_count)
2836 for (i = 0; i < old_count; i++){
2837 if (old_args [i] != new_args [i])
2850 // We copy methods from `new_members' into `target_list' if the signature
2851 // for the method from in the new list does not exist in the target_list
2853 // The name is assumed to be the same.
2855 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2857 if (target_list == null){
2858 target_list = new ArrayList ();
2860 foreach (MemberInfo mi in new_members){
2861 if (mi is MethodBase)
2862 target_list.Add (mi);
2867 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2868 target_list.CopyTo (target_array, 0);
2870 foreach (MemberInfo mi in new_members){
2871 MethodBase new_method = (MethodBase) mi;
2873 if (!ArrayContainsMethod (target_array, new_method))
2874 target_list.Add (new_method);
2879 static public bool IsGenericMethod (MethodBase mb)
2881 if (mb.DeclaringType is TypeBuilder) {
2882 IMethodData method = (IMethodData) builder_to_method [mb];
2886 return method.GenericMethod != null;
2889 return mb.IsGenericMethodDefinition;
2892 #region MemberLookup implementation
2895 // Whether we allow private members in the result (since FindMembers
2896 // uses NonPublic for both protected and private), we need to distinguish.
2899 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2904 internal class Closure {
2905 internal bool private_ok;
2907 // Who is invoking us and which type is being queried currently.
2908 internal Type invocation_type;
2909 internal Type qualifier_type;
2911 // The assembly that defines the type is that is calling us
2912 internal Assembly invocation_assembly;
2913 internal IList almost_match;
2915 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2917 if (invocation_type == null)
2923 // A nested class has access to all the protected members visible
2925 if (qualifier_type != null
2926 && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2929 if (invocation_type == m.DeclaringType
2930 || invocation_type.IsSubclassOf (m.DeclaringType)) {
2931 // Although a derived class can access protected members of
2932 // its base class it cannot do so through an instance of the
2933 // base class (CS1540).
2934 // => Ancestry should be: declaring_type ->* invocation_type
2935 // ->* qualified_type
2936 if (qualifier_type == null
2937 || qualifier_type == invocation_type
2938 || qualifier_type.IsSubclassOf (invocation_type))
2942 if (almost_match != null)
2943 almost_match.Add (m);
2947 bool Filter (MethodBase mb, object filter_criteria)
2949 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2951 if (ma == MethodAttributes.Private)
2952 return private_ok ||
2953 IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
2954 IsNestedChildOf (invocation_type, mb.DeclaringType);
2957 // FamAndAssem requires that we not only derivate, but we are on the
2960 if (ma == MethodAttributes.FamANDAssem){
2961 if (invocation_assembly != mb.DeclaringType.Assembly)
2965 // Assembly and FamORAssem succeed if we're in the same assembly.
2966 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2967 if (invocation_assembly == mb.DeclaringType.Assembly)
2971 // We already know that we aren't in the same assembly.
2972 if (ma == MethodAttributes.Assembly)
2975 // Family and FamANDAssem require that we derive.
2976 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2977 if (invocation_type == null)
2980 if (!IsNestedFamilyAccessible (invocation_type, mb.DeclaringType))
2983 // Although a derived class can access protected members of its base class
2984 // it cannot do so through an instance of the base class (CS1540).
2985 if (!mb.IsStatic && (qualifier_type != null) &&
2986 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
2987 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
2988 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2998 bool Filter (FieldInfo fi, object filter_criteria)
3000 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3002 if (fa == FieldAttributes.Private)
3003 return private_ok ||
3004 IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
3005 IsNestedChildOf (invocation_type, fi.DeclaringType);
3008 // FamAndAssem requires that we not only derivate, but we are on the
3011 if (fa == FieldAttributes.FamANDAssem){
3012 if (invocation_assembly != fi.DeclaringType.Assembly)
3016 // Assembly and FamORAssem succeed if we're in the same assembly.
3017 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
3018 if (invocation_assembly == fi.DeclaringType.Assembly)
3022 // We already know that we aren't in the same assembly.
3023 if (fa == FieldAttributes.Assembly)
3026 // Family and FamANDAssem require that we derive.
3027 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
3028 if (invocation_type == null)
3031 if (!IsNestedFamilyAccessible (invocation_type, fi.DeclaringType))
3034 // Although a derived class can access protected members of its base class
3035 // it cannot do so through an instance of the base class (CS1540).
3036 if (!fi.IsStatic && (qualifier_type != null) &&
3037 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
3038 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
3039 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3050 // This filter filters by name + whether it is ok to include private
3051 // members in the search
3053 internal bool Filter (MemberInfo m, object filter_criteria)
3056 // Hack: we know that the filter criteria will always be in the
3057 // `closure' // fields.
3060 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3063 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3064 (invocation_type != null) &&
3065 IsPrivateAccessible (m.DeclaringType, invocation_type))
3069 // Ugly: we need to find out the type of `m', and depending
3070 // on this, tell whether we accept or not
3072 if (m is MethodBase)
3073 return Filter ((MethodBase) m, filter_criteria);
3076 return Filter ((FieldInfo) m, filter_criteria);
3079 // EventInfos and PropertyInfos, return true because they lack
3080 // permission information, so we need to check later on the methods.
3086 static Closure closure = new Closure ();
3087 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3090 // Looks up a member called `name' in the `queried_type'. This lookup
3091 // is done by code that is contained in the definition for `invocation_type'
3092 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3094 // `invocation_type' is used to check whether we're allowed to access the requested
3095 // member wrt its protection level.
3097 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3098 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3099 // is B and qualifier_type is A). This is used to do the CS1540 check.
3101 // When resolving a SimpleName, `qualifier_type' is null.
3103 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3104 // the same than `queried_type' - except when we're being called from BaseAccess;
3105 // in this case, `invocation_type' is the current type and `queried_type' the base
3106 // type, so this'd normally trigger a CS1540.
3108 // The binding flags are `bf' and the kind of members being looked up are `mt'
3110 // The return value always includes private members which code in `invocation_type'
3111 // is allowed to access (using the specified `qualifier_type' if given); only use
3112 // BindingFlags.NonPublic to bypass the permission check.
3114 // The 'almost_match' argument is used for reporting error CS1540.
3116 // Returns an array of a single element for everything but Methods/Constructors
3117 // that might return multiple matches.
3119 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3120 Type queried_type, MemberTypes mt,
3121 BindingFlags original_bf, string name, IList almost_match)
3123 Timer.StartTimer (TimerType.MemberLookup);
3125 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3126 queried_type, mt, original_bf, name, almost_match);
3128 Timer.StopTimer (TimerType.MemberLookup);
3133 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3134 Type queried_type, MemberTypes mt,
3135 BindingFlags original_bf, string name, IList almost_match)
3137 BindingFlags bf = original_bf;
3139 ArrayList method_list = null;
3140 Type current_type = queried_type;
3141 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3142 bool skip_iface_check = true, used_cache = false;
3143 bool always_ok_flag = false;
3145 closure.invocation_type = invocation_type;
3146 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3147 closure.qualifier_type = qualifier_type;
3148 closure.almost_match = almost_match;
3151 // If we are a nested class, we always have access to our container
3154 if (invocation_type != null){
3155 string invocation_name = invocation_type.FullName;
3156 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
3157 string container = queried_type.FullName + "+";
3158 int container_length = container.Length;
3160 if (invocation_name.Length > container_length){
3161 string shared = invocation_name.Substring (0, container_length);
3163 if (shared == container)
3164 always_ok_flag = true;
3169 // This is from the first time we find a method
3170 // in most cases, we do not actually find a method in the base class
3171 // so we can just ignore it, and save the arraylist allocation
3172 MemberInfo [] first_members_list = null;
3173 bool use_first_members_list = false;
3179 // `NonPublic' is lame, because it includes both protected and
3180 // private methods, so we need to control this behavior by
3181 // explicitly tracking if a private method is ok or not.
3183 // The possible cases are:
3184 // public, private and protected (internal does not come into the
3187 if ((invocation_type != null) &&
3188 ((invocation_type == current_type) ||
3189 IsNestedChildOf (invocation_type, current_type)) ||
3191 bf = original_bf | BindingFlags.NonPublic;
3195 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3197 Timer.StopTimer (TimerType.MemberLookup);
3199 list = MemberLookup_FindMembers (
3200 current_type, mt, bf, name, out used_cache);
3202 Timer.StartTimer (TimerType.MemberLookup);
3205 // When queried for an interface type, the cache will automatically check all
3206 // inherited members, so we don't need to do this here. However, this only
3207 // works if we already used the cache in the first iteration of this loop.
3209 // If we used the cache in any further iteration, we can still terminate the
3210 // loop since the cache always looks in all parent classes.
3216 skip_iface_check = false;
3218 if (current_type == TypeManager.object_type)
3221 current_type = current_type.BaseType;
3224 // This happens with interfaces, they have a null
3225 // basetype. Look members up in the Object class.
3227 if (current_type == null) {
3228 current_type = TypeManager.object_type;
3233 if (list.Length == 0)
3237 // Events and types are returned by both `static' and `instance'
3238 // searches, which means that our above FindMembers will
3239 // return two copies of the same.
3241 if (list.Length == 1 && !(list [0] is MethodBase)){
3246 // Multiple properties: we query those just to find out the indexer
3249 if (list [0] is PropertyInfo)
3253 // We found an event: the cache lookup returns both the event and
3254 // its private field.
3256 if (list [0] is EventInfo) {
3257 if ((list.Length == 2) && (list [1] is FieldInfo))
3258 return new MemberInfo [] { list [0] };
3265 // We found methods, turn the search into "method scan"
3269 if (first_members_list != null) {
3270 if (use_first_members_list) {
3271 method_list = CopyNewMethods (method_list, first_members_list);
3272 use_first_members_list = false;
3275 method_list = CopyNewMethods (method_list, list);
3277 first_members_list = list;
3278 use_first_members_list = true;
3280 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3282 } while (searching);
3284 if (use_first_members_list) {
3285 foreach (MemberInfo mi in first_members_list) {
3286 if (! (mi is MethodBase)) {
3287 method_list = CopyNewMethods (method_list, first_members_list);
3288 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3291 return (MemberInfo []) first_members_list;
3294 if (method_list != null && method_list.Count > 0) {
3295 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3298 // This happens if we already used the cache in the first iteration, in this case
3299 // the cache already looked in all interfaces.
3301 if (skip_iface_check)
3305 // Interfaces do not list members they inherit, so we have to
3308 if (!queried_type.IsInterface)
3311 if (queried_type.IsArray)
3312 queried_type = TypeManager.array_type;
3314 Type [] ifaces = GetInterfaces (queried_type);
3318 foreach (Type itype in ifaces){
3321 x = MemberLookup (null, null, itype, mt, bf, name, null);
3329 // Tests whether external method is really special
3330 public static bool IsSpecialMethod (MethodBase mb)
3332 string name = mb.Name;
3333 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3334 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3336 if (name.StartsWith ("add_"))
3337 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3339 if (name.StartsWith ("remove_"))
3340 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3342 if (name.StartsWith ("op_")){
3343 foreach (string oname in Unary.oper_names) {
3348 foreach (string oname in Binary.oper_names) {
3361 /// There is exactly one instance of this class per type.
3363 public sealed class TypeHandle : IMemberContainer {
3364 public readonly TypeHandle BaseType;
3366 readonly int id = ++next_id;
3367 static int next_id = 0;
3370 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3371 /// a TypeHandle yet, a new instance of it is created. This static method
3372 /// ensures that we'll only have one TypeHandle instance per type.
3374 private static TypeHandle GetTypeHandle (Type t)
3376 TypeHandle handle = (TypeHandle) type_hash [t];
3380 handle = new TypeHandle (t);
3381 type_hash.Add (t, handle);
3385 public static MemberCache GetMemberCache (Type t)
3387 return GetTypeHandle (t).MemberCache;
3390 public static void CleanUp ()
3396 /// Returns the TypeHandle for TypeManager.object_type.
3398 public static IMemberContainer ObjectType {
3400 if (object_type != null)
3403 object_type = GetTypeHandle (TypeManager.object_type);
3410 /// Returns the TypeHandle for TypeManager.array_type.
3412 public static IMemberContainer ArrayType {
3414 if (array_type != null)
3417 array_type = GetTypeHandle (TypeManager.array_type);
3423 private static PtrHashtable type_hash = new PtrHashtable ();
3425 private static TypeHandle object_type = null;
3426 private static TypeHandle array_type = null;
3429 private string full_name;
3430 private bool is_interface;
3431 private MemberCache member_cache;
3432 private MemberCache parent_cache;
3434 private TypeHandle (Type type)
3437 full_name = type.FullName != null ? type.FullName : type.Name;
3438 if (type.BaseType != null) {
3439 BaseType = GetTypeHandle (type.BaseType);
3440 parent_cache = BaseType.MemberCache;
3441 } else if (type.IsInterface)
3442 parent_cache = TypeManager.LookupParentInterfacesCache (type);
3443 this.is_interface = type.IsInterface || type.IsGenericParameter;
3444 this.member_cache = new MemberCache (this);
3447 // IMemberContainer methods
3449 public string Name {
3461 public MemberCache ParentCache {
3463 return parent_cache;
3467 public bool IsInterface {
3469 return is_interface;
3473 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3475 MemberInfo [] members;
3476 if (type is GenericTypeParameterBuilder)
3477 return MemberList.Empty;
3478 if (mt == MemberTypes.Event)
3479 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3481 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3483 Array.Reverse (members);
3485 return new MemberList (members);
3488 // IMemberFinder methods
3490 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3491 MemberFilter filter, object criteria)
3493 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3496 public MemberCache MemberCache {
3498 return member_cache;
3502 public override string ToString ()
3504 if (BaseType != null)
3505 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3507 return "TypeHandle (" + id + "," + Name + ")";