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)
12 #define BROKEN_RUNTIME
15 using System.Globalization;
16 using System.Collections;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Text.RegularExpressions;
20 using System.Runtime.CompilerServices;
21 using System.Diagnostics;
23 namespace Mono.CSharp {
25 public class MemberList : IList {
26 public readonly IList List;
29 public MemberList (IList list)
34 this.List = new ArrayList ();
38 public static readonly MemberList Empty = new MemberList (new ArrayList ());
40 public static explicit operator MemberInfo [] (MemberList list)
42 Timer.StartTimer (TimerType.MiscTimer);
43 MemberInfo [] result = new MemberInfo [list.Count];
44 list.CopyTo (result, 0);
45 Timer.StopTimer (TimerType.MiscTimer);
57 public bool IsSynchronized {
59 return List.IsSynchronized;
63 public object SyncRoot {
69 public void CopyTo (Array array, int index)
71 List.CopyTo (array, index);
76 public IEnumerator GetEnumerator ()
78 return List.GetEnumerator ();
83 public bool IsFixedSize {
89 public bool IsReadOnly {
95 object IList.this [int index] {
101 throw new NotSupportedException ();
105 public MemberInfo this [int index] {
107 return (MemberInfo) List [index];
111 public int Add (object value)
113 throw new NotSupportedException ();
118 throw new NotSupportedException ();
121 public bool Contains (object value)
123 return List.Contains (value);
126 public int IndexOf (object value)
128 return List.IndexOf (value);
131 public void Insert (int index, object value)
133 throw new NotSupportedException ();
136 public void Remove (object value)
138 throw new NotSupportedException ();
141 public void RemoveAt (int index)
143 throw new NotSupportedException ();
147 public interface IMemberFinder {
148 MemberList FindMembers (MemberTypes mt, BindingFlags bf,
149 MemberFilter filter, object criteria);
152 public interface ICachingMemberFinder : IMemberFinder {
153 MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
154 MemberFilter filter, object criteria);
157 public interface IMemberContainer : ICachingMemberFinder {
166 IMemberContainer Parent {
174 MemberList GetMembers (MemberTypes mt, BindingFlags bf);
177 public class TypeManager {
179 // A list of core types that the compiler requires or uses
181 static public Type object_type;
182 static public Type value_type;
183 static public Type string_type;
184 static public Type int32_type;
185 static public Type uint32_type;
186 static public Type int64_type;
187 static public Type uint64_type;
188 static public Type float_type;
189 static public Type double_type;
190 static public Type char_type;
191 static public Type char_ptr_type;
192 static public Type short_type;
193 static public Type decimal_type;
194 static public Type bool_type;
195 static public Type sbyte_type;
196 static public Type byte_type;
197 static public Type ushort_type;
198 static public Type enum_type;
199 static public Type delegate_type;
200 static public Type multicast_delegate_type;
201 static public Type void_type;
202 static public Type enumeration_type;
203 static public Type array_type;
204 static public Type runtime_handle_type;
205 static public Type icloneable_type;
206 static public Type type_type;
207 static public Type ienumerator_type;
208 static public Type idisposable_type;
209 static public Type default_member_type;
210 static public Type iasyncresult_type;
211 static public Type asynccallback_type;
212 static public Type intptr_type;
213 static public Type monitor_type;
214 static public Type runtime_field_handle_type;
215 static public Type attribute_type;
216 static public Type attribute_usage_type;
217 static public Type dllimport_type;
218 static public Type unverifiable_code_type;
219 static public Type methodimpl_attr_type;
220 static public Type marshal_as_attr_type;
221 static public Type param_array_type;
222 static public Type void_ptr_type;
223 static public Type indexer_name_type;
224 static public Type exception_type;
225 static public object obsolete_attribute_type;
226 static public object conditional_attribute_type;
229 // An empty array of types
231 static public Type [] NoTypes;
235 // Expressions representing the internal types. Used during declaration
238 static public Expression system_object_expr, system_string_expr;
239 static public Expression system_boolean_expr, system_decimal_expr;
240 static public Expression system_single_expr, system_double_expr;
241 static public Expression system_sbyte_expr, system_byte_expr;
242 static public Expression system_int16_expr, system_uint16_expr;
243 static public Expression system_int32_expr, system_uint32_expr;
244 static public Expression system_int64_expr, system_uint64_expr;
245 static public Expression system_char_expr, system_void_expr;
246 static public Expression system_asynccallback_expr;
247 static public Expression system_iasyncresult_expr;
250 // This is only used when compiling corlib
252 static public Type system_int32_type;
253 static public Type system_array_type;
254 static public Type system_type_type;
255 static public Type system_assemblybuilder_type;
256 static public MethodInfo system_int_array_get_length;
257 static public MethodInfo system_int_array_get_rank;
258 static public MethodInfo system_object_array_clone;
259 static public MethodInfo system_int_array_get_length_int;
260 static public MethodInfo system_int_array_get_lower_bound_int;
261 static public MethodInfo system_int_array_get_upper_bound_int;
262 static public MethodInfo system_void_array_copyto_array_int;
263 static public MethodInfo system_void_set_corlib_type_builders;
267 // Internal, not really used outside
269 static Type runtime_helpers_type;
272 // These methods are called by code generated by the compiler
274 static public MethodInfo string_concat_string_string;
275 static public MethodInfo string_concat_object_object;
276 static public MethodInfo string_isinterneted_string;
277 static public MethodInfo system_type_get_type_from_handle;
278 static public MethodInfo object_getcurrent_void;
279 static public MethodInfo bool_movenext_void;
280 static public MethodInfo void_dispose_void;
281 static public MethodInfo void_monitor_enter_object;
282 static public MethodInfo void_monitor_exit_object;
283 static public MethodInfo void_initializearray_array_fieldhandle;
284 static public MethodInfo int_getlength_int;
285 static public MethodInfo delegate_combine_delegate_delegate;
286 static public MethodInfo delegate_remove_delegate_delegate;
287 static public MethodInfo int_get_offset_to_string_data;
288 static public MethodInfo int_array_get_length;
289 static public MethodInfo int_array_get_rank;
290 static public MethodInfo object_array_clone;
291 static public MethodInfo int_array_get_length_int;
292 static public MethodInfo int_array_get_lower_bound_int;
293 static public MethodInfo int_array_get_upper_bound_int;
294 static public MethodInfo void_array_copyto_array_int;
297 // The attribute constructors.
299 static public ConstructorInfo cons_param_array_attribute;
300 static public ConstructorInfo void_decimal_ctor_five_args;
301 static public ConstructorInfo unverifiable_code_ctor;
304 // Holds the Array of Assemblies that have been loaded
305 // (either because it is the default or the user used the
306 // -r command line option)
308 static Assembly [] assemblies;
311 // Keeps a list of module builders. We used this to do lookups
312 // on the modulebuilder using GetType -- needed for arrays
314 static ModuleBuilder [] modules;
317 // This is the type_cache from the assemblies to avoid
318 // hitting System.Reflection on every lookup.
320 static Hashtable types;
323 // This is used to hotld the corresponding TypeContainer objects
324 // since we need this in FindMembers
326 static Hashtable typecontainers;
329 // Keeps track of those types that are defined by the
332 static ArrayList user_types;
334 static PtrHashtable builder_to_member_finder;
337 // Tracks the interfaces implemented by typebuilders. We only
338 // enter those who do implement or or more interfaces
340 static PtrHashtable builder_to_ifaces;
343 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
344 // the arguments to the method
346 static Hashtable method_arguments;
349 // Maps PropertyBuilder to a Type array that contains
350 // the arguments to the indexer
352 static Hashtable indexer_arguments;
355 // Maybe `method_arguments' should be replaced and only
356 // method_internal_params should be kept?
358 static Hashtable method_internal_params;
361 // Keeps track of attribute types
364 static Hashtable builder_to_attr;
367 // Keeps track of methods
370 static Hashtable builder_to_method;
378 /// A filter for Findmembers that uses the Signature object to
381 static bool SignatureFilter (MemberInfo mi, object criteria)
383 Signature sig = (Signature) criteria;
385 if (!(mi is MethodBase))
388 if (mi.Name != sig.name)
391 int count = sig.args.Length;
393 if (mi is MethodBuilder || mi is ConstructorBuilder){
394 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
396 if (candidate_args.Length != count)
399 for (int i = 0; i < count; i++)
400 if (candidate_args [i] != sig.args [i])
405 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
407 if (pars.Length != count)
410 for (int i = 0; i < count; i++)
411 if (pars [i].ParameterType != sig.args [i])
417 // A delegate that points to the filter above.
418 static MemberFilter signature_filter;
421 // These are expressions that represent some of the internal data types, used
424 static void InitExpressionTypes ()
426 system_object_expr = new TypeLookupExpression ("System.Object");
427 system_string_expr = new TypeLookupExpression ("System.String");
428 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
429 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
430 system_single_expr = new TypeLookupExpression ("System.Single");
431 system_double_expr = new TypeLookupExpression ("System.Double");
432 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
433 system_byte_expr = new TypeLookupExpression ("System.Byte");
434 system_int16_expr = new TypeLookupExpression ("System.Int16");
435 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
436 system_int32_expr = new TypeLookupExpression ("System.Int32");
437 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
438 system_int64_expr = new TypeLookupExpression ("System.Int64");
439 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
440 system_char_expr = new TypeLookupExpression ("System.Char");
441 system_void_expr = new TypeLookupExpression ("System.Void");
442 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
443 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
446 static TypeManager ()
448 assemblies = new Assembly [0];
450 user_types = new ArrayList ();
452 types = new Hashtable ();
453 typecontainers = new Hashtable ();
455 builder_to_member_finder = new PtrHashtable ();
456 builder_to_attr = new PtrHashtable ();
457 builder_to_method = new PtrHashtable ();
458 method_arguments = new PtrHashtable ();
459 method_internal_params = new PtrHashtable ();
460 indexer_arguments = new PtrHashtable ();
461 builder_to_ifaces = new PtrHashtable ();
463 NoTypes = new Type [0];
465 signature_filter = new MemberFilter (SignatureFilter);
466 InitExpressionTypes ();
469 public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
474 Type prev = (Type) types [name];
475 TypeContainer tc = builder_to_member_finder [prev] as TypeContainer;
479 // This probably never happens, as we catch this before
481 Report.Error (-17, "The type `" + name + "' has already been defined.");
485 tc = builder_to_member_finder [t] as TypeContainer;
488 1595, "The type `" + name + "' is defined in an existing assembly;"+
489 " Using the new definition from: " + tc.Location);
490 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
498 builder_to_ifaces [t] = ifaces;
502 // This entry point is used by types that we define under the covers
504 public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
507 builder_to_ifaces [tb] = ifaces;
510 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
512 builder_to_member_finder.Add (t, tc);
513 typecontainers.Add (name, tc);
514 AddUserType (name, t, ifaces);
517 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
520 builder_to_member_finder.Add (t, del);
523 public static void AddEnumType (string name, TypeBuilder t, Enum en)
526 builder_to_member_finder.Add (t, en);
529 public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
531 AddUserType (name, t, ifaces);
532 builder_to_member_finder.Add (t, i);
535 public static void AddMethod (MethodBuilder builder, MethodData method)
537 builder_to_method.Add (builder, method);
540 public static void RegisterAttrType (Type t, TypeContainer tc)
542 builder_to_attr.Add (t, tc);
546 /// Returns the TypeContainer whose Type is `t' or null if there is no
547 /// TypeContainer for `t' (ie, the Type comes from a library)
549 public static TypeContainer LookupTypeContainer (Type t)
551 return builder_to_member_finder [t] as TypeContainer;
554 public static Interface LookupInterface (Type t)
556 return builder_to_member_finder [t] as Interface;
559 public static Delegate LookupDelegate (Type t)
561 return builder_to_member_finder [t] as Delegate;
564 public static Enum LookupEnum (Type t)
566 return builder_to_member_finder [t] as Enum;
569 public static TypeContainer LookupAttr (Type t)
571 return (TypeContainer) builder_to_attr [t];
575 /// Registers an assembly to load types from.
577 public static void AddAssembly (Assembly a)
579 int top = assemblies.Length;
580 Assembly [] n = new Assembly [top + 1];
582 assemblies.CopyTo (n, 0);
589 /// Registers a module builder to lookup types from
591 public static void AddModule (ModuleBuilder mb)
593 int top = modules != null ? modules.Length : 0;
594 ModuleBuilder [] n = new ModuleBuilder [top + 1];
597 modules.CopyTo (n, 0);
603 /// Returns the Type associated with @name
605 public static Type LookupType (string name)
610 // First lookup in user defined and cached values
613 t = (Type) types [name];
617 foreach (Assembly a in assemblies){
618 t = a.GetType (name);
626 foreach (ModuleBuilder mb in modules) {
627 t = mb.GetType (name);
638 /// Returns the C# name of a type if possible, or the full type name otherwise
640 static public string CSharpName (Type t)
642 return Regex.Replace (t.FullName,
644 @"(Int32|UInt32|Int16|Uint16|Int64|UInt64|" +
645 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
646 @"Boolean|String|Void)" +
648 new MatchEvaluator (CSharpNameMatch));
651 static String CSharpNameMatch (Match match)
653 string s = match.Groups [1].Captures [0].Value;
655 Replace ("int32", "int").
656 Replace ("uint32", "uint").
657 Replace ("int16", "short").
658 Replace ("uint16", "ushort").
659 Replace ("int64", "long").
660 Replace ("uint64", "ulong").
661 Replace ("single", "float").
662 Replace ("boolean", "bool")
663 + match.Groups [2].Captures [0].Value;
667 /// Returns the signature of the method
669 static public string CSharpSignature (MethodBase mb)
674 // FIXME: We should really have a single function to do
675 // everything instead of the following 5 line pattern
677 ParameterData iparams = LookupParametersByBuilder (mb);
679 if (iparams == null){
680 ParameterInfo [] pi = mb.GetParameters ();
681 iparams = new ReflectionParameters (pi);
684 for (int i = 0; i < iparams.Count; i++) {
688 sig += iparams.ParameterDesc(i);
692 return mb.DeclaringType.Name + "." + mb.Name + sig;
696 /// Looks up a type, and aborts if it is not found. This is used
697 /// by types required by the compiler
699 static Type CoreLookupType (string name)
701 Type t = LookupType (name);
704 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
705 Environment.Exit (0);
712 /// Returns the MethodInfo for a method named `name' defined
713 /// in type `t' which takes arguments of types `args'
715 static MethodInfo GetMethod (Type t, string name, Type [] args)
723 list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
724 signature_filter, sig);
725 if (list.Count == 0) {
726 Report.Error (-19, "Can not find the core function `" + name + "'");
730 MethodInfo mi = list [0] as MethodInfo;
732 Report.Error (-19, "Can not find the core function `" + name + "'");
740 /// Returns the ConstructorInfo for "args"
742 static ConstructorInfo GetConstructor (Type t, Type [] args)
750 list = FindMembers (t, MemberTypes.Constructor,
751 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
752 signature_filter, sig);
753 if (list.Count == 0){
754 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
758 ConstructorInfo ci = list [0] as ConstructorInfo;
760 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
767 public static void InitEnumUnderlyingTypes ()
770 int32_type = CoreLookupType ("System.Int32");
771 int64_type = CoreLookupType ("System.Int64");
772 uint32_type = CoreLookupType ("System.UInt32");
773 uint64_type = CoreLookupType ("System.UInt64");
774 byte_type = CoreLookupType ("System.Byte");
775 sbyte_type = CoreLookupType ("System.SByte");
776 short_type = CoreLookupType ("System.Int16");
777 ushort_type = CoreLookupType ("System.UInt16");
781 /// The types have to be initialized after the initial
782 /// population of the type has happened (for example, to
783 /// bootstrap the corlib.dll
785 public static void InitCoreTypes ()
787 object_type = CoreLookupType ("System.Object");
788 value_type = CoreLookupType ("System.ValueType");
790 InitEnumUnderlyingTypes ();
792 char_type = CoreLookupType ("System.Char");
793 string_type = CoreLookupType ("System.String");
794 float_type = CoreLookupType ("System.Single");
795 double_type = CoreLookupType ("System.Double");
796 char_ptr_type = CoreLookupType ("System.Char*");
797 decimal_type = CoreLookupType ("System.Decimal");
798 bool_type = CoreLookupType ("System.Boolean");
799 enum_type = CoreLookupType ("System.Enum");
801 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
802 delegate_type = CoreLookupType ("System.Delegate");
804 array_type = CoreLookupType ("System.Array");
805 void_type = CoreLookupType ("System.Void");
806 type_type = CoreLookupType ("System.Type");
808 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
809 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
810 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
811 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
812 asynccallback_type = CoreLookupType ("System.AsyncCallback");
813 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
814 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
815 idisposable_type = CoreLookupType ("System.IDisposable");
816 icloneable_type = CoreLookupType ("System.ICloneable");
817 monitor_type = CoreLookupType ("System.Threading.Monitor");
818 intptr_type = CoreLookupType ("System.IntPtr");
820 attribute_type = CoreLookupType ("System.Attribute");
821 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
822 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
823 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
824 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
825 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
827 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
829 void_ptr_type = CoreLookupType ("System.Void*");
831 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
833 exception_type = CoreLookupType ("System.Exception");
838 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
839 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
842 // When compiling corlib, store the "real" types here.
844 if (!RootContext.StdLib) {
845 system_int32_type = typeof (System.Int32);
846 system_array_type = typeof (System.Array);
847 system_type_type = typeof (System.Type);
848 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
850 Type [] void_arg = { };
851 system_int_array_get_length = GetMethod (
852 system_array_type, "get_Length", void_arg);
853 system_int_array_get_rank = GetMethod (
854 system_array_type, "get_Rank", void_arg);
855 system_object_array_clone = GetMethod (
856 system_array_type, "Clone", void_arg);
858 Type [] system_int_arg = { system_int32_type };
859 system_int_array_get_length_int = GetMethod (
860 system_array_type, "GetLength", system_int_arg);
861 system_int_array_get_upper_bound_int = GetMethod (
862 system_array_type, "GetUpperBound", system_int_arg);
863 system_int_array_get_lower_bound_int = GetMethod (
864 system_array_type, "GetLowerBound", system_int_arg);
866 Type [] system_array_int_arg = { system_array_type, system_int32_type };
867 system_void_array_copyto_array_int = GetMethod (
868 system_array_type, "CopyTo", system_array_int_arg);
870 Type [] system_type_type_arg = { system_type_type, system_type_type, system_type_type };
873 system_void_set_corlib_type_builders = GetMethod (
874 system_assemblybuilder_type, "SetCorlibTypeBuilders",
875 system_type_type_arg);
877 object[] args = new object [3];
878 args [0] = object_type;
879 args [1] = value_type;
880 args [2] = enum_type;
882 system_void_set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
884 Console.WriteLine ("Corlib compilation is not supported in Microsoft.NET due to bugs in it");
890 // The helper methods that are used by the compiler
892 public static void InitCodeHelpers ()
895 // Now load the default methods that we use.
897 Type [] string_string = { string_type, string_type };
898 string_concat_string_string = GetMethod (
899 string_type, "Concat", string_string);
901 Type [] object_object = { object_type, object_type };
902 string_concat_object_object = GetMethod (
903 string_type, "Concat", object_object);
905 Type [] string_ = { string_type };
906 string_isinterneted_string = GetMethod (
907 string_type, "IsInterned", string_);
909 Type [] runtime_type_handle = { runtime_handle_type };
910 system_type_get_type_from_handle = GetMethod (
911 type_type, "GetTypeFromHandle", runtime_type_handle);
913 Type [] delegate_delegate = { delegate_type, delegate_type };
914 delegate_combine_delegate_delegate = GetMethod (
915 delegate_type, "Combine", delegate_delegate);
917 delegate_remove_delegate_delegate = GetMethod (
918 delegate_type, "Remove", delegate_delegate);
923 Type [] void_arg = { };
924 object_getcurrent_void = GetMethod (
925 ienumerator_type, "get_Current", void_arg);
926 bool_movenext_void = GetMethod (
927 ienumerator_type, "MoveNext", void_arg);
928 void_dispose_void = GetMethod (
929 idisposable_type, "Dispose", void_arg);
930 int_get_offset_to_string_data = GetMethod (
931 runtime_helpers_type, "get_OffsetToStringData", void_arg);
932 int_array_get_length = GetMethod (
933 array_type, "get_Length", void_arg);
934 int_array_get_rank = GetMethod (
935 array_type, "get_Rank", void_arg);
940 Type [] int_arg = { int32_type };
941 int_array_get_length_int = GetMethod (
942 array_type, "GetLength", int_arg);
943 int_array_get_upper_bound_int = GetMethod (
944 array_type, "GetUpperBound", int_arg);
945 int_array_get_lower_bound_int = GetMethod (
946 array_type, "GetLowerBound", int_arg);
949 // System.Array methods
951 object_array_clone = GetMethod (
952 array_type, "Clone", void_arg);
953 Type [] array_int_arg = { array_type, int32_type };
954 void_array_copyto_array_int = GetMethod (
955 array_type, "CopyTo", array_int_arg);
960 Type [] object_arg = { object_type };
961 void_monitor_enter_object = GetMethod (
962 monitor_type, "Enter", object_arg);
963 void_monitor_exit_object = GetMethod (
964 monitor_type, "Exit", object_arg);
966 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
968 void_initializearray_array_fieldhandle = GetMethod (
969 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
974 int_getlength_int = GetMethod (
975 array_type, "GetLength", int_arg);
978 // Decimal constructors
980 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
981 void_decimal_ctor_five_args = GetConstructor (
982 decimal_type, dec_arg);
987 cons_param_array_attribute = GetConstructor (
988 param_array_type, void_arg);
990 unverifiable_code_ctor = GetConstructor (
991 unverifiable_code_type, void_arg);
995 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
997 static Hashtable type_hash = new Hashtable ();
999 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1000 MemberFilter filter, object criteria)
1002 IMemberFinder finder = (IMemberFinder) builder_to_member_finder [t];
1003 ICachingMemberFinder caching_finder = finder as ICachingMemberFinder;
1005 if (finder != null) {
1006 if ((caching_finder == null) || (filter != FilterWithClosure_delegate)) {
1008 Timer.StartTimer (TimerType.FindMembers);
1009 list = finder.FindMembers (mt, bf, filter, criteria);
1010 Timer.StopTimer (TimerType.FindMembers);
1014 return caching_finder.FindMembers (mt, bf, (string) criteria, filter, null);
1018 // We have to take care of arrays specially, because GetType on
1019 // a TypeBuilder array will return a Type, not a TypeBuilder,
1020 // and we can not call FindMembers on this type.
1023 if (t.IsSubclassOf (TypeManager.array_type))
1024 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1026 if (filter != FilterWithClosure_delegate)
1027 return new MemberList (RealFindMembers (t, mt, bf, filter, criteria));
1029 caching_finder = TypeHandle.GetTypeHandle (t);
1030 builder_to_member_finder.Add (t, caching_finder);
1032 return caching_finder.FindMembers (mt, bf, (string) criteria, filter, null);
1036 /// FIXME FIXME FIXME
1037 /// This method is a big hack until the new MemberCache is finished, it will be gone in
1039 /// FIXME FIXME FIXME
1041 private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1042 string name, ref bool searching)
1045 // We have to take care of arrays specially, because GetType on
1046 // a TypeBuilder array will return a Type, not a TypeBuilder,
1047 // and we can not call FindMembers on this type.
1050 if (t.IsSubclassOf (TypeManager.array_type)) {
1052 return TypeHandle.ArrayType.FindMembers (
1053 mt, bf, name, FilterWithClosure_delegate, null);
1054 // return new MemberList (TypeManager.array_type.FindMembers (
1055 // mt, bf | BindingFlags.DeclaredOnly, FilterWithClosure_delegate, name));
1058 IMemberFinder finder = (IMemberFinder) builder_to_member_finder [t];
1059 ICachingMemberFinder caching_finder = finder as ICachingMemberFinder;
1061 if (caching_finder != null) {
1063 return caching_finder.FindMembers (
1064 mt, bf, name, FilterWithClosure_delegate, null);
1067 if (finder != null) {
1069 Timer.StartTimer (TimerType.FindMembers);
1070 list = finder.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1071 FilterWithClosure_delegate, name);
1072 Timer.StopTimer (TimerType.FindMembers);
1076 caching_finder = TypeHandle.GetTypeHandle (t);
1077 builder_to_member_finder.Add (t, caching_finder);
1080 return caching_finder.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1084 // FIXME: This can be optimized easily. speedup by having a single builder mapping
1086 static MemberInfo [] RealFindMembers (Type t, MemberTypes mt, BindingFlags bf,
1087 MemberFilter filter, object criteria)
1089 if (t is TypeBuilder)
1093 // Since FindMembers will not lookup both static and instance
1094 // members, we emulate this behaviour here.
1096 if ((bf & instance_and_static) == instance_and_static){
1097 MemberInfo [] i_members = t.FindMembers (
1098 mt, bf & ~BindingFlags.Static, filter, criteria);
1100 int i_len = i_members.Length;
1102 MemberInfo one = i_members [0];
1105 // If any of these are present, we are done!
1107 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1111 MemberInfo [] s_members = t.FindMembers (
1112 mt, bf & ~BindingFlags.Instance, filter, criteria);
1114 int s_len = s_members.Length;
1115 if (i_len > 0 || s_len > 0){
1116 MemberInfo [] both = new MemberInfo [i_len + s_len];
1118 i_members.CopyTo (both, 0);
1119 s_members.CopyTo (both, i_len);
1129 return t.FindMembers (mt, bf, filter, criteria);
1132 public static bool IsBuiltinType (Type t)
1134 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1135 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1136 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1137 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1143 public static bool IsDelegateType (Type t)
1145 if (t.IsSubclassOf (TypeManager.delegate_type))
1151 public static bool IsEnumType (Type t)
1153 if (t.IsSubclassOf (TypeManager.enum_type))
1159 public static bool IsValueType (Type t)
1161 if (t.IsSubclassOf (TypeManager.value_type))
1167 public static bool IsInterfaceType (Type t)
1169 Interface iface = builder_to_member_finder [t] as Interface;
1178 // Checks whether `type' is a subclass or nested child of `parent'.
1180 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1183 if ((type == parent) || type.IsSubclassOf (parent))
1186 // Handle nested types.
1187 type = type.DeclaringType;
1188 } while (type != null);
1194 /// Returns the User Defined Types
1196 public static ArrayList UserTypes {
1202 public static Hashtable TypeContainers {
1204 return typecontainers;
1208 static Hashtable builder_to_constant;
1210 public static void RegisterConstant (FieldBuilder fb, Const c)
1212 if (builder_to_constant == null)
1213 builder_to_constant = new PtrHashtable ();
1215 if (builder_to_constant.Contains (fb))
1218 builder_to_constant.Add (fb, c);
1221 public static Const LookupConstant (FieldBuilder fb)
1223 if (builder_to_constant == null)
1226 return (Const) builder_to_constant [fb];
1230 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1234 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1235 /// for anything which is dynamic, and we need this in a number of places,
1236 /// we register this information here, and use it afterwards.
1238 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1243 method_arguments.Add (mb, args);
1244 method_internal_params.Add (mb, ip);
1249 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1251 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1254 if (method_internal_params.Contains (mb))
1255 return (InternalParameters) method_internal_params [mb];
1257 throw new Exception ("Argument for Method not registered" + mb);
1261 /// Returns the argument types for a method based on its methodbase
1263 /// For dynamic methods, we use the compiler provided types, for
1264 /// methods from existing assemblies we load them from GetParameters,
1265 /// and insert them into the cache
1267 static public Type [] GetArgumentTypes (MethodBase mb)
1269 if (method_arguments.Contains (mb))
1270 return (Type []) method_arguments [mb];
1272 ParameterInfo [] pi = mb.GetParameters ();
1274 Type [] types = new Type [c];
1276 for (int i = 0; i < c; i++)
1277 types [i] = pi [i].ParameterType;
1279 method_arguments.Add (mb, types);
1285 /// Returns the argument types for an indexer based on its PropertyInfo
1287 /// For dynamic indexers, we use the compiler provided types, for
1288 /// indexers from existing assemblies we load them from GetParameters,
1289 /// and insert them into the cache
1291 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1293 if (indexer_arguments.Contains (indexer))
1294 return (Type []) indexer_arguments [indexer];
1295 else if (indexer is PropertyBuilder)
1296 // If we're a PropertyBuilder and not in the
1297 // `indexer_arguments' hash, then we're a property and
1301 ParameterInfo [] pi = indexer.GetIndexParameters ();
1302 // Property, not an indexer.
1306 Type [] types = new Type [c];
1308 for (int i = 0; i < c; i++)
1309 types [i] = pi [i].ParameterType;
1311 indexer_arguments.Add (indexer, types);
1317 // This is a workaround the fact that GetValue is not
1318 // supported for dynamic types
1320 static Hashtable fields = new Hashtable ();
1321 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1323 if (fields.Contains (fb))
1326 fields.Add (fb, value);
1331 static public object GetValue (FieldBuilder fb)
1336 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1337 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1339 if (fieldbuilders_to_fields.Contains (fb))
1342 fieldbuilders_to_fields.Add (fb, f);
1346 static public FieldBase GetField (FieldInfo fb)
1348 return (FieldBase) fieldbuilders_to_fields [fb];
1351 static Hashtable events;
1353 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1356 events = new Hashtable ();
1358 if (events.Contains (eb))
1361 events.Add (eb, new Pair (add, remove));
1366 static public MethodInfo GetAddMethod (EventInfo ei)
1368 if (ei is MyEventBuilder) {
1369 Pair pair = (Pair) events [ei];
1371 return (MethodInfo) pair.First;
1373 return ei.GetAddMethod ();
1376 static public MethodInfo GetRemoveMethod (EventInfo ei)
1378 if (ei is MyEventBuilder) {
1379 Pair pair = (Pair) events [ei];
1381 return (MethodInfo) pair.Second;
1383 return ei.GetAddMethod ();
1386 static Hashtable priv_fields_events;
1388 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1390 if (priv_fields_events == null)
1391 priv_fields_events = new Hashtable ();
1393 if (priv_fields_events.Contains (einfo))
1396 priv_fields_events.Add (einfo, builder);
1401 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1403 return (MemberInfo) priv_fields_events [ei];
1406 static Hashtable properties;
1408 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1410 if (properties == null)
1411 properties = new Hashtable ();
1413 if (properties.Contains (pb))
1416 properties.Add (pb, new Pair (get, set));
1421 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1423 if (!RegisterProperty (pb, get,set))
1426 indexer_arguments.Add (pb, args);
1432 // FIXME: we need to return the accessors depending on whether
1433 // they are visible or not.
1435 static public MethodInfo [] GetAccessors (PropertyInfo pi)
1439 if (pi is PropertyBuilder){
1440 Pair pair = (Pair) properties [pi];
1442 ret = new MethodInfo [2];
1443 ret [0] = (MethodInfo) pair.First;
1444 ret [1] = (MethodInfo) pair.Second;
1448 MethodInfo [] mi = new MethodInfo [2];
1451 // Why this and not pi.GetAccessors?
1452 // Because sometimes index 0 is the getter
1453 // sometimes it is 1
1455 mi [0] = pi.GetGetMethod (true);
1456 mi [1] = pi.GetSetMethod (true);
1462 static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1464 if (pi is PropertyBuilder){
1465 Pair de = (Pair) properties [pi];
1467 return (MethodInfo) de.Second;
1469 return pi.GetSetMethod ();
1472 static public MethodInfo GetPropertySetter (PropertyInfo pi)
1474 if (pi is PropertyBuilder){
1475 Pair de = (Pair) properties [pi];
1477 return (MethodInfo) de.First;
1479 return pi.GetGetMethod ();
1483 /// Given an array of interface types, expand and eliminate repeated ocurrences
1484 /// of an interface.
1488 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1491 public static Type [] ExpandInterfaces (Type [] base_interfaces)
1493 ArrayList new_ifaces = new ArrayList ();
1495 foreach (Type iface in base_interfaces){
1496 if (!new_ifaces.Contains (iface))
1497 new_ifaces.Add (iface);
1499 Type [] implementing = TypeManager.GetInterfaces (iface);
1501 foreach (Type imp in implementing){
1502 if (!new_ifaces.Contains (imp))
1503 new_ifaces.Add (imp);
1506 Type [] ret = new Type [new_ifaces.Count];
1507 new_ifaces.CopyTo (ret, 0);
1512 /// This function returns the interfaces in the type `t'. Works with
1513 /// both types and TypeBuilders.
1515 public static Type [] GetInterfaces (Type t)
1518 // The reason for catching the Array case is that Reflection.Emit
1519 // will not return a TypeBuilder for Array types of TypeBuilder types,
1520 // but will still throw an exception if we try to call GetInterfaces
1523 // Since the array interfaces are always constant, we return those for
1528 t = TypeManager.array_type;
1530 if (t is TypeBuilder){
1531 Type [] parent_ifaces;
1533 if (t.BaseType == null)
1534 parent_ifaces = NoTypes;
1536 parent_ifaces = GetInterfaces (t.BaseType);
1537 Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1538 if (type_ifaces == null)
1539 type_ifaces = NoTypes;
1541 int parent_count = parent_ifaces.Length;
1542 Type [] result = new Type [parent_count + type_ifaces.Length];
1543 parent_ifaces.CopyTo (result, 0);
1544 type_ifaces.CopyTo (result, parent_count);
1548 return t.GetInterfaces ();
1552 /// The following is used to check if a given type implements an interface.
1553 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1555 public static bool ImplementsInterface (Type t, Type iface)
1560 // FIXME OPTIMIZATION:
1561 // as soon as we hit a non-TypeBuiler in the interface
1562 // chain, we could return, as the `Type.GetInterfaces'
1563 // will return all the interfaces implement by the type
1567 interfaces = GetInterfaces (t);
1569 if (interfaces != null){
1570 foreach (Type i in interfaces){
1577 } while (t != null);
1582 // This is a custom version of Convert.ChangeType() which works
1583 // with the TypeBuilder defined types when compiling corlib.
1584 public static object ChangeType (object value, Type conversionType)
1586 if (!(value is IConvertible))
1587 throw new ArgumentException ();
1589 IConvertible convertValue = (IConvertible) value;
1590 CultureInfo ci = CultureInfo.CurrentCulture;
1591 NumberFormatInfo provider = ci.NumberFormat;
1594 // We must use Type.Equals() here since `conversionType' is
1595 // the TypeBuilder created version of a system type and not
1596 // the system type itself. You cannot use Type.GetTypeCode()
1597 // on such a type - it'd always return TypeCode.Object.
1599 if (conversionType.Equals (typeof (Boolean)))
1600 return (object)(convertValue.ToBoolean (provider));
1601 else if (conversionType.Equals (typeof (Byte)))
1602 return (object)(convertValue.ToByte (provider));
1603 else if (conversionType.Equals (typeof (Char)))
1604 return (object)(convertValue.ToChar (provider));
1605 else if (conversionType.Equals (typeof (DateTime)))
1606 return (object)(convertValue.ToDateTime (provider));
1607 else if (conversionType.Equals (typeof (Decimal)))
1608 return (object)(convertValue.ToDecimal (provider));
1609 else if (conversionType.Equals (typeof (Double)))
1610 return (object)(convertValue.ToDouble (provider));
1611 else if (conversionType.Equals (typeof (Int16)))
1612 return (object)(convertValue.ToInt16 (provider));
1613 else if (conversionType.Equals (typeof (Int32)))
1614 return (object)(convertValue.ToInt32 (provider));
1615 else if (conversionType.Equals (typeof (Int64)))
1616 return (object)(convertValue.ToInt64 (provider));
1617 else if (conversionType.Equals (typeof (SByte)))
1618 return (object)(convertValue.ToSByte (provider));
1619 else if (conversionType.Equals (typeof (Single)))
1620 return (object)(convertValue.ToSingle (provider));
1621 else if (conversionType.Equals (typeof (String)))
1622 return (object)(convertValue.ToString (provider));
1623 else if (conversionType.Equals (typeof (UInt16)))
1624 return (object)(convertValue.ToUInt16 (provider));
1625 else if (conversionType.Equals (typeof (UInt32)))
1626 return (object)(convertValue.ToUInt32 (provider));
1627 else if (conversionType.Equals (typeof (UInt64)))
1628 return (object)(convertValue.ToUInt64 (provider));
1629 else if (conversionType.Equals (typeof (Object)))
1630 return (object)(value);
1632 throw new InvalidCastException ();
1636 // This is needed, because enumerations from assemblies
1637 // do not report their underlyingtype, but they report
1640 public static Type EnumToUnderlying (Type t)
1642 if (t == TypeManager.enum_type)
1645 t = t.UnderlyingSystemType;
1646 if (!TypeManager.IsEnumType (t))
1649 if (t is TypeBuilder) {
1650 // slow path needed to compile corlib
1651 if (t == TypeManager.bool_type ||
1652 t == TypeManager.byte_type ||
1653 t == TypeManager.sbyte_type ||
1654 t == TypeManager.char_type ||
1655 t == TypeManager.short_type ||
1656 t == TypeManager.ushort_type ||
1657 t == TypeManager.int32_type ||
1658 t == TypeManager.uint32_type ||
1659 t == TypeManager.int64_type ||
1660 t == TypeManager.uint64_type)
1662 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1664 TypeCode tc = Type.GetTypeCode (t);
1667 case TypeCode.Boolean:
1668 return TypeManager.bool_type;
1670 return TypeManager.byte_type;
1671 case TypeCode.SByte:
1672 return TypeManager.sbyte_type;
1674 return TypeManager.char_type;
1675 case TypeCode.Int16:
1676 return TypeManager.short_type;
1677 case TypeCode.UInt16:
1678 return TypeManager.ushort_type;
1679 case TypeCode.Int32:
1680 return TypeManager.int32_type;
1681 case TypeCode.UInt32:
1682 return TypeManager.uint32_type;
1683 case TypeCode.Int64:
1684 return TypeManager.int64_type;
1685 case TypeCode.UInt64:
1686 return TypeManager.uint64_type;
1688 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1692 // When compiling corlib and called with one of the core types, return
1693 // the corresponding typebuilder for that type.
1695 public static Type TypeToCoreType (Type t)
1697 if (RootContext.StdLib || (t is TypeBuilder))
1700 TypeCode tc = Type.GetTypeCode (t);
1703 case TypeCode.Boolean:
1704 return TypeManager.bool_type;
1706 return TypeManager.byte_type;
1707 case TypeCode.SByte:
1708 return TypeManager.sbyte_type;
1710 return TypeManager.char_type;
1711 case TypeCode.Int16:
1712 return TypeManager.short_type;
1713 case TypeCode.UInt16:
1714 return TypeManager.ushort_type;
1715 case TypeCode.Int32:
1716 return TypeManager.int32_type;
1717 case TypeCode.UInt32:
1718 return TypeManager.uint32_type;
1719 case TypeCode.Int64:
1720 return TypeManager.int64_type;
1721 case TypeCode.UInt64:
1722 return TypeManager.uint64_type;
1723 case TypeCode.String:
1724 return TypeManager.string_type;
1726 if (t == typeof (void))
1727 return TypeManager.void_type;
1728 if (t == typeof (object))
1729 return TypeManager.object_type;
1730 if (t == typeof (System.Type))
1731 return TypeManager.type_type;
1737 /// Utility function that can be used to probe whether a type
1738 /// is managed or not.
1740 public static bool VerifyUnManaged (Type t, Location loc)
1742 if (t.IsValueType || t.IsPointer){
1744 // FIXME: this is more complex, we actually need to
1745 // make sure that the type does not contain any
1751 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1752 // We need this explicit check here to make it work when
1753 // compiling corlib.
1758 "Cannot take the address or size of a variable of a managed type ('" +
1759 CSharpName (t) + "')");
1764 /// Returns the name of the indexer in a given type.
1767 /// The default is not always `Item'. The user can change this behaviour by
1768 /// using the DefaultMemberAttribute in the class.
1770 /// For example, the String class indexer is named `Chars' not `Item'
1772 public static string IndexerPropertyName (Type t)
1774 if (t is TypeBuilder) {
1775 if (t.IsInterface) {
1776 Interface i = LookupInterface (t);
1778 if ((i == null) || (i.IndexerName == null))
1781 return i.IndexerName;
1783 TypeContainer tc = LookupTypeContainer (t);
1785 if ((tc == null) || (tc.IndexerName == null))
1788 return tc.IndexerName;
1792 System.Attribute attr = System.Attribute.GetCustomAttribute (
1793 t, TypeManager.default_member_type);
1795 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1796 return dma.MemberName;
1802 public static void MakePinned (LocalBuilder builder)
1805 // FIXME: Flag the "LocalBuilder" type as being
1806 // pinned. Figure out API.
1812 // Returns whether the array of memberinfos contains the given method
1814 static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1816 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1818 foreach (MethodBase method in array){
1819 if (method.Name != new_method.Name)
1822 Type [] old_args = TypeManager.GetArgumentTypes (method);
1823 int old_count = old_args.Length;
1826 if (new_args.Length != old_count)
1829 for (i = 0; i < old_count; i++){
1830 if (old_args [i] != new_args [i])
1842 // We copy methods from `new_members' into `target_list' if the signature
1843 // for the method from in the new list does not exist in the target_list
1845 // The name is assumed to be the same.
1847 public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
1849 if (target_list == null){
1850 target_list = new ArrayList ();
1852 foreach (MemberInfo mi in new_members){
1853 if (mi is MethodBase)
1854 target_list.Add (mi);
1859 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1860 target_list.CopyTo (target_array, 0);
1862 foreach (MemberInfo mi in new_members){
1863 MethodBase new_method = (MethodBase) mi;
1865 if (!ArrayContainsMethod (target_array, new_method))
1866 target_list.Add (new_method);
1872 public enum MethodFlags {
1874 IsObsoleteError = 2,
1879 // Returns the TypeManager.MethodFlags for this method.
1880 // This emits an error 619 / warning 618 if the method is obsolete.
1881 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1883 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1885 MethodFlags flags = 0;
1887 if (mb.DeclaringType is TypeBuilder){
1888 MethodData method = (MethodData) builder_to_method [mb];
1889 if (method == null) {
1890 // FIXME: implement Obsolete attribute on Property,
1891 // Indexer and Event.
1895 return method.GetMethodFlags (loc);
1898 object [] attrs = mb.GetCustomAttributes (true);
1899 foreach (object ta in attrs){
1900 if (!(ta is System.Attribute)){
1901 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1904 System.Attribute a = (System.Attribute) ta;
1905 if (a.TypeId == TypeManager.obsolete_attribute_type){
1906 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1908 string method_desc = TypeManager.CSharpSignature (mb);
1911 Report.Error (619, loc, "Method `" + method_desc +
1912 "' is obsolete: `" + oa.Message + "'");
1913 return MethodFlags.IsObsoleteError;
1915 Report.Warning (618, loc, "Method `" + method_desc +
1916 "' is obsolete: `" + oa.Message + "'");
1918 flags |= MethodFlags.IsObsolete;
1924 // Skip over conditional code.
1926 if (a.TypeId == TypeManager.conditional_attribute_type){
1927 ConditionalAttribute ca = (ConditionalAttribute) a;
1929 if (RootContext.AllDefines [ca.ConditionString] == null)
1930 flags |= MethodFlags.ShouldIgnore;
1937 #region MemberLookup implementation
1940 // Name of the member
1942 static string closure_name;
1945 // Whether we allow private members in the result (since FindMembers
1946 // uses NonPublic for both protected and private), we need to distinguish.
1948 static bool closure_private_ok;
1951 // Who is invoking us and which type is being queried currently.
1953 static Type closure_invocation_type;
1954 static Type closure_queried_type;
1955 static Type closure_start_type;
1958 // The assembly that defines the type is that is calling us
1960 static Assembly closure_invocation_assembly;
1963 // This filter filters by name + whether it is ok to include private
1964 // members in the search
1966 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1969 // Hack: we know that the filter criteria will always be in the `closure'
1973 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
1976 if (closure_start_type == closure_invocation_type)
1980 // Ugly: we need to find out the type of `m', and depending
1981 // on this, tell whether we accept or not
1983 if (m is MethodBase){
1984 MethodBase mb = (MethodBase) m;
1985 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1987 if (ma == MethodAttributes.Private)
1988 return closure_private_ok;
1991 // FamAndAssem requires that we not only derivate, but we are on the
1994 if (ma == MethodAttributes.FamANDAssem){
1995 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1999 // Assembly and FamORAssem succeed if we're in the same assembly.
2000 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2001 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2005 // We already know that we aren't in the same assembly.
2006 if (ma == MethodAttributes.Assembly)
2009 // Family and FamANDAssem require that we derive.
2010 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2011 if (closure_invocation_type == null)
2014 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2017 // Although a derived class can access protected members of its base class
2018 // it cannot do so through an instance of the base class (CS1540).
2019 if ((closure_invocation_type != closure_start_type) &&
2020 closure_invocation_type.IsSubclassOf (closure_start_type))
2030 if (m is FieldInfo){
2031 FieldInfo fi = (FieldInfo) m;
2032 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2034 if (fa == FieldAttributes.Private)
2035 return closure_private_ok;
2038 // FamAndAssem requires that we not only derivate, but we are on the
2041 if (fa == FieldAttributes.FamANDAssem){
2042 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2046 // Assembly and FamORAssem succeed if we're in the same assembly.
2047 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2048 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2052 // We already know that we aren't in the same assembly.
2053 if (fa == FieldAttributes.Assembly)
2056 // Family and FamANDAssem require that we derive.
2057 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2058 if (closure_invocation_type == null)
2061 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2064 // Although a derived class can access protected members of its base class
2065 // it cannot do so through an instance of the base class (CS1540).
2066 if ((closure_invocation_type != closure_start_type) &&
2067 closure_invocation_type.IsSubclassOf (closure_start_type))
2078 // EventInfos and PropertyInfos, return true
2083 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2086 // Looks up a member called `name' in the `queried_type'. This lookup
2087 // is done by code that is contained in the definition for `invocation_type'.
2089 // The binding flags are `bf' and the kind of members being looked up are `mt'
2091 // Returns an array of a single element for everything but Methods/Constructors
2092 // that might return multiple matches.
2094 public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type,
2095 MemberTypes mt, BindingFlags original_bf, string name)
2097 Timer.StartTimer (TimerType.MemberLookup);
2099 MemberInfo[] retval = RealMemberLookup (invocation_type, queried_type,
2100 mt, original_bf, name);
2102 Timer.StopTimer (TimerType.MemberLookup);
2107 static MemberInfo [] RealMemberLookup (Type invocation_type, Type queried_type,
2108 MemberTypes mt, BindingFlags original_bf, string name)
2110 BindingFlags bf = original_bf;
2112 ArrayList method_list = null;
2113 Type current_type = queried_type;
2114 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2116 bool always_ok_flag = false;
2118 closure_name = name;
2119 closure_invocation_type = invocation_type;
2120 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2121 closure_start_type = queried_type;
2124 // If we are a nested class, we always have access to our container
2127 if (invocation_type != null){
2128 string invocation_name = invocation_type.FullName;
2129 if (invocation_name.IndexOf ('+') != -1){
2130 string container = queried_type.FullName + "+";
2131 int container_length = container.Length;
2133 if (invocation_name.Length > container_length){
2134 string shared = invocation_name.Substring (0, container_length);
2136 if (shared == container)
2137 always_ok_flag = true;
2146 // `NonPublic' is lame, because it includes both protected and
2147 // private methods, so we need to control this behavior by
2148 // explicitly tracking if a private method is ok or not.
2150 // The possible cases are:
2151 // public, private and protected (internal does not come into the
2154 if (invocation_type != null){
2155 if (invocation_type == current_type){
2158 private_ok = always_ok_flag;
2160 if (private_ok || invocation_type.IsSubclassOf (current_type))
2161 bf = original_bf | BindingFlags.NonPublic;
2164 bf = original_bf & ~BindingFlags.NonPublic;
2167 closure_private_ok = private_ok;
2168 closure_queried_type = current_type;
2170 Timer.StopTimer (TimerType.MemberLookup);
2172 list = MemberLookup_FindMembers (current_type, mt, bf, name, ref searching);
2174 Timer.StartTimer (TimerType.MemberLookup);
2176 if (current_type == TypeManager.object_type)
2179 current_type = current_type.BaseType;
2182 // This happens with interfaces, they have a null
2183 // basetype. Look members up in the Object class.
2185 if (current_type == null)
2186 current_type = TypeManager.object_type;
2189 if (list.Count == 0)
2193 // Events and types are returned by both `static' and `instance'
2194 // searches, which means that our above FindMembers will
2195 // return two copies of the same.
2197 if (list.Count == 1 && !(list [0] is MethodBase)){
2198 return (MemberInfo []) list;
2202 // Multiple properties: we query those just to find out the indexer
2205 if (list [0] is PropertyInfo)
2206 return (MemberInfo []) list;
2209 // We found methods, turn the search into "method scan"
2213 method_list = CopyNewMethods (method_list, list);
2214 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2215 } while (searching);
2217 if (method_list != null && method_list.Count > 0)
2218 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2221 // Interfaces do not list members they inherit, so we have to
2224 if (!queried_type.IsInterface)
2227 if (queried_type.IsArray)
2228 queried_type = TypeManager.array_type;
2230 Type [] ifaces = GetInterfaces (queried_type);
2234 foreach (Type itype in ifaces){
2237 x = MemberLookup (null, itype, mt, bf, name);
2248 public class MemberCache {
2249 public readonly IMemberContainer Container;
2250 protected Hashtable MemberHash;
2252 public MemberCache (IMemberContainer container)
2254 this.Container = container;
2255 this.MemberHash = new Hashtable ();
2257 Timer.IncrementCounter (CounterType.MemberCache);
2258 Timer.StartTimer (TimerType.CacheInit);
2261 IMemberContainer current = Container;
2263 AddMembers (current);
2264 current = current.Parent;
2265 } while (current != null);
2267 AddMembers (Container);
2268 if (Container.IsInterface)
2269 AddMembers (TypeHandle.ObjectType);
2272 Timer.StopTimer (TimerType.CacheInit);
2275 void AddMembers (IMemberContainer container)
2277 AddMembers (MemberTypes.Constructor, container);
2278 AddMembers (MemberTypes.Event, container);
2279 AddMembers (MemberTypes.Field, container);
2280 AddMembers (MemberTypes.Method, container);
2281 AddMembers (MemberTypes.Property, container);
2282 AddMembers (MemberTypes.NestedType, container);
2285 void AddMembers (MemberTypes mt, IMemberContainer container)
2287 AddMembers (mt, BindingFlags.Static | BindingFlags.Public, container);
2288 AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, container);
2289 AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, container);
2290 AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, container);
2293 void AddMembers (MemberTypes mt, BindingFlags bf, IMemberContainer container)
2295 MemberList members = container.GetMembers (mt, bf);
2296 BindingFlags new_bf = (container == Container) ? bf | BindingFlags.DeclaredOnly : bf;
2298 foreach (MemberInfo member in members) {
2299 string name = member.Name;
2301 ArrayList list = (ArrayList) MemberHash [name];
2303 list = new ArrayList ();
2304 MemberHash.Add (name, list);
2308 new_bf = (member.DeclaringType == container.Type) ?
2309 bf | BindingFlags.DeclaredOnly : bf;
2312 list.Add (new CacheEntry (container, member, mt, new_bf));
2316 protected static EntryType GetEntryType (MemberTypes mt, BindingFlags bf)
2318 EntryType type = EntryType.None;
2320 if ((mt & MemberTypes.Constructor) != 0)
2321 type |= EntryType.Constructor;
2322 if ((mt & MemberTypes.Event) != 0)
2323 type |= EntryType.Event;
2324 if ((mt & MemberTypes.Field) != 0)
2325 type |= EntryType.Field;
2326 if ((mt & MemberTypes.Method) != 0)
2327 type |= EntryType.Method;
2328 if ((mt & MemberTypes.Property) != 0)
2329 type |= EntryType.Property;
2330 if ((mt & MemberTypes.NestedType) != 0)
2331 type |= EntryType.NestedType;
2333 if ((bf & BindingFlags.Instance) != 0)
2334 type |= EntryType.Instance;
2335 if ((bf & BindingFlags.Static) != 0)
2336 type |= EntryType.Static;
2337 if ((bf & BindingFlags.Public) != 0)
2338 type |= EntryType.Public;
2339 if ((bf & BindingFlags.NonPublic) != 0)
2340 type |= EntryType.NonPublic;
2341 if ((bf & BindingFlags.DeclaredOnly) != 0)
2342 type |= EntryType.Declared;
2347 public static bool IsSingleMemberType (MemberTypes mt)
2350 case MemberTypes.Constructor:
2351 case MemberTypes.Event:
2352 case MemberTypes.Field:
2353 case MemberTypes.Method:
2354 case MemberTypes.Property:
2355 case MemberTypes.NestedType:
2364 protected enum EntryType {
2369 MaskStatic = Instance|Static,
2373 MaskProtection = Public|NonPublic,
2377 Constructor = 0x020,
2384 MaskType = Constructor|Event|Field|Method|Property|NestedType
2387 protected struct CacheEntry {
2389 // FIXME: This field is a temporary hack until the Mono runtime is fixed
2390 // and distinguishes between ReflectedType and DeclaringType.
2391 public readonly IMemberContainer Container;
2393 public readonly EntryType EntryType;
2394 public readonly MemberInfo Member;
2396 public CacheEntry (IMemberContainer container, MemberInfo member, MemberTypes mt,
2400 this.Container = container;
2402 this.Member = member;
2403 this.EntryType = GetEntryType (mt, bf);
2407 protected void SearchMembers (ArrayList list, MemberTypes mt, BindingFlags bf, IList applicable,
2408 MemberFilter filter, object criteria)
2410 bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;
2411 EntryType type = GetEntryType (mt, bf);
2413 IMemberContainer current = Container;
2415 foreach (CacheEntry entry in applicable) {
2417 if (entry.Container != current) {
2418 current = entry.Container;
2420 // We've reached a base class while doing a DeclaredOnly search.
2425 // Events and types are returned by both `static' and `instance'
2426 // searches, which means that our above FindMembers will
2427 // return two copies of the same.
2429 if (list.Count == 1 && !(list [0] is MethodBase))
2433 // Multiple properties: we query those just to find out the indexer
2436 if ((list.Count > 0) && (list [0] is PropertyInfo))
2440 if (declared_only && (entry.Member.DeclaringType != Container.Type))
2444 if ((entry.EntryType & type & EntryType.MaskType) == 0)
2447 if ((entry.EntryType & type & EntryType.MaskStatic) == 0)
2450 if (filter (entry.Member, criteria)) {
2451 list.Add (entry.Member);
2454 // Events and types are returned by both `static' and `instance'
2455 // searches, which means that our above FindMembers will
2456 // return two copies of the same.
2458 if (list.Count == 1 && !(list [0] is MethodBase))
2462 // Multiple properties: we query those just to find out the indexer
2465 if ((list.Count > 0) && (list [0] is PropertyInfo))
2472 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2473 MemberFilter filter, object criteria)
2475 IList applicable = (IList) MemberHash [name];
2476 if (applicable == null)
2477 return MemberList.Empty;
2479 ArrayList list = new ArrayList ();
2481 if ((bf & BindingFlags.Static) != 0) {
2482 SearchMembers (list, mt, bf & ~BindingFlags.Instance, applicable,
2485 if (list.Count == 1){
2486 MemberInfo one = (MemberInfo) list [0];
2489 // If any of these are present, we are done!
2491 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
2492 return new MemberList (list);
2496 if ((bf & BindingFlags.Instance) != 0)
2497 SearchMembers (list, mt, bf & ~BindingFlags.Static, applicable,
2500 return new MemberList (list);
2504 public sealed class TypeHandle : IMemberContainer {
2505 public readonly TypeHandle BaseType;
2506 public readonly MemberCache MemberCache;
2509 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
2510 /// a TypeHandle yet, a new instance of it is created. This static method
2511 /// ensures that we'll only have one TypeHandle instance per type.
2513 public static TypeHandle GetTypeHandle (Type t)
2515 TypeHandle handle = (TypeHandle) type_hash [t];
2519 handle = new TypeHandle (t);
2520 type_hash.Add (t, handle);
2525 /// Returns the TypeHandle for TypeManager.object_type.
2527 public static IMemberContainer ObjectType {
2529 if (object_type != null)
2539 /// Returns the TypeHandle for TypeManager.array_type.
2541 public static IMemberContainer ArrayType {
2543 if (array_type != null)
2552 // This must be called after the core types have been created.
2553 private static void Initialize ()
2555 if (object_type == null)
2556 object_type = GetTypeHandle (TypeManager.object_type);
2558 if (array_type == null)
2559 array_type = GetTypeHandle (TypeManager.array_type);
2562 private static PtrHashtable type_hash = new PtrHashtable ();
2564 private static TypeHandle object_type = null;
2565 private static TypeHandle array_type = null;
2568 private bool is_interface;
2570 private TypeHandle (Type type)
2573 if (type.BaseType != null)
2574 BaseType = GetTypeHandle (type.BaseType);
2575 else if (type != TypeManager.object_type) {
2577 // This happens with interfaces, they have a null
2578 // basetype. Look members up in the Object class.
2580 BaseType = object_type;
2581 is_interface = true;
2583 this.MemberCache = new MemberCache (this);
2586 // IMemberContainer methods
2588 public string Name {
2590 return Type.FullName;
2600 public IMemberContainer Parent {
2606 public bool IsInterface {
2608 return is_interface;
2612 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2615 return new MemberList (Type.FindMembers (
2616 mt, bf | BindingFlags.DeclaredOnly, null, null));
2618 return new MemberList (Type.FindMembers (mt, bf, null, null));
2622 // IMemberFinder methods
2624 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
2625 MemberFilter filter, object criteria)
2627 throw new NotSupportedException ();
2630 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2631 MemberFilter filter, object criteria)
2635 Timer.StartTimer (TimerType.CachedLookup);
2636 list = MemberCache.FindMembers (mt, bf, name, filter, criteria);
2637 Timer.StopTimer (TimerType.CachedLookup);