2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public partial class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static Type _uint32_type;
42 static public Type int64_type;
43 static Type _uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type _sbyte_type;
52 static public Type byte_type;
53 static public Type _ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type null_type;
59 static public Type enumeration_type;
60 static public Type array_type;
61 static public Type runtime_handle_type;
62 static public Type icloneable_type;
63 static public Type type_type;
64 static public Type ienumerator_type;
65 static public Type ienumerable_type;
66 static public Type idisposable_type;
67 static public Type iconvertible_type;
68 static public Type default_member_type;
69 static public Type iasyncresult_type;
70 static public Type asynccallback_type;
71 static public Type intptr_type;
72 static public Type monitor_type;
73 static public Type runtime_field_handle_type;
74 static public Type runtime_argument_handle_type;
75 static public Type attribute_type;
76 static public Type attribute_usage_type;
77 static public Type decimal_constant_attribute_type;
78 static public Type dllimport_type;
79 static public Type unverifiable_code_type;
80 static public Type methodimpl_attr_type;
81 static public Type marshal_as_attr_type;
82 static public Type param_array_type;
83 static public Type guid_attr_type;
84 static public Type void_ptr_type;
85 static public Type indexer_name_type;
86 static public Type exception_type;
87 static public Type invalid_operation_exception_type;
88 static public Type not_supported_exception_type;
89 static public Type obsolete_attribute_type;
90 static public Type conditional_attribute_type;
91 static public Type in_attribute_type;
92 static public Type out_attribute_type;
93 static public Type anonymous_method_type;
94 static public Type cls_compliant_attribute_type;
95 static public Type typed_reference_type;
96 static public Type arg_iterator_type;
97 static public Type mbr_type;
98 static public Type struct_layout_attribute_type;
99 static public Type field_offset_attribute_type;
100 static public Type security_attr_type;
101 static public Type date_type;
106 static public Type convert_type;
107 static public Type math_type;
110 // Type cache of helper classes in Microsoft.VisualBasic.dll
113 static public Type msvbcs_boolean_type;
114 static public Type msvbcs_byte_type;
115 static public Type msvbcs_short_type;
116 static public Type msvbcs_integer_type;
117 static public Type msvbcs_long_type;
118 static public Type msvbcs_decimal_type;
119 static public Type msvbcs_single_type;
120 static public Type msvbcs_double_type;
121 static public Type msvbcs_string_type;
122 static public Type msvbcs_char_type;
123 static public Type msvbcs_chararray_type;
124 static public Type msvbcs_date_type;
126 static public Type msvbcs_comparemethod_type;
129 // Unlike C#, VB.NET doesn't understand "signed byte",
130 // "unsigned short" and "unsigned int" as primitive types. The
131 // NotDefinedAsPrimitiveType just exists to accomodate this fact.
134 static Type not_defined_as_primitive_type = typeof (NotDefinedAsPrimitiveType);
136 public static Type sbyte_type {
138 return not_defined_as_primitive_type;
143 public static Type ushort_type {
145 return not_defined_as_primitive_type;
150 public static Type uint32_type {
152 return not_defined_as_primitive_type;
157 public static Type uint64_type {
159 return not_defined_as_primitive_type;
165 // An empty array of types
167 static public Type [] NoTypes;
168 static public TypeExpr [] NoTypeExprs;
172 // Expressions representing the internal types. Used during declaration
175 static public TypeExpr system_object_expr, system_string_expr;
176 static public TypeExpr system_boolean_expr, system_decimal_expr;
177 static public TypeExpr system_single_expr, system_double_expr;
178 static public TypeExpr system_sbyte_expr, system_byte_expr;
179 static public TypeExpr system_int16_expr, system_uint16_expr;
180 static public TypeExpr system_int32_expr, system_uint32_expr;
181 static public TypeExpr system_int64_expr, system_uint64_expr;
182 static public TypeExpr system_char_expr, system_void_expr;
183 static public TypeExpr system_asynccallback_expr;
184 static public TypeExpr system_iasyncresult_expr;
185 static public TypeExpr system_valuetype_expr;
186 static public TypeExpr system_intptr_expr;
191 static public TypeExpr system_date_expr;
194 // This is only used when compiling corlib
196 static public Type system_int32_type;
197 static public Type system_array_type;
198 static public Type system_type_type;
199 static public Type system_assemblybuilder_type;
200 static public MethodInfo system_int_array_get_length;
201 static public MethodInfo system_int_array_get_rank;
202 static public MethodInfo system_object_array_clone;
203 static public MethodInfo system_int_array_get_length_int;
204 static public MethodInfo system_int_array_get_lower_bound_int;
205 static public MethodInfo system_int_array_get_upper_bound_int;
206 static public MethodInfo system_void_array_copyto_array_int;
210 // Internal, not really used outside
212 static Type runtime_helpers_type;
215 // These methods are called by code generated by the compiler
217 static public MethodInfo string_concat_string_string;
218 static public MethodInfo string_concat_string_string_string;
219 static public MethodInfo string_concat_string_string_string_string;
220 static public MethodInfo string_concat_string_dot_dot_dot;
221 static public MethodInfo string_concat_object_object;
222 static public MethodInfo string_concat_object_object_object;
223 static public MethodInfo string_concat_object_dot_dot_dot;
224 static public MethodInfo string_isinterneted_string;
225 static public MethodInfo system_type_get_type_from_handle;
226 static public MethodInfo object_getcurrent_void;
227 static public MethodInfo bool_movenext_void;
228 static public MethodInfo ienumerable_getenumerator_void;
229 static public MethodInfo void_reset_void;
230 static public MethodInfo void_dispose_void;
231 static public MethodInfo void_monitor_enter_object;
232 static public MethodInfo void_monitor_exit_object;
233 static public MethodInfo void_initializearray_array_fieldhandle;
234 static public MethodInfo int_getlength_int;
235 static public MethodInfo delegate_combine_delegate_delegate;
236 static public MethodInfo delegate_remove_delegate_delegate;
237 static public MethodInfo int_get_offset_to_string_data;
238 static public MethodInfo int_array_get_length;
239 static public MethodInfo int_array_get_rank;
240 static public MethodInfo object_array_clone;
241 static public MethodInfo int_array_get_length_int;
242 static public MethodInfo int_array_get_lower_bound_int;
243 static public MethodInfo int_array_get_upper_bound_int;
244 static public MethodInfo void_array_copyto_array_int;
247 // The attribute constructors.
249 static public ConstructorInfo object_ctor;
250 static public ConstructorInfo cons_param_array_attribute;
251 static public ConstructorInfo void_decimal_ctor_five_args;
252 static public ConstructorInfo void_decimal_ctor_int_arg;
253 static public ConstructorInfo unverifiable_code_ctor;
254 static public ConstructorInfo invalid_operation_ctor;
255 static public ConstructorInfo default_member_ctor;
256 static public ConstructorInfo decimal_constant_attribute_ctor;
259 // Type cache of helper methods in Microsoft.VisualBasic.dll
261 static public MethodInfo convert_to_byte_decimal;
262 static public MethodInfo convert_to_int16_decimal;
263 static public MethodInfo convert_to_int32_decimal;
264 static public MethodInfo convert_to_int64_decimal;
265 static public MethodInfo convert_to_single_decimal;
266 static public MethodInfo convert_to_double_decimal;
267 static public MethodInfo convert_to_boolean_decimal;
269 static public MethodInfo decimal_compare_decimal_decimal;
270 static public MethodInfo datetime_compare_datetime_datetime;
271 static public MethodInfo math_round_double;
273 static public MethodInfo msvbcs_booleantype_from_string;
274 static public MethodInfo msvbcs_bytetype_from_string;
275 static public MethodInfo msvbcs_shorttype_from_string;
276 static public MethodInfo msvbcs_integertype_from_string;
277 static public MethodInfo msvbcs_longtype_from_string;
278 static public MethodInfo msvbcs_decimaltype_from_string;
279 static public MethodInfo msvbcs_singletype_from_string;
280 static public MethodInfo msvbcs_doubletype_from_string;
281 static public MethodInfo msvbcs_chartype_from_string;
282 static public MethodInfo msvbcs_datetype_from_string;
284 static public MethodInfo msvbcs_stringtype_from_boolean;
285 static public MethodInfo msvbcs_stringtype_from_byte;
286 static public MethodInfo msvbcs_stringtype_from_short;
287 static public MethodInfo msvbcs_stringtype_from_integer;
288 static public MethodInfo msvbcs_stringtype_from_long;
289 static public MethodInfo msvbcs_stringtype_from_decimal;
290 static public MethodInfo msvbcs_stringtype_from_single;
291 static public MethodInfo msvbcs_stringtype_from_double;
292 static public MethodInfo msvbcs_stringtype_from_date;
293 static public MethodInfo msvbcs_stringtype_from_char;
295 static public MethodInfo msvbcs_decimaltype_from_boolean;
297 static public MethodInfo msvbcs_stringtype_strcmp_string_string_boolean;
298 static public MethodInfo msvbcs_stringtype_strlike_string_string_comparemethod;
300 static public ConstructorInfo void_datetime_ctor_ticks_arg;
303 // Holds the Array of Assemblies that have been loaded
304 // (either because it is the default or the user used the
305 // -r command line option)
307 static Assembly [] assemblies;
310 // Keeps a list of modules. We used this to do lookups
311 // on the module using GetType -- needed for arrays
313 static Module [] modules;
316 // This is the type_cache from the assemblies to avoid
317 // hitting System.Reflection on every lookup.
319 static Hashtable types;
322 // This is used to hotld the corresponding TypeContainer objects
323 // since we need this in FindMembers
325 static Hashtable typecontainers;
328 // Keeps track of those types that are defined by the
331 static ArrayList user_types;
333 static PtrHashtable builder_to_declspace;
335 static PtrHashtable builder_to_member_cache;
338 // Tracks the interfaces implemented by typebuilders. We only
339 // enter those who do implement or or more interfaces
341 static PtrHashtable builder_to_ifaces;
344 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
345 // the arguments to the method
347 static Hashtable method_arguments;
350 // Maps PropertyBuilder to a Type array that contains
351 // the arguments to the indexer
353 static Hashtable indexer_arguments;
356 // Maybe `method_arguments' should be replaced and only
357 // method_internal_params should be kept?
359 static Hashtable method_internal_params;
362 // Keeps track of methods
365 static Hashtable builder_to_method;
368 // Contains all public types from referenced assemblies.
369 // This member is used only if CLS Compliance verification is required.
371 public static Hashtable all_imported_types;
378 public static void CleanUp ()
380 // Lets get everything clean so that we can collect before generating code
384 typecontainers = null;
386 builder_to_declspace = null;
387 builder_to_member_cache = null;
388 builder_to_ifaces = null;
389 method_arguments = null;
390 indexer_arguments = null;
391 method_internal_params = null;
392 builder_to_method = null;
396 negative_hits = null;
397 builder_to_constant = null;
398 fieldbuilders_to_fields = null;
400 priv_fields_events = null;
404 TypeHandle.CleanUp ();
408 /// A filter for Findmembers that uses the Signature object to
411 static bool SignatureFilter (MemberInfo mi, object criteria)
413 Signature sig = (Signature) criteria;
415 if (!(mi is MethodBase))
418 if (mi.Name != sig.name)
421 int count = sig.args.Length;
423 if (mi is MethodBuilder || mi is ConstructorBuilder){
424 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
426 if (candidate_args.Length != count)
429 for (int i = 0; i < count; i++)
430 if (candidate_args [i] != sig.args [i])
435 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
437 if (pars.Length != count)
440 for (int i = 0; i < count; i++)
441 if (pars [i].ParameterType != sig.args [i])
447 // A delegate that points to the filter above.
448 static MemberFilter signature_filter;
451 // These are expressions that represent some of the internal data types, used
454 static void InitExpressionTypes ()
456 system_object_expr = new TypeLookupExpression ("System.Object");
457 system_string_expr = new TypeLookupExpression ("System.String");
458 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
459 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
460 system_single_expr = new TypeLookupExpression ("System.Single");
461 system_double_expr = new TypeLookupExpression ("System.Double");
462 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
463 system_byte_expr = new TypeLookupExpression ("System.Byte");
464 system_int16_expr = new TypeLookupExpression ("System.Int16");
465 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
466 system_int32_expr = new TypeLookupExpression ("System.Int32");
467 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
468 system_int64_expr = new TypeLookupExpression ("System.Int64");
469 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
470 system_char_expr = new TypeLookupExpression ("System.Char");
471 system_void_expr = new TypeLookupExpression ("System.Void");
472 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
473 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
474 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
475 system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
480 system_date_expr = new TypeLookupExpression ("System.DateTime");
483 static TypeManager ()
485 assemblies = new Assembly [0];
487 user_types = new ArrayList ();
489 types = new Hashtable ();
490 typecontainers = new Hashtable ();
492 builder_to_declspace = new PtrHashtable ();
493 builder_to_member_cache = new PtrHashtable ();
494 builder_to_method = new PtrHashtable ();
495 method_arguments = new PtrHashtable ();
496 method_internal_params = new PtrHashtable ();
497 indexer_arguments = new PtrHashtable ();
498 builder_to_ifaces = new PtrHashtable ();
500 NoTypes = new Type [0];
501 NoTypeExprs = new TypeExpr [0];
503 signature_filter = new MemberFilter (SignatureFilter);
505 InitExpressionTypes ();
508 public static void HandleDuplicate (string name, Type t)
510 Type prev = (Type) types [name];
511 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
515 // This probably never happens, as we catch this before
517 Report.Error (-17, "The type `" + name + "' has already been defined.");
521 tc = builder_to_declspace [t] as TypeContainer;
524 1595, "The type `" + name + "' is defined in an existing assembly;"+
525 " Using the new definition from: " + tc.Location);
528 1595, "The type `" + name + "' is defined in an existing assembly;");
531 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
537 public static void AddUserType (string name, TypeBuilder t)
542 HandleDuplicate (name, t);
548 // This entry point is used by types that we define under the covers
550 public static void RegisterBuilder (Type tb, Type [] ifaces)
553 builder_to_ifaces [tb] = ifaces;
556 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
558 builder_to_declspace.Add (t, tc);
559 typecontainers.Add (name, tc);
560 AddUserType (name, t);
563 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
568 HandleDuplicate (name, t);
571 builder_to_declspace.Add (t, del);
574 public static void AddEnumType (string name, TypeBuilder t, Enum en)
579 HandleDuplicate (name, t);
581 builder_to_declspace.Add (t, en);
584 public static void AddMethod (MethodBase builder, IMethodData method)
586 builder_to_method.Add (builder, method);
589 public static IMethodData GetMethod (MethodBase builder)
591 return (IMethodData) builder_to_method [builder];
595 /// Returns the DeclSpace whose Type is `t' or null if there is no
596 /// DeclSpace for `t' (ie, the Type comes from a library)
598 public static DeclSpace LookupDeclSpace (Type t)
600 return builder_to_declspace [t] as DeclSpace;
604 /// Returns the TypeContainer whose Type is `t' or null if there is no
605 /// TypeContainer for `t' (ie, the Type comes from a library)
607 public static TypeContainer LookupTypeContainer (Type t)
609 return builder_to_declspace [t] as TypeContainer;
612 public static MemberCache LookupMemberCache (Type t)
614 if (t is TypeBuilder) {
615 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
616 if (container != null)
617 return container.MemberCache;
620 if (t is GenericTypeParameterBuilder) {
621 IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
623 if (container != null)
624 return container.MemberCache;
627 return TypeHandle.GetMemberCache (t);
630 public static MemberCache LookupBaseInterfacesCache (Type t)
632 Type [] ifaces = t.GetInterfaces ();
634 if (ifaces != null && ifaces.Length == 1)
635 return LookupMemberCache (ifaces [0]);
637 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
638 MemberCache cache = builder_to_member_cache [t] as MemberCache;
642 cache = new MemberCache (ifaces);
643 builder_to_member_cache.Add (t, cache);
647 public static TypeContainer LookupInterface (Type t)
649 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
650 if ((tc == null) || (tc.Kind != Kind.Interface))
656 public static Delegate LookupDelegate (Type t)
658 return builder_to_declspace [t] as Delegate;
661 public static Enum LookupEnum (Type t)
663 return builder_to_declspace [t] as Enum;
666 public static Class LookupClass (Type t)
668 return (Class) builder_to_declspace [t];
672 /// Registers an assembly to load types from.
674 public static void AddAssembly (Assembly a)
676 foreach (Assembly assembly in assemblies) {
681 int top = assemblies.Length;
682 Assembly [] n = new Assembly [top + 1];
684 assemblies.CopyTo (n, 0);
690 public static Assembly [] GetAssemblies ()
696 /// Registers a module builder to lookup types from
698 public static void AddModule (Module mb)
700 int top = modules != null ? modules.Length : 0;
701 Module [] n = new Module [top + 1];
704 modules.CopyTo (n, 0);
709 public static Module[] Modules {
715 static Hashtable references = new Hashtable ();
718 // Gets the reference to T version of the Type (T&)
720 public static Type GetReferenceType (Type t)
722 return t.MakeByRefType ();
725 static Hashtable pointers = new Hashtable ();
728 // Gets the pointer to T version of the Type (T*)
730 public static Type GetPointerType (Type t)
732 string tname = t.FullName + "*";
734 Type ret = t.Assembly.GetType (tname);
737 // If the type comes from the assembly we are building
738 // We need the Hashtable, because .NET 1.1 will return different instance types
739 // every time we call ModuleBuilder.GetType.
742 if (pointers [t] == null)
743 pointers [t] = CodeGen.Module.Builder.GetType (tname);
745 ret = (Type) pointers [t];
752 // Low-level lookup, cache-less
754 static Type LookupTypeReflection (string name)
758 foreach (Assembly a in assemblies){
759 t = a.GetType (name);
764 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
765 if (ta == TypeAttributes.NotPublic ||
766 ta == TypeAttributes.NestedPrivate ||
767 ta == TypeAttributes.NestedAssembly ||
768 ta == TypeAttributes.NestedFamANDAssem){
771 // In .NET pointers turn out to be private, even if their
772 // element type is not
775 t = t.GetElementType ();
785 foreach (Module mb in modules) {
786 t = mb.GetType (name);
794 static Hashtable negative_hits = new Hashtable ();
797 // This function is used when you want to avoid the lookups, and want to go
798 // directly to the source. This will use the cache.
800 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
801 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
802 // way to test things other than doing a fullname compare
804 public static Type LookupTypeDirect (string name)
806 Type t = (Type) types [name];
810 t = LookupTypeReflection (name);
818 static readonly char [] dot_array = { '.' };
821 /// Returns the Type associated with @name, takes care of the fact that
822 /// reflection expects nested types to be separated from the main type
823 /// with a "+" instead of a "."
825 public static Type LookupType (string name)
830 // First lookup in user defined and cached values
833 t = (Type) types [name];
837 // Two thirds of the failures are caught here.
838 if (negative_hits.Contains (name))
841 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
842 string [] elements = name.Split (dot_array);
843 int count = elements.Length;
845 for (int n = 1; n <= count; n++){
846 string top_level_type = String.Join (".", elements, 0, n);
848 // One third of the failures are caught here.
849 if (negative_hits.Contains (top_level_type))
852 t = (Type) types [top_level_type];
854 t = LookupTypeReflection (top_level_type);
856 negative_hits [top_level_type] = null;
867 // We know that System.Object does not have children, and since its the base of
868 // all the objects, it always gets probbed for inner classes.
870 if (top_level_type == "System.Object")
873 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
874 //Console.WriteLine ("Looking up: " + newt + " " + name);
875 t = LookupTypeReflection (newt);
877 negative_hits [name] = null;
882 negative_hits [name] = null;
887 /// Computes the namespaces that we import from the assemblies we reference.
889 public static void ComputeNamespaces ()
891 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
894 // First add the assembly namespaces
896 if (assembly_get_namespaces != null){
897 int count = assemblies.Length;
899 for (int i = 0; i < count; i++){
900 Assembly a = assemblies [i];
901 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
902 foreach (string ns in namespaces){
905 Namespace.LookupNamespace (ns, true);
909 Hashtable cache = new Hashtable ();
910 cache.Add ("", null);
911 foreach (Assembly a in assemblies) {
912 foreach (Type t in a.GetExportedTypes ()) {
913 string ns = t.Namespace;
914 if (ns == null || cache.Contains (ns))
917 Namespace.LookupNamespace (ns, true);
918 cache.Add (ns, null);
925 /// Fills static table with exported types from all referenced assemblies.
926 /// This information is required for CLS Compliance tests.
928 public static void LoadAllImportedTypes ()
930 all_imported_types = new Hashtable ();
931 foreach (Assembly a in assemblies) {
932 foreach (Type t in a.GetExportedTypes ()) {
933 all_imported_types [t.FullName] = t;
938 public static bool NamespaceClash (string name, Location loc)
940 if (Namespace.LookupNamespace (name, false) == null)
943 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
948 /// Returns the C# name of a type if possible, or the full type name otherwise
950 static public string CSharpName (Type t)
952 if (t.FullName == null)
955 return Regex.Replace (t.FullName,
957 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
958 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
959 @"Boolean|String|Void|Null)" +
961 new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
964 static String CSharpNameMatch (Match match)
966 string s = match.Groups [1].Captures [0].Value;
968 Replace ("int32", "int").
969 Replace ("uint32", "uint").
970 Replace ("int16", "short").
971 Replace ("uint16", "ushort").
972 Replace ("int64", "long").
973 Replace ("uint64", "ulong").
974 Replace ("single", "float").
975 Replace ("boolean", "bool")
976 + match.Groups [2].Captures [0].Value;
980 /// Returns the signature of the method with full namespace classification
982 static public string GetFullNameSignature (MemberInfo mi)
984 // Unfortunately, there's no dynamic dispatch on the arguments of a function.
985 return (mi is MethodBase)
986 ? GetFullNameSignature (mi as MethodBase)
987 : mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
990 static public string GetFullNameSignature (MethodBase mb)
992 string name = mb.Name;
994 name = mb.DeclaringType.Name;
996 if (mb.IsSpecialName) {
997 if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
998 name = name.Remove (0, 4);
1005 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
1008 static public string GetFullName (Type t)
1010 if (t.FullName == null)
1013 string name = t.FullName.Replace ('+', '.');
1015 DeclSpace tc = LookupDeclSpace (t);
1016 if ((tc != null) && tc.IsGeneric) {
1017 TypeParameter[] tparam = tc.TypeParameters;
1019 StringBuilder sb = new StringBuilder (name);
1021 for (int i = 0; i < tparam.Length; i++) {
1024 sb.Append (tparam [i].Name);
1027 return sb.ToString ();
1028 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
1029 Type[] tparam = t.GetGenericArguments ();
1031 StringBuilder sb = new StringBuilder (name);
1033 for (int i = 0; i < tparam.Length; i++) {
1036 sb.Append (tparam [i].Name);
1039 return sb.ToString ();
1046 /// Returns the signature of the property and indexer
1048 static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
1051 return GetFullNameSignature (pb);
1054 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
1055 string signature = GetFullNameSignature (mb);
1056 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
1057 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
1061 /// Returns the signature of the method
1063 static public string CSharpSignature (MethodBase mb)
1065 StringBuilder sig = new StringBuilder ("(");
1068 // FIXME: We should really have a single function to do
1069 // everything instead of the following 5 line pattern
1071 ParameterData iparams = LookupParametersByBuilder (mb);
1073 if (iparams == null)
1074 iparams = new ReflectionParameters (mb);
1077 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
1078 return GetFullNameSignature (mb);
1080 for (int i = 0; i < iparams.Count; i++) {
1084 sig.Append (iparams.ParameterDesc (i));
1089 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
1090 sig.Replace ('(', '[');
1091 sig.Replace (')', ']');
1094 return GetFullNameSignature (mb) + sig.ToString ();
1097 public static string GetMethodName (MethodInfo m)
1099 if (!IsGenericMethod (m))
1102 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
1106 /// Looks up a type, and aborts if it is not found. This is used
1107 /// by types required by the compiler
1109 static Type CoreLookupType (string name)
1111 Type t = LookupTypeDirect (name);
1114 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1115 Environment.Exit (1);
1122 /// Returns the MethodInfo for a method named `name' defined
1123 /// in type `t' which takes arguments of types `args'
1125 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1129 BindingFlags flags = instance_and_static | BindingFlags.Public;
1135 flags |= BindingFlags.NonPublic;
1137 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1138 if (list.Count == 0) {
1140 Report.Error (-19, "Can not find the core function `" + name + "'");
1144 MethodInfo mi = list [0] as MethodInfo;
1147 Report.Error (-19, "Can not find the core function `" + name + "'");
1154 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1156 return GetMethod (t, name, args, false, report_errors);
1159 static MethodInfo GetMethod (Type t, string name, Type [] args)
1161 return GetMethod (t, name, args, true);
1166 /// Returns the ConstructorInfo for "args"
1168 static ConstructorInfo GetConstructor (Type t, Type [] args)
1176 list = FindMembers (t, MemberTypes.Constructor,
1177 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1178 signature_filter, sig);
1179 if (list.Count == 0){
1180 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1184 ConstructorInfo ci = list [0] as ConstructorInfo;
1186 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1193 public static void InitEnumUnderlyingTypes ()
1196 int32_type = CoreLookupType ("System.Int32");
1197 int64_type = CoreLookupType ("System.Int64");
1198 _uint32_type = CoreLookupType ("System.UInt32");
1199 _uint64_type = CoreLookupType ("System.UInt64");
1200 byte_type = CoreLookupType ("System.Byte");
1201 _sbyte_type = CoreLookupType ("System.SByte");
1202 short_type = CoreLookupType ("System.Int16");
1203 _ushort_type = CoreLookupType ("System.UInt16");
1207 /// The types have to be initialized after the initial
1208 /// population of the type has happened (for example, to
1209 /// bootstrap the corlib.dll
1211 public static void InitCoreTypes ()
1213 object_type = CoreLookupType ("System.Object");
1214 value_type = CoreLookupType ("System.ValueType");
1216 InitEnumUnderlyingTypes ();
1218 char_type = CoreLookupType ("System.Char");
1219 string_type = CoreLookupType ("System.String");
1220 float_type = CoreLookupType ("System.Single");
1221 double_type = CoreLookupType ("System.Double");
1222 char_ptr_type = CoreLookupType ("System.Char*");
1223 decimal_type = CoreLookupType ("System.Decimal");
1224 bool_type = CoreLookupType ("System.Boolean");
1225 enum_type = CoreLookupType ("System.Enum");
1230 convert_type = CoreLookupType ("System.Convert");
1231 date_type = CoreLookupType ("System.DateTime");
1232 math_type = CoreLookupType ("System.Math");
1234 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1235 delegate_type = CoreLookupType ("System.Delegate");
1237 array_type = CoreLookupType ("System.Array");
1238 void_type = CoreLookupType ("System.Void");
1239 type_type = CoreLookupType ("System.Type");
1241 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1242 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1243 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1244 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1245 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
1246 asynccallback_type = CoreLookupType ("System.AsyncCallback");
1247 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
1248 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
1249 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
1250 idisposable_type = CoreLookupType ("System.IDisposable");
1251 icloneable_type = CoreLookupType ("System.ICloneable");
1252 iconvertible_type = CoreLookupType ("System.IConvertible");
1253 monitor_type = CoreLookupType ("System.Threading.Monitor");
1254 intptr_type = CoreLookupType ("System.IntPtr");
1256 attribute_type = CoreLookupType ("System.Attribute");
1257 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1258 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1259 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1260 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1261 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
1262 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1263 out_attribute_type = CoreLookupType ("System.Runtime.InteropServices.OutAttribute");
1264 typed_reference_type = CoreLookupType ("System.TypedReference");
1265 arg_iterator_type = CoreLookupType ("System.ArgIterator");
1266 mbr_type = CoreLookupType ("System.MarshalByRefObject");
1267 decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
1270 // Sigh. Remove this before the release. Wonder what versions of Mono
1271 // people are running.
1273 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1275 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1277 void_ptr_type = CoreLookupType ("System.Void*");
1279 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1281 exception_type = CoreLookupType ("System.Exception");
1282 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1283 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1288 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1289 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1290 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1291 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1292 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1293 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1295 InitGenericCoreTypes ();
1298 // When compiling corlib, store the "real" types here.
1300 if (!RootContext.StdLib) {
1301 system_int32_type = typeof (System.Int32);
1302 system_array_type = typeof (System.Array);
1303 system_type_type = typeof (System.Type);
1304 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1306 Type [] void_arg = { };
1307 system_int_array_get_length = GetMethod (
1308 system_array_type, "get_Length", void_arg);
1309 system_int_array_get_rank = GetMethod (
1310 system_array_type, "get_Rank", void_arg);
1311 system_object_array_clone = GetMethod (
1312 system_array_type, "Clone", void_arg);
1314 Type [] system_int_arg = { system_int32_type };
1315 system_int_array_get_length_int = GetMethod (
1316 system_array_type, "GetLength", system_int_arg);
1317 system_int_array_get_upper_bound_int = GetMethod (
1318 system_array_type, "GetUpperBound", system_int_arg);
1319 system_int_array_get_lower_bound_int = GetMethod (
1320 system_array_type, "GetLowerBound", system_int_arg);
1322 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1323 system_void_array_copyto_array_int = GetMethod (
1324 system_array_type, "CopyTo", system_array_int_arg);
1326 Type [] system_3_type_arg = {
1327 system_type_type, system_type_type, system_type_type };
1328 Type [] system_4_type_arg = {
1329 system_type_type, system_type_type, system_type_type, system_type_type };
1331 MethodInfo set_corlib_type_builders = GetMethod (
1332 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1333 system_4_type_arg, true, false);
1335 if (set_corlib_type_builders != null) {
1336 object[] args = new object [4];
1337 args [0] = object_type;
1338 args [1] = value_type;
1339 args [2] = enum_type;
1340 args [3] = void_type;
1342 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1344 // Compatibility for an older version of the class libs.
1345 set_corlib_type_builders = GetMethod (
1346 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1347 system_3_type_arg, true, true);
1349 if (set_corlib_type_builders == null) {
1350 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1354 object[] args = new object [3];
1355 args [0] = object_type;
1356 args [1] = value_type;
1357 args [2] = enum_type;
1359 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1363 system_object_expr.Type = object_type;
1364 system_string_expr.Type = string_type;
1365 system_boolean_expr.Type = bool_type;
1366 system_decimal_expr.Type = decimal_type;
1367 system_single_expr.Type = float_type;
1368 system_double_expr.Type = double_type;
1369 system_sbyte_expr.Type = _sbyte_type;
1370 system_byte_expr.Type = byte_type;
1371 system_int16_expr.Type = short_type;
1372 system_uint16_expr.Type = _ushort_type;
1373 system_int32_expr.Type = int32_type;
1374 system_uint32_expr.Type = _uint32_type;
1375 system_int64_expr.Type = int64_type;
1376 system_uint64_expr.Type = _uint64_type;
1377 system_char_expr.Type = char_type;
1378 system_void_expr.Type = void_type;
1379 system_asynccallback_expr.Type = asynccallback_type;
1380 system_iasyncresult_expr.Type = iasyncresult_type;
1381 system_valuetype_expr.Type = value_type;
1387 system_date_expr.Type = date_type;
1390 // These are only used for compare purposes
1392 anonymous_method_type = typeof (AnonymousMethod);
1393 null_type = typeof (NullType);
1395 InitVisualBasicHelperTypes ();
1399 // This method preloads helper types in Microsoft.VisualBasic.dll for later use
1401 public static void InitVisualBasicHelperTypes ()
1403 msvbcs_boolean_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.BooleanType");
1404 msvbcs_byte_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.ByteType");
1405 msvbcs_short_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.ShortType");
1406 msvbcs_integer_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.IntegerType");
1407 msvbcs_long_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.LongType");
1408 msvbcs_decimal_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DecimalType");
1409 msvbcs_single_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.SingleType");
1410 msvbcs_double_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DoubleType");
1412 msvbcs_char_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.CharType");
1413 msvbcs_chararray_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.CharArrayType");
1414 msvbcs_date_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.DateType");
1415 msvbcs_string_type = CoreLookupType ("Microsoft.VisualBasic.CompilerServices.StringType");
1417 msvbcs_comparemethod_type = CoreLookupType ("Microsoft.VisualBasic.CompareMethod");
1421 // The helper methods that are used by the compiler
1423 public static void InitCodeHelpers ()
1426 // Now load the default methods that we use.
1428 Type [] string_string = { string_type, string_type };
1429 string_concat_string_string = GetMethod (
1430 string_type, "Concat", string_string);
1431 Type [] string_string_string = { string_type, string_type, string_type };
1432 string_concat_string_string_string = GetMethod (
1433 string_type, "Concat", string_string_string);
1434 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1435 string_concat_string_string_string_string = GetMethod (
1436 string_type, "Concat", string_string_string_string);
1437 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1438 string_concat_string_dot_dot_dot = GetMethod (
1439 string_type, "Concat", params_string);
1441 Type [] object_object = { object_type, object_type };
1442 string_concat_object_object = GetMethod (
1443 string_type, "Concat", object_object);
1444 Type [] object_object_object = { object_type, object_type, object_type };
1445 string_concat_object_object_object = GetMethod (
1446 string_type, "Concat", object_object_object);
1447 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1448 string_concat_object_dot_dot_dot = GetMethod (
1449 string_type, "Concat", params_object);
1451 Type [] string_ = { string_type };
1452 string_isinterneted_string = GetMethod (
1453 string_type, "IsInterned", string_);
1455 Type [] runtime_type_handle = { runtime_handle_type };
1456 system_type_get_type_from_handle = GetMethod (
1457 type_type, "GetTypeFromHandle", runtime_type_handle);
1459 Type [] delegate_delegate = { delegate_type, delegate_type };
1460 delegate_combine_delegate_delegate = GetMethod (
1461 delegate_type, "Combine", delegate_delegate);
1463 delegate_remove_delegate_delegate = GetMethod (
1464 delegate_type, "Remove", delegate_delegate);
1470 Type [] decimal_arg = { decimal_type };
1471 convert_to_byte_decimal = GetMethod (
1472 convert_type, "ToByte", decimal_arg);
1473 convert_to_int16_decimal = GetMethod (
1474 convert_type, "ToInt16", decimal_arg);
1475 convert_to_int32_decimal = GetMethod (
1476 convert_type, "ToInt32", decimal_arg);
1477 convert_to_int64_decimal = GetMethod (
1478 convert_type, "ToInt64", decimal_arg);
1479 convert_to_single_decimal = GetMethod (
1480 convert_type, "ToSingle", decimal_arg);
1481 convert_to_double_decimal = GetMethod (
1482 convert_type, "ToDouble", decimal_arg);
1483 convert_to_boolean_decimal = GetMethod (
1484 convert_type, "ToBoolean", decimal_arg);
1486 Type [] decimal_decimal = { decimal_type, decimal_type };
1487 decimal_compare_decimal_decimal = GetMethod (
1488 decimal_type, "Compare", decimal_decimal);
1490 Type [] datetime_datetime = { date_type, date_type };
1491 datetime_compare_datetime_datetime = GetMethod (
1492 date_type, "Compare", datetime_datetime);
1494 Type [] double_arg = { double_type };
1495 math_round_double = GetMethod (
1496 math_type, "Round", double_arg);
1502 Type [] void_arg = { };
1503 object_getcurrent_void = GetMethod (
1504 ienumerator_type, "get_Current", void_arg);
1505 bool_movenext_void = GetMethod (
1506 ienumerator_type, "MoveNext", void_arg);
1507 void_reset_void = GetMethod (
1508 ienumerator_type, "Reset", void_arg);
1509 void_dispose_void = GetMethod (
1510 idisposable_type, "Dispose", void_arg);
1511 int_get_offset_to_string_data = GetMethod (
1512 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1513 int_array_get_length = GetMethod (
1514 array_type, "get_Length", void_arg);
1515 int_array_get_rank = GetMethod (
1516 array_type, "get_Rank", void_arg);
1517 ienumerable_getenumerator_void = GetMethod (
1518 ienumerable_type, "GetEnumerator", void_arg);
1523 Type [] int_arg = { int32_type };
1524 int_array_get_length_int = GetMethod (
1525 array_type, "GetLength", int_arg);
1526 int_array_get_upper_bound_int = GetMethod (
1527 array_type, "GetUpperBound", int_arg);
1528 int_array_get_lower_bound_int = GetMethod (
1529 array_type, "GetLowerBound", int_arg);
1532 // System.Array methods
1534 object_array_clone = GetMethod (
1535 array_type, "Clone", void_arg);
1536 Type [] array_int_arg = { array_type, int32_type };
1537 void_array_copyto_array_int = GetMethod (
1538 array_type, "CopyTo", array_int_arg);
1543 Type [] object_arg = { object_type };
1544 void_monitor_enter_object = GetMethod (
1545 monitor_type, "Enter", object_arg);
1546 void_monitor_exit_object = GetMethod (
1547 monitor_type, "Exit", object_arg);
1549 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1551 void_initializearray_array_fieldhandle = GetMethod (
1552 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1557 int_getlength_int = GetMethod (
1558 array_type, "GetLength", int_arg);
1561 // Decimal constructors
1563 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1564 void_decimal_ctor_five_args = GetConstructor (
1565 decimal_type, dec_arg);
1567 void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
1570 // VB.NET specific: DateTime constructor
1572 Type [] ticks_arg = { int64_type };
1573 void_datetime_ctor_ticks_arg = GetConstructor ( date_type, ticks_arg);
1578 cons_param_array_attribute = GetConstructor (
1579 param_array_type, void_arg);
1581 unverifiable_code_ctor = GetConstructor (
1582 unverifiable_code_type, void_arg);
1584 decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
1585 { byte_type, byte_type, _uint32_type, _uint32_type, _uint32_type } );
1587 default_member_ctor = GetConstructor (default_member_type, string_);
1590 // InvalidOperationException
1592 invalid_operation_ctor = GetConstructor (
1593 invalid_operation_exception_type, void_arg);
1597 object_ctor = GetConstructor (object_type, void_arg);
1599 InitGenericCodeHelpers ();
1600 InitVisualBasicCodeHelpers ();
1605 // This method preloads helper methods that are used by the VB.NET compiler
1607 public static void InitVisualBasicCodeHelpers ()
1609 Type [] boolean_arg = { bool_type };
1610 Type [] byte_arg = { byte_type };
1611 Type [] short_arg = { short_type };
1612 Type [] integer_arg = { int32_type };
1613 Type [] long_arg = { int64_type };
1614 Type [] decimal_arg = { decimal_type };
1615 Type [] single_arg = { float_type };
1616 Type [] double_arg = { double_type };
1617 Type [] char_arg = { char_type };
1618 Type [] string_arg = { string_type };
1619 Type [] date_arg = { date_type };
1621 msvbcs_booleantype_from_string = GetMethod (
1622 msvbcs_boolean_type, "FromString", string_arg);
1623 msvbcs_bytetype_from_string = GetMethod (
1624 msvbcs_byte_type, "FromString", string_arg);
1625 msvbcs_shorttype_from_string = GetMethod (
1626 msvbcs_short_type, "FromString", string_arg);
1627 msvbcs_integertype_from_string = GetMethod (
1628 msvbcs_integer_type, "FromString", string_arg);
1629 msvbcs_longtype_from_string = GetMethod (
1630 msvbcs_long_type, "FromString", string_arg);
1631 msvbcs_decimaltype_from_string = GetMethod (
1632 msvbcs_decimal_type, "FromString", string_arg);
1633 msvbcs_singletype_from_string = GetMethod (
1634 msvbcs_single_type, "FromString", string_arg);
1635 msvbcs_doubletype_from_string = GetMethod (
1636 msvbcs_double_type, "FromString", string_arg);
1637 msvbcs_chartype_from_string = GetMethod (
1638 msvbcs_char_type, "FromString", string_arg);
1639 msvbcs_datetype_from_string = GetMethod (
1640 msvbcs_date_type, "FromString", string_arg);
1642 msvbcs_stringtype_from_boolean = GetMethod (
1643 msvbcs_string_type, "FromBoolean", boolean_arg);
1644 msvbcs_stringtype_from_byte = GetMethod (
1645 msvbcs_string_type, "FromByte", byte_arg);
1646 msvbcs_stringtype_from_short = GetMethod (
1647 msvbcs_string_type, "FromShort", short_arg);
1648 msvbcs_stringtype_from_integer = GetMethod (
1649 msvbcs_string_type, "FromInteger", integer_arg);
1650 msvbcs_stringtype_from_long = GetMethod (
1651 msvbcs_string_type, "FromLong", long_arg);
1652 msvbcs_stringtype_from_decimal = GetMethod (
1653 msvbcs_string_type, "FromDecimal", decimal_arg);
1654 msvbcs_stringtype_from_single = GetMethod (
1655 msvbcs_string_type, "FromSingle", single_arg);
1656 msvbcs_stringtype_from_double = GetMethod (
1657 msvbcs_string_type, "FromDouble", double_arg);
1658 msvbcs_stringtype_from_date = GetMethod (
1659 msvbcs_string_type, "FromDate", date_arg);
1660 msvbcs_stringtype_from_char = GetMethod (
1661 msvbcs_string_type, "FromChar", char_arg);
1663 msvbcs_decimaltype_from_boolean = GetMethod (
1664 msvbcs_decimal_type, "FromBoolean", boolean_arg);
1666 Type [] string_string_boolean_arg = { string_type, string_type, bool_type };
1667 msvbcs_stringtype_strcmp_string_string_boolean = GetMethod (
1668 msvbcs_string_type, "StrCmp", string_string_boolean_arg);
1670 Type [] string_string_comparemethod_arg = { string_type, string_type, msvbcs_comparemethod_type };
1671 msvbcs_stringtype_strlike_string_string_comparemethod = GetMethod (
1672 msvbcs_string_type, "StrLike", string_string_comparemethod_arg);
1676 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1679 /// This is the "old", non-cache based FindMembers() function. We cannot use
1680 /// the cache here because there is no member name argument.
1682 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1683 MemberFilter filter, object criteria)
1685 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1688 // `builder_to_declspace' contains all dynamic types.
1692 Timer.StartTimer (TimerType.FindMembers);
1693 list = decl.FindMembers (mt, bf, filter, criteria);
1694 Timer.StopTimer (TimerType.FindMembers);
1699 // We have to take care of arrays specially, because GetType on
1700 // a TypeBuilder array will return a Type, not a TypeBuilder,
1701 // and we can not call FindMembers on this type.
1703 if (t.IsSubclassOf (TypeManager.array_type))
1704 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1706 if (t is GenericTypeParameterBuilder) {
1707 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1709 Timer.StartTimer (TimerType.FindMembers);
1710 MemberList list = tparam.FindMembers (
1711 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1712 Timer.StopTimer (TimerType.FindMembers);
1717 // Since FindMembers will not lookup both static and instance
1718 // members, we emulate this behaviour here.
1720 if ((bf & instance_and_static) == instance_and_static){
1721 MemberInfo [] i_members = t.FindMembers (
1722 mt, bf & ~BindingFlags.Static, filter, criteria);
1724 int i_len = i_members.Length;
1726 MemberInfo one = i_members [0];
1729 // If any of these are present, we are done!
1731 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1732 return new MemberList (i_members);
1735 MemberInfo [] s_members = t.FindMembers (
1736 mt, bf & ~BindingFlags.Instance, filter, criteria);
1738 int s_len = s_members.Length;
1739 if (i_len > 0 || s_len > 0)
1740 return new MemberList (i_members, s_members);
1743 return new MemberList (i_members);
1745 return new MemberList (s_members);
1749 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1754 /// This method is only called from within MemberLookup. It tries to use the member
1755 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1756 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1757 /// our return value will already contain all inherited members and the caller don't need
1758 /// to check base classes and interfaces anymore.
1760 private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1761 string name, out bool used_cache)
1766 // We have to take care of arrays specially, because GetType on
1767 // a TypeBuilder array will return a Type, not a TypeBuilder,
1768 // and we can not call FindMembers on this type.
1770 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1772 return TypeHandle.ArrayType.MemberCache.FindMembers (
1773 mt, bf, name, FilterWithClosure_delegate, null);
1777 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1778 // and we can ask the DeclSpace for the MemberCache.
1780 if (t is TypeBuilder) {
1781 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1782 cache = decl.MemberCache;
1785 // If this DeclSpace has a MemberCache, use it.
1788 if (cache != null) {
1790 return cache.FindMembers (
1791 mt, bf, name, FilterWithClosure_delegate, null);
1794 // If there is no MemberCache, we need to use the "normal" FindMembers.
1795 // Note, this is a VERY uncommon route!
1798 Timer.StartTimer (TimerType.FindMembers);
1799 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1800 FilterWithClosure_delegate, name);
1801 Timer.StopTimer (TimerType.FindMembers);
1803 return (MemberInfo []) list;
1806 if (t is GenericTypeParameterBuilder) {
1807 TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1810 Timer.StartTimer (TimerType.FindMembers);
1811 list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1812 FilterWithClosure_delegate, name);
1813 Timer.StopTimer (TimerType.FindMembers);
1815 return (MemberInfo []) list;
1819 // This call will always succeed. There is exactly one TypeHandle instance per
1820 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1821 // the corresponding MemberCache.
1823 cache = TypeHandle.GetMemberCache (t);
1826 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1829 public static bool IsBuiltinType (Type t)
1831 if (t == object_type || t == string_type || t == int32_type || t == _uint32_type ||
1832 t == int64_type || t == _uint64_type || t == float_type || t == double_type ||
1833 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1834 t == _sbyte_type || t == byte_type || t == _ushort_type || t == void_type)
1840 public static bool IsBuiltinType (TypeContainer tc)
1842 return IsBuiltinType (tc.TypeBuilder);
1846 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1847 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1849 public static bool IsCLRType (Type t)
1851 if (t == object_type || t == int32_type || t == _uint32_type ||
1852 t == int64_type || t == _uint64_type || t == float_type || t == double_type ||
1853 t == char_type || t == short_type || t == bool_type ||
1854 t == _sbyte_type || t == byte_type || t == _ushort_type)
1861 // The following three methods are used by the VB.NET compiler
1864 public static bool IsFixedNumericType (Type type)
1866 if (type == byte_type || type == short_type ||
1867 type == int32_type || type == int64_type)
1873 public static bool IsFloatingNumericType (Type type)
1875 if (type == decimal_type ||
1876 type == float_type || type == double_type)
1882 public static bool IsNumericType (Type type)
1884 if (IsFixedNumericType (type) || IsFloatingNumericType(type))
1890 public static bool IsDelegateType (Type t)
1892 if (t.IsGenericInstance)
1893 t = t.GetGenericTypeDefinition ();
1895 if (t.IsSubclassOf (TypeManager.delegate_type))
1901 public static bool IsEnumType (Type t)
1903 if (t.IsSubclassOf (TypeManager.enum_type))
1908 public static bool IsBuiltinOrEnum (Type t)
1910 if (IsBuiltinType (t))
1919 public static bool IsNullType (Type t)
1921 return t == null_type;
1925 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1927 public static bool IsUnmanagedType (Type t)
1929 if (IsBuiltinType (t) && t != TypeManager.string_type)
1938 if (IsValueType (t)){
1939 if (t is TypeBuilder){
1940 TypeContainer tc = LookupTypeContainer (t);
1942 if (tc.Fields != null){
1943 foreach (Field f in tc.Fields){
1944 if (f.FieldBuilder.IsStatic)
1946 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1952 FieldInfo [] fields = t.GetFields ();
1954 foreach (FieldInfo f in fields){
1957 if (!IsUnmanagedType (f.FieldType))
1967 public static bool IsValueType (Type t)
1969 return t.IsGenericParameter || t.IsValueType;
1972 public static bool IsInterfaceType (Type t)
1974 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1978 return tc.Kind == Kind.Interface;
1981 public static bool IsSubclassOf (Type type, Type base_type)
1983 TypeParameter tparam = LookupTypeParameter (type);
1984 TypeParameter pparam = LookupTypeParameter (base_type);
1986 if ((tparam != null) && (pparam != null)) {
1987 if (tparam == pparam)
1990 return tparam.IsSubclassOf (base_type);
1994 if (type.Equals (base_type))
1997 type = type.BaseType;
1998 } while (type != null);
2003 public static bool IsPrivateAccessible (Type type, Type parent)
2005 if (type.Equals (parent))
2008 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
2010 // `a' is a generic type definition's TypeBuilder and `b' is a
2011 // generic instance of the same type.
2017 // void Test (Stack<T> stack) { }
2020 // The first argument of `Test' will be the generic instance
2021 // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
2024 // We hit this via Closure.Filter() for gen-82.cs.
2026 if (type != parent.GetGenericTypeDefinition ())
2032 if (type.IsGenericInstance && parent.IsGenericInstance) {
2033 if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
2042 public static bool IsFamilyAccessible (Type type, Type parent)
2044 TypeParameter tparam = LookupTypeParameter (type);
2045 TypeParameter pparam = LookupTypeParameter (parent);
2047 if ((tparam != null) && (pparam != null)) {
2048 if (tparam == pparam)
2051 return tparam.IsSubclassOf (parent);
2055 if (IsEqualGenericInstance (type, parent))
2058 type = type.BaseType;
2059 } while (type != null);
2065 // Checks whether `type' is a subclass or nested child of `base_type'.
2067 public static bool IsNestedFamilyAccessible (Type type, Type base_type)
2070 if (IsFamilyAccessible (type, base_type))
2073 // Handle nested types.
2074 type = type.DeclaringType;
2075 } while (type != null);
2081 // Checks whether `type' is a nested child of `parent'.
2083 public static bool IsNestedChildOf (Type type, Type parent)
2085 if (IsEqual (type, parent))
2088 type = type.DeclaringType;
2089 while (type != null) {
2090 if (IsEqual (type, parent))
2093 type = type.DeclaringType;
2100 // Do the right thing when returning the element type of an
2101 // array type based on whether we are compiling corlib or not
2103 public static Type GetElementType (Type t)
2105 if (RootContext.StdLib)
2106 return t.GetElementType ();
2108 return TypeToCoreType (t.GetElementType ());
2112 /// Returns the User Defined Types
2114 public static ArrayList UserTypes {
2120 public static Hashtable TypeContainers {
2122 return typecontainers;
2126 static Hashtable builder_to_constant;
2128 public static void RegisterConstant (FieldBuilder fb, Const c)
2130 if (builder_to_constant == null)
2131 builder_to_constant = new PtrHashtable ();
2133 if (builder_to_constant.Contains (fb))
2136 builder_to_constant.Add (fb, c);
2139 public static Const LookupConstant (FieldBuilder fb)
2141 if (builder_to_constant == null)
2144 return (Const) builder_to_constant [fb];
2148 /// Gigantic work around for missing features in System.Reflection.Emit follows.
2152 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
2153 /// for anything which is dynamic, and we need this in a number of places,
2154 /// we register this information here, and use it afterwards.
2156 static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
2161 method_arguments.Add (mb, args);
2162 method_internal_params.Add (mb, ip);
2165 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
2167 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
2170 if (method_internal_params.Contains (mb))
2171 return (InternalParameters) method_internal_params [mb];
2173 throw new Exception ("Argument for Method not registered" + mb);
2177 /// Returns the argument types for a method based on its methodbase
2179 /// For dynamic methods, we use the compiler provided types, for
2180 /// methods from existing assemblies we load them from GetParameters,
2181 /// and insert them into the cache
2183 static public Type [] GetArgumentTypes (MethodBase mb)
2185 object t = method_arguments [mb];
2189 ParameterInfo [] pi = mb.GetParameters ();
2196 types = new Type [c];
2197 for (int i = 0; i < c; i++)
2198 types [i] = pi [i].ParameterType;
2200 method_arguments.Add (mb, types);
2205 /// Returns the argument types for an indexer based on its PropertyInfo
2207 /// For dynamic indexers, we use the compiler provided types, for
2208 /// indexers from existing assemblies we load them from GetParameters,
2209 /// and insert them into the cache
2211 static public Type [] GetArgumentTypes (PropertyInfo indexer)
2213 if (indexer_arguments.Contains (indexer))
2214 return (Type []) indexer_arguments [indexer];
2215 else if (indexer is PropertyBuilder)
2216 // If we're a PropertyBuilder and not in the
2217 // `indexer_arguments' hash, then we're a property and
2221 ParameterInfo [] pi = indexer.GetIndexParameters ();
2222 // Property, not an indexer.
2226 Type [] types = new Type [c];
2228 for (int i = 0; i < c; i++)
2229 types [i] = pi [i].ParameterType;
2231 indexer_arguments.Add (indexer, types);
2237 // This is a workaround the fact that GetValue is not
2238 // supported for dynamic types
2240 static Hashtable fields = new Hashtable ();
2241 static public bool RegisterFieldValue (FieldBuilder fb, object value)
2243 if (fields.Contains (fb))
2246 fields.Add (fb, value);
2251 static public object GetValue (FieldBuilder fb)
2256 static Hashtable fieldbuilders_to_fields = new Hashtable ();
2257 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2259 if (fieldbuilders_to_fields.Contains (fb))
2262 fieldbuilders_to_fields.Add (fb, f);
2267 // The return value can be null; This will be the case for
2268 // auxiliary FieldBuilders created by the compiler that have no
2269 // real field being declared on the source code
2271 static public FieldBase GetField (FieldInfo fb)
2273 return (FieldBase) fieldbuilders_to_fields [fb];
2276 static Hashtable events;
2278 static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2281 events = new Hashtable ();
2283 if (!events.Contains (eb)) {
2284 events.Add (eb, new Pair (add, remove));
2288 static public MethodInfo GetAddMethod (EventInfo ei)
2290 if (ei is MyEventBuilder) {
2291 Pair pair = (Pair) events [ei];
2293 return (MethodInfo) pair.First;
2295 return ei.GetAddMethod (true);
2298 static public MethodInfo GetRemoveMethod (EventInfo ei)
2300 if (ei is MyEventBuilder) {
2301 Pair pair = (Pair) events [ei];
2303 return (MethodInfo) pair.Second;
2305 return ei.GetRemoveMethod (true);
2308 static Hashtable priv_fields_events;
2310 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2312 if (priv_fields_events == null)
2313 priv_fields_events = new Hashtable ();
2315 if (priv_fields_events.Contains (einfo))
2318 priv_fields_events.Add (einfo, builder);
2323 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2325 if (priv_fields_events == null)
2328 return (MemberInfo) priv_fields_events [ei];
2331 static Hashtable properties;
2333 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2335 if (properties == null)
2336 properties = new Hashtable ();
2338 if (properties.Contains (pb))
2341 properties.Add (pb, new Pair (get, set));
2346 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2347 MethodBase set, Type[] args)
2349 if (!RegisterProperty (pb, get,set))
2352 indexer_arguments.Add (pb, args);
2357 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2359 Hashtable hash = new Hashtable ();
2360 return CheckStructCycles (tc, seen, hash);
2363 public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2366 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2370 // `seen' contains all types we've already visited.
2372 if (seen.Contains (tc))
2374 seen.Add (tc, null);
2376 if (tc.Fields == null)
2379 foreach (Field field in tc.Fields) {
2380 if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
2383 Type ftype = field.FieldBuilder.FieldType;
2384 TypeContainer ftc = LookupTypeContainer (ftype);
2388 if (hash.Contains (ftc)) {
2389 Report.Error (523, tc.Location,
2390 "Struct member `{0}.{1}' of type `{2}' " +
2391 "causes a cycle in the struct layout",
2392 tc.Name, field.Name, ftc.Name);
2397 // `hash' contains all types in the current path.
2399 hash.Add (tc, null);
2401 bool ok = CheckStructCycles (ftc, seen, hash);
2408 if (!seen.Contains (ftc))
2409 seen.Add (ftc, null);
2416 /// Given an array of interface types, expand and eliminate repeated ocurrences
2417 /// of an interface.
2421 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2424 public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2426 ArrayList new_ifaces = new ArrayList ();
2428 foreach (TypeExpr iface in base_interfaces){
2429 TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
2433 if (!new_ifaces.Contains (texpr.Type))
2434 new_ifaces.Add (texpr.Type);
2436 Type [] implementing = texpr.Type.GetInterfaces ();
2438 foreach (Type imp in implementing){
2439 if (!new_ifaces.Contains (imp))
2440 new_ifaces.Add (imp);
2443 Type [] ret = new Type [new_ifaces.Count];
2444 new_ifaces.CopyTo (ret, 0);
2448 static PtrHashtable iface_cache = new PtrHashtable ();
2451 /// This function returns the interfaces in the type `t'. Works with
2452 /// both types and TypeBuilders.
2454 public static Type [] GetInterfaces (Type t)
2457 Type [] cached = iface_cache [t] as Type [];
2462 // The reason for catching the Array case is that Reflection.Emit
2463 // will not return a TypeBuilder for Array types of TypeBuilder types,
2464 // but will still throw an exception if we try to call GetInterfaces
2467 // Since the array interfaces are always constant, we return those for
2472 t = TypeManager.array_type;
2474 if (t is TypeBuilder){
2475 Type [] base_ifaces;
2477 if (t.BaseType == null)
2478 base_ifaces = NoTypes;
2480 base_ifaces = GetInterfaces (t.BaseType);
2481 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2482 if (type_ifaces == null)
2483 type_ifaces = NoTypes;
2485 int base_count = base_ifaces.Length;
2486 Type [] result = new Type [base_count + type_ifaces.Length];
2487 base_ifaces.CopyTo (result, 0);
2488 type_ifaces.CopyTo (result, base_count);
2490 iface_cache [t] = result;
2492 } else if (t is GenericTypeParameterBuilder){
2493 Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2494 if (type_ifaces == null)
2495 type_ifaces = NoTypes;
2497 iface_cache [t] = type_ifaces;
2500 Type[] ifaces = t.GetInterfaces ();
2501 iface_cache [t] = ifaces;
2507 // gets the interfaces that are declared explicitly on t
2509 public static Type [] GetExplicitInterfaces (TypeBuilder t)
2511 return (Type []) builder_to_ifaces [t];
2515 /// The following is used to check if a given type implements an interface.
2516 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2518 public static bool ImplementsInterface (Type t, Type iface)
2523 // FIXME OPTIMIZATION:
2524 // as soon as we hit a non-TypeBuiler in the interface
2525 // chain, we could return, as the `Type.GetInterfaces'
2526 // will return all the interfaces implement by the type
2530 interfaces = GetInterfaces (t);
2532 if (interfaces != null){
2533 foreach (Type i in interfaces){
2540 } while (t != null);
2545 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2547 // This is a custom version of Convert.ChangeType() which works
2548 // with the TypeBuilder defined types when compiling corlib.
2549 public static object ChangeType (object value, Type conversionType, out bool error)
2551 IConvertible convert_value = value as IConvertible;
2553 if (convert_value == null){
2559 // We must use Type.Equals() here since `conversionType' is
2560 // the TypeBuilder created version of a system type and not
2561 // the system type itself. You cannot use Type.GetTypeCode()
2562 // on such a type - it'd always return TypeCode.Object.
2566 if (conversionType.Equals (typeof (Boolean)))
2567 return (object)(convert_value.ToBoolean (nf_provider));
2568 else if (conversionType.Equals (typeof (Byte)))
2569 return (object)(convert_value.ToByte (nf_provider));
2570 else if (conversionType.Equals (typeof (Char)))
2571 return (object)(convert_value.ToChar (nf_provider));
2572 else if (conversionType.Equals (typeof (DateTime)))
2573 return (object)(convert_value.ToDateTime (nf_provider));
2574 else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
2575 return (object)(convert_value.ToDecimal (nf_provider));
2576 else if (conversionType.Equals (typeof (Double)))
2577 return (object)(convert_value.ToDouble (nf_provider));
2578 else if (conversionType.Equals (typeof (Int16)))
2579 return (object)(convert_value.ToInt16 (nf_provider));
2580 else if (conversionType.Equals (typeof (Int32)))
2581 return (object)(convert_value.ToInt32 (nf_provider));
2582 else if (conversionType.Equals (typeof (Int64)))
2583 return (object)(convert_value.ToInt64 (nf_provider));
2584 else if (conversionType.Equals (typeof (SByte)))
2585 return (object)(convert_value.ToSByte (nf_provider));
2586 else if (conversionType.Equals (typeof (Single)))
2587 return (object)(convert_value.ToSingle (nf_provider));
2588 else if (conversionType.Equals (typeof (String)))
2589 return (object)(convert_value.ToString (nf_provider));
2590 else if (conversionType.Equals (typeof (UInt16)))
2591 return (object)(convert_value.ToUInt16 (nf_provider));
2592 else if (conversionType.Equals (typeof (UInt32)))
2593 return (object)(convert_value.ToUInt32 (nf_provider));
2594 else if (conversionType.Equals (typeof (UInt64)))
2595 return (object)(convert_value.ToUInt64 (nf_provider));
2596 else if (conversionType.Equals (typeof (Object)))
2597 return (object)(value);
2607 // This is needed, because enumerations from assemblies
2608 // do not report their underlyingtype, but they report
2611 public static Type EnumToUnderlying (Type t)
2613 if (t == TypeManager.enum_type)
2616 t = t.UnderlyingSystemType;
2617 if (!TypeManager.IsEnumType (t))
2620 if (t is TypeBuilder) {
2621 // slow path needed to compile corlib
2622 if (t == TypeManager.bool_type ||
2623 t == TypeManager.byte_type ||
2624 t == TypeManager._sbyte_type ||
2625 t == TypeManager.char_type ||
2626 t == TypeManager.short_type ||
2627 t == TypeManager._ushort_type ||
2628 t == TypeManager.int32_type ||
2629 t == TypeManager._uint32_type ||
2630 t == TypeManager.int64_type ||
2631 t == TypeManager._uint64_type)
2633 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2635 TypeCode tc = Type.GetTypeCode (t);
2638 case TypeCode.Boolean:
2639 return TypeManager.bool_type;
2641 return TypeManager.byte_type;
2642 case TypeCode.SByte:
2643 return TypeManager._sbyte_type;
2645 return TypeManager.char_type;
2646 case TypeCode.Int16:
2647 return TypeManager.short_type;
2648 case TypeCode.UInt16:
2649 return TypeManager._ushort_type;
2650 case TypeCode.Int32:
2651 return TypeManager.int32_type;
2652 case TypeCode.UInt32:
2653 return TypeManager._uint32_type;
2654 case TypeCode.Int64:
2655 return TypeManager.int64_type;
2656 case TypeCode.UInt64:
2657 return TypeManager._uint64_type;
2659 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2663 // When compiling corlib and called with one of the core types, return
2664 // the corresponding typebuilder for that type.
2666 public static Type TypeToCoreType (Type t)
2668 if (RootContext.StdLib || (t is TypeBuilder))
2671 TypeCode tc = Type.GetTypeCode (t);
2674 case TypeCode.Boolean:
2675 return TypeManager.bool_type;
2677 return TypeManager.byte_type;
2678 case TypeCode.SByte:
2679 return TypeManager._sbyte_type;
2681 return TypeManager.char_type;
2682 case TypeCode.Int16:
2683 return TypeManager.short_type;
2684 case TypeCode.UInt16:
2685 return TypeManager._ushort_type;
2686 case TypeCode.Int32:
2687 return TypeManager.int32_type;
2688 case TypeCode.UInt32:
2689 return TypeManager._uint32_type;
2690 case TypeCode.Int64:
2691 return TypeManager.int64_type;
2692 case TypeCode.UInt64:
2693 return TypeManager._uint64_type;
2694 case TypeCode.Single:
2695 return TypeManager.float_type;
2696 case TypeCode.Double:
2697 return TypeManager.double_type;
2698 case TypeCode.String:
2699 return TypeManager.string_type;
2700 case TypeCode.Decimal:
2701 return TypeManager.decimal_type;
2703 if (t == typeof (void))
2704 return TypeManager.void_type;
2705 if (t == typeof (object))
2706 return TypeManager.object_type;
2707 if (t == typeof (System.Type))
2708 return TypeManager.type_type;
2709 if (t == typeof (System.IntPtr))
2710 return TypeManager.intptr_type;
2716 /// Utility function that can be used to probe whether a type
2717 /// is managed or not.
2719 public static bool VerifyUnManaged (Type t, Location loc)
2721 if (t.IsValueType || t.IsPointer){
2723 // FIXME: this is more complex, we actually need to
2724 // make sure that the type does not contain any
2730 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2731 // We need this explicit check here to make it work when
2732 // compiling corlib.
2737 "Cannot take the address or size of a variable of a managed type ('" +
2738 CSharpName (t) + "')");
2743 /// Returns the name of the indexer in a given type.
2746 /// The default is not always `Item'. The user can change this behaviour by
2747 /// using the IndexerNameAttribute in the container.
2749 /// For example, the String class indexer is named `Chars' not `Item'
2751 public static string IndexerPropertyName (Type t)
2753 if (t.IsGenericInstance)
2754 t = t.GetGenericTypeDefinition ();
2756 if (t is TypeBuilder) {
2757 TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2758 return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2761 System.Attribute attr = System.Attribute.GetCustomAttribute (
2762 t, TypeManager.default_member_type);
2764 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2765 return dma.MemberName;
2768 return TypeContainer.DefaultIndexerName;
2771 static MethodInfo declare_local_method = null;
2773 public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2775 if (declare_local_method == null){
2776 declare_local_method = typeof (ILGenerator).GetMethod (
2778 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2780 new Type [] { typeof (Type), typeof (bool)},
2782 if (declare_local_method == null){
2783 Report.Warning (-24, new Location (-1),
2784 "This version of the runtime does not support making pinned local variables. " +
2785 "This code may cause errors on a runtime with a moving GC");
2786 return ig.DeclareLocal (t);
2789 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2793 // Returns whether the array of memberinfos contains the given method
2795 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2797 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2799 foreach (MethodBase method in array) {
2800 if (method.Name != new_method.Name)
2803 if (method is MethodInfo && new_method is MethodInfo)
2804 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2808 Type [] old_args = TypeManager.GetArgumentTypes (method);
2809 int old_count = old_args.Length;
2812 if (new_args.Length != old_count)
2815 for (i = 0; i < old_count; i++){
2816 if (old_args [i] != new_args [i])
2829 // We copy methods from `new_members' into `target_list' if the signature
2830 // for the method from in the new list does not exist in the target_list
2832 // The name is assumed to be the same.
2834 public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2836 if (target_list == null){
2837 target_list = new ArrayList ();
2839 foreach (MemberInfo mi in new_members){
2840 if (mi is MethodBase)
2841 target_list.Add (mi);
2846 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2847 target_list.CopyTo (target_array, 0);
2849 foreach (MemberInfo mi in new_members){
2850 MethodBase new_method = (MethodBase) mi;
2852 if (!ArrayContainsMethod (target_array, new_method))
2853 target_list.Add (new_method);
2858 #region MemberLookup implementation
2861 // Whether we allow private members in the result (since FindMembers
2862 // uses NonPublic for both protected and private), we need to distinguish.
2865 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2870 internal class Closure {
2871 internal bool private_ok;
2873 // Who is invoking us and which type is being queried currently.
2874 internal Type invocation_type;
2875 internal Type qualifier_type;
2877 // The assembly that defines the type is that is calling us
2878 internal Assembly invocation_assembly;
2879 internal IList almost_match;
2881 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2883 if (invocation_type == null)
2886 Debug.Assert (IsNestedFamilyAccessible (invocation_type, m.DeclaringType));
2891 // A nested class has access to all the protected members visible
2893 if (qualifier_type != null
2894 && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2897 if (invocation_type == m.DeclaringType
2898 || invocation_type.IsSubclassOf (m.DeclaringType)) {
2899 // Although a derived class can access protected members of
2900 // its base class it cannot do so through an instance of the
2901 // base class (CS1540).
2902 // => Ancestry should be: declaring_type ->* invocation_type
2903 // ->* qualified_type
2904 if (qualifier_type == null
2905 || qualifier_type == invocation_type
2906 || qualifier_type.IsSubclassOf (invocation_type))
2910 if (almost_match != null)
2911 almost_match.Add (m);
2915 bool Filter (MethodBase mb, object filter_criteria)
2917 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2919 if (ma == MethodAttributes.Private)
2920 return private_ok ||
2921 IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
2922 IsNestedChildOf (invocation_type, mb.DeclaringType);
2925 // FamAndAssem requires that we not only derivate, but we are on the
2928 if (ma == MethodAttributes.FamANDAssem){
2929 if (invocation_assembly != mb.DeclaringType.Assembly)
2933 // Assembly and FamORAssem succeed if we're in the same assembly.
2934 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2935 if (invocation_assembly == mb.DeclaringType.Assembly)
2939 // We already know that we aren't in the same assembly.
2940 if (ma == MethodAttributes.Assembly)
2943 // Family and FamANDAssem require that we derive.
2944 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2945 if (invocation_type == null)
2948 if (!IsNestedFamilyAccessible (invocation_type, mb.DeclaringType))
2951 // Although a derived class can access protected members of its base class
2952 // it cannot do so through an instance of the base class (CS1540).
2953 if (!mb.IsStatic && (qualifier_type != null) &&
2954 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
2955 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
2956 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2966 bool Filter (FieldInfo fi, object filter_criteria)
2968 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2970 if (fa == FieldAttributes.Private)
2971 return private_ok ||
2972 IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
2973 IsNestedChildOf (invocation_type, fi.DeclaringType);
2976 // FamAndAssem requires that we not only derivate, but we are on the
2979 if (fa == FieldAttributes.FamANDAssem){
2980 if (invocation_assembly != fi.DeclaringType.Assembly)
2984 // Assembly and FamORAssem succeed if we're in the same assembly.
2985 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2986 if (invocation_assembly == fi.DeclaringType.Assembly)
2990 // We already know that we aren't in the same assembly.
2991 if (fa == FieldAttributes.Assembly)
2994 // Family and FamANDAssem require that we derive.
2995 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2996 if (invocation_type == null)
2999 if (!IsNestedFamilyAccessible (invocation_type, fi.DeclaringType))
3002 // Although a derived class can access protected members of its base class
3003 // it cannot do so through an instance of the base class (CS1540).
3004 if (!fi.IsStatic && (qualifier_type != null) &&
3005 !IsEqualGenericInstance (invocation_type, qualifier_type) &&
3006 TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
3007 !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3018 // This filter filters by name + whether it is ok to include private
3019 // members in the search
3021 internal bool Filter (MemberInfo m, object filter_criteria)
3024 // Hack: we know that the filter criteria will always be in the
3025 // `closure' // fields.
3028 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3031 if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3032 (invocation_type != null) &&
3033 IsPrivateAccessible (m.DeclaringType, invocation_type))
3037 // Ugly: we need to find out the type of `m', and depending
3038 // on this, tell whether we accept or not
3040 if (m is MethodBase)
3041 return Filter ((MethodBase) m, filter_criteria);
3044 return Filter ((FieldInfo) m, filter_criteria);
3047 // EventInfos and PropertyInfos, return true because they lack
3048 // permission information, so we need to check later on the methods.
3054 static Closure closure = new Closure ();
3055 static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3058 // Looks up a member called `name' in the `queried_type'. This lookup
3059 // is done by code that is contained in the definition for `invocation_type'
3060 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3062 // `invocation_type' is used to check whether we're allowed to access the requested
3063 // member wrt its protection level.
3065 // When called from MemberAccess, `qualifier_type' is the type which is used to access
3066 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3067 // is B and qualifier_type is A). This is used to do the CS1540 check.
3069 // When resolving a SimpleName, `qualifier_type' is null.
3071 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3072 // the same than `queried_type' - except when we're being called from BaseAccess;
3073 // in this case, `invocation_type' is the current type and `queried_type' the base
3074 // type, so this'd normally trigger a CS1540.
3076 // The binding flags are `bf' and the kind of members being looked up are `mt'
3078 // The return value always includes private members which code in `invocation_type'
3079 // is allowed to access (using the specified `qualifier_type' if given); only use
3080 // BindingFlags.NonPublic to bypass the permission check.
3082 // The 'almost_match' argument is used for reporting error CS1540.
3084 // Returns an array of a single element for everything but Methods/Constructors
3085 // that might return multiple matches.
3087 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3088 Type queried_type, MemberTypes mt,
3089 BindingFlags original_bf, string name, IList almost_match)
3091 Timer.StartTimer (TimerType.MemberLookup);
3093 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3094 queried_type, mt, original_bf, name, almost_match);
3096 Timer.StopTimer (TimerType.MemberLookup);
3101 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3102 Type queried_type, MemberTypes mt,
3103 BindingFlags original_bf, string name, IList almost_match)
3105 BindingFlags bf = original_bf;
3107 ArrayList method_list = null;
3108 Type current_type = queried_type;
3109 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3110 bool skip_iface_check = true, used_cache = false;
3111 bool always_ok_flag = false;
3113 closure.invocation_type = invocation_type;
3114 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3115 closure.qualifier_type = qualifier_type;
3116 closure.almost_match = almost_match;
3119 // If we are a nested class, we always have access to our container
3122 if (invocation_type != null){
3123 string invocation_name = invocation_type.FullName;
3124 if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
3125 string container = queried_type.FullName + "+";
3126 int container_length = container.Length;
3128 if (invocation_name.Length > container_length){
3129 string shared = invocation_name.Substring (0, container_length);
3131 if (shared == container)
3132 always_ok_flag = true;
3137 // This is from the first time we find a method
3138 // in most cases, we do not actually find a method in the base class
3139 // so we can just ignore it, and save the arraylist allocation
3140 MemberInfo [] first_members_list = null;
3141 bool use_first_members_list = false;
3147 // `NonPublic' is lame, because it includes both protected and
3148 // private methods, so we need to control this behavior by
3149 // explicitly tracking if a private method is ok or not.
3151 // The possible cases are:
3152 // public, private and protected (internal does not come into the
3155 if ((invocation_type != null) &&
3156 ((invocation_type == current_type) ||
3157 IsNestedChildOf (invocation_type, current_type)) ||
3159 bf = original_bf | BindingFlags.NonPublic;
3163 closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3165 Timer.StopTimer (TimerType.MemberLookup);
3167 list = MemberLookup_FindMembers (
3168 current_type, mt, bf, name, out used_cache);
3170 Timer.StartTimer (TimerType.MemberLookup);
3173 // When queried for an interface type, the cache will automatically check all
3174 // inherited members, so we don't need to do this here. However, this only
3175 // works if we already used the cache in the first iteration of this loop.
3177 // If we used the cache in any further iteration, we can still terminate the
3178 // loop since the cache always looks in all base classes.
3184 skip_iface_check = false;
3186 if (current_type == TypeManager.object_type)
3189 current_type = current_type.BaseType;
3192 // This happens with interfaces, they have a null
3193 // basetype. Look members up in the Object class.
3195 if (current_type == null) {
3196 current_type = TypeManager.object_type;
3201 if (list.Length == 0)
3205 // Events and types are returned by both `static' and `instance'
3206 // searches, which means that our above FindMembers will
3207 // return two copies of the same.
3209 if (list.Length == 1 && !(list [0] is MethodBase)){
3214 // Multiple properties: we query those just to find out the indexer
3217 if (list [0] is PropertyInfo)
3221 // We found an event: the cache lookup returns both the event and
3222 // its private field.
3224 if (list [0] is EventInfo) {
3225 if ((list.Length == 2) && (list [1] is FieldInfo))
3226 return new MemberInfo [] { list [0] };
3233 // We found methods, turn the search into "method scan"
3237 if (first_members_list != null) {
3238 if (use_first_members_list) {
3239 method_list = CopyNewMethods (method_list, first_members_list);
3240 use_first_members_list = false;
3243 method_list = CopyNewMethods (method_list, list);
3245 first_members_list = list;
3246 use_first_members_list = true;
3248 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3250 } while (searching);
3252 if (use_first_members_list) {
3253 foreach (MemberInfo mi in first_members_list) {
3254 if (! (mi is MethodBase)) {
3255 method_list = CopyNewMethods (method_list, first_members_list);
3256 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3259 return (MemberInfo []) first_members_list;
3262 if (method_list != null && method_list.Count > 0) {
3263 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3266 // This happens if we already used the cache in the first iteration, in this case
3267 // the cache already looked in all interfaces.
3269 if (skip_iface_check)
3273 // Interfaces do not list members they inherit, so we have to
3276 if (!queried_type.IsInterface)
3279 if (queried_type.IsArray)
3280 queried_type = TypeManager.array_type;
3282 Type [] ifaces = GetInterfaces (queried_type);
3286 foreach (Type itype in ifaces){
3289 x = MemberLookup (null, null, itype, mt, bf, name, null);
3297 // Tests whether external method is really special
3298 public static bool IsSpecialMethod (MethodBase mb)
3300 string name = mb.Name;
3301 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3302 return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3304 if (name.StartsWith ("add_"))
3305 return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3307 if (name.StartsWith ("remove_"))
3308 return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3310 if (name.StartsWith ("op_")){
3311 foreach (string oname in Unary.oper_names) {
3316 foreach (string oname in Binary.oper_names) {
3329 /// There is exactly one instance of this class per type.
3331 public sealed class TypeHandle : IMemberContainer {
3332 public readonly TypeHandle BaseType;
3334 readonly int id = ++next_id;
3335 static int next_id = 0;
3338 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
3339 /// a TypeHandle yet, a new instance of it is created. This static method
3340 /// ensures that we'll only have one TypeHandle instance per type.
3342 private static TypeHandle GetTypeHandle (Type t)
3344 TypeHandle handle = (TypeHandle) type_hash [t];
3348 handle = new TypeHandle (t);
3349 type_hash.Add (t, handle);
3353 public static MemberCache GetMemberCache (Type t)
3355 return GetTypeHandle (t).MemberCache;
3358 public static void CleanUp ()
3364 /// Returns the TypeHandle for TypeManager.object_type.
3366 public static IMemberContainer ObjectType {
3368 if (object_type != null)
3371 object_type = GetTypeHandle (TypeManager.object_type);
3378 /// Returns the TypeHandle for TypeManager.array_type.
3380 public static IMemberContainer ArrayType {
3382 if (array_type != null)
3385 array_type = GetTypeHandle (TypeManager.array_type);
3391 private static PtrHashtable type_hash = new PtrHashtable ();
3393 private static TypeHandle object_type = null;
3394 private static TypeHandle array_type = null;
3397 private string full_name;
3398 private bool is_interface;
3399 private MemberCache member_cache;
3400 private MemberCache base_cache;
3402 private TypeHandle (Type type)
3405 full_name = type.FullName != null ? type.FullName : type.Name;
3406 if (type.BaseType != null) {
3407 BaseType = GetTypeHandle (type.BaseType);
3408 base_cache = BaseType.MemberCache;
3409 } else if (type.IsInterface)
3410 base_cache = TypeManager.LookupBaseInterfacesCache (type);
3411 this.is_interface = type.IsInterface || type.IsGenericParameter;
3412 this.member_cache = new MemberCache (this);
3415 // IMemberContainer methods
3417 public string Name {
3429 public MemberCache BaseCache {
3435 public bool IsInterface {
3437 return is_interface;
3441 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3443 MemberInfo [] members;
3444 if (type is GenericTypeParameterBuilder)
3445 return MemberList.Empty;
3446 if (mt == MemberTypes.Event)
3447 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3449 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3451 Array.Reverse (members);
3453 return new MemberList (members);
3456 // IMemberFinder methods
3458 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3459 MemberFilter filter, object criteria)
3461 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3464 public MemberCache MemberCache {
3466 return member_cache;
3470 public override string ToString ()
3472 if (BaseType != null)
3473 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3475 return "TypeHandle (" + id + "," + Name + ")";