2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static public Type uint32_type;
42 static public Type int64_type;
43 static public Type uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type sbyte_type;
52 static public Type byte_type;
53 static public Type ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type enumeration_type;
59 static public Type array_type;
60 static public Type runtime_handle_type;
61 static public Type icloneable_type;
62 static public Type type_type;
63 static public Type ienumerator_type;
64 static public Type ienumerable_type;
65 static public Type idisposable_type;
66 static public Type default_member_type;
67 static public Type iasyncresult_type;
68 static public Type asynccallback_type;
69 static public Type intptr_type;
70 static public Type monitor_type;
71 static public Type runtime_field_handle_type;
72 static public Type attribute_type;
73 static public Type attribute_usage_type;
74 static public Type dllimport_type;
75 static public Type unverifiable_code_type;
76 static public Type methodimpl_attr_type;
77 static public Type marshal_as_attr_type;
78 static public Type param_array_type;
79 static public Type guid_attr_type;
80 static public Type void_ptr_type;
81 static public Type indexer_name_type;
82 static public Type exception_type;
83 static public Type invalid_operation_exception_type;
84 static public object obsolete_attribute_type;
85 static public object conditional_attribute_type;
86 static public Type in_attribute_type;
89 // An empty array of types
91 static public Type [] NoTypes;
92 static public TypeExpr [] NoTypeExprs;
96 // Expressions representing the internal types. Used during declaration
99 static public TypeExpr system_object_expr, system_string_expr;
100 static public TypeExpr system_boolean_expr, system_decimal_expr;
101 static public TypeExpr system_single_expr, system_double_expr;
102 static public TypeExpr system_sbyte_expr, system_byte_expr;
103 static public TypeExpr system_int16_expr, system_uint16_expr;
104 static public TypeExpr system_int32_expr, system_uint32_expr;
105 static public TypeExpr system_int64_expr, system_uint64_expr;
106 static public TypeExpr system_char_expr, system_void_expr;
107 static public TypeExpr system_asynccallback_expr;
108 static public TypeExpr system_iasyncresult_expr;
109 static public TypeExpr system_valuetype_expr;
112 // This is only used when compiling corlib
114 static public Type system_int32_type;
115 static public Type system_array_type;
116 static public Type system_type_type;
117 static public Type system_assemblybuilder_type;
118 static public MethodInfo system_int_array_get_length;
119 static public MethodInfo system_int_array_get_rank;
120 static public MethodInfo system_object_array_clone;
121 static public MethodInfo system_int_array_get_length_int;
122 static public MethodInfo system_int_array_get_lower_bound_int;
123 static public MethodInfo system_int_array_get_upper_bound_int;
124 static public MethodInfo system_void_array_copyto_array_int;
128 // Internal, not really used outside
130 static Type runtime_helpers_type;
133 // These methods are called by code generated by the compiler
135 static public MethodInfo string_concat_string_string;
136 static public MethodInfo string_concat_string_string_string;
137 static public MethodInfo string_concat_string_string_string_string;
138 static public MethodInfo string_concat_object_object;
139 static public MethodInfo string_isinterneted_string;
140 static public MethodInfo system_type_get_type_from_handle;
141 static public MethodInfo object_getcurrent_void;
142 static public MethodInfo bool_movenext_void;
143 static public MethodInfo ienumerable_getenumerator_void;
144 static public MethodInfo void_reset_void;
145 static public MethodInfo void_dispose_void;
146 static public MethodInfo void_monitor_enter_object;
147 static public MethodInfo void_monitor_exit_object;
148 static public MethodInfo void_initializearray_array_fieldhandle;
149 static public MethodInfo int_getlength_int;
150 static public MethodInfo delegate_combine_delegate_delegate;
151 static public MethodInfo delegate_remove_delegate_delegate;
152 static public MethodInfo int_get_offset_to_string_data;
153 static public MethodInfo int_array_get_length;
154 static public MethodInfo int_array_get_rank;
155 static public MethodInfo object_array_clone;
156 static public MethodInfo int_array_get_length_int;
157 static public MethodInfo int_array_get_lower_bound_int;
158 static public MethodInfo int_array_get_upper_bound_int;
159 static public MethodInfo void_array_copyto_array_int;
162 // The attribute constructors.
164 static public ConstructorInfo object_ctor;
165 static public ConstructorInfo cons_param_array_attribute;
166 static public ConstructorInfo void_decimal_ctor_five_args;
167 static public ConstructorInfo unverifiable_code_ctor;
168 static public ConstructorInfo invalid_operation_ctor;
171 // Holds the Array of Assemblies that have been loaded
172 // (either because it is the default or the user used the
173 // -r command line option)
175 static Assembly [] assemblies;
178 // Keeps a list of modules. We used this to do lookups
179 // on the module using GetType -- needed for arrays
181 static Module [] modules;
184 // This is the type_cache from the assemblies to avoid
185 // hitting System.Reflection on every lookup.
187 static Hashtable types;
190 // This is used to hotld the corresponding TypeContainer objects
191 // since we need this in FindMembers
193 static Hashtable typecontainers;
196 // Keeps track of those types that are defined by the
199 static ArrayList user_types;
201 static PtrHashtable builder_to_declspace;
204 // Tracks the interfaces implemented by typebuilders. We only
205 // enter those who do implement or or more interfaces
207 static PtrHashtable builder_to_ifaces;
210 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
211 // the arguments to the method
213 static Hashtable method_arguments;
216 // Maps PropertyBuilder to a Type array that contains
217 // the arguments to the indexer
219 static Hashtable indexer_arguments;
222 // Maybe `method_arguments' should be replaced and only
223 // method_internal_params should be kept?
225 static Hashtable method_internal_params;
228 // Keeps track of attribute types
231 static Hashtable builder_to_attr;
234 // Keeps track of methods
237 static Hashtable builder_to_method;
244 public static void CleanUp ()
246 // Lets get everything clean so that we can collect before generating code
250 typecontainers = null;
252 builder_to_declspace = null;
253 builder_to_ifaces = null;
254 method_arguments = null;
255 indexer_arguments = null;
256 method_internal_params = null;
257 builder_to_attr = null;
258 builder_to_method = null;
262 negative_hits = null;
263 attr_to_allowmult = null;
264 builder_to_constant = null;
265 fieldbuilders_to_fields = null;
267 priv_fields_events = null;
270 TypeHandle.CleanUp ();
274 /// A filter for Findmembers that uses the Signature object to
277 static bool SignatureFilter (MemberInfo mi, object criteria)
279 Signature sig = (Signature) criteria;
281 if (!(mi is MethodBase))
284 if (mi.Name != sig.name)
287 int count = sig.args.Length;
289 if (mi is MethodBuilder || mi is ConstructorBuilder){
290 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
292 if (candidate_args.Length != count)
295 for (int i = 0; i < count; i++)
296 if (candidate_args [i] != sig.args [i])
301 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
303 if (pars.Length != count)
306 for (int i = 0; i < count; i++)
307 if (pars [i].ParameterType != sig.args [i])
313 // A delegate that points to the filter above.
314 static MemberFilter signature_filter;
317 // These are expressions that represent some of the internal data types, used
320 static void InitExpressionTypes ()
322 system_object_expr = new TypeLookupExpression ("System.Object");
323 system_string_expr = new TypeLookupExpression ("System.String");
324 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
325 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
326 system_single_expr = new TypeLookupExpression ("System.Single");
327 system_double_expr = new TypeLookupExpression ("System.Double");
328 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
329 system_byte_expr = new TypeLookupExpression ("System.Byte");
330 system_int16_expr = new TypeLookupExpression ("System.Int16");
331 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
332 system_int32_expr = new TypeLookupExpression ("System.Int32");
333 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
334 system_int64_expr = new TypeLookupExpression ("System.Int64");
335 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
336 system_char_expr = new TypeLookupExpression ("System.Char");
337 system_void_expr = new TypeLookupExpression ("System.Void");
338 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
339 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
340 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
343 static TypeManager ()
345 assemblies = new Assembly [0];
347 user_types = new ArrayList ();
349 types = new Hashtable ();
350 typecontainers = new Hashtable ();
352 builder_to_declspace = new PtrHashtable ();
353 builder_to_attr = new PtrHashtable ();
354 builder_to_method = new PtrHashtable ();
355 method_arguments = new PtrHashtable ();
356 method_internal_params = new PtrHashtable ();
357 indexer_arguments = new PtrHashtable ();
358 builder_to_ifaces = new PtrHashtable ();
360 NoTypes = new Type [0];
361 NoTypeExprs = new TypeExpr [0];
363 signature_filter = new MemberFilter (SignatureFilter);
364 InitExpressionTypes ();
367 public static void HandleDuplicate (string name, Type t)
369 Type prev = (Type) types [name];
370 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
374 // This probably never happens, as we catch this before
376 Report.Error (-17, "The type `" + name + "' has already been defined.");
380 tc = builder_to_declspace [t] as TypeContainer;
383 1595, "The type `" + name + "' is defined in an existing assembly;"+
384 " Using the new definition from: " + tc.Location);
387 1595, "The type `" + name + "' is defined in an existing assembly;");
390 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
396 public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
401 HandleDuplicate (name, t);
406 builder_to_ifaces [t] = ifaces;
410 // This entry point is used by types that we define under the covers
412 public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
415 builder_to_ifaces [tb] = ifaces;
418 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
420 builder_to_declspace.Add (t, tc);
421 typecontainers.Add (name, tc);
422 AddUserType (name, t, ifaces);
425 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
430 HandleDuplicate (name, t);
433 builder_to_declspace.Add (t, del);
436 public static void AddEnumType (string name, TypeBuilder t, Enum en)
441 HandleDuplicate (name, t);
443 builder_to_declspace.Add (t, en);
446 public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
448 AddUserType (name, t, ifaces);
449 builder_to_declspace.Add (t, i);
452 public static void AddMethod (MethodBuilder builder, MethodData method)
454 builder_to_method.Add (builder, method);
457 public static void RegisterAttrType (Type t, TypeContainer tc)
459 builder_to_attr.Add (t, tc);
463 /// Returns the DeclSpace whose Type is `t' or null if there is no
464 /// DeclSpace for `t' (ie, the Type comes from a library)
466 public static DeclSpace LookupDeclSpace (Type t)
468 return builder_to_declspace [t] as DeclSpace;
472 /// Returns the TypeContainer whose Type is `t' or null if there is no
473 /// TypeContainer for `t' (ie, the Type comes from a library)
475 public static TypeContainer LookupTypeContainer (Type t)
477 return builder_to_declspace [t] as TypeContainer;
480 public static IMemberContainer LookupMemberContainer (Type t)
482 if (t is TypeBuilder) {
483 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
484 if (container != null)
488 return TypeHandle.GetTypeHandle (t);
491 public static Interface LookupInterface (Type t)
493 return builder_to_declspace [t] as Interface;
496 public static Delegate LookupDelegate (Type t)
498 return builder_to_declspace [t] as Delegate;
501 public static Enum LookupEnum (Type t)
503 return builder_to_declspace [t] as Enum;
506 public static TypeContainer LookupAttr (Type t)
508 return (TypeContainer) builder_to_attr [t];
512 /// Registers an assembly to load types from.
514 public static void AddAssembly (Assembly a)
516 foreach (Assembly assembly in assemblies) {
521 int top = assemblies.Length;
522 Assembly [] n = new Assembly [top + 1];
524 assemblies.CopyTo (n, 0);
531 /// Registers a module builder to lookup types from
533 public static void AddModule (Module mb)
535 int top = modules != null ? modules.Length : 0;
536 Module [] n = new Module [top + 1];
539 modules.CopyTo (n, 0);
544 static Hashtable references = new Hashtable ();
547 // Gets the reference to T version of the Type (T&)
549 public static Type GetReferenceType (Type t)
551 return t.MakeByRefType ();
554 static Hashtable pointers = new Hashtable ();
557 // Gets the pointer to T version of the Type (T*)
559 public static Type GetPointerType (Type t)
561 string tname = t.FullName + "*";
563 Type ret = t.Assembly.GetType (tname);
566 // If the type comes from the assembly we are building
567 // We need the Hashtable, because .NET 1.1 will return different instance types
568 // every time we call ModuleBuilder.GetType.
571 if (pointers [t] == null)
572 pointers [t] = CodeGen.Module.Builder.GetType (tname);
574 ret = (Type) pointers [t];
581 // Low-level lookup, cache-less
583 static Type LookupTypeReflection (string name)
587 foreach (Assembly a in assemblies){
588 t = a.GetType (name);
593 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
594 if (ta == TypeAttributes.NotPublic ||
595 ta == TypeAttributes.NestedPrivate ||
596 ta == TypeAttributes.NestedAssembly ||
597 ta == TypeAttributes.NestedFamANDAssem){
600 // In .NET pointers turn out to be private, even if their
601 // element type is not
604 t = t.GetElementType ();
614 foreach (Module mb in modules) {
615 t = mb.GetType (name);
623 static Hashtable negative_hits = new Hashtable ();
626 // This function is used when you want to avoid the lookups, and want to go
627 // directly to the source. This will use the cache.
629 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
630 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
631 // way to test things other than doing a fullname compare
633 public static Type LookupTypeDirect (string name)
635 Type t = (Type) types [name];
639 t = LookupTypeReflection (name);
647 static readonly char [] dot_array = { '.' };
650 /// Returns the Type associated with @name, takes care of the fact that
651 /// reflection expects nested types to be separated from the main type
652 /// with a "+" instead of a "."
654 public static Type LookupType (string name)
659 // First lookup in user defined and cached values
662 t = (Type) types [name];
666 // Two thirds of the failures are caught here.
667 if (negative_hits.Contains (name))
670 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
671 string [] elements = name.Split (dot_array);
672 int count = elements.Length;
674 for (int n = 1; n <= count; n++){
675 string top_level_type = String.Join (".", elements, 0, n);
677 // One third of the failures are caught here.
678 if (negative_hits.Contains (top_level_type))
681 t = (Type) types [top_level_type];
683 t = LookupTypeReflection (top_level_type);
685 negative_hits [top_level_type] = null;
696 // We know that System.Object does not have children, and since its the parent of
697 // all the objects, it always gets probbed for inner classes.
699 if (top_level_type == "System.Object")
702 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
703 //Console.WriteLine ("Looking up: " + newt + " " + name);
704 t = LookupTypeReflection (newt);
706 negative_hits [name] = null;
711 negative_hits [name] = null;
716 /// Computes the namespaces that we import from the assemblies we reference.
718 public static void ComputeNamespaces ()
720 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
723 // First add the assembly namespaces
725 if (assembly_get_namespaces != null){
726 int count = assemblies.Length;
728 for (int i = 0; i < count; i++){
729 Assembly a = assemblies [i];
730 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
731 foreach (string ns in namespaces){
734 Namespace.LookupNamespace (ns, true);
738 foreach (Assembly a in assemblies){
739 foreach (Type t in a.GetTypes ()){
740 string ns = t.Namespace;
742 // t.Namespace returns null for <PrivateImplDetails>
743 if (ns == ""|| ns == null)
745 Namespace.LookupNamespace (ns, true);
751 public static bool NamespaceClash (string name, Location loc)
753 if (Namespace.LookupNamespace (name, false) == null)
756 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
761 /// Returns the C# name of a type if possible, or the full type name otherwise
763 static public string CSharpName (Type t)
765 return Regex.Replace (t.FullName,
767 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
768 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
769 @"Boolean|String|Void)" +
771 new MatchEvaluator (CSharpNameMatch));
774 static String CSharpNameMatch (Match match)
776 string s = match.Groups [1].Captures [0].Value;
778 Replace ("int32", "int").
779 Replace ("uint32", "uint").
780 Replace ("int16", "short").
781 Replace ("uint16", "ushort").
782 Replace ("int64", "long").
783 Replace ("uint64", "ulong").
784 Replace ("single", "float").
785 Replace ("boolean", "bool")
786 + match.Groups [2].Captures [0].Value;
790 /// Returns the signature of the method with full namespace classification
792 static public string GetFullNameSignature (MemberInfo mi)
794 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
797 static public string GetFullName (Type t)
799 string name = t.FullName.Replace ('+', '.');
801 DeclSpace tc = LookupDeclSpace (t);
802 if ((tc != null) && tc.IsGeneric) {
803 TypeParameter[] tparam = tc.TypeParameters;
805 StringBuilder sb = new StringBuilder (name);
807 for (int i = 0; i < tparam.Length; i++) {
810 sb.Append (tparam [i].Name);
813 return sb.ToString ();
814 } else if (t.HasGenericArguments) {
815 Type[] tparam = t.GetGenericArguments ();
817 StringBuilder sb = new StringBuilder (name);
819 for (int i = 0; i < tparam.Length; i++) {
822 Report.Debug (64, "TEST", i, tparam [i],
823 tparam [i].GetType (),
825 sb.Append (tparam [i].Name);
828 return sb.ToString ();
835 /// Returns the signature of the property and indexer
837 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
840 return GetFullNameSignature (pb);
843 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
844 string signature = GetFullNameSignature (mb);
845 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
846 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
850 /// Returns the signature of the method
852 static public string CSharpSignature (MethodBase mb)
857 // FIXME: We should really have a single function to do
858 // everything instead of the following 5 line pattern
860 ParameterData iparams = LookupParametersByBuilder (mb);
863 iparams = new ReflectionParameters (mb);
865 for (int i = 0; i < iparams.Count; i++) {
869 sig += iparams.ParameterDesc(i);
873 return GetFullNameSignature (mb) + sig;
877 /// Looks up a type, and aborts if it is not found. This is used
878 /// by types required by the compiler
880 static Type CoreLookupType (string name)
882 Type t = LookupTypeDirect (name);
885 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
886 Environment.Exit (0);
893 /// Returns the MethodInfo for a method named `name' defined
894 /// in type `t' which takes arguments of types `args'
896 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
900 BindingFlags flags = instance_and_static | BindingFlags.Public;
906 flags |= BindingFlags.NonPublic;
908 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
909 if (list.Count == 0) {
911 Report.Error (-19, "Can not find the core function `" + name + "'");
915 MethodInfo mi = list [0] as MethodInfo;
918 Report.Error (-19, "Can not find the core function `" + name + "'");
925 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
927 return GetMethod (t, name, args, false, report_errors);
930 static MethodInfo GetMethod (Type t, string name, Type [] args)
932 return GetMethod (t, name, args, true);
937 /// Returns the ConstructorInfo for "args"
939 static ConstructorInfo GetConstructor (Type t, Type [] args)
947 list = FindMembers (t, MemberTypes.Constructor,
948 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
949 signature_filter, sig);
950 if (list.Count == 0){
951 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
955 ConstructorInfo ci = list [0] as ConstructorInfo;
957 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
964 public static void InitEnumUnderlyingTypes ()
967 int32_type = CoreLookupType ("System.Int32");
968 int64_type = CoreLookupType ("System.Int64");
969 uint32_type = CoreLookupType ("System.UInt32");
970 uint64_type = CoreLookupType ("System.UInt64");
971 byte_type = CoreLookupType ("System.Byte");
972 sbyte_type = CoreLookupType ("System.SByte");
973 short_type = CoreLookupType ("System.Int16");
974 ushort_type = CoreLookupType ("System.UInt16");
978 /// The types have to be initialized after the initial
979 /// population of the type has happened (for example, to
980 /// bootstrap the corlib.dll
982 public static void InitCoreTypes ()
984 object_type = CoreLookupType ("System.Object");
985 value_type = CoreLookupType ("System.ValueType");
987 InitEnumUnderlyingTypes ();
989 char_type = CoreLookupType ("System.Char");
990 string_type = CoreLookupType ("System.String");
991 float_type = CoreLookupType ("System.Single");
992 double_type = CoreLookupType ("System.Double");
993 char_ptr_type = CoreLookupType ("System.Char*");
994 decimal_type = CoreLookupType ("System.Decimal");
995 bool_type = CoreLookupType ("System.Boolean");
996 enum_type = CoreLookupType ("System.Enum");
998 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
999 delegate_type = CoreLookupType ("System.Delegate");
1001 array_type = CoreLookupType ("System.Array");
1002 void_type = CoreLookupType ("System.Void");
1003 type_type = CoreLookupType ("System.Type");
1005 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1006 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1007 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1008 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1009 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1010 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1011 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1012 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1013 idisposable_type = CoreLookupType ("System.IDisposable");
1014 icloneable_type = CoreLookupType ("System.ICloneable");
1015 monitor_type = CoreLookupType ("System.Threading.Monitor");
1016 intptr_type = CoreLookupType ("System.IntPtr");
1018 attribute_type = CoreLookupType ("System.Attribute");
1019 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1020 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1021 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1022 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1023 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1024 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1027 // Sigh. Remove this before the release. Wonder what versions of Mono
1028 // people are running.
1030 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1032 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1034 void_ptr_type = CoreLookupType ("System.Void*");
1036 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1038 exception_type = CoreLookupType ("System.Exception");
1039 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1044 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1045 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1048 // When compiling corlib, store the "real" types here.
1050 if (!RootContext.StdLib) {
1051 system_int32_type = typeof (System.Int32);
1052 system_array_type = typeof (System.Array);
1053 system_type_type = typeof (System.Type);
1054 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1056 Type [] void_arg = { };
1057 system_int_array_get_length = GetMethod (
1058 system_array_type, "get_Length", void_arg);
1059 system_int_array_get_rank = GetMethod (
1060 system_array_type, "get_Rank", void_arg);
1061 system_object_array_clone = GetMethod (
1062 system_array_type, "Clone", void_arg);
1064 Type [] system_int_arg = { system_int32_type };
1065 system_int_array_get_length_int = GetMethod (
1066 system_array_type, "GetLength", system_int_arg);
1067 system_int_array_get_upper_bound_int = GetMethod (
1068 system_array_type, "GetUpperBound", system_int_arg);
1069 system_int_array_get_lower_bound_int = GetMethod (
1070 system_array_type, "GetLowerBound", system_int_arg);
1072 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1073 system_void_array_copyto_array_int = GetMethod (
1074 system_array_type, "CopyTo", system_array_int_arg);
1076 Type [] system_3_type_arg = {
1077 system_type_type, system_type_type, system_type_type };
1078 Type [] system_4_type_arg = {
1079 system_type_type, system_type_type, system_type_type, system_type_type };
1081 MethodInfo set_corlib_type_builders = GetMethod (
1082 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1083 system_4_type_arg, true, false);
1085 if (set_corlib_type_builders != null) {
1086 object[] args = new object [4];
1087 args [0] = object_type;
1088 args [1] = value_type;
1089 args [2] = enum_type;
1090 args [3] = void_type;
1092 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1094 // Compatibility for an older version of the class libs.
1095 set_corlib_type_builders = GetMethod (
1096 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1097 system_3_type_arg, true, true);
1099 if (set_corlib_type_builders == null) {
1100 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1104 object[] args = new object [3];
1105 args [0] = object_type;
1106 args [1] = value_type;
1107 args [2] = enum_type;
1109 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1113 system_object_expr.Type = object_type;
1114 system_string_expr.Type = string_type;
1115 system_boolean_expr.Type = bool_type;
1116 system_decimal_expr.Type = decimal_type;
1117 system_single_expr.Type = float_type;
1118 system_double_expr.Type = double_type;
1119 system_sbyte_expr.Type = sbyte_type;
1120 system_byte_expr.Type = byte_type;
1121 system_int16_expr.Type = short_type;
1122 system_uint16_expr.Type = ushort_type;
1123 system_int32_expr.Type = int32_type;
1124 system_uint32_expr.Type = uint32_type;
1125 system_int64_expr.Type = int64_type;
1126 system_uint64_expr.Type = uint64_type;
1127 system_char_expr.Type = char_type;
1128 system_void_expr.Type = void_type;
1129 system_asynccallback_expr.Type = asynccallback_type;
1130 system_iasyncresult_expr.Type = iasyncresult_type;
1131 system_valuetype_expr.Type = value_type;
1135 // The helper methods that are used by the compiler
1137 public static void InitCodeHelpers ()
1140 // Now load the default methods that we use.
1142 Type [] string_string = { string_type, string_type };
1143 string_concat_string_string = GetMethod (
1144 string_type, "Concat", string_string);
1145 Type [] string_string_string = { string_type, string_type, string_type };
1146 string_concat_string_string_string = GetMethod (
1147 string_type, "Concat", string_string_string);
1148 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1149 string_concat_string_string_string_string = GetMethod (
1150 string_type, "Concat", string_string_string_string);
1152 Type [] object_object = { object_type, object_type };
1153 string_concat_object_object = GetMethod (
1154 string_type, "Concat", object_object);
1156 Type [] string_ = { string_type };
1157 string_isinterneted_string = GetMethod (
1158 string_type, "IsInterned", string_);
1160 Type [] runtime_type_handle = { runtime_handle_type };
1161 system_type_get_type_from_handle = GetMethod (
1162 type_type, "GetTypeFromHandle", runtime_type_handle);
1164 Type [] delegate_delegate = { delegate_type, delegate_type };
1165 delegate_combine_delegate_delegate = GetMethod (
1166 delegate_type, "Combine", delegate_delegate);
1168 delegate_remove_delegate_delegate = GetMethod (
1169 delegate_type, "Remove", delegate_delegate);
1174 Type [] void_arg = { };
1175 object_getcurrent_void = GetMethod (
1176 ienumerator_type, "get_Current", void_arg);
1177 bool_movenext_void = GetMethod (
1178 ienumerator_type, "MoveNext", void_arg);
1179 void_reset_void = GetMethod (
1180 ienumerator_type, "Reset", void_arg);
1181 void_dispose_void = GetMethod (
1182 idisposable_type, "Dispose", void_arg);
1183 int_get_offset_to_string_data = GetMethod (
1184 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1185 int_array_get_length = GetMethod (
1186 array_type, "get_Length", void_arg);
1187 int_array_get_rank = GetMethod (
1188 array_type, "get_Rank", void_arg);
1189 ienumerable_getenumerator_void = GetMethod (
1190 ienumerable_type, "GetEnumerator", void_arg);
1195 Type [] int_arg = { int32_type };
1196 int_array_get_length_int = GetMethod (
1197 array_type, "GetLength", int_arg);
1198 int_array_get_upper_bound_int = GetMethod (
1199 array_type, "GetUpperBound", int_arg);
1200 int_array_get_lower_bound_int = GetMethod (
1201 array_type, "GetLowerBound", int_arg);
1204 // System.Array methods
1206 object_array_clone = GetMethod (
1207 array_type, "Clone", void_arg);
1208 Type [] array_int_arg = { array_type, int32_type };
1209 void_array_copyto_array_int = GetMethod (
1210 array_type, "CopyTo", array_int_arg);
1215 Type [] object_arg = { object_type };
1216 void_monitor_enter_object = GetMethod (
1217 monitor_type, "Enter", object_arg);
1218 void_monitor_exit_object = GetMethod (
1219 monitor_type, "Exit", object_arg);
1221 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1223 void_initializearray_array_fieldhandle = GetMethod (
1224 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1229 int_getlength_int = GetMethod (
1230 array_type, "GetLength", int_arg);
1233 // Decimal constructors
1235 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1236 void_decimal_ctor_five_args = GetConstructor (
1237 decimal_type, dec_arg);
1242 cons_param_array_attribute = GetConstructor (
1243 param_array_type, void_arg);
1245 unverifiable_code_ctor = GetConstructor (
1246 unverifiable_code_type, void_arg);
1249 // InvalidOperationException
1251 invalid_operation_ctor = GetConstructor (
1252 invalid_operation_exception_type, void_arg);
1256 object_ctor = GetConstructor (object_type, void_arg);
1260 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1263 /// This is the "old", non-cache based FindMembers() function. We cannot use
1264 /// the cache here because there is no member name argument.
1266 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1267 MemberFilter filter, object criteria)
1269 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1272 // `builder_to_declspace' contains all dynamic types.
1276 Timer.StartTimer (TimerType.FindMembers);
1277 list = decl.FindMembers (mt, bf, filter, criteria);
1278 Timer.StopTimer (TimerType.FindMembers);
1283 // We have to take care of arrays specially, because GetType on
1284 // a TypeBuilder array will return a Type, not a TypeBuilder,
1285 // and we can not call FindMembers on this type.
1287 if (t.IsSubclassOf (TypeManager.array_type))
1288 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1291 // Since FindMembers will not lookup both static and instance
1292 // members, we emulate this behaviour here.
1294 if ((bf & instance_and_static) == instance_and_static){
1295 MemberInfo [] i_members = t.FindMembers (
1296 mt, bf & ~BindingFlags.Static, filter, criteria);
1298 int i_len = i_members.Length;
1300 MemberInfo one = i_members [0];
1303 // If any of these are present, we are done!
1305 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1306 return new MemberList (i_members);
1309 MemberInfo [] s_members = t.FindMembers (
1310 mt, bf & ~BindingFlags.Instance, filter, criteria);
1312 int s_len = s_members.Length;
1313 if (i_len > 0 || s_len > 0)
1314 return new MemberList (i_members, s_members);
1317 return new MemberList (i_members);
1319 return new MemberList (s_members);
1323 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1328 /// This method is only called from within MemberLookup. It tries to use the member
1329 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1330 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1331 /// our return value will already contain all inherited members and the caller don't need
1332 /// to check base classes and interfaces anymore.
1334 private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1335 string name, int num_type_arguments,
1336 out bool used_cache)
1339 // We have to take care of arrays specially, because GetType on
1340 // a TypeBuilder array will return a Type, not a TypeBuilder,
1341 // and we can not call FindMembers on this type.
1343 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1345 return TypeHandle.ArrayType.MemberCache.FindMembers (
1346 mt, bf, name, FilterWithClosure_delegate, null);
1350 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1351 // and we can ask the DeclSpace for the MemberCache.
1353 if (t is TypeBuilder) {
1354 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1355 MemberCache cache = decl.MemberCache;
1358 // If this DeclSpace has a MemberCache, use it.
1361 if (cache != null) {
1363 return cache.FindMembers (
1364 mt, bf, name, FilterWithClosure_delegate, null);
1367 // If there is no MemberCache, we need to use the "normal" FindMembers.
1370 Timer.StartTimer (TimerType.FindMembers);
1371 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1372 FilterWithClosure_delegate, name);
1373 Timer.StopTimer (TimerType.FindMembers);
1379 // This call will always succeed. There is exactly one TypeHandle instance per
1380 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1381 // if it didn't already exist.
1383 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1386 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1389 public static bool IsBuiltinType (Type t)
1391 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1392 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1393 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1394 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1401 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1402 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1404 public static bool IsCLRType (Type t)
1406 if (t == object_type || t == int32_type || t == uint32_type ||
1407 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1408 t == char_type || t == short_type || t == bool_type ||
1409 t == sbyte_type || t == byte_type || t == ushort_type)
1415 public static bool IsDelegateType (Type t)
1417 if (t.IsSubclassOf (TypeManager.delegate_type))
1423 public static bool IsEnumType (Type t)
1425 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1430 public static bool IsBuiltinOrEnum (Type t)
1432 if (IsBuiltinType (t))
1442 // Only a quick hack to get things moving, while real runtime support appears
1444 public static bool IsGeneric (Type t)
1446 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1448 return ds.IsGeneric;
1451 public static int GetNumberOfTypeArguments (Type t)
1453 DeclSpace tc = LookupDeclSpace (t);
1455 return tc.IsGeneric ? tc.CountTypeParameters : 0;
1457 return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1460 public static Type[] GetTypeArguments (Type t)
1462 DeclSpace tc = LookupDeclSpace (t);
1465 throw new InvalidOperationException ();
1467 TypeParameter[] tparam = tc.TypeParameters;
1468 Type[] ret = new Type [tparam.Length];
1469 for (int i = 0; i < tparam.Length; i++) {
1470 ret [i] = tparam [i].Type;
1471 if (ret [i] == null)
1472 throw new InternalErrorException ();
1477 return t.GetGenericArguments ();
1480 public static bool CheckGeneric (Type t, int num_type_arguments)
1482 if (num_type_arguments < 0)
1485 DeclSpace tc = LookupDeclSpace (t);
1489 return num_type_arguments == 0;
1491 if (num_type_arguments == 0)
1494 if (num_type_arguments != tc.CountTypeParameters)
1497 if (!t.HasGenericArguments)
1498 return num_type_arguments == 0;
1500 if (num_type_arguments == 0)
1503 if (num_type_arguments != t.GetGenericArguments ().Length)
1511 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1513 public static bool IsUnmanagedType (Type t)
1515 if (IsBuiltinType (t) && t != TypeManager.string_type)
1524 if (IsValueType (t)){
1525 if (t is TypeBuilder){
1526 TypeContainer tc = LookupTypeContainer (t);
1528 foreach (Field f in tc.Fields){
1529 if (f.FieldBuilder.IsStatic)
1531 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1535 FieldInfo [] fields = t.GetFields ();
1537 foreach (FieldInfo f in fields){
1540 if (!IsUnmanagedType (f.FieldType))
1550 public static bool IsValueType (Type t)
1552 return t.IsGenericParameter || t.IsValueType;
1555 public static bool IsInterfaceType (Type t)
1557 Interface iface = builder_to_declspace [t] as Interface;
1565 public static bool IsEqualGenericType (Type a, Type b)
1567 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1569 // `a' is a generic type definition's TypeBuilder and `b' is a
1570 // generic instance of the same type.
1576 // void Test (Stack<T> stack) { }
1579 // The first argument of `Test' will be the generic instance
1580 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1582 if (a != b.GetGenericTypeDefinition ())
1585 Type[] aparams = a.GetGenericArguments ();
1586 Type[] bparams = b.GetGenericArguments ();
1588 if (aparams.Length != bparams.Length)
1591 for (int i = 0; i < aparams.Length; i++)
1592 if (!aparams [i].Equals (bparams [i]))
1601 public static bool IsEqual (Type a, Type b)
1606 return IsEqualGenericType (a, b);
1609 static bool MayBecomeEqualGenericTypes (Type a, Type b)
1611 if (a.IsGenericParameter) {
1613 // If b is a generic parameter or an actual type,
1614 // they may become equal:
1616 // class X<T,U> : I<T>, I<U>
1617 // class X<T> : I<T>, I<float>
1619 if (b.IsGenericParameter || !b.IsGenericInstance)
1623 // We're now comparing a type parameter with a
1624 // generic instance. They may become equal unless
1625 // the type parameter appears anywhere in the
1626 // generic instance:
1628 // class X<T,U> : I<T>, I<X<U>>
1629 // -> error because you could instanciate it as
1632 // class X<T> : I<T>, I<X<T>> -> ok
1635 Type[] bargs = GetTypeArguments (b);
1636 for (int i = 0; i < bargs.Length; i++) {
1637 if (a.Equals (bargs [i]))
1644 if (b.IsGenericParameter)
1645 return MayBecomeEqualGenericTypes (b, a);
1648 // At this point, neither a nor b are a type parameter.
1650 // If one of them is a generic instance, let
1651 // MayBecomeEqualGenericInstances() compare them (if the
1652 // other one is not a generic instance, they can never
1656 if (a.IsGenericInstance || b.IsGenericInstance)
1657 return MayBecomeEqualGenericInstances (a, b);
1660 // Ok, two ordinary types.
1663 return a.Equals (b);
1667 // Checks whether two generic instances may become equal for some
1668 // particular instantiation (26.3.1).
1670 public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1672 if (!a.IsGenericInstance || !b.IsGenericInstance)
1674 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1677 Type[] aargs = GetTypeArguments (a);
1678 Type[] bargs = GetTypeArguments (b);
1680 if (aargs.Length != bargs.Length)
1683 for (int i = 0; i < aargs.Length; i++) {
1684 if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1692 // Checks whether `type' is a subclass or nested child of `parent'.
1694 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1697 if ((type == parent) || type.IsSubclassOf (parent) ||
1698 IsEqualGenericType (type, parent))
1701 // Handle nested types.
1702 type = type.DeclaringType;
1703 } while (type != null);
1709 // Checks whether `type' is a nested child of `parent'.
1711 public static bool IsNestedChildOf (Type type, Type parent)
1716 type = type.DeclaringType;
1717 while (type != null) {
1721 type = type.DeclaringType;
1728 // Do the right thing when returning the element type of an
1729 // array type based on whether we are compiling corlib or not
1731 public static Type GetElementType (Type t)
1733 if (RootContext.StdLib)
1734 return t.GetElementType ();
1736 return TypeToCoreType (t.GetElementType ());
1740 /// Returns the User Defined Types
1742 public static ArrayList UserTypes {
1748 public static Hashtable TypeContainers {
1750 return typecontainers;
1754 static Hashtable attr_to_allowmult;
1756 public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1758 if (attr_to_allowmult == null)
1759 attr_to_allowmult = new PtrHashtable ();
1761 if (attr_to_allowmult.Contains (attr_type))
1764 attr_to_allowmult.Add (attr_type, allow);
1768 public static bool AreMultipleAllowed (Type attr_type)
1770 if (!(attr_type is TypeBuilder)) {
1771 System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1773 foreach (System.Attribute tmp in attrs)
1774 if (tmp is AttributeUsageAttribute) {
1775 return ((AttributeUsageAttribute) tmp).AllowMultiple;
1781 if (attr_to_allowmult == null)
1784 return (bool) attr_to_allowmult [attr_type];
1787 static Hashtable builder_to_constant;
1789 public static void RegisterConstant (FieldBuilder fb, Const c)
1791 if (builder_to_constant == null)
1792 builder_to_constant = new PtrHashtable ();
1794 if (builder_to_constant.Contains (fb))
1797 builder_to_constant.Add (fb, c);
1800 public static Const LookupConstant (FieldBuilder fb)
1802 if (builder_to_constant == null)
1805 return (Const) builder_to_constant [fb];
1809 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1813 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1814 /// for anything which is dynamic, and we need this in a number of places,
1815 /// we register this information here, and use it afterwards.
1817 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1822 method_arguments.Add (mb, args);
1823 method_internal_params.Add (mb, ip);
1828 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1830 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1833 if (method_internal_params.Contains (mb))
1834 return (InternalParameters) method_internal_params [mb];
1836 throw new Exception ("Argument for Method not registered" + mb);
1840 /// Returns the argument types for a method based on its methodbase
1842 /// For dynamic methods, we use the compiler provided types, for
1843 /// methods from existing assemblies we load them from GetParameters,
1844 /// and insert them into the cache
1846 static public Type [] GetArgumentTypes (MethodBase mb)
1848 if (method_arguments.Contains (mb))
1849 return (Type []) method_arguments [mb];
1851 ParameterInfo [] pi = mb.GetParameters ();
1853 Type [] types = new Type [c];
1855 for (int i = 0; i < c; i++)
1856 types [i] = pi [i].ParameterType;
1858 method_arguments.Add (mb, types);
1864 /// Returns the argument types for an indexer based on its PropertyInfo
1866 /// For dynamic indexers, we use the compiler provided types, for
1867 /// indexers from existing assemblies we load them from GetParameters,
1868 /// and insert them into the cache
1870 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1872 if (indexer_arguments.Contains (indexer))
1873 return (Type []) indexer_arguments [indexer];
1874 else if (indexer is PropertyBuilder)
1875 // If we're a PropertyBuilder and not in the
1876 // `indexer_arguments' hash, then we're a property and
1880 ParameterInfo [] pi = indexer.GetIndexParameters ();
1881 // Property, not an indexer.
1885 Type [] types = new Type [c];
1887 for (int i = 0; i < c; i++)
1888 types [i] = pi [i].ParameterType;
1890 indexer_arguments.Add (indexer, types);
1896 // This is a workaround the fact that GetValue is not
1897 // supported for dynamic types
1899 static Hashtable fields = new Hashtable ();
1900 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1902 if (fields.Contains (fb))
1905 fields.Add (fb, value);
1910 static public object GetValue (FieldBuilder fb)
1915 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1916 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1918 if (fieldbuilders_to_fields.Contains (fb))
1921 fieldbuilders_to_fields.Add (fb, f);
1926 // The return value can be null; This will be the case for
1927 // auxiliary FieldBuilders created by the compiler that have no
1928 // real field being declared on the source code
1930 static public FieldBase GetField (FieldInfo fb)
1932 return (FieldBase) fieldbuilders_to_fields [fb];
1935 static Hashtable events;
1937 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1940 events = new Hashtable ();
1942 if (events.Contains (eb))
1945 events.Add (eb, new Pair (add, remove));
1950 static public MethodInfo GetAddMethod (EventInfo ei)
1952 if (ei is MyEventBuilder) {
1953 Pair pair = (Pair) events [ei];
1955 return (MethodInfo) pair.First;
1957 return ei.GetAddMethod ();
1960 static public MethodInfo GetRemoveMethod (EventInfo ei)
1962 if (ei is MyEventBuilder) {
1963 Pair pair = (Pair) events [ei];
1965 return (MethodInfo) pair.Second;
1967 return ei.GetRemoveMethod ();
1970 static Hashtable priv_fields_events;
1972 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1974 if (priv_fields_events == null)
1975 priv_fields_events = new Hashtable ();
1977 if (priv_fields_events.Contains (einfo))
1980 priv_fields_events.Add (einfo, builder);
1985 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1987 if (priv_fields_events == null)
1990 return (MemberInfo) priv_fields_events [ei];
1993 static Hashtable properties;
1995 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1997 if (properties == null)
1998 properties = new Hashtable ();
2000 if (properties.Contains (pb))
2003 properties.Add (pb, new Pair (get, set));
2008 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2009 MethodBase set, Type[] args)
2011 if (!RegisterProperty (pb, get,set))
2014 indexer_arguments.Add (pb, args);
2020 /// Given an array of interface types, expand and eliminate repeated ocurrences
2021 /// of an interface.
2025 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2028 public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
2030 ArrayList new_ifaces = new ArrayList ();
2032 foreach (TypeExpr iface in base_interfaces){
2033 if (!new_ifaces.Contains (iface))
2034 new_ifaces.Add (iface);
2036 TypeExpr [] implementing = iface.GetInterfaces ();
2038 foreach (TypeExpr imp in implementing){
2039 if (!new_ifaces.Contains (imp))
2040 new_ifaces.Add (imp);
2043 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
2044 new_ifaces.CopyTo (ret, 0);
2048 static PtrHashtable iface_cache = new PtrHashtable ();
2051 /// This function returns the interfaces in the type `t'. Works with
2052 /// both types and TypeBuilders.
2054 public static TypeExpr [] GetInterfaces (Type t)
2057 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
2062 // The reason for catching the Array case is that Reflection.Emit
2063 // will not return a TypeBuilder for Array types of TypeBuilder types,
2064 // but will still throw an exception if we try to call GetInterfaces
2067 // Since the array interfaces are always constant, we return those for
2072 t = TypeManager.array_type;
2074 if (t is TypeBuilder){
2075 TypeExpr [] parent_ifaces;
2077 if (t.BaseType == null)
2078 parent_ifaces = NoTypeExprs;
2080 parent_ifaces = GetInterfaces (t.BaseType);
2081 TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2082 if (type_ifaces == null)
2083 type_ifaces = NoTypeExprs;
2085 int parent_count = parent_ifaces.Length;
2086 TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2087 parent_ifaces.CopyTo (result, 0);
2088 type_ifaces.CopyTo (result, parent_count);
2090 iface_cache [t] = result;
2093 Type [] ifaces = t.GetInterfaces ();
2094 if (ifaces.Length == 0)
2097 TypeExpr [] result = new TypeExpr [ifaces.Length];
2098 for (int i = 0; i < ifaces.Length; i++)
2099 result [i] = new TypeExpression (ifaces [i], Location.Null);
2101 iface_cache [t] = result;
2107 // gets the interfaces that are declared explicitly on t
2109 public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2111 return (TypeExpr []) builder_to_ifaces [t];
2115 /// The following is used to check if a given type implements an interface.
2116 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2118 public static bool ImplementsInterface (Type t, Type iface)
2120 TypeExpr [] interfaces;
2123 // FIXME OPTIMIZATION:
2124 // as soon as we hit a non-TypeBuiler in the interface
2125 // chain, we could return, as the `Type.GetInterfaces'
2126 // will return all the interfaces implement by the type
2130 interfaces = GetInterfaces (t);
2132 if (interfaces != null){
2133 foreach (TypeExpr i in interfaces){
2134 if (i.Type == iface)
2140 } while (t != null);
2145 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2147 // This is a custom version of Convert.ChangeType() which works
2148 // with the TypeBuilder defined types when compiling corlib.
2149 public static object ChangeType (object value, Type conversionType, out bool error)
2151 IConvertible convert_value = value as IConvertible;
2153 if (convert_value == null){
2159 // We must use Type.Equals() here since `conversionType' is
2160 // the TypeBuilder created version of a system type and not
2161 // the system type itself. You cannot use Type.GetTypeCode()
2162 // on such a type - it'd always return TypeCode.Object.
2166 if (conversionType.Equals (typeof (Boolean)))
2167 return (object)(convert_value.ToBoolean (nf_provider));
2168 else if (conversionType.Equals (typeof (Byte)))
2169 return (object)(convert_value.ToByte (nf_provider));
2170 else if (conversionType.Equals (typeof (Char)))
2171 return (object)(convert_value.ToChar (nf_provider));
2172 else if (conversionType.Equals (typeof (DateTime)))
2173 return (object)(convert_value.ToDateTime (nf_provider));
2174 else if (conversionType.Equals (typeof (Decimal)))
2175 return (object)(convert_value.ToDecimal (nf_provider));
2176 else if (conversionType.Equals (typeof (Double)))
2177 return (object)(convert_value.ToDouble (nf_provider));
2178 else if (conversionType.Equals (typeof (Int16)))
2179 return (object)(convert_value.ToInt16 (nf_provider));
2180 else if (conversionType.Equals (typeof (Int32)))
2181 return (object)(convert_value.ToInt32 (nf_provider));
2182 else if (conversionType.Equals (typeof (Int64)))
2183 return (object)(convert_value.ToInt64 (nf_provider));
2184 else if (conversionType.Equals (typeof (SByte)))
2185 return (object)(convert_value.ToSByte (nf_provider));
2186 else if (conversionType.Equals (typeof (Single)))
2187 return (object)(convert_value.ToSingle (nf_provider));
2188 else if (conversionType.Equals (typeof (String)))
2189 return (object)(convert_value.ToString (nf_provider));
2190 else if (conversionType.Equals (typeof (UInt16)))
2191 return (object)(convert_value.ToUInt16 (nf_provider));
2192 else if (conversionType.Equals (typeof (UInt32)))
2193 return (object)(convert_value.ToUInt32 (nf_provider));
2194 else if (conversionType.Equals (typeof (UInt64)))
2195 return (object)(convert_value.ToUInt64 (nf_provider));
2196 else if (conversionType.Equals (typeof (Object)))
2197 return (object)(value);
2207 // This is needed, because enumerations from assemblies
2208 // do not report their underlyingtype, but they report
2211 public static Type EnumToUnderlying (Type t)
2213 if (t == TypeManager.enum_type)
2216 t = t.UnderlyingSystemType;
2217 if (!TypeManager.IsEnumType (t))
2220 if (t is TypeBuilder) {
2221 // slow path needed to compile corlib
2222 if (t == TypeManager.bool_type ||
2223 t == TypeManager.byte_type ||
2224 t == TypeManager.sbyte_type ||
2225 t == TypeManager.char_type ||
2226 t == TypeManager.short_type ||
2227 t == TypeManager.ushort_type ||
2228 t == TypeManager.int32_type ||
2229 t == TypeManager.uint32_type ||
2230 t == TypeManager.int64_type ||
2231 t == TypeManager.uint64_type)
2233 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2235 TypeCode tc = Type.GetTypeCode (t);
2238 case TypeCode.Boolean:
2239 return TypeManager.bool_type;
2241 return TypeManager.byte_type;
2242 case TypeCode.SByte:
2243 return TypeManager.sbyte_type;
2245 return TypeManager.char_type;
2246 case TypeCode.Int16:
2247 return TypeManager.short_type;
2248 case TypeCode.UInt16:
2249 return TypeManager.ushort_type;
2250 case TypeCode.Int32:
2251 return TypeManager.int32_type;
2252 case TypeCode.UInt32:
2253 return TypeManager.uint32_type;
2254 case TypeCode.Int64:
2255 return TypeManager.int64_type;
2256 case TypeCode.UInt64:
2257 return TypeManager.uint64_type;
2259 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2263 // When compiling corlib and called with one of the core types, return
2264 // the corresponding typebuilder for that type.
2266 public static Type TypeToCoreType (Type t)
2268 if (RootContext.StdLib || (t is TypeBuilder))
2271 TypeCode tc = Type.GetTypeCode (t);
2274 case TypeCode.Boolean:
2275 return TypeManager.bool_type;
2277 return TypeManager.byte_type;
2278 case TypeCode.SByte:
2279 return TypeManager.sbyte_type;
2281 return TypeManager.char_type;
2282 case TypeCode.Int16:
2283 return TypeManager.short_type;
2284 case TypeCode.UInt16:
2285 return TypeManager.ushort_type;
2286 case TypeCode.Int32:
2287 return TypeManager.int32_type;
2288 case TypeCode.UInt32:
2289 return TypeManager.uint32_type;
2290 case TypeCode.Int64:
2291 return TypeManager.int64_type;
2292 case TypeCode.UInt64:
2293 return TypeManager.uint64_type;
2294 case TypeCode.Single:
2295 return TypeManager.float_type;
2296 case TypeCode.Double:
2297 return TypeManager.double_type;
2298 case TypeCode.String:
2299 return TypeManager.string_type;
2301 if (t == typeof (void))
2302 return TypeManager.void_type;
2303 if (t == typeof (object))
2304 return TypeManager.object_type;
2305 if (t == typeof (System.Type))
2306 return TypeManager.type_type;
2312 /// Utility function that can be used to probe whether a type
2313 /// is managed or not.
2315 public static bool VerifyUnManaged (Type t, Location loc)
2317 if (t.IsValueType || t.IsPointer){
2319 // FIXME: this is more complex, we actually need to
2320 // make sure that the type does not contain any
2326 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2327 // We need this explicit check here to make it work when
2328 // compiling corlib.
2333 "Cannot take the address or size of a variable of a managed type ('" +
2334 CSharpName (t) + "')");
2339 /// Returns the name of the indexer in a given type.
2342 /// The default is not always `Item'. The user can change this behaviour by
2343 /// using the DefaultMemberAttribute in the class.
2345 /// For example, the String class indexer is named `Chars' not `Item'
2347 public static string IndexerPropertyName (Type t)
2349 if (t.IsGenericInstance)
2350 t = t.GetGenericTypeDefinition ();
2352 if (t is TypeBuilder) {
2353 if (t.IsInterface) {
2354 Interface i = LookupInterface (t);
2356 if ((i == null) || (i.IndexerName == null))
2359 return i.IndexerName;
2361 TypeContainer tc = LookupTypeContainer (t);
2363 if ((tc == null) || (tc.IndexerName == null))
2366 return tc.IndexerName;
2370 System.Attribute attr = System.Attribute.GetCustomAttribute (
2371 t, TypeManager.default_member_type);
2373 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2374 return dma.MemberName;
2380 public static void MakePinned (LocalBuilder builder)
2383 // FIXME: Flag the "LocalBuilder" type as being
2384 // pinned. Figure out API.
2390 // Returns whether the array of memberinfos contains the given method
2392 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2394 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2396 foreach (MethodBase method in array) {
2397 if (method.Name != new_method.Name)
2400 if (method is MethodInfo && new_method is MethodInfo)
2401 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2405 Type [] old_args = TypeManager.GetArgumentTypes (method);
2406 int old_count = old_args.Length;
2409 if (new_args.Length != old_count)
2412 for (i = 0; i < old_count; i++){
2413 if (old_args [i] != new_args [i])
2426 // We copy methods from `new_members' into `target_list' if the signature
2427 // for the method from in the new list does not exist in the target_list
2429 // The name is assumed to be the same.
2431 public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
2433 if (target_list == null){
2434 target_list = new ArrayList ();
2436 foreach (MemberInfo mi in new_members){
2437 if (mi is MethodBase)
2438 target_list.Add (mi);
2443 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2444 target_list.CopyTo (target_array, 0);
2446 foreach (MemberInfo mi in new_members){
2447 MethodBase new_method = (MethodBase) mi;
2449 if (!ArrayContainsMethod (target_array, new_method))
2450 target_list.Add (new_method);
2456 public enum MethodFlags {
2458 IsObsoleteError = 1 << 1,
2459 ShouldIgnore = 1 << 2
2463 // Returns the TypeManager.MethodFlags for this method.
2464 // This emits an error 619 / warning 618 if the method is obsolete.
2465 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2467 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2469 MethodFlags flags = 0;
2471 if (mb.DeclaringType is TypeBuilder){
2472 MethodData method = (MethodData) builder_to_method [mb];
2473 if (method == null) {
2474 // FIXME: implement Obsolete attribute on Property,
2475 // Indexer and Event.
2479 return method.GetMethodFlags (loc);
2483 if (mb.IsInflatedGeneric) {
2484 MethodBase generic = mb.GetGenericMethodDefinition ();
2486 return GetMethodFlags (generic, loc);
2490 object [] attrs = mb.GetCustomAttributes (true);
2491 foreach (object ta in attrs){
2492 if (!(ta is System.Attribute)){
2493 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2496 System.Attribute a = (System.Attribute) ta;
2497 if (a.TypeId == TypeManager.obsolete_attribute_type){
2498 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2500 string method_desc = TypeManager.CSharpSignature (mb);
2503 Report.Error (619, loc, "Method `" + method_desc +
2504 "' is obsolete: `" + oa.Message + "'");
2505 return MethodFlags.IsObsoleteError;
2507 Report.Warning (618, loc, "Method `" + method_desc +
2508 "' is obsolete: `" + oa.Message + "'");
2510 flags |= MethodFlags.IsObsolete;
2516 // Skip over conditional code.
2518 if (a.TypeId == TypeManager.conditional_attribute_type){
2519 ConditionalAttribute ca = (ConditionalAttribute) a;
2521 if (RootContext.AllDefines [ca.ConditionString] == null)
2522 flags |= MethodFlags.ShouldIgnore;
2529 #region MemberLookup implementation
2532 // Whether we allow private members in the result (since FindMembers
2533 // uses NonPublic for both protected and private), we need to distinguish.
2535 static bool closure_private_ok;
2538 // Who is invoking us and which type is being queried currently.
2540 static Type closure_invocation_type;
2541 static Type closure_qualifier_type;
2542 static int closure_num_type_arguments;
2545 // The assembly that defines the type is that is calling us
2547 static Assembly closure_invocation_assembly;
2549 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2555 // This filter filters by name + whether it is ok to include private
2556 // members in the search
2558 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2561 // Hack: we know that the filter criteria will always be in the `closure'
2565 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2569 return TypeManager.CheckGeneric ((Type) m, closure_num_type_arguments);
2571 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2572 (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
2576 // Ugly: we need to find out the type of `m', and depending
2577 // on this, tell whether we accept or not
2579 if (m is MethodBase){
2580 MethodBase mb = (MethodBase) m;
2581 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2583 if (ma == MethodAttributes.Private)
2584 return closure_private_ok ||
2585 IsEqual (closure_invocation_type, m.DeclaringType) ||
2586 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2589 // FamAndAssem requires that we not only derivate, but we are on the
2592 if (ma == MethodAttributes.FamANDAssem){
2593 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2597 // Assembly and FamORAssem succeed if we're in the same assembly.
2598 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2599 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2603 // We already know that we aren't in the same assembly.
2604 if (ma == MethodAttributes.Assembly)
2607 // Family and FamANDAssem require that we derive.
2608 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2609 if (closure_invocation_type == null)
2612 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2615 // Although a derived class can access protected members of its base class
2616 // it cannot do so through an instance of the base class (CS1540).
2617 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2618 (closure_qualifier_type != null) &&
2619 closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2629 if (m is FieldInfo){
2630 FieldInfo fi = (FieldInfo) m;
2631 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2633 if (fa == FieldAttributes.Private)
2634 return closure_private_ok ||
2635 IsEqual (closure_invocation_type, m.DeclaringType) ||
2636 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2639 // FamAndAssem requires that we not only derivate, but we are on the
2642 if (fa == FieldAttributes.FamANDAssem){
2643 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2647 // Assembly and FamORAssem succeed if we're in the same assembly.
2648 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2649 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2653 // We already know that we aren't in the same assembly.
2654 if (fa == FieldAttributes.Assembly)
2657 // Family and FamANDAssem require that we derive.
2658 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2659 if (closure_invocation_type == null)
2662 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2665 // Although a derived class can access protected members of its base class
2666 // it cannot do so through an instance of the base class (CS1540).
2667 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2668 (closure_qualifier_type != null) &&
2669 closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2680 // EventInfos and PropertyInfos, return true because they lack permission
2681 // informaiton, so we need to check later on the methods.
2686 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2687 static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2690 // Looks up a member called `name' in the `queried_type'. This lookup
2691 // is done by code that is contained in the definition for `invocation_type'
2692 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2694 // `invocation_type' is used to check whether we're allowed to access the requested
2695 // member wrt its protection level.
2697 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2698 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2699 // is B and qualifier_type is A). This is used to do the CS1540 check.
2701 // When resolving a SimpleName, `qualifier_type' is null.
2703 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2704 // the same than `queried_type' - except when we're being called from BaseAccess;
2705 // in this case, `invocation_type' is the current type and `queried_type' the base
2706 // type, so this'd normally trigger a CS1540.
2708 // The binding flags are `bf' and the kind of members being looked up are `mt'
2710 // The return value always includes private members which code in `invocation_type'
2711 // is allowed to access (using the specified `qualifier_type' if given); only use
2712 // BindingFlags.NonPublic to bypass the permission check.
2714 // Returns an array of a single element for everything but Methods/Constructors
2715 // that might return multiple matches.
2717 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2718 Type queried_type, int num_type_arguments,
2719 MemberTypes mt, BindingFlags original_bf,
2722 Timer.StartTimer (TimerType.MemberLookup);
2724 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2725 queried_type, num_type_arguments,
2726 mt, original_bf, name);
2728 Timer.StopTimer (TimerType.MemberLookup);
2733 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2734 Type queried_type, int num_type_arguments,
2735 MemberTypes mt, BindingFlags original_bf,
2738 BindingFlags bf = original_bf;
2740 ArrayList method_list = null;
2741 Type current_type = queried_type;
2742 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2743 bool skip_iface_check = true, used_cache = false;
2744 bool always_ok_flag = false;
2746 closure_invocation_type = invocation_type;
2747 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2748 closure_qualifier_type = qualifier_type;
2750 closure_num_type_arguments = num_type_arguments;
2753 // If we are a nested class, we always have access to our container
2756 if (invocation_type != null){
2757 string invocation_name = invocation_type.FullName;
2758 if (invocation_name.IndexOf ('+') != -1){
2759 string container = queried_type.FullName + "+";
2760 int container_length = container.Length;
2762 if (invocation_name.Length > container_length){
2763 string shared = invocation_name.Substring (0, container_length);
2765 if (shared == container)
2766 always_ok_flag = true;
2775 // `NonPublic' is lame, because it includes both protected and
2776 // private methods, so we need to control this behavior by
2777 // explicitly tracking if a private method is ok or not.
2779 // The possible cases are:
2780 // public, private and protected (internal does not come into the
2783 if ((invocation_type != null) &&
2784 ((invocation_type == current_type) ||
2785 IsNestedChildOf (invocation_type, current_type)) ||
2787 bf = original_bf | BindingFlags.NonPublic;
2791 closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2793 Timer.StopTimer (TimerType.MemberLookup);
2795 list = MemberLookup_FindMembers (current_type, mt, bf, name,
2796 num_type_arguments, out used_cache);
2798 Timer.StartTimer (TimerType.MemberLookup);
2801 // When queried for an interface type, the cache will automatically check all
2802 // inherited members, so we don't need to do this here. However, this only
2803 // works if we already used the cache in the first iteration of this loop.
2805 // If we used the cache in any further iteration, we can still terminate the
2806 // loop since the cache always looks in all parent classes.
2812 skip_iface_check = false;
2814 if (current_type == TypeManager.object_type)
2817 current_type = current_type.BaseType;
2820 // This happens with interfaces, they have a null
2821 // basetype. Look members up in the Object class.
2823 if (current_type == null)
2824 current_type = TypeManager.object_type;
2827 if (list.Count == 0)
2831 // Events and types are returned by both `static' and `instance'
2832 // searches, which means that our above FindMembers will
2833 // return two copies of the same.
2835 if (list.Count == 1 && !(list [0] is MethodBase)){
2836 return (MemberInfo []) list;
2840 // Multiple properties: we query those just to find out the indexer
2843 if (list [0] is PropertyInfo)
2844 return (MemberInfo []) list;
2847 // We found an event: the cache lookup returns both the event and
2848 // its private field.
2850 if (list [0] is EventInfo) {
2851 if ((list.Count == 2) && (list [1] is FieldInfo))
2852 return new MemberInfo [] { list [0] };
2859 // We found methods, turn the search into "method scan"
2863 method_list = CopyNewMethods (method_list, list);
2864 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2865 } while (searching);
2867 if (method_list != null && method_list.Count > 0) {
2868 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2871 // This happens if we already used the cache in the first iteration, in this case
2872 // the cache already looked in all interfaces.
2874 if (skip_iface_check)
2878 // Interfaces do not list members they inherit, so we have to
2881 if (!queried_type.IsInterface)
2884 if (queried_type.IsArray)
2885 queried_type = TypeManager.array_type;
2887 TypeExpr [] ifaces = GetInterfaces (queried_type);
2891 foreach (TypeExpr itype in ifaces){
2894 x = MemberLookup (null, null, itype.Type, num_type_arguments,
2904 // This is used to extract properties and event declarations from a type
2906 static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2908 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2910 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2912 if (t is TypeBuilder) {
2913 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2915 return (MemberInfo []) decl.FindMembers (
2916 MemberTypes.Property | MemberTypes.Event,
2917 bf, FilterNone_delegate, null);
2919 return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2920 bf, FilterNone_delegate, null);
2925 public static bool IsSpecialMethod (MethodBase mb)
2927 Type t = mb.DeclaringType;
2929 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2930 if (matches == null)
2933 foreach (MemberInfo mi in matches){
2934 if (mi is PropertyBuilder){
2935 Pair p = (Pair) properties [mi];
2937 if (p.First == mb || p.Second == mb)
2939 } else if (mi is PropertyInfo){
2940 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2942 foreach (MethodInfo m in methods){
2946 } else if (mi is MyEventBuilder){
2947 Pair p = (Pair) events [mi];
2949 if (p.First == mb || p.Second == mb)
2951 } else if (mi is EventInfo){
2952 EventInfo ei = ((EventInfo) mi);
2954 if (ei.GetAddMethod (true) == mb)
2957 if (ei.GetRemoveMethod (true) == mb)
2960 if (ei.GetRaiseMethod (true) == mb)
2966 // Now check if it is an operator method
2970 if (s.StartsWith ("op_")){
2971 foreach (string name in Unary.oper_names){
2976 foreach (string name in Binary.oper_names){
2990 /// There is exactly one instance of this class per type.
2992 public sealed class TypeHandle : IMemberContainer {
2993 public readonly TypeHandle BaseType;
2995 readonly int id = ++next_id;
2996 static int next_id = 0;
2999 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3000 /// a TypeHandle yet, a new instance of it is created. This static method
3001 /// ensures that we'll only have one TypeHandle instance per type.
3003 public static TypeHandle GetTypeHandle (Type t)
3005 TypeHandle handle = (TypeHandle) type_hash [t];
3009 handle = new TypeHandle (t);
3010 type_hash.Add (t, handle);
3014 public static void CleanUp ()
3020 /// Returns the TypeHandle for TypeManager.object_type.
3022 public static IMemberContainer ObjectType {
3024 if (object_type != null)
3027 object_type = GetTypeHandle (TypeManager.object_type);
3034 /// Returns the TypeHandle for TypeManager.array_type.
3036 public static IMemberContainer ArrayType {
3038 if (array_type != null)
3041 array_type = GetTypeHandle (TypeManager.array_type);
3047 private static PtrHashtable type_hash = new PtrHashtable ();
3049 private static TypeHandle object_type = null;
3050 private static TypeHandle array_type = null;
3053 private bool is_interface;
3054 private MemberCache member_cache;
3056 private TypeHandle (Type type)
3059 if (type.BaseType != null)
3060 BaseType = GetTypeHandle (type.BaseType);
3061 this.is_interface = type.IsInterface;
3062 this.member_cache = new MemberCache (this);
3065 // IMemberContainer methods
3067 public string Name {
3069 return type.FullName;
3079 public IMemberContainer Parent {
3085 public bool IsInterface {
3087 return is_interface;
3091 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3093 MemberInfo [] members;
3094 if (mt == MemberTypes.Event)
3095 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3097 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3099 Array.Reverse (members);
3101 return new MemberList (members);
3104 // IMemberFinder methods
3106 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3107 MemberFilter filter, object criteria)
3109 return member_cache.FindMembers (mt, bf, name, filter, criteria);
3112 public MemberCache MemberCache {
3114 return member_cache;
3118 public override string ToString ()
3120 if (BaseType != null)
3121 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3123 return "TypeHandle (" + id + "," + Name + ")";