2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
15 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
16 // the behavior of the compilation. This can be removed if we rework
17 // the code to get a list of namespaces available.
19 #define SIMPLE_SPEEDUP
23 using System.Globalization;
24 using System.Collections;
25 using System.Reflection;
26 using System.Reflection.Emit;
28 using System.Text.RegularExpressions;
29 using System.Runtime.CompilerServices;
30 using System.Diagnostics;
32 namespace Mono.CSharp {
34 public class TypeManager {
36 // A list of core types that the compiler requires or uses
38 static public Type object_type;
39 static public Type value_type;
40 static public Type string_type;
41 static public Type int32_type;
42 static public Type uint32_type;
43 static public Type int64_type;
44 static public Type uint64_type;
45 static public Type float_type;
46 static public Type double_type;
47 static public Type char_type;
48 static public Type char_ptr_type;
49 static public Type short_type;
50 static public Type decimal_type;
51 static public Type bool_type;
52 static public Type sbyte_type;
53 static public Type byte_type;
54 static public Type ushort_type;
55 static public Type enum_type;
56 static public Type delegate_type;
57 static public Type multicast_delegate_type;
58 static public Type void_type;
59 static public Type null_type;
60 static public Type enumeration_type;
61 static public Type array_type;
62 static public Type runtime_handle_type;
63 static public Type icloneable_type;
64 static public Type type_type;
65 static public Type ienumerator_type;
66 static public Type ienumerable_type;
67 static public Type idisposable_type;
68 static public Type iconvertible_type;
69 static public Type default_member_type;
70 static public Type iasyncresult_type;
71 static public Type asynccallback_type;
72 static public Type intptr_type;
73 static public Type monitor_type;
74 static public Type runtime_field_handle_type;
75 static public Type runtime_argument_handle_type;
76 static public Type attribute_type;
77 static public Type attribute_usage_type;
78 static public Type decimal_constant_attribute_type;
79 static public Type dllimport_type;
80 static public Type unverifiable_code_type;
81 static public Type methodimpl_attr_type;
82 static public Type marshal_as_attr_type;
83 static public Type param_array_type;
84 static public Type void_ptr_type;
85 static public Type indexer_name_type;
86 static public Type exception_type;
87 static public Type invalid_operation_exception_type;
88 static public Type not_supported_exception_type;
89 static public Type obsolete_attribute_type;
90 static public Type conditional_attribute_type;
91 static public Type in_attribute_type;
92 static public Type out_attribute_type;
93 static public Type default_parameter_value_attribute_type;
95 static public Type anonymous_method_type;
96 static public Type cls_compliant_attribute_type;
97 static public Type typed_reference_type;
98 static public Type arg_iterator_type;
99 static public Type mbr_type;
100 static public Type struct_layout_attribute_type;
101 static public Type field_offset_attribute_type;
102 static public Type security_attr_type;
103 static public Type required_attr_type;
104 static public Type guid_attr_type;
105 static public Type assembly_culture_attribute_type;
106 static public Type coclass_attr_type;
107 static public Type comimport_attr_type;
113 static internal Type runtime_compatibility_attr_type;
114 static internal Type compiler_generated_attr_type;
115 static internal Type fixed_buffer_attr_type;
116 static internal Type default_charset_type;
120 // Expressions representing the internal types. Used during declaration
123 static public TypeExpr system_object_expr, system_string_expr;
124 static public TypeExpr system_boolean_expr, system_decimal_expr;
125 static public TypeExpr system_single_expr, system_double_expr;
126 static public TypeExpr system_sbyte_expr, system_byte_expr;
127 static public TypeExpr system_int16_expr, system_uint16_expr;
128 static public TypeExpr system_int32_expr, system_uint32_expr;
129 static public TypeExpr system_int64_expr, system_uint64_expr;
130 static public TypeExpr system_char_expr, system_void_expr;
131 static public TypeExpr system_asynccallback_expr;
132 static public TypeExpr system_iasyncresult_expr;
133 static public TypeExpr system_valuetype_expr;
134 static public TypeExpr system_intptr_expr;
137 // This is only used when compiling corlib
139 static public Type system_int32_type;
140 static public Type system_array_type;
141 static public Type system_type_type;
142 static public Type system_assemblybuilder_type;
143 static public MethodInfo system_int_array_get_length;
144 static public MethodInfo system_int_array_get_rank;
145 static public MethodInfo system_object_array_clone;
146 static public MethodInfo system_int_array_get_length_int;
147 static public MethodInfo system_int_array_get_lower_bound_int;
148 static public MethodInfo system_int_array_get_upper_bound_int;
149 static public MethodInfo system_void_array_copyto_array_int;
153 // Internal, not really used outside
155 static Type runtime_helpers_type;
158 // These methods are called by code generated by the compiler
160 static public MethodInfo string_concat_string_string;
161 static public MethodInfo string_concat_string_string_string;
162 static public MethodInfo string_concat_string_string_string_string;
163 static public MethodInfo string_concat_string_dot_dot_dot;
164 static public MethodInfo string_concat_object_object;
165 static public MethodInfo string_concat_object_object_object;
166 static public MethodInfo string_concat_object_dot_dot_dot;
167 static public MethodInfo string_isinterneted_string;
168 static public MethodInfo system_type_get_type_from_handle;
169 static public MethodInfo bool_movenext_void;
170 static public MethodInfo ienumerable_getenumerator_void;
171 static public MethodInfo void_reset_void;
172 static public MethodInfo void_dispose_void;
173 static public MethodInfo void_monitor_enter_object;
174 static public MethodInfo void_monitor_exit_object;
175 static public MethodInfo void_initializearray_array_fieldhandle;
176 static public MethodInfo int_getlength_int;
177 static public MethodInfo delegate_combine_delegate_delegate;
178 static public MethodInfo delegate_remove_delegate_delegate;
179 static public MethodInfo int_get_offset_to_string_data;
180 static public MethodInfo int_array_get_length;
181 static public MethodInfo int_array_get_rank;
182 static public MethodInfo object_array_clone;
183 static public MethodInfo int_array_get_length_int;
184 static public MethodInfo int_array_get_lower_bound_int;
185 static public MethodInfo int_array_get_upper_bound_int;
186 static public MethodInfo void_array_copyto_array_int;
187 static public PropertyInfo ienumerator_getcurrent;
190 // The attribute constructors.
192 static public ConstructorInfo object_ctor;
193 static private ConstructorInfo cons_param_array_attribute;
194 static public ConstructorInfo void_decimal_ctor_five_args;
195 static public ConstructorInfo void_decimal_ctor_int_arg;
196 static public ConstructorInfo unverifiable_code_ctor;
197 static public ConstructorInfo default_member_ctor;
198 static public ConstructorInfo decimal_constant_attribute_ctor;
199 static internal ConstructorInfo struct_layout_attribute_ctor;
200 static public ConstructorInfo field_offset_attribute_ctor;
206 static internal CustomAttributeBuilder compiler_generated_attr;
207 static internal ConstructorInfo fixed_buffer_attr_ctor;
210 static PtrHashtable builder_to_declspace;
212 static PtrHashtable builder_to_member_cache;
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 PropertyBuilder to a Type array that contains
222 // the arguments to the indexer
224 static Hashtable indexer_arguments;
227 // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
229 static Hashtable method_params;
232 // A hash table from override methods to their base virtual method.
234 static Hashtable method_overrides;
237 // Keeps track of methods
240 static Hashtable builder_to_method;
243 // Contains all public types from referenced assemblies.
244 // This member is used only if CLS Compliance verification is required.
246 public static Hashtable AllClsTopLevelTypes;
248 static Hashtable fieldbuilders_to_fields;
249 static Hashtable propertybuilder_to_property;
250 static Hashtable fields;
251 static Hashtable events;
258 public static void CleanUp ()
260 // Lets get everything clean so that we can collect before generating code
261 builder_to_declspace = null;
262 builder_to_member_cache = null;
263 builder_to_ifaces = null;
264 indexer_arguments = null;
265 method_params = null;
266 builder_to_method = null;
269 fieldbuilders_to_fields = null;
271 priv_fields_events = null;
273 propertybuilder_to_property = null;
275 TypeHandle.CleanUp ();
279 /// A filter for Findmembers that uses the Signature object to
282 static bool SignatureFilter (MemberInfo mi, object criteria)
284 Signature sig = (Signature) criteria;
286 if (!(mi is MethodBase))
289 if (mi.Name != sig.name)
292 int count = sig.args.Length;
294 if (mi is MethodBuilder || mi is ConstructorBuilder){
295 Type [] candidate_args = GetParameterData ((MethodBase) mi).Types;
297 if (candidate_args.Length != count)
300 for (int i = 0; i < count; i++)
301 if (candidate_args [i] != sig.args [i])
306 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
308 if (pars.Length != count)
311 for (int i = 0; i < count; i++)
312 if (pars [i].ParameterType != sig.args [i])
318 // A delegate that points to the filter above.
319 static MemberFilter signature_filter;
322 // These are expressions that represent some of the internal data types, used
325 static void InitExpressionTypes ()
327 system_object_expr = new TypeLookupExpression ("System.Object");
328 system_string_expr = new TypeLookupExpression ("System.String");
329 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
330 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
331 system_single_expr = new TypeLookupExpression ("System.Single");
332 system_double_expr = new TypeLookupExpression ("System.Double");
333 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
334 system_byte_expr = new TypeLookupExpression ("System.Byte");
335 system_int16_expr = new TypeLookupExpression ("System.Int16");
336 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
337 system_int32_expr = new TypeLookupExpression ("System.Int32");
338 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
339 system_int64_expr = new TypeLookupExpression ("System.Int64");
340 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
341 system_char_expr = new TypeLookupExpression ("System.Char");
342 system_void_expr = new TypeLookupExpression ("System.Void");
343 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
344 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
345 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
346 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
349 static TypeManager ()
353 signature_filter = new MemberFilter (SignatureFilter);
354 InitExpressionTypes ();
357 static public void Reset ()
359 builder_to_declspace = new PtrHashtable ();
360 builder_to_member_cache = new PtrHashtable ();
361 builder_to_method = new PtrHashtable ();
362 method_params = new PtrHashtable ();
363 method_overrides = new PtrHashtable ();
364 indexer_arguments = new PtrHashtable ();
365 builder_to_ifaces = new PtrHashtable ();
367 fieldbuilders_to_fields = new Hashtable ();
368 propertybuilder_to_property = new Hashtable ();
369 fields = new Hashtable ();
370 type_hash = new DoubleHash ();
372 // to uncover regressions
373 cons_param_array_attribute = null;
376 public static void AddUserType (DeclSpace ds)
378 builder_to_declspace.Add (ds.TypeBuilder, ds);
382 // This entry point is used by types that we define under the covers
384 public static void RegisterBuilder (Type tb, Type [] ifaces)
387 builder_to_ifaces [tb] = ifaces;
390 public static void AddMethod (MethodBase builder, IMethodData method)
392 builder_to_method.Add (builder, method);
393 method_params.Add (builder, method.ParameterInfo);
396 public static IMethodData GetMethod (MethodBase builder)
398 return (IMethodData) builder_to_method [builder];
402 /// Returns the DeclSpace whose Type is `t' or null if there is no
403 /// DeclSpace for `t' (ie, the Type comes from a library)
405 public static DeclSpace LookupDeclSpace (Type t)
407 return builder_to_declspace [t] as DeclSpace;
411 /// Returns the TypeContainer whose Type is `t' or null if there is no
412 /// TypeContainer for `t' (ie, the Type comes from a library)
414 public static TypeContainer LookupTypeContainer (Type t)
416 return builder_to_declspace [t] as TypeContainer;
419 public static MemberCache LookupMemberCache (Type t)
421 if (t is TypeBuilder) {
422 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
423 if (container != null)
424 return container.MemberCache;
427 return TypeHandle.GetMemberCache (t);
430 public static MemberCache LookupBaseInterfacesCache (Type t)
432 Type [] ifaces = t.GetInterfaces ();
434 if (ifaces != null && ifaces.Length == 1)
435 return LookupMemberCache (ifaces [0]);
437 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
438 MemberCache cache = builder_to_member_cache [t] as MemberCache;
442 cache = new MemberCache (ifaces);
443 builder_to_member_cache.Add (t, cache);
447 public static TypeContainer LookupInterface (Type t)
449 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
450 if ((tc == null) || (tc.Kind != Kind.Interface))
456 public static Delegate LookupDelegate (Type t)
458 return builder_to_declspace [t] as Delegate;
461 public static Class LookupClass (Type t)
463 return (Class) builder_to_declspace [t];
467 // We use this hash for multiple kinds of constructed types:
469 // (T, "&") Given T, get T &
470 // (T, "*") Given T, get T *
471 // (T, "[]") Given T and a array dimension, get T []
472 // (T, X) Given a type T and a simple name X, get the type T+X
474 // Accessibility tests, if necessary, should be done by the user
476 static DoubleHash type_hash = new DoubleHash ();
479 // Gets the reference to T version of the Type (T&)
481 public static Type GetReferenceType (Type t)
483 return GetConstructedType (t, "&");
487 // Gets the pointer to T version of the Type (T*)
489 public static Type GetPointerType (Type t)
491 return GetConstructedType (t, "*");
494 public static Type GetConstructedType (Type t, string dim)
497 if (!type_hash.Lookup (t, dim, out ret)) {
498 ret = t.Module.GetType (t.ToString () + dim);
499 type_hash.Insert (t, dim, ret);
504 public static Type GetNestedType (Type t, string name)
507 if (!type_hash.Lookup (t, name, out ret)) {
508 ret = t.GetNestedType (name,
509 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
510 type_hash.Insert (t, name, ret);
516 /// Fills static table with exported types from all referenced assemblies.
517 /// This information is required for CLS Compliance tests.
519 public static void LoadAllImportedTypes ()
521 AllClsTopLevelTypes = new Hashtable (1500);
522 foreach (Assembly a in RootNamespace.Global.Assemblies) {
523 foreach (Type t in a.GetExportedTypes ()) {
524 AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
529 public static bool NamespaceClash (string name, Location loc)
531 if (! RootNamespace.Global.IsNamespace (name))
534 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
539 /// Returns the C# name of a type if possible, or the full type name otherwise
541 static public string CSharpName (Type t)
543 return Regex.Replace (t.FullName,
545 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
546 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
547 @"Boolean|String|Void|Null)" +
549 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
552 static public string CSharpName (Type[] types)
554 StringBuilder sb = new StringBuilder ();
555 foreach (Type t in types) {
556 sb.Append (CSharpName (t));
559 sb.Remove (sb.Length - 1, 1);
560 return sb.ToString ();
563 static String CSharpNameMatch (Match match)
565 string s = match.Groups [1].Captures [0].Value;
567 Replace ("int32", "int").
568 Replace ("uint32", "uint").
569 Replace ("int16", "short").
570 Replace ("uint16", "ushort").
571 Replace ("int64", "long").
572 Replace ("uint64", "ulong").
573 Replace ("single", "float").
574 Replace ("boolean", "bool")
575 + match.Groups [2].Captures [0].Value;
579 /// Returns the signature of the method with full namespace classification
581 static public string GetFullNameSignature (MemberInfo mi)
583 PropertyInfo pi = mi as PropertyInfo;
585 MethodBase pmi = pi.GetGetMethod (true);
587 pmi = pi.GetSetMethod (true);
588 if (GetParameterData (pmi).Count > 0)
591 return (mi is MethodBase)
592 ? CSharpSignature (mi as MethodBase)
593 : CSharpName (mi.DeclaringType) + '.' + mi.Name;
597 /// When we need to report accessors as well
599 static public string CSharpSignature (MethodBase mb)
601 return CSharpSignature (mb, false);
605 /// Returns the signature of the method
607 static public string CSharpSignature (MethodBase mb, bool show_accessor)
609 StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
612 ParameterData iparams = GetParameterData (mb);
613 string parameters = iparams.GetSignatureForError ();
614 string accessor = "";
617 if (mb.IsSpecialName) {
618 Operator.OpType ot = Operator.GetOperatorType (mb.Name);
619 if (ot != Operator.OpType.TOP) {
620 sig.Append ("operator ");
621 sig.Append (Operator.GetName (ot));
622 sig.Append (parameters);
623 return sig.ToString ();
626 if (mb.Name.StartsWith ("get_") || mb.Name.StartsWith ("set_")) {
627 accessor = mb.Name.Substring (0, 3);
632 if (mb.IsSpecialName && !mb.IsConstructor) {
633 if (iparams.Count > (mb.Name.StartsWith ("get_") ? 0 : 1)) {
634 sig.Append ("this[");
636 sig.Append (parameters.Substring (1, parameters.Length - 2));
639 int before_ret_val = parameters.LastIndexOf (',');
640 if (before_ret_val < 0)
641 sig.Append (parameters.Substring (1, parameters.Length - 2));
643 sig.Append (parameters.Substring (1, before_ret_val - 1));
647 sig.Append (mb.Name.Substring (4));
650 if (mb.Name == ".ctor")
651 sig.Append (mb.DeclaringType.Name);
653 sig.Append (mb.Name);
655 sig.Append (parameters);
658 if (show_accessor && accessor.Length > 0) {
660 sig.Append (accessor);
663 return sig.ToString ();
666 static public string CSharpSignature (EventInfo ei)
668 return CSharpName (ei.DeclaringType) + '.' + ei.Name;
672 /// Looks up a type, and aborts if it is not found. This is used
673 /// by types required by the compiler
675 static Type CoreLookupType (string ns_name, string name)
677 Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
678 FullNamedExpression fne = ns.Lookup (RootContext.Tree.Types, name, Location.Null);
679 Type t = fne == null ? null : fne.Type;
681 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
686 /// Returns the MethodInfo for a method named `name' defined
687 /// in type `t' which takes arguments of types `args'
689 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
693 BindingFlags flags = instance_and_static | BindingFlags.Public;
699 flags |= BindingFlags.NonPublic;
701 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
702 if (list.Count == 0) {
704 Report.Error (-19, "Can not find the core function `" + name + "'");
708 MethodInfo mi = list [0] as MethodInfo;
711 Report.Error (-19, "Can not find the core function `" + name + "'");
718 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
720 return GetMethod (t, name, args, false, report_errors);
723 static MethodInfo GetMethod (Type t, string name, Type [] args)
725 return GetMethod (t, name, args, true);
729 /// Returns the PropertyInfo for a property named `name' defined
732 static PropertyInfo GetProperty (Type t, string name)
734 MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
735 BindingFlags.Instance, Type.FilterName, name);
736 if (list.Count == 0) {
737 Report.Error (-19, "Can not find the core property `" + name + "'");
741 PropertyInfo pi = list [0] as PropertyInfo;
743 Report.Error (-19, "Can not find the core function `" + name + "'");
751 /// Returns the ConstructorInfo for "args"
753 private static ConstructorInfo GetConstructor (Type t, Type [] args)
762 throw new InternalErrorException ("Core types haven't been initialized yet?");
764 list = FindMembers (t, MemberTypes.Constructor,
765 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
766 signature_filter, sig);
767 if (list.Count == 0){
768 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
772 ConstructorInfo ci = list [0] as ConstructorInfo;
774 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
781 public static void InitEnumUnderlyingTypes ()
784 int32_type = CoreLookupType ("System", "Int32");
785 int64_type = CoreLookupType ("System", "Int64");
786 uint32_type = CoreLookupType ("System", "UInt32");
787 uint64_type = CoreLookupType ("System", "UInt64");
788 byte_type = CoreLookupType ("System", "Byte");
789 sbyte_type = CoreLookupType ("System", "SByte");
790 short_type = CoreLookupType ("System", "Int16");
791 ushort_type = CoreLookupType ("System", "UInt16");
795 /// The types have to be initialized after the initial
796 /// population of the type has happened (for example, to
797 /// bootstrap the corlib.dll
799 public static void InitCoreTypes ()
801 object_type = CoreLookupType ("System", "Object");
802 value_type = CoreLookupType ("System", "ValueType");
804 InitEnumUnderlyingTypes ();
806 char_type = CoreLookupType ("System", "Char");
807 string_type = CoreLookupType ("System", "String");
808 float_type = CoreLookupType ("System", "Single");
809 double_type = CoreLookupType ("System", "Double");
810 char_ptr_type = GetPointerType (char_type);
811 decimal_type = CoreLookupType ("System", "Decimal");
812 bool_type = CoreLookupType ("System", "Boolean");
813 enum_type = CoreLookupType ("System", "Enum");
815 multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate");
816 delegate_type = CoreLookupType ("System", "Delegate");
818 array_type = CoreLookupType ("System", "Array");
819 void_type = CoreLookupType ("System", "Void");
820 type_type = CoreLookupType ("System", "Type");
822 runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle");
823 runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle");
824 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers");
825 default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute");
826 runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
827 asynccallback_type = CoreLookupType ("System", "AsyncCallback");
828 iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
829 ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
830 ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
831 idisposable_type = CoreLookupType ("System", "IDisposable");
832 icloneable_type = CoreLookupType ("System", "ICloneable");
833 iconvertible_type = CoreLookupType ("System", "IConvertible");
834 monitor_type = CoreLookupType ("System.Threading", "Monitor");
835 intptr_type = CoreLookupType ("System", "IntPtr");
837 attribute_type = CoreLookupType ("System", "Attribute");
838 attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
839 dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute");
840 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute");
841 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute");
842 param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
843 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
844 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
846 default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
848 typed_reference_type = CoreLookupType ("System", "TypedReference");
849 arg_iterator_type = CoreLookupType ("System", "ArgIterator");
850 mbr_type = CoreLookupType ("System", "MarshalByRefObject");
851 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
853 unverifiable_code_type= CoreLookupType ("System.Security", "UnverifiableCodeAttribute");
855 void_ptr_type = GetPointerType (void_type);
857 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute");
859 exception_type = CoreLookupType ("System", "Exception");
860 invalid_operation_exception_type = CoreLookupType ("System", "InvalidOperationException");
861 not_supported_exception_type = CoreLookupType ("System", "NotSupportedException");
866 obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute");
867 conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute");
868 cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute");
869 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute");
870 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute");
871 security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute");
872 required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
873 guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute");
874 assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute");
875 comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute");
876 coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute");
882 compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
883 fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
884 default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
885 runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
888 // When compiling corlib, store the "real" types here.
890 if (!RootContext.StdLib) {
891 system_int32_type = typeof (System.Int32);
892 system_array_type = typeof (System.Array);
893 system_type_type = typeof (System.Type);
894 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
896 system_int_array_get_length = GetMethod (
897 system_array_type, "get_Length", Type.EmptyTypes);
898 system_int_array_get_rank = GetMethod (
899 system_array_type, "get_Rank", Type.EmptyTypes);
900 system_object_array_clone = GetMethod (
901 system_array_type, "Clone", Type.EmptyTypes);
903 Type [] system_int_arg = { system_int32_type };
904 system_int_array_get_length_int = GetMethod (
905 system_array_type, "GetLength", system_int_arg);
906 system_int_array_get_upper_bound_int = GetMethod (
907 system_array_type, "GetUpperBound", system_int_arg);
908 system_int_array_get_lower_bound_int = GetMethod (
909 system_array_type, "GetLowerBound", system_int_arg);
911 Type [] system_array_int_arg = { system_array_type, system_int32_type };
912 system_void_array_copyto_array_int = GetMethod (
913 system_array_type, "CopyTo", system_array_int_arg);
915 Type [] system_3_type_arg = {
916 system_type_type, system_type_type, system_type_type };
917 Type [] system_4_type_arg = {
918 system_type_type, system_type_type, system_type_type, system_type_type };
920 MethodInfo set_corlib_type_builders = GetMethod (
921 system_assemblybuilder_type, "SetCorlibTypeBuilders",
922 system_4_type_arg, true, false);
924 if (set_corlib_type_builders != null) {
925 object[] args = new object [4];
926 args [0] = object_type;
927 args [1] = value_type;
928 args [2] = enum_type;
929 args [3] = void_type;
931 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
933 // Compatibility for an older version of the class libs.
934 set_corlib_type_builders = GetMethod (
935 system_assemblybuilder_type, "SetCorlibTypeBuilders",
936 system_3_type_arg, true, true);
938 if (set_corlib_type_builders == null) {
939 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
943 object[] args = new object [3];
944 args [0] = object_type;
945 args [1] = value_type;
946 args [2] = enum_type;
948 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
952 system_object_expr.Type = object_type;
953 system_string_expr.Type = string_type;
954 system_boolean_expr.Type = bool_type;
955 system_decimal_expr.Type = decimal_type;
956 system_single_expr.Type = float_type;
957 system_double_expr.Type = double_type;
958 system_sbyte_expr.Type = sbyte_type;
959 system_byte_expr.Type = byte_type;
960 system_int16_expr.Type = short_type;
961 system_uint16_expr.Type = ushort_type;
962 system_int32_expr.Type = int32_type;
963 system_uint32_expr.Type = uint32_type;
964 system_int64_expr.Type = int64_type;
965 system_uint64_expr.Type = uint64_type;
966 system_char_expr.Type = char_type;
967 system_void_expr.Type = void_type;
968 system_asynccallback_expr.Type = asynccallback_type;
969 system_iasyncresult_expr.Type = iasyncresult_type;
970 system_valuetype_expr.Type = value_type;
973 // These are only used for compare purposes
975 anonymous_method_type = typeof (AnonymousMethod);
976 null_type = typeof (NullType);
980 // The helper methods that are used by the compiler
982 public static void InitCodeHelpers ()
985 // Now load the default methods that we use.
987 Type [] string_string = { string_type, string_type };
988 string_concat_string_string = GetMethod (
989 string_type, "Concat", string_string);
990 Type [] string_string_string = { string_type, string_type, string_type };
991 string_concat_string_string_string = GetMethod (
992 string_type, "Concat", string_string_string);
993 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
994 string_concat_string_string_string_string = GetMethod (
995 string_type, "Concat", string_string_string_string);
996 Type[] params_string = { GetConstructedType (string_type, "[]") };
997 string_concat_string_dot_dot_dot = GetMethod (
998 string_type, "Concat", params_string);
1000 Type [] object_object = { object_type, object_type };
1001 string_concat_object_object = GetMethod (
1002 string_type, "Concat", object_object);
1003 Type [] object_object_object = { object_type, object_type, object_type };
1004 string_concat_object_object_object = GetMethod (
1005 string_type, "Concat", object_object_object);
1006 Type[] params_object = { GetConstructedType (object_type, "[]") };
1007 string_concat_object_dot_dot_dot = GetMethod (
1008 string_type, "Concat", params_object);
1010 Type [] string_ = { string_type };
1011 string_isinterneted_string = GetMethod (
1012 string_type, "IsInterned", string_);
1014 Type [] runtime_type_handle = { runtime_handle_type };
1015 system_type_get_type_from_handle = GetMethod (
1016 type_type, "GetTypeFromHandle", runtime_type_handle);
1018 Type [] delegate_delegate = { delegate_type, delegate_type };
1019 delegate_combine_delegate_delegate = GetMethod (
1020 delegate_type, "Combine", delegate_delegate);
1022 delegate_remove_delegate_delegate = GetMethod (
1023 delegate_type, "Remove", delegate_delegate);
1028 ienumerator_getcurrent = GetProperty (
1029 ienumerator_type, "Current");
1030 bool_movenext_void = GetMethod (
1031 ienumerator_type, "MoveNext", Type.EmptyTypes);
1032 void_reset_void = GetMethod (
1033 ienumerator_type, "Reset", Type.EmptyTypes);
1034 void_dispose_void = GetMethod (
1035 idisposable_type, "Dispose", Type.EmptyTypes);
1036 int_get_offset_to_string_data = GetMethod (
1037 runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
1038 int_array_get_length = GetMethod (
1039 array_type, "get_Length", Type.EmptyTypes);
1040 int_array_get_rank = GetMethod (
1041 array_type, "get_Rank", Type.EmptyTypes);
1042 ienumerable_getenumerator_void = GetMethod (
1043 ienumerable_type, "GetEnumerator", Type.EmptyTypes);
1048 Type [] int_arg = { int32_type };
1049 int_array_get_length_int = GetMethod (
1050 array_type, "GetLength", int_arg);
1051 int_array_get_upper_bound_int = GetMethod (
1052 array_type, "GetUpperBound", int_arg);
1053 int_array_get_lower_bound_int = GetMethod (
1054 array_type, "GetLowerBound", int_arg);
1057 // System.Array methods
1059 object_array_clone = GetMethod (
1060 array_type, "Clone", Type.EmptyTypes);
1061 Type [] array_int_arg = { array_type, int32_type };
1062 void_array_copyto_array_int = GetMethod (
1063 array_type, "CopyTo", array_int_arg);
1068 Type [] object_arg = { object_type };
1069 void_monitor_enter_object = GetMethod (
1070 monitor_type, "Enter", object_arg);
1071 void_monitor_exit_object = GetMethod (
1072 monitor_type, "Exit", object_arg);
1074 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1076 void_initializearray_array_fieldhandle = GetMethod (
1077 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1082 int_getlength_int = GetMethod (
1083 array_type, "GetLength", int_arg);
1086 // Decimal constructors
1088 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1089 void_decimal_ctor_five_args = GetConstructor (
1090 decimal_type, dec_arg);
1092 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1097 unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
1098 default_member_ctor = GetConstructor (default_member_type, string_);
1100 Type[] short_arg = { short_type };
1101 struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
1103 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1104 { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
1106 field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
1113 compiler_generated_attr = new CustomAttributeBuilder (
1114 GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
1116 Type[] type_int_arg = { type_type, int32_type };
1117 fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
1121 object_ctor = GetConstructor (object_type, Type.EmptyTypes);
1125 static public ConstructorInfo ConsParamArrayAttribute {
1127 if (cons_param_array_attribute == null)
1128 cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
1129 return cons_param_array_attribute;
1133 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1136 /// This is the "old", non-cache based FindMembers() function. We cannot use
1137 /// the cache here because there is no member name argument.
1139 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1140 MemberFilter filter, object criteria)
1142 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1145 // `builder_to_declspace' contains all dynamic types.
1149 Timer.StartTimer (TimerType.FindMembers);
1150 list = decl.FindMembers (mt, bf, filter, criteria);
1151 Timer.StopTimer (TimerType.FindMembers);
1156 // We have to take care of arrays specially, because GetType on
1157 // a TypeBuilder array will return a Type, not a TypeBuilder,
1158 // and we can not call FindMembers on this type.
1160 if (TypeManager.IsSubclassOf (t, TypeManager.array_type))
1161 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1164 // Since FindMembers will not lookup both static and instance
1165 // members, we emulate this behaviour here.
1167 if ((bf & instance_and_static) == instance_and_static){
1168 MemberInfo [] i_members = t.FindMembers (
1169 mt, bf & ~BindingFlags.Static, filter, criteria);
1171 int i_len = i_members.Length;
1173 MemberInfo one = i_members [0];
1176 // If any of these are present, we are done!
1178 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1179 return new MemberList (i_members);
1182 MemberInfo [] s_members = t.FindMembers (
1183 mt, bf & ~BindingFlags.Instance, filter, criteria);
1185 int s_len = s_members.Length;
1186 if (i_len > 0 || s_len > 0)
1187 return new MemberList (i_members, s_members);
1190 return new MemberList (i_members);
1192 return new MemberList (s_members);
1196 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1201 /// This method is only called from within MemberLookup. It tries to use the member
1202 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1203 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1204 /// our return value will already contain all inherited members and the caller don't need
1205 /// to check base classes and interfaces anymore.
1207 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1208 string name, out bool used_cache)
1213 // We have to take care of arrays specially, because GetType on
1214 // a TypeBuilder array will return a Type, not a TypeBuilder,
1215 // and we can not call FindMembers on this type.
1217 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1219 return TypeHandle.ArrayType.MemberCache.FindMembers (
1220 mt, bf, name, FilterWithClosure_delegate, null);
1224 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1225 // and we can ask the DeclSpace for the MemberCache.
1227 if (t is TypeBuilder) {
1228 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1229 cache = decl.MemberCache;
1232 // If this DeclSpace has a MemberCache, use it.
1235 if (cache != null) {
1237 return cache.FindMembers (
1238 mt, bf, name, FilterWithClosure_delegate, null);
1241 // If there is no MemberCache, we need to use the "normal" FindMembers.
1242 // Note, this is a VERY uncommon route!
1245 Timer.StartTimer (TimerType.FindMembers);
1246 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1247 FilterWithClosure_delegate, name);
1248 Timer.StopTimer (TimerType.FindMembers);
1251 return (MemberInfo []) list;
1255 // This call will always succeed. There is exactly one TypeHandle instance per
1256 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1257 // the corresponding MemberCache.
1259 cache = TypeHandle.GetMemberCache (t);
1262 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1265 public static bool IsBuiltinType (Type t)
1267 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1268 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1269 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1270 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1276 public static bool IsBuiltinType (TypeContainer tc)
1278 return IsBuiltinType (tc.TypeBuilder);
1282 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1283 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1285 public static bool IsPrimitiveType (Type t)
1287 return (t == int32_type || t == uint32_type ||
1288 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1289 t == char_type || t == short_type || t == bool_type ||
1290 t == sbyte_type || t == byte_type || t == ushort_type);
1293 public static bool IsDelegateType (Type t)
1295 if (t.IsSubclassOf (TypeManager.delegate_type))
1301 public static bool IsEnumType (Type t)
1303 if (builder_to_declspace [t] is Enum)
1309 public static bool IsBuiltinOrEnum (Type t)
1311 if (IsBuiltinType (t))
1320 static Stack unmanaged_enclosing_types = new Stack (4);
1323 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1325 public static bool IsUnmanagedType (Type t)
1327 // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
1328 if (unmanaged_enclosing_types.Contains (t))
1331 // builtins that are not unmanaged types
1332 if (t == TypeManager.object_type || t == TypeManager.string_type)
1335 if (IsBuiltinOrEnum (t))
1338 // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
1342 // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
1346 if (!IsValueType (t))
1349 unmanaged_enclosing_types.Push (t);
1353 if (t is TypeBuilder){
1354 TypeContainer tc = LookupTypeContainer (t);
1355 if (tc.Fields != null){
1356 foreach (FieldMember f in tc.Fields){
1357 // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
1358 if ((f.ModFlags & Modifiers.STATIC) != 0)
1360 if (f.MemberType == null)
1362 if (!IsUnmanagedType (f.MemberType)){
1363 Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
1369 FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
1371 foreach (FieldInfo f in fields){
1372 if (!IsUnmanagedType (f.FieldType)){
1373 Report.SymbolRelatedToPreviousError (f);
1379 unmanaged_enclosing_types.Pop ();
1384 public static bool IsValueType (Type t)
1386 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1392 public static bool IsInterfaceType (Type t)
1394 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1398 return tc.Kind == Kind.Interface;
1401 public static bool IsSubclassOf (Type type, Type base_type)
1404 if (type.Equals (base_type))
1407 type = type.BaseType;
1408 } while (type != null);
1413 public static bool IsFamilyAccessible (Type type, Type base_type)
1415 return IsSubclassOf (type, base_type);
1419 // Checks whether `type' is a subclass or nested child of `base_type'.
1421 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
1424 if ((type == base_type) || type.IsSubclassOf (base_type))
1427 // Handle nested types.
1428 type = type.DeclaringType;
1429 } while (type != null);
1435 // Checks whether `type' is a nested child of `parent'.
1437 public static bool IsNestedChildOf (Type type, Type parent)
1442 type = type.DeclaringType;
1443 while (type != null) {
1447 type = type.DeclaringType;
1454 // Do the right thing when returning the element type of an
1455 // array type based on whether we are compiling corlib or not
1457 public static Type GetElementType (Type t)
1459 if (RootContext.StdLib)
1460 return t.GetElementType ();
1462 return TypeToCoreType (t.GetElementType ());
1466 /// This method is not implemented by MS runtime for dynamic types
1468 public static bool HasElementType (Type t)
1470 return t.IsArray || t.IsPointer || t.IsByRef;
1474 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1478 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1479 /// for anything which is dynamic, and we need this in a number of places,
1480 /// we register this information here, and use it afterwards.
1482 static public void RegisterMethod (MethodBase mb, Parameters ip)
1484 method_params.Add (mb, ip);
1487 static public ParameterData GetParameterData (MethodBase mb)
1489 ParameterData pd = (ParameterData)method_params [mb];
1491 if (mb is MethodBuilder || mb is ConstructorBuilder)
1492 throw new InternalErrorException ("Argument for Method not registered" + mb);
1494 pd = new ReflectionParameters (mb);
1495 method_params.Add (mb, pd);
1500 static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
1502 if (!method_overrides.Contains (override_method))
1503 method_overrides [override_method] = base_method;
1504 if (method_overrides [override_method] != base_method)
1505 throw new InternalErrorException ("Override mismatch: " + override_method);
1508 static public bool IsOverride (MethodBase m)
1510 return m.IsVirtual &&
1511 (m.Attributes & MethodAttributes.NewSlot) == 0 &&
1512 (m is MethodBuilder || method_overrides.Contains (m));
1515 static public MethodBase TryGetBaseDefinition (MethodBase m)
1517 return (MethodBase) method_overrides [m];
1521 /// Returns the argument types for an indexer based on its PropertyInfo
1523 /// For dynamic indexers, we use the compiler provided types, for
1524 /// indexers from existing assemblies we load them from GetParameters,
1525 /// and insert them into the cache
1527 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1529 if (indexer_arguments.Contains (indexer))
1530 return (Type []) indexer_arguments [indexer];
1531 else if (indexer is PropertyBuilder)
1532 // If we're a PropertyBuilder and not in the
1533 // `indexer_arguments' hash, then we're a property and
1535 return Type.EmptyTypes;
1537 ParameterInfo [] pi = indexer.GetIndexParameters ();
1538 // Property, not an indexer.
1540 return Type.EmptyTypes;
1542 Type [] types = new Type [c];
1544 for (int i = 0; i < c; i++)
1545 types [i] = pi [i].ParameterType;
1547 indexer_arguments.Add (indexer, types);
1552 public static void RegisterConstant (FieldInfo fb, IConstant ic)
1554 fields.Add (fb, ic);
1557 public static IConstant GetConstant (FieldInfo fb)
1562 return (IConstant)fields [fb];
1565 public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
1567 propertybuilder_to_property.Add (pi, pb);
1570 public static PropertyBase GetProperty (PropertyInfo pi)
1572 return (PropertyBase)propertybuilder_to_property [pi];
1575 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1577 if (fieldbuilders_to_fields.Contains (fb))
1580 fieldbuilders_to_fields.Add (fb, f);
1585 // The return value can be null; This will be the case for
1586 // auxiliary FieldBuilders created by the compiler that have no
1587 // real field being declared on the source code
1589 static public FieldBase GetField (FieldInfo fb)
1591 return (FieldBase) fieldbuilders_to_fields [fb];
1594 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1597 events = new Hashtable ();
1599 if (!events.Contains (eb)) {
1600 events.Add (eb, new Pair (add, remove));
1604 static public MethodInfo GetAddMethod (EventInfo ei)
1606 if (ei is MyEventBuilder) {
1607 Pair pair = (Pair) events [ei];
1609 return (MethodInfo) pair.First;
1611 return ei.GetAddMethod (true);
1614 static public MethodInfo GetRemoveMethod (EventInfo ei)
1616 if (ei is MyEventBuilder) {
1617 Pair pair = (Pair) events [ei];
1619 return (MethodInfo) pair.Second;
1621 return ei.GetRemoveMethod (true);
1624 static Hashtable priv_fields_events;
1626 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1628 if (priv_fields_events == null)
1629 priv_fields_events = new Hashtable ();
1631 if (priv_fields_events.Contains (einfo))
1634 priv_fields_events.Add (einfo, builder);
1639 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1641 if (priv_fields_events == null)
1644 return (MemberInfo) priv_fields_events [ei];
1647 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1648 MethodBase set, Type[] args)
1650 indexer_arguments.Add (pb, args);
1655 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1657 Hashtable hash = new Hashtable ();
1658 return CheckStructCycles (tc, seen, hash);
1661 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1664 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
1668 // `seen' contains all types we've already visited.
1670 if (seen.Contains (tc))
1672 seen.Add (tc, null);
1674 if (tc.Fields == null)
1677 foreach (FieldMember field in tc.Fields) {
1678 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
1681 Type ftype = field.FieldBuilder.FieldType;
1682 TypeContainer ftc = LookupTypeContainer (ftype);
1686 if (hash.Contains (ftc)) {
1687 Report.Error (523, tc.Location,
1688 "Struct member `{0}.{1}' of type `{2}' " +
1689 "causes a cycle in the struct layout",
1690 tc.Name, field.Name, ftc.Name);
1695 // `hash' contains all types in the current path.
1697 hash.Add (tc, null);
1699 bool ok = CheckStructCycles (ftc, seen, hash);
1706 if (!seen.Contains (ftc))
1707 seen.Add (ftc, null);
1714 /// Given an array of interface types, expand and eliminate repeated ocurrences
1715 /// of an interface.
1719 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1722 public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
1724 ArrayList new_ifaces = new ArrayList ();
1726 foreach (TypeExpr iface in base_interfaces){
1727 Type itype = iface.Type;
1729 if (!new_ifaces.Contains (itype))
1730 new_ifaces.Add (itype);
1732 Type [] implementing = itype.GetInterfaces ();
1734 foreach (Type imp in implementing){
1735 if (!new_ifaces.Contains (imp))
1736 new_ifaces.Add (imp);
1739 Type [] ret = new Type [new_ifaces.Count];
1740 new_ifaces.CopyTo (ret, 0);
1744 static PtrHashtable iface_cache = new PtrHashtable ();
1747 /// This function returns the interfaces in the type `t'. Works with
1748 /// both types and TypeBuilders.
1750 public static Type [] GetInterfaces (Type t)
1752 Type [] cached = iface_cache [t] as Type [];
1757 // The reason for catching the Array case is that Reflection.Emit
1758 // will not return a TypeBuilder for Array types of TypeBuilder types,
1759 // but will still throw an exception if we try to call GetInterfaces
1762 // Since the array interfaces are always constant, we return those for
1767 t = TypeManager.array_type;
1769 if (t is TypeBuilder){
1770 Type [] base_ifaces;
1772 if (t.BaseType == null)
1773 base_ifaces = Type.EmptyTypes;
1775 base_ifaces = GetInterfaces (t.BaseType);
1776 Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1777 if (type_ifaces == null || type_ifaces.Length == 0)
1778 type_ifaces = Type.EmptyTypes;
1780 int base_count = base_ifaces.Length;
1781 Type [] result = new Type [base_count + type_ifaces.Length];
1782 base_ifaces.CopyTo (result, 0);
1783 type_ifaces.CopyTo (result, base_count);
1785 iface_cache [t] = result;
1788 Type[] ifaces = t.GetInterfaces ();
1789 iface_cache [t] = ifaces;
1795 // gets the interfaces that are declared explicitly on t
1797 public static Type [] GetExplicitInterfaces (TypeBuilder t)
1799 return (Type []) builder_to_ifaces [t];
1803 /// The following is used to check if a given type implements an interface.
1804 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1806 public static bool ImplementsInterface (Type t, Type iface)
1811 // FIXME OPTIMIZATION:
1812 // as soon as we hit a non-TypeBuiler in the interface
1813 // chain, we could return, as the `Type.GetInterfaces'
1814 // will return all the interfaces implement by the type
1818 interfaces = GetInterfaces (t);
1820 if (interfaces != null){
1821 foreach (Type i in interfaces){
1828 } while (t != null);
1833 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
1835 // This is a custom version of Convert.ChangeType() which works
1836 // with the TypeBuilder defined types when compiling corlib.
1837 public static object ChangeType (object value, Type conversionType, out bool error)
1839 IConvertible convert_value = value as IConvertible;
1841 if (convert_value == null){
1847 // We must use Type.Equals() here since `conversionType' is
1848 // the TypeBuilder created version of a system type and not
1849 // the system type itself. You cannot use Type.GetTypeCode()
1850 // on such a type - it'd always return TypeCode.Object.
1854 if (conversionType.Equals (typeof (Boolean)))
1855 return (object)(convert_value.ToBoolean (nf_provider));
1856 else if (conversionType.Equals (typeof (Byte)))
1857 return (object)(convert_value.ToByte (nf_provider));
1858 else if (conversionType.Equals (typeof (Char)))
1859 return (object)(convert_value.ToChar (nf_provider));
1860 else if (conversionType.Equals (typeof (DateTime)))
1861 return (object)(convert_value.ToDateTime (nf_provider));
1862 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
1863 return (object)(convert_value.ToDecimal (nf_provider));
1864 else if (conversionType.Equals (typeof (Double)))
1865 return (object)(convert_value.ToDouble (nf_provider));
1866 else if (conversionType.Equals (typeof (Int16)))
1867 return (object)(convert_value.ToInt16 (nf_provider));
1868 else if (conversionType.Equals (typeof (Int32)))
1869 return (object)(convert_value.ToInt32 (nf_provider));
1870 else if (conversionType.Equals (typeof (Int64)))
1871 return (object)(convert_value.ToInt64 (nf_provider));
1872 else if (conversionType.Equals (typeof (SByte)))
1873 return (object)(convert_value.ToSByte (nf_provider));
1874 else if (conversionType.Equals (typeof (Single)))
1875 return (object)(convert_value.ToSingle (nf_provider));
1876 else if (conversionType.Equals (typeof (String)))
1877 return (object)(convert_value.ToString (nf_provider));
1878 else if (conversionType.Equals (typeof (UInt16)))
1879 return (object)(convert_value.ToUInt16 (nf_provider));
1880 else if (conversionType.Equals (typeof (UInt32)))
1881 return (object)(convert_value.ToUInt32 (nf_provider));
1882 else if (conversionType.Equals (typeof (UInt64)))
1883 return (object)(convert_value.ToUInt64 (nf_provider));
1884 else if (conversionType.Equals (typeof (Object)))
1885 return (object)(value);
1895 // This is needed, because enumerations from assemblies
1896 // do not report their underlyingtype, but they report
1899 public static Type EnumToUnderlying (Type t)
1901 if (t == TypeManager.enum_type)
1904 t = t.UnderlyingSystemType;
1905 if (!TypeManager.IsEnumType (t))
1908 if (t is TypeBuilder) {
1909 // slow path needed to compile corlib
1910 if (t == TypeManager.bool_type ||
1911 t == TypeManager.byte_type ||
1912 t == TypeManager.sbyte_type ||
1913 t == TypeManager.char_type ||
1914 t == TypeManager.short_type ||
1915 t == TypeManager.ushort_type ||
1916 t == TypeManager.int32_type ||
1917 t == TypeManager.uint32_type ||
1918 t == TypeManager.int64_type ||
1919 t == TypeManager.uint64_type)
1922 TypeCode tc = Type.GetTypeCode (t);
1925 case TypeCode.Boolean:
1926 return TypeManager.bool_type;
1928 return TypeManager.byte_type;
1929 case TypeCode.SByte:
1930 return TypeManager.sbyte_type;
1932 return TypeManager.char_type;
1933 case TypeCode.Int16:
1934 return TypeManager.short_type;
1935 case TypeCode.UInt16:
1936 return TypeManager.ushort_type;
1937 case TypeCode.Int32:
1938 return TypeManager.int32_type;
1939 case TypeCode.UInt32:
1940 return TypeManager.uint32_type;
1941 case TypeCode.Int64:
1942 return TypeManager.int64_type;
1943 case TypeCode.UInt64:
1944 return TypeManager.uint64_type;
1946 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1950 // When compiling corlib and called with one of the core types, return
1951 // the corresponding typebuilder for that type.
1953 public static Type TypeToCoreType (Type t)
1955 if (RootContext.StdLib || (t is TypeBuilder))
1958 TypeCode tc = Type.GetTypeCode (t);
1961 case TypeCode.Boolean:
1962 return TypeManager.bool_type;
1964 return TypeManager.byte_type;
1965 case TypeCode.SByte:
1966 return TypeManager.sbyte_type;
1968 return TypeManager.char_type;
1969 case TypeCode.Int16:
1970 return TypeManager.short_type;
1971 case TypeCode.UInt16:
1972 return TypeManager.ushort_type;
1973 case TypeCode.Int32:
1974 return TypeManager.int32_type;
1975 case TypeCode.UInt32:
1976 return TypeManager.uint32_type;
1977 case TypeCode.Int64:
1978 return TypeManager.int64_type;
1979 case TypeCode.UInt64:
1980 return TypeManager.uint64_type;
1981 case TypeCode.Single:
1982 return TypeManager.float_type;
1983 case TypeCode.Double:
1984 return TypeManager.double_type;
1985 case TypeCode.String:
1986 return TypeManager.string_type;
1987 case TypeCode.Decimal:
1988 return TypeManager.decimal_type;
1990 if (t == typeof (void))
1991 return TypeManager.void_type;
1992 if (t == typeof (object))
1993 return TypeManager.object_type;
1994 if (t == typeof (System.Type))
1995 return TypeManager.type_type;
1996 if (t == typeof (System.IntPtr))
1997 return TypeManager.intptr_type;
2003 /// Utility function that can be used to probe whether a type
2004 /// is managed or not.
2006 public static bool VerifyUnManaged (Type t, Location loc)
2008 if (IsUnmanagedType (t))
2011 Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
2018 /// Returns the name of the indexer in a given type.
2021 /// The default is not always `Item'. The user can change this behaviour by
2022 /// using the IndexerNameAttribute in the container.
2023 /// For example, the String class indexer is named `Chars' not `Item'
2025 public static string IndexerPropertyName (Type t)
2027 if (t is TypeBuilder) {
2028 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2029 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2032 System.Attribute attr = System.Attribute.GetCustomAttribute (
2033 t, TypeManager.default_member_type);
2035 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2036 return dma.MemberName;
2039 return TypeContainer.DefaultIndexerName;
2042 static MethodInfo declare_local_method = null;
2044 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2046 if (declare_local_method == null){
2047 declare_local_method = typeof (ILGenerator).GetMethod (
2049 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2051 new Type [] { typeof (Type), typeof (bool)},
2053 if (declare_local_method == null){
2054 Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
2055 return ig.DeclareLocal (t);
2058 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2062 // Returns whether the array of memberinfos contains the given method
2064 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2066 Type [] new_args = TypeManager.GetParameterData (new_method).Types;
2068 foreach (MethodBase method in array) {
2069 if (method.Name != new_method.Name)
2072 if (method is MethodInfo && new_method is MethodInfo)
2073 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2077 Type [] old_args = TypeManager.GetParameterData (method).Types;
2078 int old_count = old_args.Length;
2081 if (new_args.Length != old_count)
2084 for (i = 0; i < old_count; i++){
2085 if (old_args [i] != new_args [i])
2098 // We copy methods from `new_members' into `target_list' if the signature
2099 // for the method from in the new list does not exist in the target_list
2101 // The name is assumed to be the same.
2103 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2105 if (target_list == null){
2106 target_list = new ArrayList ();
2108 foreach (MemberInfo mi in new_members){
2109 if (mi is MethodBase)
2110 target_list.Add (mi);
2115 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2116 target_list.CopyTo (target_array, 0);
2118 foreach (MemberInfo mi in new_members){
2119 MethodBase new_method = (MethodBase) mi;
2121 if (!ArrayContainsMethod (target_array, new_method))
2122 target_list.Add (new_method);
2128 // This method always return false for non-generic compiler,
2129 // while Type.IsGenericParameter is returned if it is supported.
2130 public static bool IsGenericParameter (Type type)
2135 public static int GenericParameterPosition (Type type)
2137 throw new InternalErrorException ("should not be called");
2140 #region MemberLookup implementation
2143 // Whether we allow private members in the result (since FindMembers
2144 // uses NonPublic for both protected and private), we need to distinguish.
2147 internal class Closure {
2148 internal bool private_ok;
2150 // Who is invoking us and which type is being queried currently.
2151 internal Type invocation_type;
2152 internal Type qualifier_type;
2154 // The assembly that defines the type is that is calling us
2155 internal Assembly invocation_assembly;
2156 internal IList almost_match;
2158 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2160 if (invocation_type == null)
2163 if (is_static && qualifier_type == null)
2164 // It resolved from a simple name, so it should be visible.
2167 // A nested class has access to all the protected members visible to its parent.
2168 if (qualifier_type != null && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2171 if (invocation_type == m.DeclaringType || invocation_type.IsSubclassOf (m.DeclaringType)) {
2172 // Although a derived class can access protected members of its base class
2173 // it cannot do so through an instance of the base class (CS1540).
2174 // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
2176 qualifier_type == null ||
2177 qualifier_type == invocation_type ||
2178 qualifier_type.IsSubclassOf (invocation_type))
2182 if (almost_match != null)
2183 almost_match.Add (m);
2189 // This filter filters by name + whether it is ok to include private
2190 // members in the search
2192 internal bool Filter (MemberInfo m, object filter_criteria)
2195 // Hack: we know that the filter criteria will always be in the `closure'
2199 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2202 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2203 (m.DeclaringType == invocation_type))
2207 // Ugly: we need to find out the type of `m', and depending
2208 // on this, tell whether we accept or not
2210 if (m is MethodBase){
2211 MethodBase mb = (MethodBase) m;
2212 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2214 if (ma == MethodAttributes.Private)
2215 return private_ok || invocation_type == m.DeclaringType ||
2216 IsNestedChildOf (invocation_type, m.DeclaringType);
2218 if (invocation_assembly == mb.DeclaringType.Assembly) {
2219 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
2222 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
2226 if (ma == MethodAttributes.Family ||
2227 ma == MethodAttributes.FamANDAssem ||
2228 ma == MethodAttributes.FamORAssem)
2229 return CheckValidFamilyAccess (mb.IsStatic, m);
2235 if (m is FieldInfo){
2236 FieldInfo fi = (FieldInfo) m;
2237 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2239 if (fa == FieldAttributes.Private)
2240 return private_ok || (invocation_type == m.DeclaringType) ||
2241 IsNestedChildOf (invocation_type, m.DeclaringType);
2243 if (invocation_assembly == fi.DeclaringType.Assembly) {
2244 if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamORAssem)
2247 if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamANDAssem)
2251 if (fa == FieldAttributes.Family ||
2252 fa == FieldAttributes.FamANDAssem ||
2253 fa == FieldAttributes.FamORAssem)
2254 return CheckValidFamilyAccess (fi.IsStatic, m);
2261 // EventInfos and PropertyInfos, return true because they lack permission
2262 // information, so we need to check later on the methods.
2268 static Closure closure = new Closure ();
2269 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2272 // Looks up a member called `name' in the `queried_type'. This lookup
2273 // is done by code that is contained in the definition for `invocation_type'
2274 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2276 // `invocation_type' is used to check whether we're allowed to access the requested
2277 // member wrt its protection level.
2279 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2280 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2281 // is B and qualifier_type is A). This is used to do the CS1540 check.
2283 // When resolving a SimpleName, `qualifier_type' is null.
2285 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2286 // the same than `queried_type' - except when we're being called from BaseAccess;
2287 // in this case, `invocation_type' is the current type and `queried_type' the base
2288 // type, so this'd normally trigger a CS1540.
2290 // The binding flags are `bf' and the kind of members being looked up are `mt'
2292 // The return value always includes private members which code in `invocation_type'
2293 // is allowed to access (using the specified `qualifier_type' if given); only use
2294 // BindingFlags.NonPublic to bypass the permission check.
2296 // The 'almost_match' argument is used for reporting error CS1540.
2298 // Returns an array of a single element for everything but Methods/Constructors
2299 // that might return multiple matches.
2301 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2302 Type queried_type, MemberTypes mt,
2303 BindingFlags original_bf, string name, IList almost_match)
2305 Timer.StartTimer (TimerType.MemberLookup);
2307 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2308 queried_type, mt, original_bf, name, almost_match);
2310 Timer.StopTimer (TimerType.MemberLookup);
2315 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2316 Type queried_type, MemberTypes mt,
2317 BindingFlags original_bf, string name, IList almost_match)
2319 BindingFlags bf = original_bf;
2321 ArrayList method_list = null;
2322 Type current_type = queried_type;
2323 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2324 bool skip_iface_check = true, used_cache = false;
2325 bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
2327 closure.invocation_type = invocation_type;
2328 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2329 closure.qualifier_type = qualifier_type;
2330 closure.almost_match = almost_match;
2332 // This is from the first time we find a method
2333 // in most cases, we do not actually find a method in the base class
2334 // so we can just ignore it, and save the arraylist allocation
2335 MemberInfo [] first_members_list = null;
2336 bool use_first_members_list = false;
2342 // `NonPublic' is lame, because it includes both protected and
2343 // private methods, so we need to control this behavior by
2344 // explicitly tracking if a private method is ok or not.
2346 // The possible cases are:
2347 // public, private and protected (internal does not come into the
2350 if ((invocation_type != null) &&
2351 ((invocation_type == current_type) ||
2352 IsNestedChildOf (invocation_type, current_type)) ||
2354 bf = original_bf | BindingFlags.NonPublic;
2358 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2360 Timer.StopTimer (TimerType.MemberLookup);
2362 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2364 Timer.StartTimer (TimerType.MemberLookup);
2367 // When queried for an interface type, the cache will automatically check all
2368 // inherited members, so we don't need to do this here. However, this only
2369 // works if we already used the cache in the first iteration of this loop.
2371 // If we used the cache in any further iteration, we can still terminate the
2372 // loop since the cache always looks in all base classes.
2378 skip_iface_check = false;
2380 if (current_type == TypeManager.object_type)
2383 current_type = current_type.BaseType;
2386 // This happens with interfaces, they have a null
2387 // basetype. Look members up in the Object class.
2389 if (current_type == null) {
2390 current_type = TypeManager.object_type;
2395 if (list.Length == 0)
2399 // Events and types are returned by both `static' and `instance'
2400 // searches, which means that our above FindMembers will
2401 // return two copies of the same.
2403 if (list.Length == 1 && !(list [0] is MethodBase)){
2408 // Multiple properties: we query those just to find out the indexer
2411 if (list [0] is PropertyInfo)
2415 // We found an event: the cache lookup returns both the event and
2416 // its private field.
2418 if (list [0] is EventInfo) {
2419 if ((list.Length == 2) && (list [1] is FieldInfo))
2420 return new MemberInfo [] { list [0] };
2427 // We found methods, turn the search into "method scan"
2431 if (first_members_list != null) {
2432 if (use_first_members_list) {
2433 method_list = CopyNewMethods (method_list, first_members_list);
2434 use_first_members_list = false;
2437 method_list = CopyNewMethods (method_list, list);
2439 first_members_list = list;
2440 use_first_members_list = true;
2441 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2443 } while (searching);
2445 if (use_first_members_list) {
2446 foreach (MemberInfo mi in first_members_list) {
2447 if (! (mi is MethodBase)) {
2448 method_list = CopyNewMethods (method_list, first_members_list);
2449 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2452 return (MemberInfo []) first_members_list;
2455 if (method_list != null && method_list.Count > 0) {
2456 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2459 // This happens if we already used the cache in the first iteration, in this case
2460 // the cache already looked in all interfaces.
2462 if (skip_iface_check)
2466 // Interfaces do not list members they inherit, so we have to
2469 if (!queried_type.IsInterface)
2472 if (queried_type.IsArray)
2473 queried_type = TypeManager.array_type;
2475 Type [] ifaces = GetInterfaces (queried_type);
2479 foreach (Type itype in ifaces){
2482 x = MemberLookup (null, null, itype, mt, bf, name, null);
2490 // Tests whether external method is really special
2491 public static bool IsSpecialMethod (MethodBase mb)
2493 string name = mb.Name;
2494 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
2495 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
2497 if (name.StartsWith ("add_"))
2498 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
2500 if (name.StartsWith ("remove_"))
2501 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
2503 if (name.StartsWith ("op_")){
2504 foreach (string oname in Unary.oper_names) {
2509 foreach (string oname in Binary.oper_names) {
2522 /// There is exactly one instance of this class per type.
2524 public sealed class TypeHandle : IMemberContainer {
2525 public readonly IMemberContainer BaseType;
2527 readonly int id = ++next_id;
2528 static int next_id = 0;
2530 static TypeHandle ()
2536 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
2537 /// a TypeHandle yet, a new instance of it is created. This static method
2538 /// ensures that we'll only have one TypeHandle instance per type.
2540 private static TypeHandle GetTypeHandle (Type t)
2542 TypeHandle handle = (TypeHandle) type_hash [t];
2546 handle = new TypeHandle (t);
2547 type_hash.Add (t, handle);
2551 public static MemberCache GetMemberCache (Type t)
2553 return GetTypeHandle (t).MemberCache;
2556 public static void CleanUp ()
2561 public static void Reset ()
2563 type_hash = new PtrHashtable ();
2567 /// Returns the TypeHandle for TypeManager.object_type.
2569 public static IMemberContainer ObjectType {
2571 if (object_type != null)
2574 object_type = GetTypeHandle (TypeManager.object_type);
2581 /// Returns the TypeHandle for TypeManager.array_type.
2583 public static IMemberContainer ArrayType {
2585 if (array_type != null)
2588 array_type = GetTypeHandle (TypeManager.array_type);
2594 private static PtrHashtable type_hash;
2596 private static TypeHandle object_type = null;
2597 private static TypeHandle array_type = null;
2600 private bool is_interface;
2601 private MemberCache member_cache;
2602 private MemberCache base_cache;
2604 private TypeHandle (Type type)
2607 if (type.BaseType != null) {
2608 base_cache = TypeManager.LookupMemberCache (type.BaseType);
2609 BaseType = base_cache.Container;
2610 } else if (type.IsInterface)
2611 base_cache = TypeManager.LookupBaseInterfacesCache (type);
2612 this.is_interface = type.IsInterface;
2613 this.member_cache = new MemberCache (this);
2616 // IMemberContainer methods
2618 public string Name {
2620 return type.FullName;
2630 public MemberCache BaseCache {
2636 public bool IsInterface {
2638 return is_interface;
2642 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2644 MemberInfo [] members;
2645 if (mt == MemberTypes.Event)
2646 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2648 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2650 Array.Reverse (members);
2652 return new MemberList (members);
2655 // IMemberFinder methods
2657 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2658 MemberFilter filter, object criteria)
2660 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
2663 public MemberCache MemberCache {
2665 return member_cache;
2669 public override string ToString ()
2671 if (BaseType != null)
2672 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2674 return "TypeHandle (" + id + "," + Name + ")";