2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public partial class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static Type _uint32_type;
42 static public Type int64_type;
43 static Type _uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type _sbyte_type;
52 static public Type byte_type;
53 static public Type _ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type null_type;
59 static public Type enumeration_type;
60 static public Type array_type;
61 static public Type runtime_handle_type;
62 static public Type icloneable_type;
63 static public Type type_type;
64 static public Type ienumerator_type;
65 static public Type ienumerable_type;
66 static public Type idisposable_type;
67 static public Type iconvertible_type;
68 static public Type default_member_type;
69 static public Type iasyncresult_type;
70 static public Type asynccallback_type;
71 static public Type intptr_type;
72 static public Type monitor_type;
73 static public Type runtime_field_handle_type;
74 static public Type runtime_argument_handle_type;
75 static public Type attribute_type;
76 static public Type attribute_usage_type;
77 static public Type decimal_constant_attribute_type;
78 static public Type dllimport_type;
79 static public Type unverifiable_code_type;
80 static public Type methodimpl_attr_type;
81 static public Type marshal_as_attr_type;
82 static public Type param_array_type;
83 static public Type guid_attr_type;
84 static public Type void_ptr_type;
85 static public Type indexer_name_type;
86 static public Type exception_type;
87 static public Type invalid_operation_exception_type;
88 static public Type not_supported_exception_type;
89 static public Type obsolete_attribute_type;
90 static public Type conditional_attribute_type;
91 static public Type in_attribute_type;
92 static public Type out_attribute_type;
93 static public Type anonymous_method_type;
94 static public Type cls_compliant_attribute_type;
95 static public Type typed_reference_type;
96 static public Type arg_iterator_type;
97 static public Type mbr_type;
98 static public Type struct_layout_attribute_type;
99 static public Type field_offset_attribute_type;
100 static public Type security_attr_type;
101 static public Type date_type;
106 static public Type convert_type;
107 static public Type math_type;
110 // Type cache of helper classes in Microsoft.VisualBasic.dll
112 static public Type msvbcs_object_type;
113 static public Type msvbcs_boolean_type;
114 static public Type msvbcs_byte_type;
115 static public Type msvbcs_short_type;
116 static public Type msvbcs_integer_type;
117 static public Type msvbcs_long_type;
118 static public Type msvbcs_decimal_type;
119 static public Type msvbcs_single_type;
120 static public Type msvbcs_double_type;
121 static public Type msvbcs_string_type;
122 static public Type msvbcs_char_type;
123 static public Type msvbcs_chararray_type;
124 static public Type msvbcs_date_type;
126 static public Type msvbcs_comparemethod_type;
129 // Unlike C#, VB.NET doesn't understand "signed byte",
130 // "unsigned short" and "unsigned int" as primitive types. The
131 // NotDefinedAsPrimitiveType just exists to accomodate this fact.
134 static Type not_defined_as_primitive_type = typeof (NotDefinedAsPrimitiveType);
136 public static Type sbyte_type {
138 return not_defined_as_primitive_type;
143 public static Type ushort_type {
145 return not_defined_as_primitive_type;
150 public static Type uint32_type {
152 return not_defined_as_primitive_type;
157 public static Type uint64_type {
159 return not_defined_as_primitive_type;
165 // An empty array of types
167 static public Type [] NoTypes;
168 static public TypeExpr [] NoTypeExprs;
172 // Expressions representing the internal types. Used during declaration
175 static public TypeExpr system_object_expr, system_string_expr;
176 static public TypeExpr system_boolean_expr, system_decimal_expr;
177 static public TypeExpr system_single_expr, system_double_expr;
178 static public TypeExpr system_sbyte_expr, system_byte_expr;
179 static public TypeExpr system_int16_expr, system_uint16_expr;
180 static public TypeExpr system_int32_expr, system_uint32_expr;
181 static public TypeExpr system_int64_expr, system_uint64_expr;
182 static public TypeExpr system_char_expr, system_void_expr;
183 static public TypeExpr system_asynccallback_expr;
184 static public TypeExpr system_iasyncresult_expr;
185 static public TypeExpr system_valuetype_expr;
186 static public TypeExpr system_intptr_expr;
191 static public TypeExpr system_date_expr;
194 // This is only used when compiling corlib
196 static public Type system_int32_type;
197 static public Type system_array_type;
198 static public Type system_type_type;
199 static public Type system_assemblybuilder_type;
200 static public MethodInfo system_int_array_get_length;
201 static public MethodInfo system_int_array_get_rank;
202 static public MethodInfo system_object_array_clone;
203 static public MethodInfo system_int_array_get_length_int;
204 static public MethodInfo system_int_array_get_lower_bound_int;
205 static public MethodInfo system_int_array_get_upper_bound_int;
206 static public MethodInfo system_void_array_copyto_array_int;
210 // Internal, not really used outside
212 static Type runtime_helpers_type;
215 // These methods are called by code generated by the compiler
217 static public MethodInfo string_concat_string_string;
218 static public MethodInfo string_concat_string_string_string;
219 static public MethodInfo string_concat_string_string_string_string;
220 static public MethodInfo string_concat_string_dot_dot_dot;
221 static public MethodInfo string_concat_object_object;
222 static public MethodInfo string_concat_object_object_object;
223 static public MethodInfo string_concat_object_dot_dot_dot;
224 static public MethodInfo string_isinterneted_string;
225 static public MethodInfo system_type_get_type_from_handle;
226 static public MethodInfo object_getcurrent_void;
227 static public MethodInfo bool_movenext_void;
228 static public MethodInfo ienumerable_getenumerator_void;
229 static public MethodInfo void_reset_void;
230 static public MethodInfo void_dispose_void;
231 static public MethodInfo void_monitor_enter_object;
232 static public MethodInfo void_monitor_exit_object;
233 static public MethodInfo void_initializearray_array_fieldhandle;
234 static public MethodInfo int_getlength_int;
235 static public MethodInfo delegate_combine_delegate_delegate;
236 static public MethodInfo delegate_remove_delegate_delegate;
237 static public MethodInfo int_get_offset_to_string_data;
238 static public MethodInfo int_array_get_length;
239 static public MethodInfo int_array_get_rank;
240 static public MethodInfo object_array_clone;
241 static public MethodInfo int_array_get_length_int;
242 static public MethodInfo int_array_get_lower_bound_int;
243 static public MethodInfo int_array_get_upper_bound_int;
244 static public MethodInfo void_array_copyto_array_int;
247 // The attribute constructors.
249 static public ConstructorInfo object_ctor;
250 static public ConstructorInfo cons_param_array_attribute;
251 static public ConstructorInfo void_decimal_ctor_five_args;
252 static public ConstructorInfo void_decimal_ctor_int_arg;
253 static public ConstructorInfo unverifiable_code_ctor;
254 static public ConstructorInfo invalid_operation_ctor;
255 static public ConstructorInfo default_member_ctor;
256 static public ConstructorInfo decimal_constant_attribute_ctor;
259 // Type cache of helper methods in Microsoft.VisualBasic.dll
261 static public MethodInfo convert_to_byte_decimal;
262 static public MethodInfo convert_to_int16_decimal;
263 static public MethodInfo convert_to_int32_decimal;
264 static public MethodInfo convert_to_int64_decimal;
265 static public MethodInfo convert_to_single_decimal;
266 static public MethodInfo convert_to_double_decimal;
267 static public MethodInfo convert_to_boolean_decimal;
269 static public MethodInfo decimal_compare_decimal_decimal;
270 static public MethodInfo datetime_compare_datetime_datetime;
271 static public MethodInfo math_round_double;
273 static public MethodInfo msvbcs_booleantype_from_string;
274 static public MethodInfo msvbcs_bytetype_from_string;
275 static public MethodInfo msvbcs_shorttype_from_string;
276 static public MethodInfo msvbcs_integertype_from_string;
277 static public MethodInfo msvbcs_longtype_from_string;
278 static public MethodInfo msvbcs_decimaltype_from_string;
279 static public MethodInfo msvbcs_singletype_from_string;
280 static public MethodInfo msvbcs_doubletype_from_string;
281 static public MethodInfo msvbcs_chartype_from_string;
282 static public MethodInfo msvbcs_datetype_from_string;
284 static public MethodInfo msvbcs_stringtype_from_boolean;
285 static public MethodInfo msvbcs_stringtype_from_byte;
286 static public MethodInfo msvbcs_stringtype_from_short;
287 static public MethodInfo msvbcs_stringtype_from_integer;
288 static public MethodInfo msvbcs_stringtype_from_long;
289 static public MethodInfo msvbcs_stringtype_from_decimal;
290 static public MethodInfo msvbcs_stringtype_from_single;
291 static public MethodInfo msvbcs_stringtype_from_double;
292 static public MethodInfo msvbcs_stringtype_from_date;
293 static public MethodInfo msvbcs_stringtype_from_char;
295 static public MethodInfo msvbcs_decimaltype_from_boolean;
297 static public MethodInfo msvbcs_stringtype_strcmp_string_string_boolean;
298 static public MethodInfo msvbcs_stringtype_strlike_string_string_comparemethod;
300 static public MethodInfo msvbcs_booleantype_fromobject_object;
301 static public MethodInfo msvbcs_bytetype_fromobject_object;
302 static public MethodInfo msvbcs_shorttype_fromobject_object;
303 static public MethodInfo msvbcs_integertype_fromobject_object;
304 static public MethodInfo msvbcs_longtype_fromobject_object;
305 static public MethodInfo msvbcs_singletype_fromobject_object;
306 static public MethodInfo msvbcs_doubletype_fromobject_object;
307 static public MethodInfo msvbcs_decimaltype_fromobject_object;
308 static public MethodInfo msvbcs_chartype_fromobject_object;
309 static public MethodInfo msvbcs_datetype_fromobject_object;
310 static public MethodInfo msvbcs_stringtype_fromobject_object;
312 static public MethodInfo msvbcs_objecttype_mulobj_object_object;
313 static public MethodInfo msvbcs_objecttype_divobj_object_object;
314 static public MethodInfo msvbcs_objecttype_idivobj_object_object;
315 static public MethodInfo msvbcs_objecttype_modobj_object_object;
316 static public MethodInfo msvbcs_objecttype_addobj_object_object;
317 static public MethodInfo msvbcs_objecttype_subobj_object_object;
318 static public MethodInfo msvbcs_objecttype_objtst_object_object_boolean;
319 static public MethodInfo msvbcs_objecttype_bitandobj_object_object;
320 static public MethodInfo msvbcs_objecttype_bitorobj_object_object;
321 static public MethodInfo msvbcs_objecttype_bitxorobj_object_object;
322 static public MethodInfo msvbcs_objecttype_likeobj_object_object_comparemethod;
323 static public MethodInfo msvbcs_objecttype_strcatobj_object_object;
324 static public MethodInfo msvbcs_objecttype_powobj_object_object;
325 static public MethodInfo msvbcs_objecttype_shiftleftobj_object_int32;
326 static public MethodInfo msvbcs_objecttype_shiftrightobj_object_int32;
328 static public MethodInfo math_pow_double_double;
330 static public MethodInfo decimal_add_decimal_decimal;
331 static public MethodInfo decimal_subtract_decimal_decimal;
332 static public MethodInfo decimal_multiply_decimal_decimal;
333 static public MethodInfo decimal_divide_decimal_decimal;
334 static public MethodInfo decimal_remainder_decimal_decimal;
336 static public ConstructorInfo void_datetime_ctor_ticks_arg;
339 // Holds the Array of Assemblies that have been loaded
340 // (either because it is the default or the user used the
341 // -r command line option)
343 static Assembly [] assemblies;
346 // Keeps a list of modules. We used this to do lookups
347 // on the module using GetType -- needed for arrays
349 static Module [] modules;
352 // This is the type_cache from the assemblies to avoid
353 // hitting System.Reflection on every lookup.
355 static Hashtable types;
358 // This is used to hotld the corresponding TypeContainer objects
359 // since we need this in FindMembers
361 static Hashtable typecontainers;
364 // Keeps track of those types that are defined by the
367 static ArrayList user_types;
369 static PtrHashtable builder_to_declspace;
371 static PtrHashtable builder_to_member_cache;
374 // Tracks the interfaces implemented by typebuilders. We only
375 // enter those who do implement or or more interfaces
377 static PtrHashtable builder_to_ifaces;
380 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
381 // the arguments to the method
383 static Hashtable method_arguments;
386 // Maps PropertyBuilder to a Type array that contains
387 // the arguments to the indexer
389 static Hashtable indexer_arguments;
392 // Maybe `method_arguments' should be replaced and only
393 // method_internal_params should be kept?
395 static Hashtable method_internal_params;
398 // Keeps track of methods
401 static Hashtable builder_to_method;
404 // Contains all public types from referenced assemblies.
405 // This member is used only if CLS Compliance verification is required.
407 public static Hashtable all_imported_types;
414 public static void CleanUp ()
416 // Lets get everything clean so that we can collect before generating code
420 typecontainers = null;
422 builder_to_declspace = null;
423 builder_to_member_cache = null;
424 builder_to_ifaces = null;
425 method_arguments = null;
426 indexer_arguments = null;
427 method_internal_params = null;
428 builder_to_method = null;
432 negative_hits = null;
433 builder_to_constant = null;
434 fieldbuilders_to_fields = null;
436 priv_fields_events = null;
440 TypeHandle.CleanUp ();
444 /// A filter for Findmembers that uses the Signature object to
447 static bool SignatureFilter (MemberInfo mi, object criteria)
449 Signature sig = (Signature) criteria;
451 if (!(mi is MethodBase))
454 if (mi.Name != sig.name)
457 int count = sig.args.Length;
459 if (mi is MethodBuilder || mi is ConstructorBuilder){
460 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
462 if (candidate_args.Length != count)
465 for (int i = 0; i < count; i++)
466 if (candidate_args [i] != sig.args [i])
471 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
473 if (pars.Length != count)
476 for (int i = 0; i < count; i++)
477 if (pars [i].ParameterType != sig.args [i])
483 // A delegate that points to the filter above.
484 static MemberFilter signature_filter;
487 // These are expressions that represent some of the internal data types, used
490 static void InitExpressionTypes ()
492 system_object_expr = new TypeLookupExpression ("System.Object");
493 system_string_expr = new TypeLookupExpression ("System.String");
494 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
495 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
496 system_single_expr = new TypeLookupExpression ("System.Single");
497 system_double_expr = new TypeLookupExpression ("System.Double");
498 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
499 system_byte_expr = new TypeLookupExpression ("System.Byte");
500 system_int16_expr = new TypeLookupExpression ("System.Int16");
501 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
502 system_int32_expr = new TypeLookupExpression ("System.Int32");
503 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
504 system_int64_expr = new TypeLookupExpression ("System.Int64");
505 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
506 system_char_expr = new TypeLookupExpression ("System.Char");
507 system_void_expr = new TypeLookupExpression ("System.Void");
508 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
509 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
510 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
511 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
516 system_date_expr = new TypeLookupExpression ("System.DateTime");
519 static TypeManager ()
521 assemblies = new Assembly [0];
523 user_types = new ArrayList ();
525 types = new Hashtable ();
526 typecontainers = new Hashtable ();
528 builder_to_declspace = new PtrHashtable ();
529 builder_to_member_cache = new PtrHashtable ();
530 builder_to_method = new PtrHashtable ();
531 method_arguments = new PtrHashtable ();
532 method_internal_params = new PtrHashtable ();
533 indexer_arguments = new PtrHashtable ();
534 builder_to_ifaces = new PtrHashtable ();
536 NoTypes = new Type [0];
537 NoTypeExprs = new TypeExpr [0];
539 signature_filter = new MemberFilter (SignatureFilter);
541 InitExpressionTypes ();
544 public static void HandleDuplicate (string name, Type t)
546 Type prev = (Type) types [name];
547 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
551 // This probably never happens, as we catch this before
553 Report.Error (-17, "The type `" + name + "' has already been defined.");
557 tc = builder_to_declspace [t] as TypeContainer;
560 1595, "The type `" + name + "' is defined in an existing assembly;"+
561 " Using the new definition from: " + tc.Location);
564 1595, "The type `" + name + "' is defined in an existing assembly;");
567 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
573 public static void AddUserType (string name, TypeBuilder t)
578 HandleDuplicate (name, t);
584 // This entry point is used by types that we define under the covers
586 public static void RegisterBuilder (Type tb, Type [] ifaces)
589 builder_to_ifaces [tb] = ifaces;
592 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
594 builder_to_declspace.Add (t, tc);
595 typecontainers.Add (name, tc);
596 AddUserType (name, t);
599 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
604 HandleDuplicate (name, t);
607 builder_to_declspace.Add (t, del);
610 public static void AddEnumType (string name, TypeBuilder t, Enum en)
615 HandleDuplicate (name, t);
617 builder_to_declspace.Add (t, en);
620 public static void AddMethod (MethodBase builder, IMethodData method)
622 builder_to_method.Add (builder, method);
625 public static IMethodData GetMethod (MethodBase builder)
627 return (IMethodData) builder_to_method [builder];
631 /// Returns the DeclSpace whose Type is `t' or null if there is no
632 /// DeclSpace for `t' (ie, the Type comes from a library)
634 public static DeclSpace LookupDeclSpace (Type t)
636 return builder_to_declspace [t] as DeclSpace;
640 /// Returns the TypeContainer whose Type is `t' or null if there is no
641 /// TypeContainer for `t' (ie, the Type comes from a library)
643 public static TypeContainer LookupTypeContainer (Type t)
645 return builder_to_declspace [t] as TypeContainer;
648 public static MemberCache LookupMemberCache (Type t)
650 if (t is TypeBuilder) {
651 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
652 if (container != null)
653 return container.MemberCache;
656 if (t is GenericTypeParameterBuilder) {
657 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
659 if (container != null)
660 return container.MemberCache;
663 return TypeHandle.GetMemberCache (t);
666 public static MemberCache LookupBaseInterfacesCache (Type t)
668 Type [] ifaces = t.GetInterfaces ();
670 if (ifaces != null && ifaces.Length == 1)
671 return LookupMemberCache (ifaces [0]);
673 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
674 MemberCache cache = builder_to_member_cache [t] as MemberCache;
678 cache = new MemberCache (ifaces);
679 builder_to_member_cache.Add (t, cache);
683 public static TypeContainer LookupInterface (Type t)
685 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
686 if ((tc == null) || (tc.Kind != Kind.Interface))
692 public static Delegate LookupDelegate (Type t)
694 return builder_to_declspace [t] as Delegate;
697 public static Enum LookupEnum (Type t)
699 return builder_to_declspace [t] as Enum;
702 public static Class LookupClass (Type t)
704 return (Class) builder_to_declspace [t];
708 /// Registers an assembly to load types from.
710 public static void AddAssembly (Assembly a)
712 foreach (Assembly assembly in assemblies) {
717 int top = assemblies.Length;
718 Assembly [] n = new Assembly [top + 1];
720 assemblies.CopyTo (n, 0);
726 public static Assembly [] GetAssemblies ()
732 /// Registers a module builder to lookup types from
734 public static void AddModule (Module mb)
736 int top = modules != null ? modules.Length : 0;
737 Module [] n = new Module [top + 1];
740 modules.CopyTo (n, 0);
745 public static Module[] Modules {
751 static Hashtable references = new Hashtable ();
754 // Gets the reference to T version of the Type (T&)
756 public static Type GetReferenceType (Type t)
758 return t.MakeByRefType ();
761 static Hashtable pointers = new Hashtable ();
764 // Gets the pointer to T version of the Type (T*)
766 public static Type GetPointerType (Type t)
768 string tname = t.FullName + "*";
770 Type ret = t.Assembly.GetType (tname);
773 // If the type comes from the assembly we are building
774 // We need the Hashtable, because .NET 1.1 will return different instance types
775 // every time we call ModuleBuilder.GetType.
778 if (pointers [t] == null)
779 pointers [t] = CodeGen.Module.Builder.GetType (tname);
781 ret = (Type) pointers [t];
788 // Low-level lookup, cache-less
790 static Type LookupTypeReflection (string name)
794 foreach (Assembly a in assemblies){
795 t = a.GetType (name);
800 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
801 if (ta == TypeAttributes.NotPublic ||
802 ta == TypeAttributes.NestedPrivate ||
803 ta == TypeAttributes.NestedAssembly ||
804 ta == TypeAttributes.NestedFamANDAssem){
807 // In .NET pointers turn out to be private, even if their
808 // element type is not
811 t = t.GetElementType ();
821 foreach (Module mb in modules) {
822 t = mb.GetType (name);
830 static Hashtable negative_hits = new Hashtable ();
833 // This function is used when you want to avoid the lookups, and want to go
834 // directly to the source. This will use the cache.
836 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
837 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
838 // way to test things other than doing a fullname compare
840 public static Type LookupTypeDirect (string name)
842 Type t = (Type) types [name];
846 t = LookupTypeReflection (name);
854 static readonly char [] dot_array = { '.' };
857 /// Returns the Type associated with @name, takes care of the fact that
858 /// reflection expects nested types to be separated from the main type
859 /// with a "+" instead of a "."
861 public static Type LookupType (string name)
866 // First lookup in user defined and cached values
869 t = (Type) types [name];
873 // Two thirds of the failures are caught here.
874 if (negative_hits.Contains (name))
877 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
878 string [] elements = name.Split (dot_array);
879 int count = elements.Length;
881 for (int n = 1; n <= count; n++){
882 string top_level_type = String.Join (".", elements, 0, n);
884 // One third of the failures are caught here.
885 if (negative_hits.Contains (top_level_type))
888 t = (Type) types [top_level_type];
890 t = LookupTypeReflection (top_level_type);
892 negative_hits [top_level_type] = null;
903 // We know that System.Object does not have children, and since its the base of
904 // all the objects, it always gets probbed for inner classes.
906 if (top_level_type == "System.Object")
909 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
910 //Console.WriteLine ("Looking up: " + newt + " " + name);
911 t = LookupTypeReflection (newt);
913 negative_hits [name] = null;
918 negative_hits [name] = null;
923 /// Computes the namespaces that we import from the assemblies we reference.
925 public static void ComputeNamespaces ()
927 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
930 // First add the assembly namespaces
932 if (assembly_get_namespaces != null){
933 int count = assemblies.Length;
935 for (int i = 0; i < count; i++){
936 Assembly a = assemblies [i];
937 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
938 foreach (string ns in namespaces){
941 Namespace.LookupNamespace (ns, true);
945 Hashtable cache = new Hashtable ();
946 cache.Add ("", null);
947 foreach (Assembly a in assemblies) {
948 foreach (Type t in a.GetExportedTypes ()) {
949 string ns = t.Namespace;
950 if (ns == null || cache.Contains (ns))
953 Namespace.LookupNamespace (ns, true);
954 cache.Add (ns, null);
961 /// Fills static table with exported types from all referenced assemblies.
962 /// This information is required for CLS Compliance tests.
964 public static void LoadAllImportedTypes ()
966 all_imported_types = new Hashtable ();
967 foreach (Assembly a in assemblies) {
968 foreach (Type t in a.GetExportedTypes ()) {
969 all_imported_types [t.FullName] = t;
974 public static bool NamespaceClash (string name, Location loc)
976 if (Namespace.LookupNamespace (name, false) == null)
979 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
984 /// Returns the C# name of a type if possible, or the full type name otherwise
986 static public string CSharpName (Type t)
988 if (t.FullName == null)
991 return Regex.Replace (t.FullName,
993 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
994 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
995 @"Boolean|String|Void|Null)" +
997 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
1000 static String CSharpNameMatch (Match match)
1002 string s = match.Groups [1].Captures [0].Value;
1003 return s.ToLower ().
1004 Replace ("int32", "int").
1005 Replace ("uint32", "uint").
1006 Replace ("int16", "short").
1007 Replace ("uint16", "ushort").
1008 Replace ("int64", "long").
1009 Replace ("uint64", "ulong").
1010 Replace ("single", "float").
1011 Replace ("boolean", "bool")
1012 + match.Groups [2].Captures [0].Value;
1016 /// Returns the signature of the method with full namespace classification
1018 static public string GetFullNameSignature (MemberInfo mi)
1020 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
1021 return (mi is MethodBase)
1022 ? GetFullNameSignature (mi as MethodBase)
1023 : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
1026 static public string GetFullNameSignature (MethodBase mb)
1028 string name = mb.Name;
1029 if (name == ".ctor")
1030 name = mb.DeclaringType.Name;
1032 if (mb.IsSpecialName) {
1033 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
1034 name = name.Remove (0, 4);
1041 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
1044 static public string GetFullName (Type t)
1046 if (t.FullName == null)
1049 string name = t.FullName.Replace ('+', '.');
1051 DeclSpace tc = LookupDeclSpace (t);
1052 if ((tc != null) && tc.IsGeneric) {
1053 TypeParameter[] tparam = tc.TypeParameters;
1055 StringBuilder sb = new StringBuilder (name);
1057 for (int i = 0; i < tparam.Length; i++) {
1060 sb.Append (tparam [i].Name);
1063 return sb.ToString ();
1064 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
1065 Type[] tparam = t.GetGenericArguments ();
1067 StringBuilder sb = new StringBuilder (name);
1069 for (int i = 0; i < tparam.Length; i++) {
1072 sb.Append (tparam [i].Name);
1075 return sb.ToString ();
1082 /// Returns the signature of the property and indexer
1084 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
1087 return GetFullNameSignature (pb);
1090 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
1091 string signature = GetFullNameSignature (mb);
1092 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
1093 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
1097 /// Returns the signature of the method
1099 static public string CSharpSignature (MethodBase mb)
1101 StringBuilder sig = new StringBuilder ("(");
1104 // FIXME: We should really have a single function to do
1105 // everything instead of the following 5 line pattern
1107 ParameterData iparams = LookupParametersByBuilder (mb);
1109 if (iparams == null)
1110 iparams = new ReflectionParameters (mb);
1113 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
1114 return GetFullNameSignature (mb);
1116 for (int i = 0; i < iparams.Count; i++) {
1120 sig.Append (iparams.ParameterDesc (i));
1125 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
1126 sig.Replace ('(', '[');
1127 sig.Replace (')', ']');
1130 return GetFullNameSignature (mb) + sig.ToString ();
1133 public static string GetMethodName (MethodInfo m)
1135 if (!IsGenericMethod (m))
1138 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
1142 /// Looks up a type, and aborts if it is not found. This is used
1143 /// by types required by the compiler
1145 static Type CoreLookupType (string name)
1147 Type t = LookupTypeDirect (name);
1150 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1151 Environment.Exit (1);
1158 /// Returns the MethodInfo for a method named `name' defined
1159 /// in type `t' which takes arguments of types `args'
1161 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1165 BindingFlags flags = instance_and_static | BindingFlags.Public;
1171 flags |= BindingFlags.NonPublic;
1173 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1174 if (list.Count == 0) {
1176 Report.Error (-19, "Can not find the core function `" + name + "'");
1180 MethodInfo mi = list [0] as MethodInfo;
1183 Report.Error (-19, "Can not find the core function `" + name + "'");
1190 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1192 return GetMethod (t, name, args, false, report_errors);
1195 static MethodInfo GetMethod (Type t, string name, Type [] args)
1197 return GetMethod (t, name, args, true);
1202 /// Returns the ConstructorInfo for "args"
1204 static ConstructorInfo GetConstructor (Type t, Type [] args)
1212 list = FindMembers (t, MemberTypes.Constructor,
1213 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1214 signature_filter, sig);
1215 if (list.Count == 0){
1216 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1220 ConstructorInfo ci = list [0] as ConstructorInfo;
1222 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1229 public static void InitEnumUnderlyingTypes ()
1232 int32_type = CoreLookupType ("System.Int32");
1233 int64_type = CoreLookupType ("System.Int64");
1234 _uint32_type = CoreLookupType ("System.UInt32");
1235 _uint64_type = CoreLookupType ("System.UInt64");
1236 byte_type = CoreLookupType ("System.Byte");
1237 _sbyte_type = CoreLookupType ("System.SByte");
1238 short_type = CoreLookupType ("System.Int16");
1239 _ushort_type = CoreLookupType ("System.UInt16");
1242 public static Hashtable relative_type_order;
1245 /// The types have to be initialized after the initial
1246 /// population of the type has happened (for example, to
1247 /// bootstrap the corlib.dll
1249 public static void InitCoreTypes ()
1251 object_type = CoreLookupType ("System.Object");
1252 value_type = CoreLookupType ("System.ValueType");
1254 InitEnumUnderlyingTypes ();
1256 char_type = CoreLookupType ("System.Char");
1257 string_type = CoreLookupType ("System.String");
1258 float_type = CoreLookupType ("System.Single");
1259 double_type = CoreLookupType ("System.Double");
1260 char_ptr_type = CoreLookupType ("System.Char*");
1261 decimal_type = CoreLookupType ("System.Decimal");
1262 bool_type = CoreLookupType ("System.Boolean");
1263 enum_type = CoreLookupType ("System.Enum");
1268 convert_type = CoreLookupType ("System.Convert");
1269 date_type = CoreLookupType ("System.DateTime");
1270 math_type = CoreLookupType ("System.Math");
1272 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1273 delegate_type = CoreLookupType ("System.Delegate");
1275 array_type = CoreLookupType ("System.Array");
1276 void_type = CoreLookupType ("System.Void");
1277 type_type = CoreLookupType ("System.Type");
1279 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1280 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1281 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1282 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1283 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1284 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1285 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1286 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1287 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1288 idisposable_type = CoreLookupType ("System.IDisposable");
1289 icloneable_type = CoreLookupType ("System.ICloneable");
1290 iconvertible_type = CoreLookupType ("System.IConvertible");
1291 monitor_type = CoreLookupType ("System.Threading.Monitor");
1292 intptr_type = CoreLookupType ("System.IntPtr");
1294 attribute_type = CoreLookupType ("System.Attribute");
1295 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1296 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1297 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1298 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1299 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1300 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1301 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1302 typed_reference_type = CoreLookupType ("System.TypedReference");
1303 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1304 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1305 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1308 // Sigh. Remove this before the release. Wonder what versions of Mono
1309 // people are running.
1311 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1313 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1315 void_ptr_type = CoreLookupType ("System.Void*");
1317 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1319 exception_type = CoreLookupType ("System.Exception");
1320 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1321 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1326 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1327 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1328 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1329 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1330 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1331 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1333 InitGenericCoreTypes ();
1336 // When compiling corlib, store the "real" types here.
1338 if (!RootContext.StdLib) {
1339 system_int32_type = typeof (System.Int32);
1340 system_array_type = typeof (System.Array);
1341 system_type_type = typeof (System.Type);
1342 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1344 Type [] void_arg = { };
1345 system_int_array_get_length = GetMethod (
1346 system_array_type, "get_Length", void_arg);
1347 system_int_array_get_rank = GetMethod (
1348 system_array_type, "get_Rank", void_arg);
1349 system_object_array_clone = GetMethod (
1350 system_array_type, "Clone", void_arg);
1352 Type [] system_int_arg = { system_int32_type };
1353 system_int_array_get_length_int = GetMethod (
1354 system_array_type, "GetLength", system_int_arg);
1355 system_int_array_get_upper_bound_int = GetMethod (
1356 system_array_type, "GetUpperBound", system_int_arg);
1357 system_int_array_get_lower_bound_int = GetMethod (
1358 system_array_type, "GetLowerBound", system_int_arg);
1360 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1361 system_void_array_copyto_array_int = GetMethod (
1362 system_array_type, "CopyTo", system_array_int_arg);
1364 Type [] system_3_type_arg = {
1365 system_type_type, system_type_type, system_type_type };
1366 Type [] system_4_type_arg = {
1367 system_type_type, system_type_type, system_type_type, system_type_type };
1369 MethodInfo set_corlib_type_builders = GetMethod (
1370 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1371 system_4_type_arg, true, false);
1373 if (set_corlib_type_builders != null) {
1374 object[] args = new object [4];
1375 args [0] = object_type;
1376 args [1] = value_type;
1377 args [2] = enum_type;
1378 args [3] = void_type;
1380 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1382 // Compatibility for an older version of the class libs.
1383 set_corlib_type_builders = GetMethod (
1384 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1385 system_3_type_arg, true, true);
1387 if (set_corlib_type_builders == null) {
1388 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1392 object[] args = new object [3];
1393 args [0] = object_type;
1394 args [1] = value_type;
1395 args [2] = enum_type;
1397 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1401 system_object_expr.Type = object_type;
1402 system_string_expr.Type = string_type;
1403 system_boolean_expr.Type = bool_type;
1404 system_decimal_expr.Type = decimal_type;
1405 system_single_expr.Type = float_type;
1406 system_double_expr.Type = double_type;
1407 system_sbyte_expr.Type = _sbyte_type;
1408 system_byte_expr.Type = byte_type;
1409 system_int16_expr.Type = short_type;
1410 system_uint16_expr.Type = _ushort_type;
1411 system_int32_expr.Type = int32_type;
1412 system_uint32_expr.Type = _uint32_type;
1413 system_int64_expr.Type = int64_type;
1414 system_uint64_expr.Type = _uint64_type;
1415 system_char_expr.Type = char_type;
1416 system_void_expr.Type = void_type;
1417 system_asynccallback_expr.Type = asynccallback_type;
1418 system_iasyncresult_expr.Type = iasyncresult_type;
1419 system_valuetype_expr.Type = value_type;
1425 system_date_expr.Type = date_type;
1427 relative_type_order = new Hashtable ();
1428 relative_type_order[TypeManager.bool_type] = 1;
1429 relative_type_order[TypeManager.byte_type] = 1;
1430 relative_type_order[TypeManager.short_type] = 2;
1431 relative_type_order[TypeManager.int32_type] = 3;
1432 relative_type_order[TypeManager.int64_type] = 4;
1433 relative_type_order[TypeManager.decimal_type] = 5;
1434 relative_type_order[TypeManager.float_type] = 6;
1435 relative_type_order[TypeManager.double_type] = 7;
1436 relative_type_order[TypeManager.string_type] = 8;
1439 // These are only used for compare purposes
1441 anonymous_method_type = typeof (AnonymousMethod);
1442 null_type = typeof (NullType);
1444 InitVisualBasicHelperTypes ();
1448 // This method preloads helper types in Microsoft.VisualBasic.dll for later use
1450 public static void InitVisualBasicHelperTypes ()
1452 msvbcs_object_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.ObjectType");
1453 msvbcs_boolean_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.BooleanType");
1454 msvbcs_byte_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.ByteType");
1455 msvbcs_short_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.ShortType");
1456 msvbcs_integer_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.IntegerType");
1457 msvbcs_long_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.LongType");
1458 msvbcs_decimal_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DecimalType");
1459 msvbcs_single_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.SingleType");
1460 msvbcs_double_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DoubleType");
1462 msvbcs_char_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.CharType");
1463 msvbcs_chararray_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.CharArrayType");
1464 msvbcs_date_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DateType");
1465 msvbcs_string_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.StringType");
1467 msvbcs_comparemethod_type = CoreLookupType ("Microsoft.VisualBasic.CompareMethod");
1471 // The helper methods that are used by the compiler
1473 public static void InitCodeHelpers ()
1476 // Now load the default methods that we use.
1478 Type [] string_string = { string_type, string_type };
1479 string_concat_string_string = GetMethod (
1480 string_type, "Concat", string_string);
1481 Type [] string_string_string = { string_type, string_type, string_type };
1482 string_concat_string_string_string = GetMethod (
1483 string_type, "Concat", string_string_string);
1484 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1485 string_concat_string_string_string_string = GetMethod (
1486 string_type, "Concat", string_string_string_string);
1487 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1488 string_concat_string_dot_dot_dot = GetMethod (
1489 string_type, "Concat", params_string);
1491 Type [] object_object = { object_type, object_type };
1492 string_concat_object_object = GetMethod (
1493 string_type, "Concat", object_object);
1494 Type [] object_object_object = { object_type, object_type, object_type };
1495 string_concat_object_object_object = GetMethod (
1496 string_type, "Concat", object_object_object);
1497 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1498 string_concat_object_dot_dot_dot = GetMethod (
1499 string_type, "Concat", params_object);
1501 Type [] string_ = { string_type };
1502 string_isinterneted_string = GetMethod (
1503 string_type, "IsInterned", string_);
1505 Type [] runtime_type_handle = { runtime_handle_type };
1506 system_type_get_type_from_handle = GetMethod (
1507 type_type, "GetTypeFromHandle", runtime_type_handle);
1509 Type [] delegate_delegate = { delegate_type, delegate_type };
1510 delegate_combine_delegate_delegate = GetMethod (
1511 delegate_type, "Combine", delegate_delegate);
1513 delegate_remove_delegate_delegate = GetMethod (
1514 delegate_type, "Remove", delegate_delegate);
1520 Type [] decimal_arg = { decimal_type };
1521 convert_to_byte_decimal = GetMethod (
1522 convert_type, "ToByte", decimal_arg);
1523 convert_to_int16_decimal = GetMethod (
1524 convert_type, "ToInt16", decimal_arg);
1525 convert_to_int32_decimal = GetMethod (
1526 convert_type, "ToInt32", decimal_arg);
1527 convert_to_int64_decimal = GetMethod (
1528 convert_type, "ToInt64", decimal_arg);
1529 convert_to_single_decimal = GetMethod (
1530 convert_type, "ToSingle", decimal_arg);
1531 convert_to_double_decimal = GetMethod (
1532 convert_type, "ToDouble", decimal_arg);
1533 convert_to_boolean_decimal = GetMethod (
1534 convert_type, "ToBoolean", decimal_arg);
1536 Type [] decimal_decimal = { decimal_type, decimal_type };
1537 decimal_compare_decimal_decimal = GetMethod (
1538 decimal_type, "Compare", decimal_decimal);
1540 Type [] datetime_datetime = { date_type, date_type };
1541 datetime_compare_datetime_datetime = GetMethod (
1542 date_type, "Compare", datetime_datetime);
1544 Type [] double_arg = { double_type };
1545 math_round_double = GetMethod (
1546 math_type, "Round", double_arg);
1548 Type [] double_double_arg = { double_type, double_type };
1549 math_pow_double_double = GetMethod (
1550 math_type, "Pow", double_double_arg);
1552 Type [] decimal_decimal_arg = { decimal_type, decimal_type };
1553 decimal_add_decimal_decimal = GetMethod (
1554 decimal_type, "Add", decimal_decimal_arg);
1555 decimal_subtract_decimal_decimal = GetMethod (
1556 decimal_type, "Subtract", decimal_decimal_arg);
1557 decimal_multiply_decimal_decimal = GetMethod (
1558 decimal_type, "Multiply", decimal_decimal_arg);
1559 decimal_divide_decimal_decimal = GetMethod (
1560 decimal_type, "Divide", decimal_decimal_arg);
1561 decimal_remainder_decimal_decimal = GetMethod (
1562 decimal_type, "Remainder", decimal_decimal_arg);
1568 Type [] void_arg = { };
1569 object_getcurrent_void = GetMethod (
1570 ienumerator_type, "get_Current", void_arg);
1571 bool_movenext_void = GetMethod (
1572 ienumerator_type, "MoveNext", void_arg);
1573 void_reset_void = GetMethod (
1574 ienumerator_type, "Reset", void_arg);
1575 void_dispose_void = GetMethod (
1576 idisposable_type, "Dispose", void_arg);
1577 int_get_offset_to_string_data = GetMethod (
1578 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1579 int_array_get_length = GetMethod (
1580 array_type, "get_Length", void_arg);
1581 int_array_get_rank = GetMethod (
1582 array_type, "get_Rank", void_arg);
1583 ienumerable_getenumerator_void = GetMethod (
1584 ienumerable_type, "GetEnumerator", void_arg);
1589 Type [] int_arg = { int32_type };
1590 int_array_get_length_int = GetMethod (
1591 array_type, "GetLength", int_arg);
1592 int_array_get_upper_bound_int = GetMethod (
1593 array_type, "GetUpperBound", int_arg);
1594 int_array_get_lower_bound_int = GetMethod (
1595 array_type, "GetLowerBound", int_arg);
1598 // System.Array methods
1600 object_array_clone = GetMethod (
1601 array_type, "Clone", void_arg);
1602 Type [] array_int_arg = { array_type, int32_type };
1603 void_array_copyto_array_int = GetMethod (
1604 array_type, "CopyTo", array_int_arg);
1609 Type [] object_arg = { object_type };
1610 void_monitor_enter_object = GetMethod (
1611 monitor_type, "Enter", object_arg);
1612 void_monitor_exit_object = GetMethod (
1613 monitor_type, "Exit", object_arg);
1615 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1617 void_initializearray_array_fieldhandle = GetMethod (
1618 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1623 int_getlength_int = GetMethod (
1624 array_type, "GetLength", int_arg);
1627 // Decimal constructors
1629 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1630 void_decimal_ctor_five_args = GetConstructor (
1631 decimal_type, dec_arg);
1633 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1636 // VB.NET specific: DateTime constructor
1638 Type [] ticks_arg = { int64_type };
1639 void_datetime_ctor_ticks_arg = GetConstructor ( date_type, ticks_arg);
1644 cons_param_array_attribute = GetConstructor (
1645 param_array_type, void_arg);
1647 unverifiable_code_ctor = GetConstructor (
1648 unverifiable_code_type, void_arg);
1650 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1651 { byte_type, byte_type, _uint32_type, _uint32_type, _uint32_type } );
1653 default_member_ctor = GetConstructor (default_member_type, string_);
1656 // InvalidOperationException
1658 invalid_operation_ctor = GetConstructor (
1659 invalid_operation_exception_type, void_arg);
1663 object_ctor = GetConstructor (object_type, void_arg);
1665 InitGenericCodeHelpers ();
1666 InitVisualBasicCodeHelpers ();
1671 // This method preloads helper methods that are used by the VB.NET compiler
1673 public static void InitVisualBasicCodeHelpers ()
1675 Type [] object_arg = { object_type };
1676 Type [] boolean_arg = { bool_type };
1677 Type [] byte_arg = { byte_type };
1678 Type [] short_arg = { short_type };
1679 Type [] integer_arg = { int32_type };
1680 Type [] long_arg = { int64_type };
1681 Type [] decimal_arg = { decimal_type };
1682 Type [] single_arg = { float_type };
1683 Type [] double_arg = { double_type };
1684 Type [] char_arg = { char_type };
1685 Type [] string_arg = { string_type };
1686 Type [] date_arg = { date_type };
1688 msvbcs_booleantype_from_string = GetMethod (
1689 msvbcs_boolean_type, "FromString", string_arg);
1690 msvbcs_bytetype_from_string = GetMethod (
1691 msvbcs_byte_type, "FromString", string_arg);
1692 msvbcs_shorttype_from_string = GetMethod (
1693 msvbcs_short_type, "FromString", string_arg);
1694 msvbcs_integertype_from_string = GetMethod (
1695 msvbcs_integer_type, "FromString", string_arg);
1696 msvbcs_longtype_from_string = GetMethod (
1697 msvbcs_long_type, "FromString", string_arg);
1698 msvbcs_decimaltype_from_string = GetMethod (
1699 msvbcs_decimal_type, "FromString", string_arg);
1700 msvbcs_singletype_from_string = GetMethod (
1701 msvbcs_single_type, "FromString", string_arg);
1702 msvbcs_doubletype_from_string = GetMethod (
1703 msvbcs_double_type, "FromString", string_arg);
1704 msvbcs_chartype_from_string = GetMethod (
1705 msvbcs_char_type, "FromString", string_arg);
1706 msvbcs_datetype_from_string = GetMethod (
1707 msvbcs_date_type, "FromString", string_arg);
1709 msvbcs_stringtype_from_boolean = GetMethod (
1710 msvbcs_string_type, "FromBoolean", boolean_arg);
1711 msvbcs_stringtype_from_byte = GetMethod (
1712 msvbcs_string_type, "FromByte", byte_arg);
1713 msvbcs_stringtype_from_short = GetMethod (
1714 msvbcs_string_type, "FromShort", short_arg);
1715 msvbcs_stringtype_from_integer = GetMethod (
1716 msvbcs_string_type, "FromInteger", integer_arg);
1717 msvbcs_stringtype_from_long = GetMethod (
1718 msvbcs_string_type, "FromLong", long_arg);
1719 msvbcs_stringtype_from_decimal = GetMethod (
1720 msvbcs_string_type, "FromDecimal", decimal_arg);
1721 msvbcs_stringtype_from_single = GetMethod (
1722 msvbcs_string_type, "FromSingle", single_arg);
1723 msvbcs_stringtype_from_double = GetMethod (
1724 msvbcs_string_type, "FromDouble", double_arg);
1725 msvbcs_stringtype_from_date = GetMethod (
1726 msvbcs_string_type, "FromDate", date_arg);
1727 msvbcs_stringtype_from_char = GetMethod (
1728 msvbcs_string_type, "FromChar", char_arg);
1730 msvbcs_decimaltype_from_boolean = GetMethod (
1731 msvbcs_decimal_type, "FromBoolean", boolean_arg);
1733 Type [] string_string_boolean_arg = { string_type, string_type, bool_type };
1734 msvbcs_stringtype_strcmp_string_string_boolean = GetMethod (
1735 msvbcs_string_type, "StrCmp", string_string_boolean_arg);
1737 Type [] string_string_comparemethod_arg = { string_type, string_type, msvbcs_comparemethod_type };
1738 msvbcs_stringtype_strlike_string_string_comparemethod = GetMethod (
1739 msvbcs_string_type, "StrLike", string_string_comparemethod_arg);
1741 msvbcs_booleantype_fromobject_object = GetMethod (
1742 msvbcs_boolean_type, "FromObject", object_arg);
1743 msvbcs_bytetype_fromobject_object = GetMethod (
1744 msvbcs_byte_type, "FromObject", object_arg);
1745 msvbcs_shorttype_fromobject_object = GetMethod (
1746 msvbcs_short_type, "FromObject", object_arg);
1747 msvbcs_integertype_fromobject_object = GetMethod (
1748 msvbcs_integer_type, "FromObject", object_arg);
1749 msvbcs_longtype_fromobject_object = GetMethod (
1750 msvbcs_long_type, "FromObject", object_arg);
1751 msvbcs_singletype_fromobject_object = GetMethod (
1752 msvbcs_single_type, "FromObject", object_arg);
1753 msvbcs_doubletype_fromobject_object = GetMethod (
1754 msvbcs_double_type, "FromObject", object_arg);
1755 msvbcs_decimaltype_fromobject_object = GetMethod (
1756 msvbcs_decimal_type, "FromObject", object_arg);
1757 msvbcs_chartype_fromobject_object = GetMethod (
1758 msvbcs_char_type, "FromObject", object_arg);
1759 msvbcs_datetype_fromobject_object = GetMethod (
1760 msvbcs_date_type, "FromObject", object_arg);
1761 msvbcs_stringtype_fromobject_object = GetMethod (
1762 msvbcs_string_type, "FromObject", object_arg);
1764 Type [] object_object_arg = { object_type, object_type };
1765 msvbcs_objecttype_mulobj_object_object = GetMethod (
1766 msvbcs_object_type, "MulObj", object_object_arg);
1767 msvbcs_objecttype_divobj_object_object = GetMethod (
1768 msvbcs_object_type, "DivObj", object_object_arg);
1769 msvbcs_objecttype_idivobj_object_object = GetMethod (
1770 msvbcs_object_type, "IDivObj", object_object_arg);
1771 msvbcs_objecttype_modobj_object_object = GetMethod (
1772 msvbcs_object_type, "ModObj", object_object_arg);
1773 msvbcs_objecttype_addobj_object_object = GetMethod (
1774 msvbcs_object_type, "AddObj", object_object_arg);
1775 msvbcs_objecttype_subobj_object_object = GetMethod (
1776 msvbcs_object_type, "SubObj", object_object_arg);
1777 msvbcs_objecttype_bitandobj_object_object = GetMethod (
1778 msvbcs_object_type, "BitAndObj", object_object_arg);
1779 msvbcs_objecttype_bitorobj_object_object = GetMethod (
1780 msvbcs_object_type, "BitOrObj", object_object_arg);
1781 msvbcs_objecttype_bitxorobj_object_object = GetMethod (
1782 msvbcs_object_type, "BitXorObj", object_object_arg);
1783 msvbcs_objecttype_strcatobj_object_object = GetMethod (
1784 msvbcs_object_type, "StrCatObj", object_object_arg);
1785 msvbcs_objecttype_powobj_object_object = GetMethod (
1786 msvbcs_object_type, "PowObj", object_object_arg);
1789 Type [] object_object_boolean_arg = { object_type, object_type, bool_type };
1790 msvbcs_objecttype_objtst_object_object_boolean = GetMethod (
1791 msvbcs_object_type, "ObjTst", object_object_boolean_arg);
1794 Type [] object_object_comparemethod_arg = { object_type, object_type, msvbcs_comparemethod_type };
1795 msvbcs_objecttype_likeobj_object_object_comparemethod = GetMethod (
1796 msvbcs_object_type, "LikeObj", object_object_comparemethod_arg);
1798 Type [] object_int32_arg = { object_type, int32_type };
1799 msvbcs_objecttype_shiftleftobj_object_int32 = GetMethod (
1800 msvbcs_object_type, "ShiftLeftObj", object_int32_arg);
1801 msvbcs_objecttype_shiftrightobj_object_int32 = GetMethod (
1802 msvbcs_object_type, "ShiftRightObj", object_int32_arg);
1806 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1809 /// This is the "old", non-cache based FindMembers() function. We cannot use
1810 /// the cache here because there is no member name argument.
1812 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1813 MemberFilter filter, object criteria)
1815 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1818 // `builder_to_declspace' contains all dynamic types.
1822 Timer.StartTimer (TimerType.FindMembers);
1823 list = decl.FindMembers (mt, bf, filter, criteria);
1824 Timer.StopTimer (TimerType.FindMembers);
1829 // We have to take care of arrays specially, because GetType on
1830 // a TypeBuilder array will return a Type, not a TypeBuilder,
1831 // and we can not call FindMembers on this type.
1833 if (t.IsSubclassOf (TypeManager.array_type))
1834 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1836 if (t is GenericTypeParameterBuilder) {
1837 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1839 Timer.StartTimer (TimerType.FindMembers);
1840 MemberList list = tparam.FindMembers (
1841 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1842 Timer.StopTimer (TimerType.FindMembers);
1847 // Since FindMembers will not lookup both static and instance
1848 // members, we emulate this behaviour here.
1850 if ((bf & instance_and_static) == instance_and_static){
1851 MemberInfo [] i_members = t.FindMembers (
1852 mt, bf & ~BindingFlags.Static, filter, criteria);
1854 int i_len = i_members.Length;
1856 MemberInfo one = i_members [0];
1859 // If any of these are present, we are done!
1861 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1862 return new MemberList (i_members);
1865 MemberInfo [] s_members = t.FindMembers (
1866 mt, bf & ~BindingFlags.Instance, filter, criteria);
1868 int s_len = s_members.Length;
1869 if (i_len > 0 || s_len > 0)
1870 return new MemberList (i_members, s_members);
1873 return new MemberList (i_members);
1875 return new MemberList (s_members);
1879 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1884 /// This method is only called from within MemberLookup. It tries to use the member
1885 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1886 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1887 /// our return value will already contain all inherited members and the caller don't need
1888 /// to check base classes and interfaces anymore.
1890 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1891 string name, out bool used_cache)
1896 // We have to take care of arrays specially, because GetType on
1897 // a TypeBuilder array will return a Type, not a TypeBuilder,
1898 // and we can not call FindMembers on this type.
1900 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1902 return TypeHandle.ArrayType.MemberCache.FindMembers (
1903 mt, bf, name, FilterWithClosure_delegate, null);
1907 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1908 // and we can ask the DeclSpace for the MemberCache.
1910 if (t is TypeBuilder) {
1911 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1912 cache = decl.MemberCache;
1915 // If this DeclSpace has a MemberCache, use it.
1918 if (cache != null) {
1920 return cache.FindMembers (
1921 mt, bf, name, FilterWithClosure_delegate, null);
1924 // If there is no MemberCache, we need to use the "normal" FindMembers.
1925 // Note, this is a VERY uncommon route!
1928 Timer.StartTimer (TimerType.FindMembers);
1929 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1930 FilterWithClosure_delegate, name);
1931 Timer.StopTimer (TimerType.FindMembers);
1933 return (MemberInfo []) list;
1936 if (t is GenericTypeParameterBuilder) {
1937 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1940 Timer.StartTimer (TimerType.FindMembers);
1941 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1942 FilterWithClosure_delegate, name);
1943 Timer.StopTimer (TimerType.FindMembers);
1945 return (MemberInfo []) list;
1949 // This call will always succeed. There is exactly one TypeHandle instance per
1950 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1951 // the corresponding MemberCache.
1953 cache = TypeHandle.GetMemberCache (t);
1956 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1959 public static bool IsBuiltinType (Type t)
1961 if (t == object_type || t == string_type || t == int32_type || t == _uint32_type ||
1962 t == int64_type || t == _uint64_type || t == float_type || t == double_type ||
1963 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1964 t == _sbyte_type || t == byte_type || t == _ushort_type || t == void_type)
1970 public static bool IsBuiltinType (TypeContainer tc)
1972 return IsBuiltinType (tc.TypeBuilder);
1976 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1977 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1979 public static bool IsCLRType (Type t)
1981 if (t == object_type || t == int32_type || t == _uint32_type ||
1982 t == int64_type || t == _uint64_type || t == float_type || t == double_type ||
1983 t == char_type || t == short_type || t == bool_type ||
1984 t == _sbyte_type || t == byte_type || t == _ushort_type)
1991 // The following three methods are used by the VB.NET compiler
1994 public static bool IsFixedNumericType (Type type)
1996 if (type == byte_type || type == short_type ||
1997 type == int32_type || type == int64_type)
2003 public static bool IsFloatingNumericType (Type type)
2005 if (type == decimal_type ||
2006 type == float_type || type == double_type)
2012 public static bool IsNumericType (Type type)
2014 if (IsFixedNumericType (type) || IsFloatingNumericType(type))
2020 public static bool IsDelegateType (Type t)
2022 if (t.IsGenericInstance)
2023 t = t.GetGenericTypeDefinition ();
2025 if (t.IsSubclassOf (TypeManager.delegate_type))
2031 public static bool IsEnumType (Type t)
2033 if (t.IsSubclassOf (TypeManager.enum_type))
2038 public static bool IsBuiltinOrEnum (Type t)
2040 if (IsBuiltinType (t))
2049 public static bool IsNullType (Type t)
2051 return t == null_type;
2055 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
2057 public static bool IsUnmanagedType (Type t)
2059 if (IsBuiltinType (t) && t != TypeManager.string_type)
2068 if (IsValueType (t)){
2069 if (t is TypeBuilder){
2070 TypeContainer tc = LookupTypeContainer (t);
2072 if (tc.Fields != null){
2073 foreach (Field f in tc.Fields){
2074 if (f.FieldBuilder.IsStatic)
2076 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
2082 FieldInfo [] fields = t.GetFields ();
2084 foreach (FieldInfo f in fields){
2087 if (!IsUnmanagedType (f.FieldType))
2097 public static bool IsValueType (Type t)
2099 return t.IsGenericParameter || t.IsValueType;
2102 public static bool IsInterfaceType (Type t)
2104 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
2108 return tc.Kind == Kind.Interface;
2111 public static bool IsSubclassOf (Type type, Type base_type)
2113 TypeParameter tparam = LookupTypeParameter (type);
2114 TypeParameter pparam = LookupTypeParameter (base_type);
2116 if ((tparam != null) && (pparam != null)) {
2117 if (tparam == pparam)
2120 return tparam.IsSubclassOf (base_type);
2124 if (type.Equals (base_type))
2127 type = type.BaseType;
2128 } while (type != null);
2133 public static bool IsPrivateAccessible (Type type, Type parent)
2135 if (type.Equals (parent))
2138 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
2140 // `a' is a generic type definition's TypeBuilder and `b' is a
2141 // generic instance of the same type.
2147 // void Test (Stack<T> stack) { }
2150 // The first argument of `Test' will be the generic instance
2151 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
2154 // We hit this via Closure.Filter() for gen-82.cs.
2156 if (type != parent.GetGenericTypeDefinition ())
2162 if (type.IsGenericInstance && parent.IsGenericInstance) {
2163 if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
2172 public static bool IsFamilyAccessible (Type type, Type parent)
2174 TypeParameter tparam = LookupTypeParameter (type);
2175 TypeParameter pparam = LookupTypeParameter (parent);
2177 if ((tparam != null) && (pparam != null)) {
2178 if (tparam == pparam)
2181 return tparam.IsSubclassOf (parent);
2185 if (IsEqualGenericInstance (type, parent))
2188 type = type.BaseType;
2189 } while (type != null);
2195 // Checks whether `type' is a subclass or nested child of `base_type'.
2197 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
2200 if (IsFamilyAccessible (type, base_type))
2203 // Handle nested types.
2204 type = type.DeclaringType;
2205 } while (type != null);
2211 // Checks whether `type' is a nested child of `parent'.
2213 public static bool IsNestedChildOf (Type type, Type parent)
2215 if (IsEqual (type, parent))
2218 type = type.DeclaringType;
2219 while (type != null) {
2220 if (IsEqual (type, parent))
2223 type = type.DeclaringType;
2230 // Do the right thing when returning the element type of an
2231 // array type based on whether we are compiling corlib or not
2233 public static Type GetElementType (Type t)
2235 if (RootContext.StdLib)
2236 return t.GetElementType ();
2238 return TypeToCoreType (t.GetElementType ());
2242 /// Returns the User Defined Types
2244 public static ArrayList UserTypes {
2250 public static Hashtable TypeContainers {
2252 return typecontainers;
2256 static Hashtable builder_to_constant;
2258 public static void RegisterConstant (FieldBuilder fb, Const c)
2260 if (builder_to_constant == null)
2261 builder_to_constant = new PtrHashtable ();
2263 if (builder_to_constant.Contains (fb))
2266 builder_to_constant.Add (fb, c);
2269 public static Const LookupConstant (FieldBuilder fb)
2271 if (builder_to_constant == null)
2274 return (Const) builder_to_constant [fb];
2278 /// Gigantic work around for missing features in System.Reflection.Emit follows.
2282 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
2283 /// for anything which is dynamic, and we need this in a number of places,
2284 /// we register this information here, and use it afterwards.
2286 static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
2291 method_arguments.Add (mb, args);
2292 method_internal_params.Add (mb, ip);
2295 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
2297 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
2300 if (method_internal_params.Contains (mb))
2301 return (InternalParameters) method_internal_params [mb];
2303 throw new Exception ("Argument for Method not registered" + mb);
2307 /// Returns the argument types for a method based on its methodbase
2309 /// For dynamic methods, we use the compiler provided types, for
2310 /// methods from existing assemblies we load them from GetParameters,
2311 /// and insert them into the cache
2313 static public Type [] GetArgumentTypes (MethodBase mb)
2315 object t = method_arguments [mb];
2319 ParameterInfo [] pi = mb.GetParameters ();
2326 types = new Type [c];
2327 for (int i = 0; i < c; i++)
2328 types [i] = pi [i].ParameterType;
2330 method_arguments.Add (mb, types);
2335 /// Returns the argument types for an indexer based on its PropertyInfo
2337 /// For dynamic indexers, we use the compiler provided types, for
2338 /// indexers from existing assemblies we load them from GetParameters,
2339 /// and insert them into the cache
2341 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2343 if (indexer_arguments.Contains (indexer))
2344 return (Type []) indexer_arguments [indexer];
2345 else if (indexer is PropertyBuilder)
2346 // If we're a PropertyBuilder and not in the
2347 // `indexer_arguments' hash, then we're a property and
2351 ParameterInfo [] pi = indexer.GetIndexParameters ();
2352 // Property, not an indexer.
2356 Type [] types = new Type [c];
2358 for (int i = 0; i < c; i++)
2359 types [i] = pi [i].ParameterType;
2361 indexer_arguments.Add (indexer, types);
2367 // This is a workaround the fact that GetValue is not
2368 // supported for dynamic types
2370 static Hashtable fields = new Hashtable ();
2371 static public bool RegisterFieldValue (FieldBuilder fb, object value)
2373 if (fields.Contains (fb))
2376 fields.Add (fb, value);
2381 static public object GetValue (FieldBuilder fb)
2386 static Hashtable fieldbuilders_to_fields = new Hashtable ();
2387 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2389 if (fieldbuilders_to_fields.Contains (fb))
2392 fieldbuilders_to_fields.Add (fb, f);
2397 // The return value can be null; This will be the case for
2398 // auxiliary FieldBuilders created by the compiler that have no
2399 // real field being declared on the source code
2401 static public FieldBase GetField (FieldInfo fb)
2403 return (FieldBase) fieldbuilders_to_fields [fb];
2406 static Hashtable events;
2408 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2411 events = new Hashtable ();
2413 if (!events.Contains (eb)) {
2414 events.Add (eb, new Pair (add, remove));
2418 static public MethodInfo GetAddMethod (EventInfo ei)
2420 if (ei is MyEventBuilder) {
2421 Pair pair = (Pair) events [ei];
2423 return (MethodInfo) pair.First;
2425 return ei.GetAddMethod (true);
2428 static public MethodInfo GetRemoveMethod (EventInfo ei)
2430 if (ei is MyEventBuilder) {
2431 Pair pair = (Pair) events [ei];
2433 return (MethodInfo) pair.Second;
2435 return ei.GetRemoveMethod (true);
2438 static Hashtable priv_fields_events;
2440 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2442 if (priv_fields_events == null)
2443 priv_fields_events = new Hashtable ();
2445 if (priv_fields_events.Contains (einfo))
2448 priv_fields_events.Add (einfo, builder);
2453 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2455 if (priv_fields_events == null)
2458 return (MemberInfo) priv_fields_events [ei];
2461 static Hashtable properties;
2463 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2465 if (properties == null)
2466 properties = new Hashtable ();
2468 if (properties.Contains (pb))
2471 properties.Add (pb, new Pair (get, set));
2476 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2477 MethodBase set, Type[] args)
2479 if (!RegisterProperty (pb, get,set))
2482 indexer_arguments.Add (pb, args);
2487 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2489 Hashtable hash = new Hashtable ();
2490 return CheckStructCycles (tc, seen, hash);
2493 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2496 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2500 // `seen' contains all types we've already visited.
2502 if (seen.Contains (tc))
2504 seen.Add (tc, null);
2506 if (tc.Fields == null)
2509 foreach (Field field in tc.Fields) {
2510 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2513 Type ftype = field.FieldBuilder.FieldType;
2514 TypeContainer ftc = LookupTypeContainer (ftype);
2518 if (hash.Contains (ftc)) {
2519 Report.Error (523, tc.Location,
2520 "Struct member `{0}.{1}' of type `{2}' " +
2521 "causes a cycle in the struct layout",
2522 tc.Name, field.Name, ftc.Name);
2527 // `hash' contains all types in the current path.
2529 hash.Add (tc, null);
2531 bool ok = CheckStructCycles (ftc, seen, hash);
2538 if (!seen.Contains (ftc))
2539 seen.Add (ftc, null);
2546 /// Given an array of interface types, expand and eliminate repeated ocurrences
2547 /// of an interface.
2551 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2554 public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2556 ArrayList new_ifaces = new ArrayList ();
2558 foreach (TypeExpr iface in base_interfaces){
2559 TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
2563 if (!new_ifaces.Contains (texpr.Type))
2564 new_ifaces.Add (texpr.Type);
2566 Type [] implementing = texpr.Type.GetInterfaces ();
2568 foreach (Type imp in implementing){
2569 if (!new_ifaces.Contains (imp))
2570 new_ifaces.Add (imp);
2573 Type [] ret = new Type [new_ifaces.Count];
2574 new_ifaces.CopyTo (ret, 0);
2578 static PtrHashtable iface_cache = new PtrHashtable ();
2581 /// This function returns the interfaces in the type `t'. Works with
2582 /// both types and TypeBuilders.
2584 public static Type [] GetInterfaces (Type t)
2587 Type [] cached = iface_cache [t] as Type [];
2592 // The reason for catching the Array case is that Reflection.Emit
2593 // will not return a TypeBuilder for Array types of TypeBuilder types,
2594 // but will still throw an exception if we try to call GetInterfaces
2597 // Since the array interfaces are always constant, we return those for
2602 t = TypeManager.array_type;
2604 if (t is TypeBuilder){
2605 Type [] base_ifaces;
2607 if (t.BaseType == null)
2608 base_ifaces = NoTypes;
2610 base_ifaces = GetInterfaces (t.BaseType);
2611 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2612 if (type_ifaces == null)
2613 type_ifaces = NoTypes;
2615 int base_count = base_ifaces.Length;
2616 Type [] result = new Type [base_count + type_ifaces.Length];
2617 base_ifaces.CopyTo (result, 0);
2618 type_ifaces.CopyTo (result, base_count);
2620 iface_cache [t] = result;
2622 } else if (t is GenericTypeParameterBuilder){
2623 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2624 if (type_ifaces == null)
2625 type_ifaces = NoTypes;
2627 iface_cache [t] = type_ifaces;
2630 Type[] ifaces = t.GetInterfaces ();
2631 iface_cache [t] = ifaces;
2637 // gets the interfaces that are declared explicitly on t
2639 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2641 return (Type []) builder_to_ifaces [t];
2645 /// The following is used to check if a given type implements an interface.
2646 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2648 public static bool ImplementsInterface (Type t, Type iface)
2653 // FIXME OPTIMIZATION:
2654 // as soon as we hit a non-TypeBuiler in the interface
2655 // chain, we could return, as the `Type.GetInterfaces'
2656 // will return all the interfaces implement by the type
2660 interfaces = GetInterfaces (t);
2662 if (interfaces != null){
2663 foreach (Type i in interfaces){
2670 } while (t != null);
2675 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2677 // This is a custom version of Convert.ChangeType() which works
2678 // with the TypeBuilder defined types when compiling corlib.
2679 public static object ChangeType (object value, Type conversionType, out bool error)
2681 IConvertible convert_value = value as IConvertible;
2683 if (convert_value == null){
2689 // We must use Type.Equals() here since `conversionType' is
2690 // the TypeBuilder created version of a system type and not
2691 // the system type itself. You cannot use Type.GetTypeCode()
2692 // on such a type - it'd always return TypeCode.Object.
2696 if (conversionType.Equals (typeof (Boolean)))
2697 return (object)(convert_value.ToBoolean (nf_provider));
2698 else if (conversionType.Equals (typeof (Byte)))
2699 return (object)(convert_value.ToByte (nf_provider));
2700 else if (conversionType.Equals (typeof (Char)))
2701 return (object)(convert_value.ToChar (nf_provider));
2702 else if (conversionType.Equals (typeof (DateTime)))
2703 return (object)(convert_value.ToDateTime (nf_provider));
2704 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2705 return (object)(convert_value.ToDecimal (nf_provider));
2706 else if (conversionType.Equals (typeof (Double)))
2707 return (object)(convert_value.ToDouble (nf_provider));
2708 else if (conversionType.Equals (typeof (Int16)))
2709 return (object)(convert_value.ToInt16 (nf_provider));
2710 else if (conversionType.Equals (typeof (Int32)))
2711 return (object)(convert_value.ToInt32 (nf_provider));
2712 else if (conversionType.Equals (typeof (Int64)))
2713 return (object)(convert_value.ToInt64 (nf_provider));
2714 else if (conversionType.Equals (typeof (SByte)))
2715 return (object)(convert_value.ToSByte (nf_provider));
2716 else if (conversionType.Equals (typeof (Single)))
2717 return (object)(convert_value.ToSingle (nf_provider));
2718 else if (conversionType.Equals (typeof (String)))
2719 return (object)(convert_value.ToString (nf_provider));
2720 else if (conversionType.Equals (typeof (UInt16)))
2721 return (object)(convert_value.ToUInt16 (nf_provider));
2722 else if (conversionType.Equals (typeof (UInt32)))
2723 return (object)(convert_value.ToUInt32 (nf_provider));
2724 else if (conversionType.Equals (typeof (UInt64)))
2725 return (object)(convert_value.ToUInt64 (nf_provider));
2726 else if (conversionType.Equals (typeof (Object)))
2727 return (object)(value);
2737 // This is needed, because enumerations from assemblies
2738 // do not report their underlyingtype, but they report
2741 public static Type EnumToUnderlying (Type t)
2743 if (t == TypeManager.enum_type)
2746 t = t.UnderlyingSystemType;
2747 if (!TypeManager.IsEnumType (t))
2750 if (t is TypeBuilder) {
2751 // slow path needed to compile corlib
2752 if (t == TypeManager.bool_type ||
2753 t == TypeManager.byte_type ||
2754 t == TypeManager._sbyte_type ||
2755 t == TypeManager.char_type ||
2756 t == TypeManager.short_type ||
2757 t == TypeManager._ushort_type ||
2758 t == TypeManager.int32_type ||
2759 t == TypeManager._uint32_type ||
2760 t == TypeManager.int64_type ||
2761 t == TypeManager._uint64_type)
2763 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2765 TypeCode tc = Type.GetTypeCode (t);
2768 case TypeCode.Boolean:
2769 return TypeManager.bool_type;
2771 return TypeManager.byte_type;
2772 case TypeCode.SByte:
2773 return TypeManager._sbyte_type;
2775 return TypeManager.char_type;
2776 case TypeCode.Int16:
2777 return TypeManager.short_type;
2778 case TypeCode.UInt16:
2779 return TypeManager._ushort_type;
2780 case TypeCode.Int32:
2781 return TypeManager.int32_type;
2782 case TypeCode.UInt32:
2783 return TypeManager._uint32_type;
2784 case TypeCode.Int64:
2785 return TypeManager.int64_type;
2786 case TypeCode.UInt64:
2787 return TypeManager._uint64_type;
2789 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2793 // When compiling corlib and called with one of the core types, return
2794 // the corresponding typebuilder for that type.
2796 public static Type TypeToCoreType (Type t)
2798 if (RootContext.StdLib || (t is TypeBuilder))
2801 TypeCode tc = Type.GetTypeCode (t);
2804 case TypeCode.Boolean:
2805 return TypeManager.bool_type;
2807 return TypeManager.byte_type;
2808 case TypeCode.SByte:
2809 return TypeManager._sbyte_type;
2811 return TypeManager.char_type;
2812 case TypeCode.Int16:
2813 return TypeManager.short_type;
2814 case TypeCode.UInt16:
2815 return TypeManager._ushort_type;
2816 case TypeCode.Int32:
2817 return TypeManager.int32_type;
2818 case TypeCode.UInt32:
2819 return TypeManager._uint32_type;
2820 case TypeCode.Int64:
2821 return TypeManager.int64_type;
2822 case TypeCode.UInt64:
2823 return TypeManager._uint64_type;
2824 case TypeCode.Single:
2825 return TypeManager.float_type;
2826 case TypeCode.Double:
2827 return TypeManager.double_type;
2828 case TypeCode.String:
2829 return TypeManager.string_type;
2830 case TypeCode.Decimal:
2831 return TypeManager.decimal_type;
2833 if (t == typeof (void))
2834 return TypeManager.void_type;
2835 if (t == typeof (object))
2836 return TypeManager.object_type;
2837 if (t == typeof (System.Type))
2838 return TypeManager.type_type;
2839 if (t == typeof (System.IntPtr))
2840 return TypeManager.intptr_type;
2846 /// Utility function that can be used to probe whether a type
2847 /// is managed or not.
2849 public static bool VerifyUnManaged (Type t, Location loc)
2851 if (t.IsValueType || t.IsPointer){
2853 // FIXME: this is more complex, we actually need to
2854 // make sure that the type does not contain any
2860 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2861 // We need this explicit check here to make it work when
2862 // compiling corlib.
2867 "Cannot take the address or size of a variable of a managed type ('" +
2868 CSharpName (t) + "')");
2873 /// Returns the name of the indexer in a given type.
2876 /// The default is not always `Item'. The user can change this behaviour by
2877 /// using the IndexerNameAttribute in the container.
2879 /// For example, the String class indexer is named `Chars' not `Item'
2881 public static string IndexerPropertyName (Type t)
2883 if (t.IsGenericInstance)
2884 t = t.GetGenericTypeDefinition ();
2886 if (t is TypeBuilder) {
2887 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2888 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2891 System.Attribute attr = System.Attribute.GetCustomAttribute (
2892 t, TypeManager.default_member_type);
2894 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2895 return dma.MemberName;
2898 return TypeContainer.DefaultIndexerName;
2901 static MethodInfo declare_local_method = null;
2903 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2905 if (declare_local_method == null){
2906 declare_local_method = typeof (ILGenerator).GetMethod (
2908 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2910 new Type [] { typeof (Type), typeof (bool)},
2912 if (declare_local_method == null){
2913 Report.Warning (-24, new Location (-1),
2914 "This version of the runtime does not support making pinned local variables. " +
2915 "This code may cause errors on a runtime with a moving GC");
2916 return ig.DeclareLocal (t);
2919 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2923 // Returns whether the array of memberinfos contains the given method
2925 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2927 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2929 foreach (MethodBase method in array) {
2930 if (method.Name != new_method.Name)
2933 if (method is MethodInfo && new_method is MethodInfo)
2934 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2938 Type [] old_args = TypeManager.GetArgumentTypes (method);
2939 int old_count = old_args.Length;
2942 if (new_args.Length != old_count)
2945 for (i = 0; i < old_count; i++){
2946 if (old_args [i] != new_args [i])
2959 // We copy methods from `new_members' into `target_list' if the signature
2960 // for the method from in the new list does not exist in the target_list
2962 // The name is assumed to be the same.
2964 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2966 if (target_list == null){
2967 target_list = new ArrayList ();
2969 foreach (MemberInfo mi in new_members){
2970 if (mi is MethodBase)
2971 target_list.Add (mi);
2976 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2977 target_list.CopyTo (target_array, 0);
2979 foreach (MemberInfo mi in new_members){
2980 MethodBase new_method = (MethodBase) mi;
2982 if (!ArrayContainsMethod (target_array, new_method))
2983 target_list.Add (new_method);
2988 #region MemberLookup implementation
2991 // Whether we allow private members in the result (since FindMembers
2992 // uses NonPublic for both protected and private), we need to distinguish.
2995 static internal bool FilterNone (MemberInfo m, object filter_criteria)
3000 internal class Closure {
3001 internal bool private_ok;
3003 // Who is invoking us and which type is being queried currently.
3004 internal Type invocation_type;
3005 internal Type qualifier_type;
3007 // The assembly that defines the type is that is calling us
3008 internal Assembly invocation_assembly;
3009 internal IList almost_match;
3011 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
3013 if (invocation_type == null)
3016 Debug.Assert (IsNestedFamilyAccessible (invocation_type, m.DeclaringType));
3021 // A nested class has access to all the protected members visible
3023 if (qualifier_type != null
3024 && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3027 if (invocation_type == m.DeclaringType
3028 || invocation_type.IsSubclassOf (m.DeclaringType)) {
3029 // Although a derived class can access protected members of
3030 // its base class it cannot do so through an instance of the
3031 // base class (CS1540).
3032 // => Ancestry should be: declaring_type ->* invocation_type
3033 // ->* qualified_type
3034 if (qualifier_type == null
3035 || qualifier_type == invocation_type
3036 || qualifier_type.IsSubclassOf (invocation_type))
3040 if (almost_match != null)
3041 almost_match.Add (m);
3045 bool Filter (MethodBase mb, object filter_criteria)
3047 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
3049 if (ma == MethodAttributes.Private)
3050 return private_ok ||
3051 IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
3052 IsNestedChildOf (invocation_type, mb.DeclaringType);
3055 // FamAndAssem requires that we not only derivate, but we are on the
3058 if (ma == MethodAttributes.FamANDAssem){
3059 if (invocation_assembly != mb.DeclaringType.Assembly)
3063 // Assembly and FamORAssem succeed if we're in the same assembly.
3064 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
3065 if (invocation_assembly == mb.DeclaringType.Assembly)
3069 // We already know that we aren't in the same assembly.
3070 if (ma == MethodAttributes.Assembly)
3073 // Family and FamANDAssem require that we derive.
3074 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
3075 if (invocation_type == null)
3078 if (!IsNestedFamilyAccessible (invocation_type, mb.DeclaringType))
3081 // Although a derived class can access protected members of its base class
3082 // it cannot do so through an instance of the base class (CS1540).
3083 if (!mb.IsStatic && (qualifier_type != null) &&
3084 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
3085 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
3086 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3096 bool Filter (FieldInfo fi, object filter_criteria)
3098 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
3100 if (fa == FieldAttributes.Private)
3101 return private_ok ||
3102 IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
3103 IsNestedChildOf (invocation_type, fi.DeclaringType);
3106 // FamAndAssem requires that we not only derivate, but we are on the
3109 if (fa == FieldAttributes.FamANDAssem){
3110 if (invocation_assembly != fi.DeclaringType.Assembly)
3114 // Assembly and FamORAssem succeed if we're in the same assembly.
3115 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
3116 if (invocation_assembly == fi.DeclaringType.Assembly)
3120 // We already know that we aren't in the same assembly.
3121 if (fa == FieldAttributes.Assembly)
3124 // Family and FamANDAssem require that we derive.
3125 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
3126 if (invocation_type == null)
3129 if (!IsNestedFamilyAccessible (invocation_type, fi.DeclaringType))
3132 // Although a derived class can access protected members of its base class
3133 // it cannot do so through an instance of the base class (CS1540).
3134 if (!fi.IsStatic && (qualifier_type != null) &&
3135 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
3136 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
3137 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3148 // This filter filters by name + whether it is ok to include private
3149 // members in the search
3151 internal bool Filter (MemberInfo m, object filter_criteria)
3154 // Hack: we know that the filter criteria will always be in the
3155 // `closure' // fields.
3158 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3161 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3162 (invocation_type != null) &&
3163 IsPrivateAccessible (m.DeclaringType, invocation_type))
3167 // Ugly: we need to find out the type of `m', and depending
3168 // on this, tell whether we accept or not
3170 if (m is MethodBase)
3171 return Filter ((MethodBase) m, filter_criteria);
3174 return Filter ((FieldInfo) m, filter_criteria);
3177 // EventInfos and PropertyInfos, return true because they lack
3178 // permission information, so we need to check later on the methods.
3184 static Closure closure = new Closure ();
3185 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3188 // Looks up a member called `name' in the `queried_type'. This lookup
3189 // is done by code that is contained in the definition for `invocation_type'
3190 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3192 // `invocation_type' is used to check whether we're allowed to access the requested
3193 // member wrt its protection level.
3195 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3196 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3197 // is B and qualifier_type is A). This is used to do the CS1540 check.
3199 // When resolving a SimpleName, `qualifier_type' is null.
3201 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3202 // the same than `queried_type' - except when we're being called from BaseAccess;
3203 // in this case, `invocation_type' is the current type and `queried_type' the base
3204 // type, so this'd normally trigger a CS1540.
3206 // The binding flags are `bf' and the kind of members being looked up are `mt'
3208 // The return value always includes private members which code in `invocation_type'
3209 // is allowed to access (using the specified `qualifier_type' if given); only use
3210 // BindingFlags.NonPublic to bypass the permission check.
3212 // The 'almost_match' argument is used for reporting error CS1540.
3214 // Returns an array of a single element for everything but Methods/Constructors
3215 // that might return multiple matches.
3217 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3218 Type queried_type, MemberTypes mt,
3219 BindingFlags original_bf, string name, IList almost_match)
3221 Timer.StartTimer (TimerType.MemberLookup);
3223 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3224 queried_type, mt, original_bf, name, almost_match);
3226 Timer.StopTimer (TimerType.MemberLookup);
3231 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3232 Type queried_type, MemberTypes mt,
3233 BindingFlags original_bf, string name, IList almost_match)
3235 BindingFlags bf = original_bf;
3237 ArrayList method_list = null;
3238 Type current_type = queried_type;
3239 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3240 bool skip_iface_check = true, used_cache = false;
3241 bool always_ok_flag = false;
3243 closure.invocation_type = invocation_type;
3244 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3245 closure.qualifier_type = qualifier_type;
3246 closure.almost_match = almost_match;
3249 // If we are a nested class, we always have access to our container
3252 if (invocation_type != null){
3253 string invocation_name = invocation_type.FullName;
3254 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
3255 string container = queried_type.FullName + "+";
3256 int container_length = container.Length;
3258 if (invocation_name.Length > container_length){
3259 string shared = invocation_name.Substring (0, container_length);
3261 if (shared == container)
3262 always_ok_flag = true;
3267 // This is from the first time we find a method
3268 // in most cases, we do not actually find a method in the base class
3269 // so we can just ignore it, and save the arraylist allocation
3270 MemberInfo [] first_members_list = null;
3271 bool use_first_members_list = false;
3277 // `NonPublic' is lame, because it includes both protected and
3278 // private methods, so we need to control this behavior by
3279 // explicitly tracking if a private method is ok or not.
3281 // The possible cases are:
3282 // public, private and protected (internal does not come into the
3285 if ((invocation_type != null) &&
3286 ((invocation_type == current_type) ||
3287 IsNestedChildOf (invocation_type, current_type)) ||
3289 bf = original_bf | BindingFlags.NonPublic;
3293 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3295 Timer.StopTimer (TimerType.MemberLookup);
3297 list = MemberLookup_FindMembers (
3298 current_type, mt, bf, name, out used_cache);
3300 Timer.StartTimer (TimerType.MemberLookup);
3303 // When queried for an interface type, the cache will automatically check all
3304 // inherited members, so we don't need to do this here. However, this only
3305 // works if we already used the cache in the first iteration of this loop.
3307 // If we used the cache in any further iteration, we can still terminate the
3308 // loop since the cache always looks in all base classes.
3314 skip_iface_check = false;
3316 if (current_type == TypeManager.object_type)
3319 current_type = current_type.BaseType;
3322 // This happens with interfaces, they have a null
3323 // basetype. Look members up in the Object class.
3325 if (current_type == null) {
3326 current_type = TypeManager.object_type;
3331 if (list.Length == 0)
3335 // Events and types are returned by both `static' and `instance'
3336 // searches, which means that our above FindMembers will
3337 // return two copies of the same.
3339 if (list.Length == 1 && !(list [0] is MethodBase)){
3344 // Multiple properties: we query those just to find out the indexer
3347 if (list [0] is PropertyInfo)
3351 // We found an event: the cache lookup returns both the event and
3352 // its private field.
3354 if (list [0] is EventInfo) {
3355 if ((list.Length == 2) && (list [1] is FieldInfo))
3356 return new MemberInfo [] { list [0] };
3363 // We found methods, turn the search into "method scan"
3367 if (first_members_list != null) {
3368 if (use_first_members_list) {
3369 method_list = CopyNewMethods (method_list, first_members_list);
3370 use_first_members_list = false;
3373 method_list = CopyNewMethods (method_list, list);
3375 first_members_list = list;
3376 use_first_members_list = true;
3378 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3380 } while (searching);
3382 if (use_first_members_list) {
3383 foreach (MemberInfo mi in first_members_list) {
3384 if (! (mi is MethodBase)) {
3385 method_list = CopyNewMethods (method_list, first_members_list);
3386 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3389 return (MemberInfo []) first_members_list;
3392 if (method_list != null && method_list.Count > 0) {
3393 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3396 // This happens if we already used the cache in the first iteration, in this case
3397 // the cache already looked in all interfaces.
3399 if (skip_iface_check)
3403 // Interfaces do not list members they inherit, so we have to
3406 if (!queried_type.IsInterface)
3409 if (queried_type.IsArray)
3410 queried_type = TypeManager.array_type;
3412 Type [] ifaces = GetInterfaces (queried_type);
3416 foreach (Type itype in ifaces){
3419 x = MemberLookup (null, null, itype, mt, bf, name, null);
3427 // Tests whether external method is really special
3428 public static bool IsSpecialMethod (MethodBase mb)
3430 string name = mb.Name;
3431 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3432 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3434 if (name.StartsWith ("add_"))
3435 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3437 if (name.StartsWith ("remove_"))
3438 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3440 if (name.StartsWith ("op_")){
3441 foreach (string oname in Unary.oper_names) {
3446 foreach (string oname in Binary.oper_names) {
3459 /// There is exactly one instance of this class per type.
3461 public sealed class TypeHandle : IMemberContainer {
3462 public readonly TypeHandle BaseType;
3464 readonly int id = ++next_id;
3465 static int next_id = 0;
3468 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3469 /// a TypeHandle yet, a new instance of it is created. This static method
3470 /// ensures that we'll only have one TypeHandle instance per type.
3472 private static TypeHandle GetTypeHandle (Type t)
3474 TypeHandle handle = (TypeHandle) type_hash [t];
3478 handle = new TypeHandle (t);
3479 type_hash.Add (t, handle);
3483 public static MemberCache GetMemberCache (Type t)
3485 return GetTypeHandle (t).MemberCache;
3488 public static void CleanUp ()
3494 /// Returns the TypeHandle for TypeManager.object_type.
3496 public static IMemberContainer ObjectType {
3498 if (object_type != null)
3501 object_type = GetTypeHandle (TypeManager.object_type);
3508 /// Returns the TypeHandle for TypeManager.array_type.
3510 public static IMemberContainer ArrayType {
3512 if (array_type != null)
3515 array_type = GetTypeHandle (TypeManager.array_type);
3521 private static PtrHashtable type_hash = new PtrHashtable ();
3523 private static TypeHandle object_type = null;
3524 private static TypeHandle array_type = null;
3527 private string full_name;
3528 private bool is_interface;
3529 private MemberCache member_cache;
3530 private MemberCache base_cache;
3532 private TypeHandle (Type type)
3535 full_name = type.FullName != null ? type.FullName : type.Name;
3536 if (type.BaseType != null) {
3537 BaseType = GetTypeHandle (type.BaseType);
3538 base_cache = BaseType.MemberCache;
3539 } else if (type.IsInterface)
3540 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3541 this.is_interface = type.IsInterface || type.IsGenericParameter;
3542 this.member_cache = new MemberCache (this);
3545 // IMemberContainer methods
3547 public string Name {
3559 public MemberCache BaseCache {
3565 public bool IsInterface {
3567 return is_interface;
3571 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3573 MemberInfo [] members;
3574 if (type is GenericTypeParameterBuilder)
3575 return MemberList.Empty;
3576 if (mt == MemberTypes.Event)
3577 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3579 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3581 Array.Reverse (members);
3583 return new MemberList (members);
3586 // IMemberFinder methods
3588 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3589 MemberFilter filter, object criteria)
3591 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3594 public MemberCache MemberCache {
3596 return member_cache;
3600 public override string ToString ()
3602 if (BaseType != null)
3603 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3605 return "TypeHandle (" + id + "," + Name + ")";