2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static public Type uint32_type;
42 static public Type int64_type;
43 static public Type uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type sbyte_type;
52 static public Type byte_type;
53 static public Type ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type enumeration_type;
59 static public Type array_type;
60 static public Type runtime_handle_type;
61 static public Type icloneable_type;
62 static public Type type_type;
63 static public Type ienumerator_type;
64 static public Type ienumerable_type;
65 static public Type idisposable_type;
66 static public Type iconvertible_type;
67 static public Type default_member_type;
68 static public Type iasyncresult_type;
69 static public Type asynccallback_type;
70 static public Type intptr_type;
71 static public Type monitor_type;
72 static public Type runtime_field_handle_type;
73 static public Type runtime_argument_handle_type;
74 static public Type attribute_type;
75 static public Type attribute_usage_type;
76 static public Type dllimport_type;
77 static public Type unverifiable_code_type;
78 static public Type methodimpl_attr_type;
79 static public Type marshal_as_attr_type;
80 static public Type param_array_type;
81 static public Type guid_attr_type;
82 static public Type void_ptr_type;
83 static public Type indexer_name_type;
84 static public Type exception_type;
85 static public Type invalid_operation_exception_type;
86 static public Type obsolete_attribute_type;
87 static public Type conditional_attribute_type;
88 static public Type in_attribute_type;
89 static public Type cls_compliant_attribute_type;
90 static public Type typed_reference_type;
91 static public Type arg_iterator_type;
92 static public Type mbr_type;
93 static public Type struct_layout_attribute_type;
94 static public Type field_offset_attribute_type;
97 // An empty array of types
99 static public Type [] NoTypes;
100 static public TypeExpr [] NoTypeExprs;
104 // Expressions representing the internal types. Used during declaration
107 static public TypeExpr system_object_expr, system_string_expr;
108 static public TypeExpr system_boolean_expr, system_decimal_expr;
109 static public TypeExpr system_single_expr, system_double_expr;
110 static public TypeExpr system_sbyte_expr, system_byte_expr;
111 static public TypeExpr system_int16_expr, system_uint16_expr;
112 static public TypeExpr system_int32_expr, system_uint32_expr;
113 static public TypeExpr system_int64_expr, system_uint64_expr;
114 static public TypeExpr system_char_expr, system_void_expr;
115 static public TypeExpr system_asynccallback_expr;
116 static public TypeExpr system_iasyncresult_expr;
117 static public TypeExpr system_valuetype_expr;
120 // This is only used when compiling corlib
122 static public Type system_int32_type;
123 static public Type system_array_type;
124 static public Type system_type_type;
125 static public Type system_assemblybuilder_type;
126 static public MethodInfo system_int_array_get_length;
127 static public MethodInfo system_int_array_get_rank;
128 static public MethodInfo system_object_array_clone;
129 static public MethodInfo system_int_array_get_length_int;
130 static public MethodInfo system_int_array_get_lower_bound_int;
131 static public MethodInfo system_int_array_get_upper_bound_int;
132 static public MethodInfo system_void_array_copyto_array_int;
136 // Internal, not really used outside
138 static Type runtime_helpers_type;
141 // These methods are called by code generated by the compiler
143 static public MethodInfo string_concat_string_string;
144 static public MethodInfo string_concat_string_string_string;
145 static public MethodInfo string_concat_string_string_string_string;
146 static public MethodInfo string_concat_string_dot_dot_dot;
147 static public MethodInfo string_concat_object_object;
148 static public MethodInfo string_concat_object_object_object;
149 static public MethodInfo string_concat_object_dot_dot_dot;
150 static public MethodInfo string_isinterneted_string;
151 static public MethodInfo system_type_get_type_from_handle;
152 static public MethodInfo object_getcurrent_void;
153 static public MethodInfo bool_movenext_void;
154 static public MethodInfo ienumerable_getenumerator_void;
155 static public MethodInfo void_reset_void;
156 static public MethodInfo void_dispose_void;
157 static public MethodInfo void_monitor_enter_object;
158 static public MethodInfo void_monitor_exit_object;
159 static public MethodInfo void_initializearray_array_fieldhandle;
160 static public MethodInfo int_getlength_int;
161 static public MethodInfo delegate_combine_delegate_delegate;
162 static public MethodInfo delegate_remove_delegate_delegate;
163 static public MethodInfo int_get_offset_to_string_data;
164 static public MethodInfo int_array_get_length;
165 static public MethodInfo int_array_get_rank;
166 static public MethodInfo object_array_clone;
167 static public MethodInfo int_array_get_length_int;
168 static public MethodInfo int_array_get_lower_bound_int;
169 static public MethodInfo int_array_get_upper_bound_int;
170 static public MethodInfo void_array_copyto_array_int;
173 // The attribute constructors.
175 static public ConstructorInfo object_ctor;
176 static public ConstructorInfo cons_param_array_attribute;
177 static public ConstructorInfo void_decimal_ctor_five_args;
178 static public ConstructorInfo unverifiable_code_ctor;
179 static public ConstructorInfo invalid_operation_ctor;
182 // Holds the Array of Assemblies that have been loaded
183 // (either because it is the default or the user used the
184 // -r command line option)
186 static Assembly [] assemblies;
189 // Keeps a list of modules. We used this to do lookups
190 // on the module using GetType -- needed for arrays
192 static Module [] modules;
195 // This is the type_cache from the assemblies to avoid
196 // hitting System.Reflection on every lookup.
198 static Hashtable types;
201 // This is used to hotld the corresponding TypeContainer objects
202 // since we need this in FindMembers
204 static Hashtable typecontainers;
207 // Keeps track of those types that are defined by the
210 static ArrayList user_types;
212 static PtrHashtable builder_to_declspace;
215 // Tracks the interfaces implemented by typebuilders. We only
216 // enter those who do implement or or more interfaces
218 static PtrHashtable builder_to_ifaces;
221 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
222 // the arguments to the method
224 static Hashtable method_arguments;
227 // Maps PropertyBuilder to a Type array that contains
228 // the arguments to the indexer
230 static Hashtable indexer_arguments;
233 // Maybe `method_arguments' should be replaced and only
234 // method_internal_params should be kept?
236 static Hashtable method_internal_params;
239 // Keeps track of methods
242 static Hashtable builder_to_method;
245 // Contains all public types from referenced assemblies.
246 // This member is used only if CLS Compliance verification is required.
248 public static Hashtable all_imported_types;
255 public static void CleanUp ()
257 // Lets get everything clean so that we can collect before generating code
261 typecontainers = null;
263 builder_to_declspace = null;
264 builder_to_ifaces = null;
265 method_arguments = null;
266 indexer_arguments = null;
267 method_internal_params = null;
268 builder_to_method = null;
272 negative_hits = null;
273 builder_to_constant = null;
274 fieldbuilders_to_fields = null;
276 priv_fields_events = null;
279 TypeHandle.CleanUp ();
283 /// A filter for Findmembers that uses the Signature object to
286 static bool SignatureFilter (MemberInfo mi, object criteria)
288 Signature sig = (Signature) criteria;
290 if (!(mi is MethodBase))
293 if (mi.Name != sig.name)
296 int count = sig.args.Length;
298 if (mi is MethodBuilder || mi is ConstructorBuilder){
299 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
301 if (candidate_args.Length != count)
304 for (int i = 0; i < count; i++)
305 if (candidate_args [i] != sig.args [i])
310 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
312 if (pars.Length != count)
315 for (int i = 0; i < count; i++)
316 if (pars [i].ParameterType != sig.args [i])
322 // A delegate that points to the filter above.
323 static MemberFilter signature_filter;
326 // These are expressions that represent some of the internal data types, used
329 static void InitExpressionTypes ()
331 system_object_expr = new TypeLookupExpression ("System.Object");
332 system_string_expr = new TypeLookupExpression ("System.String");
333 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
334 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
335 system_single_expr = new TypeLookupExpression ("System.Single");
336 system_double_expr = new TypeLookupExpression ("System.Double");
337 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
338 system_byte_expr = new TypeLookupExpression ("System.Byte");
339 system_int16_expr = new TypeLookupExpression ("System.Int16");
340 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
341 system_int32_expr = new TypeLookupExpression ("System.Int32");
342 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
343 system_int64_expr = new TypeLookupExpression ("System.Int64");
344 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
345 system_char_expr = new TypeLookupExpression ("System.Char");
346 system_void_expr = new TypeLookupExpression ("System.Void");
347 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
348 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
349 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
352 static TypeManager ()
354 assemblies = new Assembly [0];
356 user_types = new ArrayList ();
358 types = new Hashtable ();
359 typecontainers = new Hashtable ();
361 builder_to_declspace = new PtrHashtable ();
362 builder_to_method = new PtrHashtable ();
363 method_arguments = new PtrHashtable ();
364 method_internal_params = new PtrHashtable ();
365 indexer_arguments = new PtrHashtable ();
366 builder_to_ifaces = new PtrHashtable ();
368 NoTypes = new Type [0];
369 NoTypeExprs = new TypeExpr [0];
371 signature_filter = new MemberFilter (SignatureFilter);
372 InitExpressionTypes ();
375 public static void HandleDuplicate (string name, Type t)
377 Type prev = (Type) types [name];
378 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
382 // This probably never happens, as we catch this before
384 Report.Error (-17, "The type `" + name + "' has already been defined.");
388 tc = builder_to_declspace [t] as TypeContainer;
391 1595, "The type `" + name + "' is defined in an existing assembly;"+
392 " Using the new definition from: " + tc.Location);
395 1595, "The type `" + name + "' is defined in an existing assembly;");
398 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
404 public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
409 HandleDuplicate (name, t);
414 builder_to_ifaces [t] = ifaces;
418 // This entry point is used by types that we define under the covers
420 public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
423 builder_to_ifaces [tb] = ifaces;
426 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
428 builder_to_declspace.Add (t, tc);
429 typecontainers.Add (name, tc);
430 AddUserType (name, t, ifaces);
433 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
438 HandleDuplicate (name, t);
441 builder_to_declspace.Add (t, del);
444 public static void AddEnumType (string name, TypeBuilder t, Enum en)
449 HandleDuplicate (name, t);
451 builder_to_declspace.Add (t, en);
454 public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
456 AddUserType (name, t, ifaces);
457 builder_to_declspace.Add (t, i);
461 public static void AddMethod (MethodBase builder, IMethodData method)
463 builder_to_method.Add (builder, method);
466 public static IMethodData GetMethod (MethodBase builder)
468 return (IMethodData) builder_to_method [builder];
472 /// Returns the DeclSpace whose Type is `t' or null if there is no
473 /// DeclSpace for `t' (ie, the Type comes from a library)
475 public static DeclSpace LookupDeclSpace (Type t)
477 return builder_to_declspace [t] as DeclSpace;
481 /// Returns the TypeContainer whose Type is `t' or null if there is no
482 /// TypeContainer for `t' (ie, the Type comes from a library)
484 public static TypeContainer LookupTypeContainer (Type t)
486 return builder_to_declspace [t] as TypeContainer;
489 public static IMemberContainer LookupMemberContainer (Type t)
491 if (t is TypeBuilder) {
492 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
493 if (container != null)
497 return TypeHandle.GetTypeHandle (t);
500 public static Interface LookupInterface (Type t)
502 return builder_to_declspace [t] as Interface;
505 public static Delegate LookupDelegate (Type t)
507 return builder_to_declspace [t] as Delegate;
510 public static Enum LookupEnum (Type t)
512 return builder_to_declspace [t] as Enum;
515 public static Class LookupClass (Type t)
517 return (Class) builder_to_declspace [t];
521 /// Registers an assembly to load types from.
523 public static void AddAssembly (Assembly a)
525 foreach (Assembly assembly in assemblies) {
530 int top = assemblies.Length;
531 Assembly [] n = new Assembly [top + 1];
533 assemblies.CopyTo (n, 0);
540 /// Registers a module builder to lookup types from
542 public static void AddModule (Module mb)
544 int top = modules != null ? modules.Length : 0;
545 Module [] n = new Module [top + 1];
548 modules.CopyTo (n, 0);
553 public static Module[] Modules {
559 static Hashtable references = new Hashtable ();
562 // Gets the reference to T version of the Type (T&)
564 public static Type GetReferenceType (Type t)
566 string tname = t.FullName + "&";
568 Type ret = t.Assembly.GetType (tname);
571 // If the type comes from the assembly we are building
572 // We need the Hashtable, because .NET 1.1 will return different instance types
573 // every time we call ModuleBuilder.GetType.
576 if (references [t] == null)
577 references [t] = CodeGen.Module.Builder.GetType (tname);
578 ret = (Type) references [t];
584 static Hashtable pointers = new Hashtable ();
587 // Gets the pointer to T version of the Type (T*)
589 public static Type GetPointerType (Type t)
591 string tname = t.FullName + "*";
593 Type ret = t.Assembly.GetType (tname);
596 // If the type comes from the assembly we are building
597 // We need the Hashtable, because .NET 1.1 will return different instance types
598 // every time we call ModuleBuilder.GetType.
601 if (pointers [t] == null)
602 pointers [t] = CodeGen.Module.Builder.GetType (tname);
604 ret = (Type) pointers [t];
611 // Low-level lookup, cache-less
613 static Type LookupTypeReflection (string name)
617 foreach (Assembly a in assemblies){
618 t = a.GetType (name);
623 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
624 if (ta == TypeAttributes.NotPublic ||
625 ta == TypeAttributes.NestedPrivate ||
626 ta == TypeAttributes.NestedAssembly ||
627 ta == TypeAttributes.NestedFamANDAssem){
630 // In .NET pointers turn out to be private, even if their
631 // element type is not
634 t = t.GetElementType ();
644 foreach (Module mb in modules) {
645 t = mb.GetType (name);
653 static Hashtable negative_hits = new Hashtable ();
656 // This function is used when you want to avoid the lookups, and want to go
657 // directly to the source. This will use the cache.
659 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
660 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
661 // way to test things other than doing a fullname compare
663 public static Type LookupTypeDirect (string name)
665 Type t = (Type) types [name];
669 if (negative_hits.Contains (name))
672 t = LookupTypeReflection (name);
675 negative_hits [name] = null;
682 static readonly char [] dot_array = { '.' };
685 /// Returns the Type associated with @name, takes care of the fact that
686 /// reflection expects nested types to be separated from the main type
687 /// with a "+" instead of a "."
689 public static Type LookupType (string name)
694 // First lookup in user defined and cached values
697 t = (Type) types [name];
701 // Two thirds of the failures are caught here.
702 if (negative_hits.Contains (name))
705 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
706 string [] elements = name.Split (dot_array);
707 int count = elements.Length;
709 for (int n = 1; n <= count; n++){
710 string top_level_type = String.Join (".", elements, 0, n);
712 // One third of the failures are caught here.
713 if (negative_hits.Contains (top_level_type))
716 t = (Type) types [top_level_type];
718 t = LookupTypeReflection (top_level_type);
720 negative_hits [top_level_type] = null;
731 // We know that System.Object does not have children, and since its the parent of
732 // all the objects, it always gets probbed for inner classes.
734 if (top_level_type == "System.Object")
737 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
738 //Console.WriteLine ("Looking up: " + newt + " " + name);
739 t = LookupTypeReflection (newt);
741 negative_hits [name] = null;
746 negative_hits [name] = null;
751 /// Computes the namespaces that we import from the assemblies we reference.
753 public static void ComputeNamespaces ()
755 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
758 // First add the assembly namespaces
760 if (assembly_get_namespaces != null){
761 int count = assemblies.Length;
763 for (int i = 0; i < count; i++){
764 Assembly a = assemblies [i];
765 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
766 foreach (string ns in namespaces){
769 Namespace.LookupNamespace (ns, true);
773 Hashtable cache = new Hashtable ();
774 cache.Add ("", null);
775 foreach (Assembly a in assemblies) {
776 foreach (Type t in a.GetExportedTypes ()) {
777 string ns = t.Namespace;
778 if (ns == null || cache.Contains (ns))
781 Namespace.LookupNamespace (ns, true);
782 cache.Add (ns, null);
789 /// Fills static table with exported types from all referenced assemblies.
790 /// This information is required for CLS Compliance tests.
792 public static void LoadAllImportedTypes ()
794 if (!CodeGen.Assembly.IsClsCompliant)
797 all_imported_types = new Hashtable ();
798 foreach (Assembly a in assemblies) {
799 foreach (Type t in a.GetExportedTypes ()) {
800 all_imported_types [t.FullName] = t;
805 public static bool NamespaceClash (string name, Location loc)
807 if (Namespace.LookupNamespace (name, false) == null)
810 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
815 /// Returns the C# name of a type if possible, or the full type name otherwise
817 static public string CSharpName (Type t)
819 return Regex.Replace (t.FullName,
821 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
822 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
823 @"Boolean|String|Void)" +
825 new MatchEvaluator (CSharpNameMatch));
828 static String CSharpNameMatch (Match match)
830 string s = match.Groups [1].Captures [0].Value;
832 Replace ("int32", "int").
833 Replace ("uint32", "uint").
834 Replace ("int16", "short").
835 Replace ("uint16", "ushort").
836 Replace ("int64", "long").
837 Replace ("uint64", "ulong").
838 Replace ("single", "float").
839 Replace ("boolean", "bool")
840 + match.Groups [2].Captures [0].Value;
844 /// Returns the signature of the method with full namespace classification
846 static public string GetFullNameSignature (MemberInfo mi)
848 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
851 static public string GetFullNameSignature (MethodBase mb)
853 string name = mb.Name;
855 name = mb.DeclaringType.Name;
857 if (mb.IsSpecialName) {
858 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
859 name = name.Remove (0, 4);
866 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
870 /// Returns the signature of the property and indexer
872 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
875 return GetFullNameSignature (pb);
878 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
879 string signature = GetFullNameSignature (mb);
880 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
881 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
885 /// Returns the signature of the method
887 static public string CSharpSignature (MethodBase mb)
889 StringBuilder sig = new StringBuilder ("(");
892 // FIXME: We should really have a single function to do
893 // everything instead of the following 5 line pattern
895 ParameterData iparams = LookupParametersByBuilder (mb);
898 iparams = new ReflectionParameters (mb);
901 if (mb.IsSpecialName && iparams.Count == 0)
902 return GetFullNameSignature (mb);
904 for (int i = 0; i < iparams.Count; i++) {
908 sig.Append (iparams.ParameterDesc (i));
913 if (mb.IsSpecialName && iparams.Count == 1) {
914 sig.Replace ('(', '[');
915 sig.Replace (')', ']');
918 return GetFullNameSignature (mb) + sig.ToString ();
922 /// Looks up a type, and aborts if it is not found. This is used
923 /// by types required by the compiler
925 static Type CoreLookupType (string name)
927 Type t = LookupTypeDirect (name);
930 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
931 Environment.Exit (1);
938 /// Returns the MethodInfo for a method named `name' defined
939 /// in type `t' which takes arguments of types `args'
941 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
945 BindingFlags flags = instance_and_static | BindingFlags.Public;
951 flags |= BindingFlags.NonPublic;
953 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
954 if (list.Count == 0) {
956 Report.Error (-19, "Can not find the core function `" + name + "'");
960 MethodInfo mi = list [0] as MethodInfo;
963 Report.Error (-19, "Can not find the core function `" + name + "'");
970 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
972 return GetMethod (t, name, args, false, report_errors);
975 static MethodInfo GetMethod (Type t, string name, Type [] args)
977 return GetMethod (t, name, args, true);
982 /// Returns the ConstructorInfo for "args"
984 static ConstructorInfo GetConstructor (Type t, Type [] args)
992 list = FindMembers (t, MemberTypes.Constructor,
993 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
994 signature_filter, sig);
995 if (list.Count == 0){
996 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1000 ConstructorInfo ci = list [0] as ConstructorInfo;
1002 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1009 public static void InitEnumUnderlyingTypes ()
1012 int32_type = CoreLookupType ("System.Int32");
1013 int64_type = CoreLookupType ("System.Int64");
1014 uint32_type = CoreLookupType ("System.UInt32");
1015 uint64_type = CoreLookupType ("System.UInt64");
1016 byte_type = CoreLookupType ("System.Byte");
1017 sbyte_type = CoreLookupType ("System.SByte");
1018 short_type = CoreLookupType ("System.Int16");
1019 ushort_type = CoreLookupType ("System.UInt16");
1023 /// The types have to be initialized after the initial
1024 /// population of the type has happened (for example, to
1025 /// bootstrap the corlib.dll
1027 public static void InitCoreTypes ()
1029 object_type = CoreLookupType ("System.Object");
1030 value_type = CoreLookupType ("System.ValueType");
1032 InitEnumUnderlyingTypes ();
1034 char_type = CoreLookupType ("System.Char");
1035 string_type = CoreLookupType ("System.String");
1036 float_type = CoreLookupType ("System.Single");
1037 double_type = CoreLookupType ("System.Double");
1038 char_ptr_type = CoreLookupType ("System.Char*");
1039 decimal_type = CoreLookupType ("System.Decimal");
1040 bool_type = CoreLookupType ("System.Boolean");
1041 enum_type = CoreLookupType ("System.Enum");
1043 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1044 delegate_type = CoreLookupType ("System.Delegate");
1046 array_type = CoreLookupType ("System.Array");
1047 void_type = CoreLookupType ("System.Void");
1048 type_type = CoreLookupType ("System.Type");
1050 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1051 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1052 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1053 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1054 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1055 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1056 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1057 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1058 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1059 idisposable_type = CoreLookupType ("System.IDisposable");
1060 icloneable_type = CoreLookupType ("System.ICloneable");
1061 iconvertible_type = CoreLookupType ("System.IConvertible");
1062 monitor_type = CoreLookupType ("System.Threading.Monitor");
1063 intptr_type = CoreLookupType ("System.IntPtr");
1065 attribute_type = CoreLookupType ("System.Attribute");
1066 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1067 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1068 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1069 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1070 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1071 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1072 typed_reference_type = CoreLookupType ("System.TypedReference");
1073 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1074 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1077 // Sigh. Remove this before the release. Wonder what versions of Mono
1078 // people are running.
1080 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1082 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1084 void_ptr_type = CoreLookupType ("System.Void*");
1086 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1088 exception_type = CoreLookupType ("System.Exception");
1089 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1094 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1095 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1096 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1097 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1098 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1101 // When compiling corlib, store the "real" types here.
1103 if (!RootContext.StdLib) {
1104 system_int32_type = typeof (System.Int32);
1105 system_array_type = typeof (System.Array);
1106 system_type_type = typeof (System.Type);
1107 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1109 Type [] void_arg = { };
1110 system_int_array_get_length = GetMethod (
1111 system_array_type, "get_Length", void_arg);
1112 system_int_array_get_rank = GetMethod (
1113 system_array_type, "get_Rank", void_arg);
1114 system_object_array_clone = GetMethod (
1115 system_array_type, "Clone", void_arg);
1117 Type [] system_int_arg = { system_int32_type };
1118 system_int_array_get_length_int = GetMethod (
1119 system_array_type, "GetLength", system_int_arg);
1120 system_int_array_get_upper_bound_int = GetMethod (
1121 system_array_type, "GetUpperBound", system_int_arg);
1122 system_int_array_get_lower_bound_int = GetMethod (
1123 system_array_type, "GetLowerBound", system_int_arg);
1125 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1126 system_void_array_copyto_array_int = GetMethod (
1127 system_array_type, "CopyTo", system_array_int_arg);
1129 Type [] system_3_type_arg = {
1130 system_type_type, system_type_type, system_type_type };
1131 Type [] system_4_type_arg = {
1132 system_type_type, system_type_type, system_type_type, system_type_type };
1134 MethodInfo set_corlib_type_builders = GetMethod (
1135 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1136 system_4_type_arg, true, false);
1138 if (set_corlib_type_builders != null) {
1139 object[] args = new object [4];
1140 args [0] = object_type;
1141 args [1] = value_type;
1142 args [2] = enum_type;
1143 args [3] = void_type;
1145 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1147 // Compatibility for an older version of the class libs.
1148 set_corlib_type_builders = GetMethod (
1149 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1150 system_3_type_arg, true, true);
1152 if (set_corlib_type_builders == null) {
1153 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1157 object[] args = new object [3];
1158 args [0] = object_type;
1159 args [1] = value_type;
1160 args [2] = enum_type;
1162 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1166 system_object_expr.Type = object_type;
1167 system_string_expr.Type = string_type;
1168 system_boolean_expr.Type = bool_type;
1169 system_decimal_expr.Type = decimal_type;
1170 system_single_expr.Type = float_type;
1171 system_double_expr.Type = double_type;
1172 system_sbyte_expr.Type = sbyte_type;
1173 system_byte_expr.Type = byte_type;
1174 system_int16_expr.Type = short_type;
1175 system_uint16_expr.Type = ushort_type;
1176 system_int32_expr.Type = int32_type;
1177 system_uint32_expr.Type = uint32_type;
1178 system_int64_expr.Type = int64_type;
1179 system_uint64_expr.Type = uint64_type;
1180 system_char_expr.Type = char_type;
1181 system_void_expr.Type = void_type;
1182 system_asynccallback_expr.Type = asynccallback_type;
1183 system_iasyncresult_expr.Type = iasyncresult_type;
1184 system_valuetype_expr.Type = value_type;
1188 // The helper methods that are used by the compiler
1190 public static void InitCodeHelpers ()
1193 // Now load the default methods that we use.
1195 Type [] string_string = { string_type, string_type };
1196 string_concat_string_string = GetMethod (
1197 string_type, "Concat", string_string);
1198 Type [] string_string_string = { string_type, string_type, string_type };
1199 string_concat_string_string_string = GetMethod (
1200 string_type, "Concat", string_string_string);
1201 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1202 string_concat_string_string_string_string = GetMethod (
1203 string_type, "Concat", string_string_string_string);
1204 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1205 string_concat_string_dot_dot_dot = GetMethod (
1206 string_type, "Concat", params_string);
1208 Type [] object_object = { object_type, object_type };
1209 string_concat_object_object = GetMethod (
1210 string_type, "Concat", object_object);
1211 Type [] object_object_object = { object_type, object_type, object_type };
1212 string_concat_object_object_object = GetMethod (
1213 string_type, "Concat", object_object_object);
1214 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1215 string_concat_object_dot_dot_dot = GetMethod (
1216 string_type, "Concat", params_object);
1218 Type [] string_ = { string_type };
1219 string_isinterneted_string = GetMethod (
1220 string_type, "IsInterned", string_);
1222 Type [] runtime_type_handle = { runtime_handle_type };
1223 system_type_get_type_from_handle = GetMethod (
1224 type_type, "GetTypeFromHandle", runtime_type_handle);
1226 Type [] delegate_delegate = { delegate_type, delegate_type };
1227 delegate_combine_delegate_delegate = GetMethod (
1228 delegate_type, "Combine", delegate_delegate);
1230 delegate_remove_delegate_delegate = GetMethod (
1231 delegate_type, "Remove", delegate_delegate);
1236 Type [] void_arg = { };
1237 object_getcurrent_void = GetMethod (
1238 ienumerator_type, "get_Current", void_arg);
1239 bool_movenext_void = GetMethod (
1240 ienumerator_type, "MoveNext", void_arg);
1241 void_reset_void = GetMethod (
1242 ienumerator_type, "Reset", void_arg);
1243 void_dispose_void = GetMethod (
1244 idisposable_type, "Dispose", void_arg);
1245 int_get_offset_to_string_data = GetMethod (
1246 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1247 int_array_get_length = GetMethod (
1248 array_type, "get_Length", void_arg);
1249 int_array_get_rank = GetMethod (
1250 array_type, "get_Rank", void_arg);
1251 ienumerable_getenumerator_void = GetMethod (
1252 ienumerable_type, "GetEnumerator", void_arg);
1257 Type [] int_arg = { int32_type };
1258 int_array_get_length_int = GetMethod (
1259 array_type, "GetLength", int_arg);
1260 int_array_get_upper_bound_int = GetMethod (
1261 array_type, "GetUpperBound", int_arg);
1262 int_array_get_lower_bound_int = GetMethod (
1263 array_type, "GetLowerBound", int_arg);
1266 // System.Array methods
1268 object_array_clone = GetMethod (
1269 array_type, "Clone", void_arg);
1270 Type [] array_int_arg = { array_type, int32_type };
1271 void_array_copyto_array_int = GetMethod (
1272 array_type, "CopyTo", array_int_arg);
1277 Type [] object_arg = { object_type };
1278 void_monitor_enter_object = GetMethod (
1279 monitor_type, "Enter", object_arg);
1280 void_monitor_exit_object = GetMethod (
1281 monitor_type, "Exit", object_arg);
1283 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1285 void_initializearray_array_fieldhandle = GetMethod (
1286 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1291 int_getlength_int = GetMethod (
1292 array_type, "GetLength", int_arg);
1295 // Decimal constructors
1297 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1298 void_decimal_ctor_five_args = GetConstructor (
1299 decimal_type, dec_arg);
1304 cons_param_array_attribute = GetConstructor (
1305 param_array_type, void_arg);
1307 unverifiable_code_ctor = GetConstructor (
1308 unverifiable_code_type, void_arg);
1311 // InvalidOperationException
1313 invalid_operation_ctor = GetConstructor (
1314 invalid_operation_exception_type, void_arg);
1318 object_ctor = GetConstructor (object_type, void_arg);
1322 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1325 /// This is the "old", non-cache based FindMembers() function. We cannot use
1326 /// the cache here because there is no member name argument.
1328 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1329 MemberFilter filter, object criteria)
1331 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1334 // `builder_to_declspace' contains all dynamic types.
1338 Timer.StartTimer (TimerType.FindMembers);
1339 list = decl.FindMembers (mt, bf, filter, criteria);
1340 Timer.StopTimer (TimerType.FindMembers);
1345 // We have to take care of arrays specially, because GetType on
1346 // a TypeBuilder array will return a Type, not a TypeBuilder,
1347 // and we can not call FindMembers on this type.
1349 if (t.IsSubclassOf (TypeManager.array_type))
1350 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1353 // Since FindMembers will not lookup both static and instance
1354 // members, we emulate this behaviour here.
1356 if ((bf & instance_and_static) == instance_and_static){
1357 MemberInfo [] i_members = t.FindMembers (
1358 mt, bf & ~BindingFlags.Static, filter, criteria);
1360 int i_len = i_members.Length;
1362 MemberInfo one = i_members [0];
1365 // If any of these are present, we are done!
1367 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1368 return new MemberList (i_members);
1371 MemberInfo [] s_members = t.FindMembers (
1372 mt, bf & ~BindingFlags.Instance, filter, criteria);
1374 int s_len = s_members.Length;
1375 if (i_len > 0 || s_len > 0)
1376 return new MemberList (i_members, s_members);
1379 return new MemberList (i_members);
1381 return new MemberList (s_members);
1385 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1390 /// This method is only called from within MemberLookup. It tries to use the member
1391 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1392 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1393 /// our return value will already contain all inherited members and the caller don't need
1394 /// to check base classes and interfaces anymore.
1396 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1397 string name, out bool used_cache)
1400 // We have to take care of arrays specially, because GetType on
1401 // a TypeBuilder array will return a Type, not a TypeBuilder,
1402 // and we can not call FindMembers on this type.
1404 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1406 return TypeHandle.ArrayType.MemberCache.FindMembers (
1407 mt, bf, name, FilterWithClosure_delegate, null);
1411 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1412 // and we can ask the DeclSpace for the MemberCache.
1414 if (t is TypeBuilder) {
1415 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1416 MemberCache cache = decl.MemberCache;
1419 // If this DeclSpace has a MemberCache, use it.
1422 if (cache != null) {
1424 return cache.FindMembers (
1425 mt, bf, name, FilterWithClosure_delegate, null);
1428 // If there is no MemberCache, we need to use the "normal" FindMembers.
1429 // Note, this is a VERY uncommon route!
1432 Timer.StartTimer (TimerType.FindMembers);
1433 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1434 FilterWithClosure_delegate, name);
1435 Timer.StopTimer (TimerType.FindMembers);
1438 return (MemberInfo []) list;
1442 // This call will always succeed. There is exactly one TypeHandle instance per
1443 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1444 // if it didn't already exist.
1446 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1449 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1452 public static bool IsBuiltinType (Type t)
1454 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1455 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1456 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1457 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1463 public static bool IsBuiltinType (TypeContainer tc)
1465 return IsBuiltinType (tc.TypeBuilder);
1469 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1470 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1472 public static bool IsCLRType (Type t)
1474 if (t == object_type || t == int32_type || t == uint32_type ||
1475 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1476 t == char_type || t == short_type || t == bool_type ||
1477 t == sbyte_type || t == byte_type || t == ushort_type)
1483 public static bool IsDelegateType (Type t)
1485 if (t.IsSubclassOf (TypeManager.delegate_type))
1491 public static bool IsEnumType (Type t)
1493 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1498 public static bool IsBuiltinOrEnum (Type t)
1500 if (IsBuiltinType (t))
1510 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1512 public static bool IsUnmanagedType (Type t)
1514 if (IsBuiltinType (t) && t != TypeManager.string_type)
1523 if (IsValueType (t)){
1524 if (t is TypeBuilder){
1525 TypeContainer tc = LookupTypeContainer (t);
1527 if (tc.Fields != null){
1528 foreach (Field f in tc.Fields){
1529 if (f.FieldBuilder.IsStatic)
1531 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1537 FieldInfo [] fields = t.GetFields ();
1539 foreach (FieldInfo f in fields){
1542 if (!IsUnmanagedType (f.FieldType))
1552 public static bool IsValueType (Type t)
1554 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1560 public static bool IsInterfaceType (Type t)
1562 Interface iface = builder_to_declspace [t] as Interface;
1571 // Checks whether `type' is a subclass or nested child of `parent'.
1573 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1576 if ((type == parent) || type.IsSubclassOf (parent))
1579 // Handle nested types.
1580 type = type.DeclaringType;
1581 } while (type != null);
1587 // Checks whether `type' is a nested child of `parent'.
1589 public static bool IsNestedChildOf (Type type, Type parent)
1594 type = type.DeclaringType;
1595 while (type != null) {
1599 type = type.DeclaringType;
1606 // Do the right thing when returning the element type of an
1607 // array type based on whether we are compiling corlib or not
1609 public static Type GetElementType (Type t)
1611 if (RootContext.StdLib)
1612 return t.GetElementType ();
1614 return TypeToCoreType (t.GetElementType ());
1618 /// Returns the User Defined Types
1620 public static ArrayList UserTypes {
1626 public static Hashtable TypeContainers {
1628 return typecontainers;
1632 static Hashtable builder_to_constant;
1634 public static void RegisterConstant (FieldBuilder fb, Const c)
1636 if (builder_to_constant == null)
1637 builder_to_constant = new PtrHashtable ();
1639 if (builder_to_constant.Contains (fb))
1642 builder_to_constant.Add (fb, c);
1645 public static Const LookupConstant (FieldBuilder fb)
1647 if (builder_to_constant == null)
1650 return (Const) builder_to_constant [fb];
1654 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1658 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1659 /// for anything which is dynamic, and we need this in a number of places,
1660 /// we register this information here, and use it afterwards.
1662 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1667 method_arguments.Add (mb, args);
1668 method_internal_params.Add (mb, ip);
1673 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1675 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1678 if (method_internal_params.Contains (mb))
1679 return (InternalParameters) method_internal_params [mb];
1681 throw new Exception ("Argument for Method not registered" + mb);
1685 /// Returns the argument types for a method based on its methodbase
1687 /// For dynamic methods, we use the compiler provided types, for
1688 /// methods from existing assemblies we load them from GetParameters,
1689 /// and insert them into the cache
1691 static public Type [] GetArgumentTypes (MethodBase mb)
1693 if (method_arguments.Contains (mb))
1694 return (Type []) method_arguments [mb];
1696 ParameterInfo [] pi = mb.GetParameters ();
1698 Type [] types = new Type [c];
1700 for (int i = 0; i < c; i++)
1701 types [i] = pi [i].ParameterType;
1703 method_arguments.Add (mb, types);
1709 /// Returns the argument types for an indexer based on its PropertyInfo
1711 /// For dynamic indexers, we use the compiler provided types, for
1712 /// indexers from existing assemblies we load them from GetParameters,
1713 /// and insert them into the cache
1715 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1717 if (indexer_arguments.Contains (indexer))
1718 return (Type []) indexer_arguments [indexer];
1719 else if (indexer is PropertyBuilder)
1720 // If we're a PropertyBuilder and not in the
1721 // `indexer_arguments' hash, then we're a property and
1725 ParameterInfo [] pi = indexer.GetIndexParameters ();
1726 // Property, not an indexer.
1730 Type [] types = new Type [c];
1732 for (int i = 0; i < c; i++)
1733 types [i] = pi [i].ParameterType;
1735 indexer_arguments.Add (indexer, types);
1741 // This is a workaround the fact that GetValue is not
1742 // supported for dynamic types
1744 static Hashtable fields = new Hashtable ();
1745 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1747 if (fields.Contains (fb))
1750 fields.Add (fb, value);
1755 static public object GetValue (FieldBuilder fb)
1760 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1761 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1763 if (fieldbuilders_to_fields.Contains (fb))
1766 fieldbuilders_to_fields.Add (fb, f);
1771 // The return value can be null; This will be the case for
1772 // auxiliary FieldBuilders created by the compiler that have no
1773 // real field being declared on the source code
1775 static public FieldBase GetField (FieldInfo fb)
1777 return (FieldBase) fieldbuilders_to_fields [fb];
1780 static Hashtable events;
1782 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1785 events = new Hashtable ();
1787 if (events.Contains (eb))
1790 events.Add (eb, new Pair (add, remove));
1795 static public MethodInfo GetAddMethod (EventInfo ei)
1797 if (ei is MyEventBuilder) {
1798 Pair pair = (Pair) events [ei];
1800 return (MethodInfo) pair.First;
1802 return ei.GetAddMethod ();
1805 static public MethodInfo GetRemoveMethod (EventInfo ei)
1807 if (ei is MyEventBuilder) {
1808 Pair pair = (Pair) events [ei];
1810 return (MethodInfo) pair.Second;
1812 return ei.GetRemoveMethod ();
1815 static Hashtable priv_fields_events;
1817 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1819 if (priv_fields_events == null)
1820 priv_fields_events = new Hashtable ();
1822 if (priv_fields_events.Contains (einfo))
1825 priv_fields_events.Add (einfo, builder);
1830 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1832 if (priv_fields_events == null)
1835 return (MemberInfo) priv_fields_events [ei];
1838 static Hashtable properties;
1840 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1842 if (properties == null)
1843 properties = new Hashtable ();
1845 if (properties.Contains (pb))
1848 properties.Add (pb, new Pair (get, set));
1853 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1854 MethodBase set, Type[] args)
1856 if (!RegisterProperty (pb, get,set))
1859 indexer_arguments.Add (pb, args);
1864 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1866 Hashtable hash = new Hashtable ();
1867 return CheckStructCycles (tc, seen, hash);
1870 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1873 if (!(tc is Struct) || IsBuiltinType (tc))
1877 // `seen' contains all types we've already visited.
1879 if (seen.Contains (tc))
1881 seen.Add (tc, null);
1883 if (tc.Fields == null)
1886 foreach (Field field in tc.Fields) {
1887 if (field.FieldBuilder.IsStatic)
1890 Type ftype = field.FieldBuilder.FieldType;
1891 TypeContainer ftc = LookupTypeContainer (ftype);
1895 if (hash.Contains (ftc)) {
1896 Report.Error (523, tc.Location,
1897 "Struct member `{0}.{1}' of type `{2}' " +
1898 "causes a cycle in the struct layout",
1899 tc.Name, field.Name, ftc.Name);
1904 // `hash' contains all types in the current path.
1906 hash.Add (tc, null);
1908 bool ok = CheckStructCycles (ftc, seen, hash);
1915 if (!seen.Contains (ftc))
1916 seen.Add (ftc, null);
1923 /// Given an array of interface types, expand and eliminate repeated ocurrences
1924 /// of an interface.
1928 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1931 public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
1933 ArrayList new_ifaces = new ArrayList ();
1935 foreach (TypeExpr iface in base_interfaces){
1936 if (!new_ifaces.Contains (iface))
1937 new_ifaces.Add (iface);
1939 TypeExpr [] implementing = iface.GetInterfaces ();
1941 foreach (TypeExpr imp in implementing){
1942 if (!new_ifaces.Contains (imp))
1943 new_ifaces.Add (imp);
1946 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
1947 new_ifaces.CopyTo (ret, 0);
1951 static PtrHashtable iface_cache = new PtrHashtable ();
1954 /// This function returns the interfaces in the type `t'. Works with
1955 /// both types and TypeBuilders.
1957 public static TypeExpr [] GetInterfaces (Type t)
1960 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
1965 // The reason for catching the Array case is that Reflection.Emit
1966 // will not return a TypeBuilder for Array types of TypeBuilder types,
1967 // but will still throw an exception if we try to call GetInterfaces
1970 // Since the array interfaces are always constant, we return those for
1975 t = TypeManager.array_type;
1977 if (t is TypeBuilder){
1978 TypeExpr [] parent_ifaces;
1980 if (t.BaseType == null)
1981 parent_ifaces = NoTypeExprs;
1983 parent_ifaces = GetInterfaces (t.BaseType);
1984 TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
1985 if (type_ifaces == null)
1986 type_ifaces = NoTypeExprs;
1988 int parent_count = parent_ifaces.Length;
1989 TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
1990 parent_ifaces.CopyTo (result, 0);
1991 type_ifaces.CopyTo (result, parent_count);
1993 iface_cache [t] = result;
1996 Type [] ifaces = t.GetInterfaces ();
1997 if (ifaces.Length == 0)
2000 TypeExpr [] result = new TypeExpr [ifaces.Length];
2001 for (int i = 0; i < ifaces.Length; i++)
2002 result [i] = new TypeExpression (ifaces [i], Location.Null);
2004 iface_cache [t] = result;
2010 // gets the interfaces that are declared explicitly on t
2012 public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2014 return (TypeExpr []) builder_to_ifaces [t];
2018 /// The following is used to check if a given type implements an interface.
2019 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2021 public static bool ImplementsInterface (Type t, Type iface)
2023 TypeExpr [] interfaces;
2026 // FIXME OPTIMIZATION:
2027 // as soon as we hit a non-TypeBuiler in the interface
2028 // chain, we could return, as the `Type.GetInterfaces'
2029 // will return all the interfaces implement by the type
2033 interfaces = GetInterfaces (t);
2035 if (interfaces != null){
2036 foreach (TypeExpr i in interfaces){
2037 if (i.Type == iface)
2043 } while (t != null);
2048 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2050 // This is a custom version of Convert.ChangeType() which works
2051 // with the TypeBuilder defined types when compiling corlib.
2052 public static object ChangeType (object value, Type conversionType, out bool error)
2054 IConvertible convert_value = value as IConvertible;
2056 if (convert_value == null){
2062 // We must use Type.Equals() here since `conversionType' is
2063 // the TypeBuilder created version of a system type and not
2064 // the system type itself. You cannot use Type.GetTypeCode()
2065 // on such a type - it'd always return TypeCode.Object.
2069 if (conversionType.Equals (typeof (Boolean)))
2070 return (object)(convert_value.ToBoolean (nf_provider));
2071 else if (conversionType.Equals (typeof (Byte)))
2072 return (object)(convert_value.ToByte (nf_provider));
2073 else if (conversionType.Equals (typeof (Char)))
2074 return (object)(convert_value.ToChar (nf_provider));
2075 else if (conversionType.Equals (typeof (DateTime)))
2076 return (object)(convert_value.ToDateTime (nf_provider));
2077 else if (conversionType.Equals (typeof (Decimal)))
2078 return (object)(convert_value.ToDecimal (nf_provider));
2079 else if (conversionType.Equals (typeof (Double)))
2080 return (object)(convert_value.ToDouble (nf_provider));
2081 else if (conversionType.Equals (typeof (Int16)))
2082 return (object)(convert_value.ToInt16 (nf_provider));
2083 else if (conversionType.Equals (typeof (Int32)))
2084 return (object)(convert_value.ToInt32 (nf_provider));
2085 else if (conversionType.Equals (typeof (Int64)))
2086 return (object)(convert_value.ToInt64 (nf_provider));
2087 else if (conversionType.Equals (typeof (SByte)))
2088 return (object)(convert_value.ToSByte (nf_provider));
2089 else if (conversionType.Equals (typeof (Single)))
2090 return (object)(convert_value.ToSingle (nf_provider));
2091 else if (conversionType.Equals (typeof (String)))
2092 return (object)(convert_value.ToString (nf_provider));
2093 else if (conversionType.Equals (typeof (UInt16)))
2094 return (object)(convert_value.ToUInt16 (nf_provider));
2095 else if (conversionType.Equals (typeof (UInt32)))
2096 return (object)(convert_value.ToUInt32 (nf_provider));
2097 else if (conversionType.Equals (typeof (UInt64)))
2098 return (object)(convert_value.ToUInt64 (nf_provider));
2099 else if (conversionType.Equals (typeof (Object)))
2100 return (object)(value);
2110 // This is needed, because enumerations from assemblies
2111 // do not report their underlyingtype, but they report
2114 public static Type EnumToUnderlying (Type t)
2116 if (t == TypeManager.enum_type)
2119 t = t.UnderlyingSystemType;
2120 if (!TypeManager.IsEnumType (t))
2123 if (t is TypeBuilder) {
2124 // slow path needed to compile corlib
2125 if (t == TypeManager.bool_type ||
2126 t == TypeManager.byte_type ||
2127 t == TypeManager.sbyte_type ||
2128 t == TypeManager.char_type ||
2129 t == TypeManager.short_type ||
2130 t == TypeManager.ushort_type ||
2131 t == TypeManager.int32_type ||
2132 t == TypeManager.uint32_type ||
2133 t == TypeManager.int64_type ||
2134 t == TypeManager.uint64_type)
2136 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2138 TypeCode tc = Type.GetTypeCode (t);
2141 case TypeCode.Boolean:
2142 return TypeManager.bool_type;
2144 return TypeManager.byte_type;
2145 case TypeCode.SByte:
2146 return TypeManager.sbyte_type;
2148 return TypeManager.char_type;
2149 case TypeCode.Int16:
2150 return TypeManager.short_type;
2151 case TypeCode.UInt16:
2152 return TypeManager.ushort_type;
2153 case TypeCode.Int32:
2154 return TypeManager.int32_type;
2155 case TypeCode.UInt32:
2156 return TypeManager.uint32_type;
2157 case TypeCode.Int64:
2158 return TypeManager.int64_type;
2159 case TypeCode.UInt64:
2160 return TypeManager.uint64_type;
2162 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2166 // When compiling corlib and called with one of the core types, return
2167 // the corresponding typebuilder for that type.
2169 public static Type TypeToCoreType (Type t)
2171 if (RootContext.StdLib || (t is TypeBuilder))
2174 TypeCode tc = Type.GetTypeCode (t);
2177 case TypeCode.Boolean:
2178 return TypeManager.bool_type;
2180 return TypeManager.byte_type;
2181 case TypeCode.SByte:
2182 return TypeManager.sbyte_type;
2184 return TypeManager.char_type;
2185 case TypeCode.Int16:
2186 return TypeManager.short_type;
2187 case TypeCode.UInt16:
2188 return TypeManager.ushort_type;
2189 case TypeCode.Int32:
2190 return TypeManager.int32_type;
2191 case TypeCode.UInt32:
2192 return TypeManager.uint32_type;
2193 case TypeCode.Int64:
2194 return TypeManager.int64_type;
2195 case TypeCode.UInt64:
2196 return TypeManager.uint64_type;
2197 case TypeCode.Single:
2198 return TypeManager.float_type;
2199 case TypeCode.Double:
2200 return TypeManager.double_type;
2201 case TypeCode.String:
2202 return TypeManager.string_type;
2204 if (t == typeof (void))
2205 return TypeManager.void_type;
2206 if (t == typeof (object))
2207 return TypeManager.object_type;
2208 if (t == typeof (System.Type))
2209 return TypeManager.type_type;
2210 if (t == typeof (System.IntPtr))
2211 return TypeManager.intptr_type;
2217 /// Utility function that can be used to probe whether a type
2218 /// is managed or not.
2220 public static bool VerifyUnManaged (Type t, Location loc)
2222 if (t.IsValueType || t.IsPointer){
2224 // FIXME: this is more complex, we actually need to
2225 // make sure that the type does not contain any
2231 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2232 // We need this explicit check here to make it work when
2233 // compiling corlib.
2238 "Cannot take the address or size of a variable of a managed type ('" +
2239 CSharpName (t) + "')");
2244 /// Returns the name of the indexer in a given type.
2247 /// The default is not always `Item'. The user can change this behaviour by
2248 /// using the DefaultMemberAttribute in the class.
2250 /// For example, the String class indexer is named `Chars' not `Item'
2252 public static string IndexerPropertyName (Type t)
2254 if (t is TypeBuilder) {
2255 if (t.IsInterface) {
2256 Interface i = LookupInterface (t);
2258 if ((i == null) || (i.IndexerName == null))
2261 return i.IndexerName;
2263 TypeContainer tc = LookupTypeContainer (t);
2265 if ((tc == null) || (tc.IndexerName == null))
2268 return tc.IndexerName;
2272 System.Attribute attr = System.Attribute.GetCustomAttribute (
2273 t, TypeManager.default_member_type);
2275 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2276 return dma.MemberName;
2282 static MethodInfo pinned_method = null;
2283 public static void MakePinned (LocalBuilder builder)
2285 if (pinned_method == null) {
2286 pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
2287 if (pinned_method == null) {
2288 Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
2289 "This code may cause errors on a runtime with a moving GC");
2295 pinned_method.Invoke (builder, null);
2300 // Returns whether the array of memberinfos contains the given method
2302 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2304 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2306 foreach (MethodBase method in array) {
2307 if (method.Name != new_method.Name)
2310 if (method is MethodInfo && new_method is MethodInfo)
2311 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2315 Type [] old_args = TypeManager.GetArgumentTypes (method);
2316 int old_count = old_args.Length;
2319 if (new_args.Length != old_count)
2322 for (i = 0; i < old_count; i++){
2323 if (old_args [i] != new_args [i])
2336 // We copy methods from `new_members' into `target_list' if the signature
2337 // for the method from in the new list does not exist in the target_list
2339 // The name is assumed to be the same.
2341 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2343 if (target_list == null){
2344 target_list = new ArrayList ();
2346 foreach (MemberInfo mi in new_members){
2347 if (mi is MethodBase)
2348 target_list.Add (mi);
2353 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2354 target_list.CopyTo (target_array, 0);
2356 foreach (MemberInfo mi in new_members){
2357 MethodBase new_method = (MethodBase) mi;
2359 if (!ArrayContainsMethod (target_array, new_method))
2360 target_list.Add (new_method);
2366 #region MemberLookup implementation
2369 // Whether we allow private members in the result (since FindMembers
2370 // uses NonPublic for both protected and private), we need to distinguish.
2373 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2378 internal class Closure {
2379 internal bool private_ok;
2381 // Who is invoking us and which type is being queried currently.
2382 internal Type invocation_type;
2383 internal Type qualifier_type;
2385 // The assembly that defines the type is that is calling us
2386 internal Assembly invocation_assembly;
2387 internal IList almost_match;
2389 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2391 if (invocation_type == null)
2394 Debug.Assert (IsSubclassOrNestedChildOf (invocation_type, m.DeclaringType));
2399 // A nested class has access to all the protected members visible to its parent.
2400 if (qualifier_type != null
2401 && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2404 if (invocation_type == m.DeclaringType
2405 || invocation_type.IsSubclassOf (m.DeclaringType)) {
2406 // Although a derived class can access protected members of its base class
2407 // it cannot do so through an instance of the base class (CS1540).
2408 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2409 if (qualifier_type == null
2410 || qualifier_type == invocation_type
2411 || qualifier_type.IsSubclassOf (invocation_type))
2415 if (almost_match != null)
2416 almost_match.Add (m);
2421 // This filter filters by name + whether it is ok to include private
2422 // members in the search
2424 internal bool Filter (MemberInfo m, object filter_criteria)
2427 // Hack: we know that the filter criteria will always be in the `closure'
2431 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2434 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2435 (m.DeclaringType == invocation_type))
2439 // Ugly: we need to find out the type of `m', and depending
2440 // on this, tell whether we accept or not
2442 if (m is MethodBase){
2443 MethodBase mb = (MethodBase) m;
2444 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2446 if (ma == MethodAttributes.Private)
2447 return private_ok || (invocation_type == m.DeclaringType) ||
2448 IsNestedChildOf (invocation_type, m.DeclaringType);
2450 // Assembly succeeds if we're in the same assembly.
2451 if (ma == MethodAttributes.Assembly)
2452 return (invocation_assembly == mb.DeclaringType.Assembly);
2454 // FamAndAssem requires that we not only derive, but we are on the same assembly.
2455 if (ma == MethodAttributes.FamANDAssem){
2456 if (invocation_assembly != mb.DeclaringType.Assembly)
2460 // Family and FamANDAssem require that we derive.
2461 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem))
2462 return CheckValidFamilyAccess (mb.IsStatic, m);
2468 if (m is FieldInfo){
2469 FieldInfo fi = (FieldInfo) m;
2470 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2472 if (fa == FieldAttributes.Private)
2473 return private_ok || (invocation_type == m.DeclaringType) ||
2474 IsNestedChildOf (invocation_type, m.DeclaringType);
2476 // Assembly succeeds if we're in the same assembly.
2477 if (fa == FieldAttributes.Assembly)
2478 return (invocation_assembly == fi.DeclaringType.Assembly);
2480 // FamAndAssem requires that we not only derive, but we are on the same assembly.
2481 if (fa == FieldAttributes.FamANDAssem){
2482 if (invocation_assembly != fi.DeclaringType.Assembly)
2486 // Family and FamANDAssem require that we derive.
2487 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem))
2488 return CheckValidFamilyAccess (fi.IsStatic, m);
2495 // EventInfos and PropertyInfos, return true because they lack permission
2496 // information, so we need to check later on the methods.
2502 static Closure closure = new Closure ();
2503 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2504 static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2507 // Looks up a member called `name' in the `queried_type'. This lookup
2508 // is done by code that is contained in the definition for `invocation_type'
2509 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2511 // `invocation_type' is used to check whether we're allowed to access the requested
2512 // member wrt its protection level.
2514 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2515 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2516 // is B and qualifier_type is A). This is used to do the CS1540 check.
2518 // When resolving a SimpleName, `qualifier_type' is null.
2520 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2521 // the same than `queried_type' - except when we're being called from BaseAccess;
2522 // in this case, `invocation_type' is the current type and `queried_type' the base
2523 // type, so this'd normally trigger a CS1540.
2525 // The binding flags are `bf' and the kind of members being looked up are `mt'
2527 // The return value always includes private members which code in `invocation_type'
2528 // is allowed to access (using the specified `qualifier_type' if given); only use
2529 // BindingFlags.NonPublic to bypass the permission check.
2531 // The 'almost_match' argument is used for reporting error CS1540.
2533 // Returns an array of a single element for everything but Methods/Constructors
2534 // that might return multiple matches.
2536 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2537 Type queried_type, MemberTypes mt,
2538 BindingFlags original_bf, string name, IList almost_match)
2540 Timer.StartTimer (TimerType.MemberLookup);
2542 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2543 queried_type, mt, original_bf, name, almost_match);
2545 Timer.StopTimer (TimerType.MemberLookup);
2550 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2551 Type queried_type, MemberTypes mt,
2552 BindingFlags original_bf, string name, IList almost_match)
2554 BindingFlags bf = original_bf;
2556 ArrayList method_list = null;
2557 Type current_type = queried_type;
2558 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2559 bool skip_iface_check = true, used_cache = false;
2560 bool always_ok_flag = false;
2562 closure.invocation_type = invocation_type;
2563 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2564 closure.qualifier_type = qualifier_type;
2565 closure.almost_match = almost_match;
2568 // If we are a nested class, we always have access to our container
2571 if (invocation_type != null){
2572 string invocation_name = invocation_type.FullName;
2573 if (invocation_name.IndexOf ('+') != -1){
2574 string container = queried_type.FullName + "+";
2575 int container_length = container.Length;
2577 if (invocation_name.Length > container_length){
2578 string shared = invocation_name.Substring (0, container_length);
2580 if (shared == container)
2581 always_ok_flag = true;
2586 // This is from the first time we find a method
2587 // in most cases, we do not actually find a method in the base class
2588 // so we can just ignore it, and save the arraylist allocation
2589 MemberInfo [] first_members_list = null;
2590 bool use_first_members_list = false;
2596 // `NonPublic' is lame, because it includes both protected and
2597 // private methods, so we need to control this behavior by
2598 // explicitly tracking if a private method is ok or not.
2600 // The possible cases are:
2601 // public, private and protected (internal does not come into the
2604 if ((invocation_type != null) &&
2605 ((invocation_type == current_type) ||
2606 IsNestedChildOf (invocation_type, current_type)) ||
2608 bf = original_bf | BindingFlags.NonPublic;
2612 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2614 Timer.StopTimer (TimerType.MemberLookup);
2616 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2618 Timer.StartTimer (TimerType.MemberLookup);
2621 // When queried for an interface type, the cache will automatically check all
2622 // inherited members, so we don't need to do this here. However, this only
2623 // works if we already used the cache in the first iteration of this loop.
2625 // If we used the cache in any further iteration, we can still terminate the
2626 // loop since the cache always looks in all parent classes.
2632 skip_iface_check = false;
2634 if (current_type == TypeManager.object_type)
2637 current_type = current_type.BaseType;
2640 // This happens with interfaces, they have a null
2641 // basetype. Look members up in the Object class.
2643 if (current_type == null)
2644 current_type = TypeManager.object_type;
2647 if (list.Length == 0)
2651 // Events and types are returned by both `static' and `instance'
2652 // searches, which means that our above FindMembers will
2653 // return two copies of the same.
2655 if (list.Length == 1 && !(list [0] is MethodBase)){
2660 // Multiple properties: we query those just to find out the indexer
2663 if (list [0] is PropertyInfo)
2667 // We found an event: the cache lookup returns both the event and
2668 // its private field.
2670 if (list [0] is EventInfo) {
2671 if ((list.Length == 2) && (list [1] is FieldInfo))
2672 return new MemberInfo [] { list [0] };
2679 // We found methods, turn the search into "method scan"
2683 if (first_members_list != null) {
2684 if (use_first_members_list) {
2685 method_list = CopyNewMethods (method_list, first_members_list);
2686 use_first_members_list = false;
2689 method_list = CopyNewMethods (method_list, list);
2691 first_members_list = list;
2692 use_first_members_list = true;
2693 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2695 } while (searching);
2697 if (use_first_members_list) {
2698 foreach (MemberInfo mi in first_members_list) {
2699 if (! (mi is MethodBase)) {
2700 method_list = CopyNewMethods (method_list, first_members_list);
2701 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2704 return (MemberInfo []) first_members_list;
2707 if (method_list != null && method_list.Count > 0)
2708 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2711 // This happens if we already used the cache in the first iteration, in this case
2712 // the cache already looked in all interfaces.
2714 if (skip_iface_check)
2718 // Interfaces do not list members they inherit, so we have to
2721 if (!queried_type.IsInterface)
2724 if (queried_type.IsArray)
2725 queried_type = TypeManager.array_type;
2727 TypeExpr [] ifaces = GetInterfaces (queried_type);
2731 foreach (TypeExpr itype in ifaces){
2734 x = MemberLookup (null, null, itype.Type, mt, bf, name, null);
2743 // This is used to extract properties and event declarations from a type
2745 static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2747 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2749 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2751 if (t is TypeBuilder) {
2752 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2754 return (MemberInfo []) decl.FindMembers (
2755 MemberTypes.Property | MemberTypes.Event,
2756 bf, FilterNone_delegate, null);
2758 return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2759 bf, FilterNone_delegate, null);
2764 public static bool IsSpecialMethod (MethodBase mb)
2766 Type t = mb.DeclaringType;
2768 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2769 if (matches == null)
2772 foreach (MemberInfo mi in matches){
2773 if (mi is PropertyBuilder){
2774 Pair p = (Pair) properties [mi];
2776 if (p.First == mb || p.Second == mb)
2778 } else if (mi is PropertyInfo){
2779 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2781 foreach (MethodInfo m in methods){
2785 } else if (mi is MyEventBuilder){
2786 Pair p = (Pair) events [mi];
2788 if (p.First == mb || p.Second == mb)
2790 } else if (mi is EventInfo){
2791 EventInfo ei = ((EventInfo) mi);
2793 if (ei.GetAddMethod (true) == mb)
2796 if (ei.GetRemoveMethod (true) == mb)
2799 if (ei.GetRaiseMethod (true) == mb)
2805 // Now check if it is an operator method
2809 if (s.StartsWith ("op_")){
2810 foreach (string name in Unary.oper_names){
2815 foreach (string name in Binary.oper_names){
2829 /// There is exactly one instance of this class per type.
2831 public sealed class TypeHandle : IMemberContainer {
2832 public readonly TypeHandle BaseType;
2834 readonly int id = ++next_id;
2835 static int next_id = 0;
2838 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
2839 /// a TypeHandle yet, a new instance of it is created. This static method
2840 /// ensures that we'll only have one TypeHandle instance per type.
2842 public static TypeHandle GetTypeHandle (Type t)
2844 TypeHandle handle = (TypeHandle) type_hash [t];
2848 handle = new TypeHandle (t);
2849 type_hash.Add (t, handle);
2853 public static void CleanUp ()
2859 /// Returns the TypeHandle for TypeManager.object_type.
2861 public static IMemberContainer ObjectType {
2863 if (object_type != null)
2866 object_type = GetTypeHandle (TypeManager.object_type);
2873 /// Returns the TypeHandle for TypeManager.array_type.
2875 public static IMemberContainer ArrayType {
2877 if (array_type != null)
2880 array_type = GetTypeHandle (TypeManager.array_type);
2886 private static PtrHashtable type_hash = new PtrHashtable ();
2888 private static TypeHandle object_type = null;
2889 private static TypeHandle array_type = null;
2892 private bool is_interface;
2893 private MemberCache member_cache;
2895 private TypeHandle (Type type)
2898 if (type.BaseType != null)
2899 BaseType = GetTypeHandle (type.BaseType);
2900 this.is_interface = type.IsInterface;
2901 this.member_cache = new MemberCache (this);
2904 // IMemberContainer methods
2906 public string Name {
2908 return type.FullName;
2918 public IMemberContainer Parent {
2924 public bool IsInterface {
2926 return is_interface;
2930 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2932 MemberInfo [] members;
2933 if (mt == MemberTypes.Event)
2934 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2936 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2938 Array.Reverse (members);
2940 return new MemberList (members);
2943 // IMemberFinder methods
2945 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2946 MemberFilter filter, object criteria)
2948 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
2951 public MemberCache MemberCache {
2953 return member_cache;
2957 public override string ToString ()
2959 if (BaseType != null)
2960 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2962 return "TypeHandle (" + id + "," + Name + ")";