X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Ftypemanager.cs;h=c7adfc1fe3e02e65af1426affb9fd062eb3b1434;hb=81dfccbd14f683f1fe46f570e76c1e99a14c5a81;hp=e000540abe88fc86ae37238ed535b93b31c3b001;hpb=913c4bd4ca478fcfc8c8004436658ad5d2ed6c36;p=mono.git diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs index e000540abe8..c7adfc1fe3e 100644 --- a/mcs/mcs/typemanager.cs +++ b/mcs/mcs/typemanager.cs @@ -11,286 +11,137 @@ // Copyright 2003-2008 Novell, Inc. // -// -// We will eventually remove the SIMPLE_SPEEDUP, and should never change -// the behavior of the compilation. This can be removed if we rework -// the code to get a list of namespaces available. -// -#define SIMPLE_SPEEDUP - using System; using System.IO; using System.Globalization; -using System.Collections; +using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Runtime.CompilerServices; using System.Diagnostics; +using System.Linq; namespace Mono.CSharp { -#if GMCS_SOURCE - partial -#endif - class TypeManager { + partial class TypeManager { // // A list of core types that the compiler requires or uses // - static public Type object_type; - static public Type value_type; - static public Type string_type; - static public Type int32_type; - static public Type uint32_type; - static public Type int64_type; - static public Type uint64_type; - static public Type float_type; - static public Type double_type; - static public Type char_type; - static public Type char_ptr_type; - static public Type short_type; - static public Type decimal_type; - static public Type bool_type; - static public Type sbyte_type; - static public Type byte_type; - static public Type ushort_type; - static public Type enum_type; - static public Type delegate_type; - static public Type multicast_delegate_type; - static public Type void_type; - static public Type null_type; - static public Type array_type; - static public Type runtime_handle_type; - static public Type type_type; - static public Type ienumerator_type; - static public Type ienumerable_type; - static public Type idisposable_type; - static public Type default_member_type; - static public Type iasyncresult_type; - static public Type asynccallback_type; - static public Type intptr_type; - static public Type uintptr_type; - static public Type runtime_field_handle_type; - static public Type runtime_argument_handle_type; - static public Type attribute_type; - static public Type attribute_usage_type; - static public Type decimal_constant_attribute_type; - static public Type dllimport_type; - static public Type methodimpl_attr_type; -#if !NET_2_0 - static public Type marshal_as_attr_type; -#endif - static public Type param_array_type; - static public Type void_ptr_type; - static public Type indexer_name_type; - static public Type exception_type; - static public Type obsolete_attribute_type; - static public Type conditional_attribute_type; - static public Type in_attribute_type; - static public Type out_attribute_type; - static public Type extension_attribute_type; - static public Type default_parameter_value_attribute_type; - - static public Type anonymous_method_type; - static public Type cls_compliant_attribute_type; - static public Type typed_reference_type; - static public Type arg_iterator_type; - static public Type mbr_type; - static public Type struct_layout_attribute_type; - static public Type field_offset_attribute_type; - static public Type security_attr_type; - static public Type required_attr_type; - static public Type guid_attr_type; - static public Type assembly_culture_attribute_type; - static public Type assembly_version_attribute_type; - static public Type coclass_attr_type; - static public Type comimport_attr_type; - public static Type runtime_helpers_type; - public static Type internals_visible_attr_type; + static public PredefinedTypeSpec object_type; + static public PredefinedTypeSpec value_type; + static public PredefinedTypeSpec string_type; + static public PredefinedTypeSpec int32_type; + static public PredefinedTypeSpec uint32_type; + static public PredefinedTypeSpec int64_type; + static public PredefinedTypeSpec uint64_type; + static public PredefinedTypeSpec float_type; + static public PredefinedTypeSpec double_type; + static public PredefinedTypeSpec char_type; + static public PredefinedTypeSpec short_type; + static public PredefinedTypeSpec decimal_type; + static public PredefinedTypeSpec bool_type; + static public PredefinedTypeSpec sbyte_type; + static public PredefinedTypeSpec byte_type; + static public PredefinedTypeSpec ushort_type; + static public PredefinedTypeSpec enum_type; + static public PredefinedTypeSpec delegate_type; + static public PredefinedTypeSpec multicast_delegate_type; + static public PredefinedTypeSpec void_type; + static public PredefinedTypeSpec array_type; + static public PredefinedTypeSpec runtime_handle_type; + static public PredefinedTypeSpec type_type; + static public PredefinedTypeSpec ienumerator_type; + static public PredefinedTypeSpec ienumerable_type; + static public PredefinedTypeSpec idisposable_type; + static public PredefinedTypeSpec intptr_type; + static public PredefinedTypeSpec uintptr_type; + static public PredefinedTypeSpec runtime_field_handle_type; + static public PredefinedTypeSpec attribute_type; + static public PredefinedTypeSpec exception_type; + + + static public TypeSpec null_type; + static public TypeSpec typed_reference_type; + static public TypeSpec arg_iterator_type; + static public TypeSpec mbr_type; + public static TypeSpec runtime_helpers_type; + static public TypeSpec iasyncresult_type; + static public TypeSpec asynccallback_type; + static public TypeSpec runtime_argument_handle_type; + static public TypeSpec void_ptr_type; // // C# 2.0 // - static internal Type fixed_buffer_attr_type; - static internal Type default_charset_type; - static internal Type type_forwarder_attr_type; - static internal Type isvolatile_type; - static public Type generic_ilist_type; - static public Type generic_icollection_type; - static public Type generic_ienumerator_type; - static public Type generic_ienumerable_type; - static public Type generic_nullable_type; + static internal TypeSpec isvolatile_type; + static public TypeSpec generic_ilist_type; + static public TypeSpec generic_icollection_type; + static public TypeSpec generic_ienumerator_type; + static public TypeSpec generic_ienumerable_type; + static public TypeSpec generic_nullable_type; // // C# 3.0 // - static internal Type expression_type; - public static Type parameter_expression_type; - - // - // Expressions representing the internal types. Used during declaration - // definition. - // - static public TypeExpr system_object_expr, system_string_expr; - static public TypeExpr system_boolean_expr, system_decimal_expr; - static public TypeExpr system_single_expr, system_double_expr; - static public TypeExpr system_sbyte_expr, system_byte_expr; - static public TypeExpr system_int16_expr, system_uint16_expr; - static public TypeExpr system_int32_expr, system_uint32_expr; - static public TypeExpr system_int64_expr, system_uint64_expr; - static public TypeExpr system_char_expr, system_void_expr; - static public TypeExpr system_valuetype_expr; - static public TypeExpr system_intptr_expr; - public static TypeExpr expression_type_expr; - + static internal TypeSpec expression_type; + public static TypeSpec parameter_expression_type; + public static TypeSpec fieldinfo_type; + public static TypeSpec methodinfo_type; + public static TypeSpec ctorinfo_type; // - // These methods are called by code generated by the compiler - // - static public FieldInfo string_empty; - static public MethodInfo system_type_get_type_from_handle; - static public MethodInfo bool_movenext_void; - static public MethodInfo void_dispose_void; - static public MethodInfo void_monitor_enter_object; - static public MethodInfo void_monitor_exit_object; - static public MethodInfo void_initializearray_array_fieldhandle; - static public MethodInfo delegate_combine_delegate_delegate; - static public MethodInfo delegate_remove_delegate_delegate; - static public MethodInfo int_get_offset_to_string_data; - static public MethodInfo int_interlocked_compare_exchange; - static public PropertyInfo ienumerator_getcurrent; - public static MethodInfo methodbase_get_type_from_handle; - public static MethodInfo methodbase_get_type_from_handle_generic; - public static MethodInfo fieldinfo_get_field_from_handle; - static public MethodInfo activator_create_instance; - - // - // The attribute constructors. + // C# 4.0 // - static public ConstructorInfo void_decimal_ctor_five_args; - static public ConstructorInfo void_decimal_ctor_int_arg; - static public ConstructorInfo default_member_ctor; - static public ConstructorInfo decimal_constant_attribute_ctor; - static internal ConstructorInfo struct_layout_attribute_ctor; - static public ConstructorInfo field_offset_attribute_ctor; - public static ConstructorInfo invalid_operation_exception_ctor; - - static public CustomAttributeBuilder param_array_attr; - static CustomAttributeBuilder compiler_generated_attr; - static CustomAttributeBuilder debugger_hidden_attr; - - // C# 2.0 - static internal ConstructorInfo fixed_buffer_attr_ctor; - - // C# 3.0 - static internal CustomAttributeBuilder extension_attribute_attr; + public static TypeSpec call_site_type; + public static TypeSpec generic_call_site_type; + public static TypeExpr binder_type; + public static TypeSpec binder_flags; - static PtrHashtable builder_to_declspace; - - static PtrHashtable builder_to_member_cache; - - // - // Tracks the interfaces implemented by typebuilders. We only - // enter those who do implement or or more interfaces - // - static PtrHashtable builder_to_ifaces; - - // - // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters) - // - static Hashtable method_params; - - // - // A hash table from override methods to their base virtual method. - // - static Hashtable method_overrides; - - // - // Keeps track of methods - // - - static Hashtable builder_to_method; - - // - // Contains all public types from referenced assemblies. - // This member is used only if CLS Compliance verification is required. - // - public static Hashtable AllClsTopLevelTypes; - - static Hashtable fieldbuilders_to_fields; - static Hashtable propertybuilder_to_property; - static Hashtable fields; - static Hashtable events; - static PtrHashtable assembly_internals_vis_attrs; - - public static void CleanUp () - { - // Lets get everything clean so that we can collect before generating code - builder_to_declspace = null; - builder_to_member_cache = null; - builder_to_ifaces = null; - builder_to_type_param = null; - method_params = null; - builder_to_method = null; - - fields = null; - events = null; - type_hash = null; - propertybuilder_to_property = null; - assembly_internals_vis_attrs = null; + public static TypeExpr expression_type_expr; - TypeHandle.CleanUp (); - } // - // These are expressions that represent some of the internal data types, used - // elsewhere + // These methods are called by code generated by the compiler // - static void InitExpressionTypes () - { - system_object_expr = new TypeLookupExpression ("System.Object"); - system_string_expr = new TypeLookupExpression ("System.String"); - system_boolean_expr = new TypeLookupExpression ("System.Boolean"); - system_decimal_expr = new TypeLookupExpression ("System.Decimal"); - system_single_expr = new TypeLookupExpression ("System.Single"); - system_double_expr = new TypeLookupExpression ("System.Double"); - system_sbyte_expr = new TypeLookupExpression ("System.SByte"); - system_byte_expr = new TypeLookupExpression ("System.Byte"); - system_int16_expr = new TypeLookupExpression ("System.Int16"); - system_uint16_expr = new TypeLookupExpression ("System.UInt16"); - system_int32_expr = new TypeLookupExpression ("System.Int32"); - system_uint32_expr = new TypeLookupExpression ("System.UInt32"); - system_int64_expr = new TypeLookupExpression ("System.Int64"); - system_uint64_expr = new TypeLookupExpression ("System.UInt64"); - system_char_expr = new TypeLookupExpression ("System.Char"); - system_void_expr = new TypeLookupExpression ("System.Void"); - system_valuetype_expr = new TypeLookupExpression ("System.ValueType"); - system_intptr_expr = new TypeLookupExpression ("System.IntPtr"); - } + static public FieldSpec string_empty; + static public MethodSpec system_type_get_type_from_handle; + static public MethodSpec bool_movenext_void; + static public MethodSpec void_dispose_void; + static public MethodSpec void_monitor_enter_object; + static public MethodSpec void_monitor_exit_object; + static public MethodSpec void_initializearray_array_fieldhandle; + static public MethodSpec delegate_combine_delegate_delegate; + static public MethodSpec delegate_remove_delegate_delegate; + static public PropertySpec int_get_offset_to_string_data; + static public MethodSpec int_interlocked_compare_exchange; + static public PropertySpec ienumerator_getcurrent; + public static MethodSpec methodbase_get_type_from_handle; + public static MethodSpec methodbase_get_type_from_handle_generic; + public static MethodSpec fieldinfo_get_field_from_handle; + public static MethodSpec fieldinfo_get_field_from_handle_generic; + static public MethodSpec activator_create_instance; + + // + // The constructors. + // + static public MethodSpec void_decimal_ctor_five_args; + static public MethodSpec void_decimal_ctor_int_arg; + public static MethodSpec void_decimal_ctor_long_arg; + + static Dictionary assembly_internals_vis_attrs; static TypeManager () { Reset (); - - InitExpressionTypes (); } static public void Reset () { - builder_to_declspace = new PtrHashtable (); - builder_to_member_cache = new PtrHashtable (); - builder_to_method = new PtrHashtable (); - builder_to_type_param = new PtrHashtable (); - method_params = new PtrHashtable (); - method_overrides = new PtrHashtable (); - builder_to_ifaces = new PtrHashtable (); +// object_type = null; + + assembly_internals_vis_attrs = new Dictionary (); - fieldbuilders_to_fields = new Hashtable (); - propertybuilder_to_property = new Hashtable (); - fields = new Hashtable (); - type_hash = new DoubleHash (); - assembly_internals_vis_attrs = new PtrHashtable (); - // TODO: I am really bored by all this static stuff system_type_get_type_from_handle = bool_movenext_void = @@ -298,2691 +149,778 @@ namespace Mono.CSharp { void_monitor_enter_object = void_monitor_exit_object = void_initializearray_array_fieldhandle = - delegate_combine_delegate_delegate = - delegate_remove_delegate_delegate = - int_get_offset_to_string_data = int_interlocked_compare_exchange = methodbase_get_type_from_handle = methodbase_get_type_from_handle_generic = fieldinfo_get_field_from_handle = - activator_create_instance = null; + fieldinfo_get_field_from_handle_generic = + activator_create_instance = + delegate_combine_delegate_delegate = + delegate_remove_delegate_delegate = null; + int_get_offset_to_string_data = ienumerator_getcurrent = null; void_decimal_ctor_five_args = void_decimal_ctor_int_arg = - default_member_ctor = - decimal_constant_attribute_ctor = - struct_layout_attribute_ctor = - field_offset_attribute_ctor = - invalid_operation_exception_ctor = - fixed_buffer_attr_ctor = null; - - param_array_attr = - compiler_generated_attr = - extension_attribute_attr = null; - - isvolatile_type = null; - - // to uncover regressions - AllClsTopLevelTypes = null; + void_decimal_ctor_long_arg = null; + + string_empty = null; + + call_site_type = + generic_call_site_type = + binder_flags = null; + + binder_type = null; + + typed_reference_type = arg_iterator_type = mbr_type = + runtime_helpers_type = iasyncresult_type = asynccallback_type = + runtime_argument_handle_type = void_ptr_type = isvolatile_type = + generic_ilist_type = generic_icollection_type = generic_ienumerator_type = + generic_ienumerable_type = generic_nullable_type = expression_type = + parameter_expression_type = fieldinfo_type = methodinfo_type = ctorinfo_type = null; + + expression_type_expr = null; } - public static void AddUserType (DeclSpace ds) + /// + /// Returns the C# name of a type if possible, or the full type name otherwise + /// + static public string CSharpName (TypeSpec t) { - builder_to_declspace.Add (ds.TypeBuilder, ds); + return t.GetSignatureForError (); } - // - // This entry point is used by types that we define under the covers - // - public static void RegisterBuilder (Type tb, Type [] ifaces) + static public string CSharpName (IList types) { - if (ifaces != null) - builder_to_ifaces [tb] = ifaces; - } + if (types.Count == 0) + return string.Empty; - public static void AddMethod (MethodBase builder, IMethodData method) - { - builder_to_method.Add (builder, method); - method_params.Add (builder, method.ParameterInfo); + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < types.Count; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (CSharpName (types [i])); + } + return sb.ToString (); } - public static IMethodData GetMethod (MethodBase builder) + static public string GetFullNameSignature (MemberSpec mi) { - return (IMethodData) builder_to_method [builder]; + return mi.GetSignatureForError (); } - /// - /// Returns the DeclSpace whose Type is `t' or null if there is no - /// DeclSpace for `t' (ie, the Type comes from a library) - /// - public static DeclSpace LookupDeclSpace (Type t) + static public string CSharpSignature (MemberSpec mb) { - return builder_to_declspace [t] as DeclSpace; + return mb.GetSignatureForError (); } - /// - /// Returns the TypeContainer whose Type is `t' or null if there is no - /// TypeContainer for `t' (ie, the Type comes from a library) - /// - public static TypeContainer LookupTypeContainer (Type t) + // + // Looks up a type, and aborts if it is not found. This is used + // by predefined types required by the compiler + // + public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, MemberKind kind, bool required) { - return builder_to_declspace [t] as TypeContainer; + return CoreLookupType (ctx, ns_name, name, 0, kind, required); } - public static MemberCache LookupMemberCache (Type t) + public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, int arity, MemberKind kind, bool required) { - if (t.Module == CodeGen.Module.Builder) { - DeclSpace container = (DeclSpace)builder_to_declspace [t]; - if (container != null) - return container.MemberCache; - } + Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true); + var te = ns.Lookup (ctx, name, arity, Location.Null); + var ts = te == null ? null : te.Type; -#if GMCS_SOURCE - if (t is GenericTypeParameterBuilder) { - TypeParameter container = builder_to_type_param [t] as TypeParameter; + if (!required) + return ts; - if (container != null) - return container.MemberCache; + if (ts == null) { + ctx.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", + ns_name, name); + return null; + } + + if (ts.Kind != kind) { + ctx.Report.Error (520, "The predefined type `{0}.{1}' is not declared correctly", + ns_name, name); + return null; } -#endif - return TypeHandle.GetMemberCache (t); + return ts; } - public static MemberCache LookupBaseInterfacesCache (Type t) + static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, Location loc) { - Type [] ifaces = GetInterfaces (t); + const BindingRestriction restrictions = BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly; + var member = MemberCache.FindMember (t, filter, restrictions); - if (ifaces != null && ifaces.Length == 1) - return LookupMemberCache (ifaces [0]); + if (member != null) + return member; - // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't' - MemberCache cache = builder_to_member_cache [t] as MemberCache; - if (cache != null) - return cache; + string method_args = null; + if (filter.Parameters != null) + method_args = filter.Parameters.GetSignatureForError (); + + RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible", + TypeManager.CSharpName (t), filter.Name, method_args); - cache = new MemberCache (ifaces); - builder_to_member_cache.Add (t, cache); - return cache; + return null; } - public static TypeContainer LookupInterface (Type t) + // + // Returns the ConstructorInfo for "args" + // + public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args) { - TypeContainer tc = (TypeContainer) builder_to_declspace [t]; - if ((tc == null) || (tc.Kind != Kind.Interface)) - return null; - - return tc; + var pc = ParametersCompiled.CreateFullyResolved (args); + return GetPredefinedMember (t, MemberFilter.Constructor (pc), loc) as MethodSpec; } - public static Delegate LookupDelegate (Type t) + // + // Returns the method specification for a method named `name' defined + // in type `t' which takes arguments of types `args' + // + public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args) { - return builder_to_declspace [t] as Delegate; + var pc = ParametersCompiled.CreateFullyResolved (args); + return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), loc); } - public static Class LookupClass (Type t) + public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc) { - return (Class) builder_to_declspace [t]; + return GetPredefinedMember (t, filter, loc) as MethodSpec; } - // - // We use this hash for multiple kinds of constructed types: - // - // (T, "&") Given T, get T & - // (T, "*") Given T, get T * - // (T, "[]") Given T and a array dimension, get T [] - // (T, X) Given a type T and a simple name X, get the type T+X - // - // Accessibility tests, if necessary, should be done by the user - // - static DoubleHash type_hash = new DoubleHash (); - - // - // Gets the reference to T version of the Type (T&) - // - public static Type GetReferenceType (Type t) + public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type) { -#if GMCS_SOURCE - return t.MakeByRefType (); -#else - return GetConstructedType (t, "&"); -#endif + return GetPredefinedMember (t, MemberFilter.Field (name, type), loc) as FieldSpec; } - // - // Gets the pointer to T version of the Type (T*) - // - public static Type GetPointerType (Type t) + public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type) { - return GetConstructedType (t, "*"); + return GetPredefinedMember (t, MemberFilter.Property (name, type), loc) as PropertySpec; } - public static Type GetConstructedType (Type t, string dim) + public static IList InitCoreTypes () { - object ret = null; - if (type_hash.Lookup (t, dim, out ret)) - return (Type) ret; - - ret = t.Module.GetType (t.ToString () + dim); - if (ret != null) { - type_hash.Insert (t, dim, ret); - return (Type) ret; - } + var core_types = new PredefinedTypeSpec[] { + object_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Object"), + value_type = new PredefinedTypeSpec (MemberKind.Class, "System", "ValueType"), + attribute_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Attribute"), - if (dim == "&") { - ret = GetReferenceType (t); - type_hash.Insert (t, dim, ret); - return (Type) ret; - } + int32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int32"), + int64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int64"), + uint32_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt32"), + uint64_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt64"), + byte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Byte"), + sbyte_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "SByte"), + short_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Int16"), + ushort_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UInt16"), -#if GMCS_SOURCE - if (t.IsGenericParameter || t.IsGenericType) { - int pos = 0; - Type result = t; - while ((pos < dim.Length) && (dim [pos] == '[')) { - pos++; + ienumerator_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator"), + ienumerable_type = new PredefinedTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable"), + idisposable_type = new PredefinedTypeSpec (MemberKind.Interface, "System", "IDisposable"), - if (dim [pos] == ']') { - result = result.MakeArrayType (); - pos++; + char_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Char"), + string_type = new PredefinedTypeSpec (MemberKind.Class, "System", "String"), + float_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Single"), + double_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Double"), + decimal_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Decimal"), + bool_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Boolean"), + intptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "IntPtr"), + uintptr_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "UIntPtr"), - if (pos < dim.Length) - continue; + multicast_delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "MulticastDelegate"), + delegate_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Delegate"), + enum_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Enum"), + array_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Array"), + void_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "Void"), + type_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Type"), + exception_type = new PredefinedTypeSpec (MemberKind.Class, "System", "Exception"), + runtime_field_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle"), + runtime_handle_type = new PredefinedTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle"), + }; - type_hash.Insert (t, dim, result); - return result; - } + return core_types; + } - int rank = 0; - while (dim [pos] == ',') { - pos++; rank++; - } + /// + /// The types have to be initialized after the initial + /// population of the type has happened (for example, to + /// bootstrap the corlib.dll + /// + public static bool InitCoreTypes (CompilerContext ctx, IList predefined) + { + foreach (var p in predefined) { + var found = CoreLookupType (ctx, p.Namespace, p.Name, p.Kind, true); + if (found == null || found == p) + continue; - if ((dim [pos] != ']') || (pos != dim.Length-1)) - break; + if (!RootContext.StdLib) { + var ns = GlobalRootNamespace.Instance.GetNamespace (p.Namespace, false); + ns.ReplaceTypeWithPredefined (found, p); - result = result.MakeArrayType (rank + 1); - type_hash.Insert (t, dim, result); - return result; + var tc = found.MemberDefinition as TypeContainer; + tc.SetPredefinedSpec (p); + p.SetDefinition (found); } } -#endif - type_hash.Insert (t, dim, null); - return null; + PredefinedAttributes.Get.ParamArray.Initialize (ctx, false); + PredefinedAttributes.Get.Out.Initialize (ctx, false); + + return ctx.Report.Errors == 0; } - public static CustomAttributeBuilder GetCompilerGeneratedAttribute (Location loc) + // + // Initializes optional core types + // + public static void InitOptionalCoreTypes (CompilerContext ctx) { - if (compiler_generated_attr != null) - return compiler_generated_attr; - - Type t = TypeManager.CoreLookupType ( - "System.Runtime.CompilerServices", "CompilerGeneratedAttribute", Kind.Class, true); - - // TODO: it cannot be null - if (t == null) - return null; - - compiler_generated_attr = new CustomAttributeBuilder ( - GetPredefinedConstructor (t, loc, Type.EmptyTypes), new object[0]); + // + // These are only used for compare purposes + // + null_type = InternalType.Null; - return compiler_generated_attr; - } + void_ptr_type = PointerContainer.MakeType (void_type); - public static CustomAttributeBuilder GetDebuggerHiddenAttribute (Location loc) - { - if (debugger_hidden_attr != null) - return debugger_hidden_attr; + // + // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate + // types cache with incorrect accessiblity when any of optional types is internal. + // + PredefinedAttributes.Get.Initialize (ctx); - Type t = TypeManager.CoreLookupType ( - "System.Diagnostics", "DebuggerHiddenAttribute", Kind.Class, true); + runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", MemberKind.Struct, false); + asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", MemberKind.Delegate, false); + iasyncresult_type = CoreLookupType (ctx, "System", "IAsyncResult", MemberKind.Interface, false); + typed_reference_type = CoreLookupType (ctx, "System", "TypedReference", MemberKind.Struct, false); + arg_iterator_type = CoreLookupType (ctx, "System", "ArgIterator", MemberKind.Struct, false); + mbr_type = CoreLookupType (ctx, "System", "MarshalByRefObject", MemberKind.Class, false); - // TODO: it cannot be null - if (t == null) - return null; + generic_ienumerator_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerator", 1, MemberKind.Interface, false); + generic_ilist_type = CoreLookupType (ctx, "System.Collections.Generic", "IList", 1, MemberKind.Interface, false); + generic_icollection_type = CoreLookupType (ctx, "System.Collections.Generic", "ICollection", 1, MemberKind.Interface, false); + generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable", 1, MemberKind.Interface, false); + generic_nullable_type = CoreLookupType (ctx, "System", "Nullable", 1, MemberKind.Struct, false); - debugger_hidden_attr = new CustomAttributeBuilder ( - GetPredefinedConstructor (t, loc, Type.EmptyTypes), new object[0]); + // + // Optional types which are used as types and for member lookup + // + runtime_helpers_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "RuntimeHelpers", MemberKind.Class, false); - return debugger_hidden_attr; + // New in .NET 3.5 + // Note: extension_attribute_type is already loaded + expression_type = CoreLookupType (ctx, "System.Linq.Expressions", "Expression", 1, MemberKind.Class, false); } - public static Type GetNestedType (Type t, string name) + public static bool IsBuiltinType (TypeSpec t) { - object ret = null; - if (!type_hash.Lookup (t, name, out ret)) { - ret = t.GetNestedType (name, - BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - type_hash.Insert (t, name, ret); - } - return (Type) ret; + if (t == object_type || t == string_type || t == int32_type || t == uint32_type || + t == int64_type || t == uint64_type || t == float_type || t == double_type || + t == char_type || t == short_type || t == decimal_type || t == bool_type || + t == sbyte_type || t == byte_type || t == ushort_type || t == void_type) + return true; + else + return false; } - /// - /// Fills static table with exported types from all referenced assemblies. - /// This information is required for CLS Compliance tests. - /// - public static void LoadAllImportedTypes () + // + // This is like IsBuiltinType, but lacks decimal_type, we should also clean up + // the pieces in the code where we use IsBuiltinType and special case decimal_type. + // + public static bool IsPrimitiveType (TypeSpec t) { - AllClsTopLevelTypes = new Hashtable (1500); - foreach (Assembly a in RootNamespace.Global.Assemblies) { - foreach (Type t in a.GetExportedTypes ()) { - AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null; - } - } + return (t == int32_type || t == uint32_type || + t == int64_type || t == uint64_type || t == float_type || t == double_type || + t == char_type || t == short_type || t == bool_type || + t == sbyte_type || t == byte_type || t == ushort_type); } - public static bool NamespaceClash (string name, Location loc) + // Obsolete + public static bool IsDelegateType (TypeSpec t) { - if (! RootNamespace.Global.IsNamespace (name)) - return false; - - Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name)); - return true; + return t.IsDelegate; } - /// - /// Returns the C# name of a type if possible, or the full type name otherwise - /// - static public string CSharpName (Type t) + // + // When any element of the type is a dynamic type + // + // This method builds a transformation array for dynamic types + // used in places where DynamicAttribute cannot be applied to. + // It uses bool flag when type is of dynamic type and each + // section always starts with "false" for some reason. + // + // LAMESPEC: This should be part of C# specification ! + // + // Example: Func + // Transformation: { false, true, false, false, true } + // + public static bool[] HasDynamicTypeUsed (TypeSpec t) { - if (t == null_type) - return "null"; + var ac = t as ArrayContainer; + if (ac != null) { + if (HasDynamicTypeUsed (ac.Element) != null) + return new bool[] { false, true }; - if (t == typeof (ArglistParameter)) - return "__arglist"; - - if (t == typeof (AnonymousMethodBody)) - return "anonymous method"; + return null; + } - return CSharpName (GetFullName (t)); - } + if (t == null) + return null; - static readonly char [] elements = new char [] { '*', '[' }; + if (IsGenericType (t)) { + List transform = null; + var targs = GetTypeArguments (t); + for (int i = 0; i < targs.Length; ++i) { + var element = HasDynamicTypeUsed (targs [i]); + if (element != null) { + if (transform == null) { + transform = new List (); + for (int ii = 0; ii <= i; ++ii) + transform.Add (false); + } - public static string CSharpName (string name) - { - if (name.Length > 10) { - switch (name) { - case "System.Int32": return "int"; - case "System.Int64": return "long"; - case "System.String": return "string"; - case "System.Boolean": return "bool"; - case "System.Void": return "void"; - case "System.Object": return "object"; - case "System.UInt32": return "uint"; - case "System.Int16": return "short"; - case "System.UInt16": return "ushort"; - case "System.UInt64": return "ulong"; - case "System.Single": return "float"; - case "System.Double": return "double"; - case "System.Decimal": return "decimal"; - case "System.Char": return "char"; - case "System.Byte": return "byte"; - case "System.SByte": return "sbyte"; + transform.AddRange (element); + } else if (transform != null) { + transform.Add (false); + } } - int idx = name.IndexOfAny (elements, 10); - if (idx > 0) - return CSharpName (name.Substring (0, idx)) + name.Substring (idx); + if (transform != null) + return transform.ToArray (); } - if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix)) - return AnonymousTypeClass.SignatureForError; + if (object.ReferenceEquals (InternalType.Dynamic, t)) + return new bool [] { true }; - return name.Replace ('+', '.'); + return null; } - - static public string CSharpName (Type[] types) + + // Obsolete + public static bool IsEnumType (TypeSpec t) { - if (types.Length == 0) - return string.Empty; - - StringBuilder sb = new StringBuilder (); - for (int i = 0; i < types.Length; ++i) { - if (i > 0) - sb.Append (", "); - - sb.Append (CSharpName (types [i])); - } - return sb.ToString (); + return t.IsEnum; } - /// - /// Returns the signature of the method with full namespace classification - /// - static public string GetFullNameSignature (MemberInfo mi) + public static bool IsBuiltinOrEnum (TypeSpec t) { - PropertyInfo pi = mi as PropertyInfo; - if (pi != null) { - MethodBase pmi = pi.GetGetMethod (true); - if (pmi == null) - pmi = pi.GetSetMethod (true); - if (GetParameterData (pmi).Count > 0) - mi = pmi; - } - return (mi is MethodBase) - ? CSharpSignature (mi as MethodBase) - : CSharpName (mi.DeclaringType) + '.' + mi.Name; + if (IsBuiltinType (t)) + return true; + + if (IsEnumType (t)) + return true; + + return false; } -#if GMCS_SOURCE - private static int GetFullName (Type t, StringBuilder sb) + // + // Whether a type is unmanaged. This is used by the unsafe code (25.2) + // + public static bool IsUnmanagedType (TypeSpec t) { - int pos = 0; + var ds = t.MemberDefinition as DeclSpace; + if (ds != null) + return ds.IsUnmanagedType (); - if (!t.IsGenericType) { - sb.Append (t.FullName); - return 0; - } + // some builtins that are not unmanaged types + if (t == TypeManager.object_type || t == TypeManager.string_type) + return false; - if (t.DeclaringType != null) { - pos = GetFullName (t.DeclaringType, sb); - sb.Append ('.'); - } else if (t.Namespace != null && t.Namespace.Length != 0) { - sb.Append (t.Namespace); - sb.Append ('.'); - } - sb.Append (RemoveGenericArity (t.Name)); - - Type[] this_args = GetTypeArguments (t); - - if (this_args.Length < pos) - throw new InternalErrorException ( - "Enclosing class " + t.DeclaringType + " has more type arguments than " + t); - if (this_args.Length == pos) - return pos; - - sb.Append ('<'); - for (;;) { - sb.Append (CSharpName (this_args [pos++])); - if (pos == this_args.Length) - break; - sb.Append (','); - } - sb.Append ('>'); - return pos; - } + if (IsBuiltinOrEnum (t)) + return true; - static string GetFullName (Type t) - { - if (t.IsArray) { - string dimension = t.Name.Substring (t.Name.LastIndexOf ('[')); - return GetFullName (t.GetElementType ()) + dimension; - } + // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it. + if (t.IsPointer) + return IsUnmanagedType (GetElementType (t)); - if (IsNullableType (t) && !t.IsGenericTypeDefinition) { - t = GetTypeArguments (t)[0]; - return CSharpName (t) + "?"; - } + if (!IsValueType (t)) + return false; - if (t.IsGenericParameter) - return t.Name; - if (!t.IsGenericType) - return t.FullName; + if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric) + return false; - StringBuilder sb = new StringBuilder (); - int pos = GetFullName (t, sb); - if (pos <= 0) - throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments"); - return sb.ToString (); + return true; } -#else - public static string GetFullName (Type t) + + // + // Null is considered to be a reference type + // + public static bool IsReferenceType (TypeSpec t) { - return t.FullName; - } -#endif + if (t.IsGenericParameter) + return ((TypeParameterSpec) t).IsReferenceType; - public static string RemoveGenericArity (string from) + return !t.IsStruct && !IsEnumType (t); + } + + public static bool IsValueType (TypeSpec t) { - int i = from.IndexOf ('`'); - if (i > 0) - return from.Substring (0, i); - return from; + if (t.IsGenericParameter) + return ((TypeParameterSpec) t).IsValueType; + + return t.IsStruct || IsEnumType (t); } - /// - /// When we need to report accessors as well - /// - static public string CSharpSignature (MethodBase mb) + public static bool IsStruct (TypeSpec t) { - return CSharpSignature (mb, false); + return t.IsStruct; } - /// - /// Returns the signature of the method - /// - static public string CSharpSignature (MethodBase mb, bool show_accessor) + public static bool IsSubclassOf (TypeSpec type, TypeSpec base_type) { - StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType)); - sig.Append ('.'); - - AParametersCollection iparams = GetParameterData (mb); - string parameters = iparams.GetSignatureForError (); - int accessor_end = 0; - - if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) { - string op_name = Operator.GetName (mb.Name); - if (op_name != null) { - sig.Append ("operator "); - sig.Append (op_name); - sig.Append (parameters); - return sig.ToString (); - } + do { + if (type == base_type) + return true; - bool is_getter = mb.Name.StartsWith ("get_"); - bool is_setter = mb.Name.StartsWith ("set_"); - if (is_getter || is_setter || mb.Name.StartsWith ("add_")) { - accessor_end = 3; - } else if (mb.Name.StartsWith ("remove_")) { - accessor_end = 6; - } + type = type.BaseType; + } while (type != null); - // Is indexer - if (iparams.Count > (is_getter ? 0 : 1)) { - sig.Append ("this["); - if (is_getter) - sig.Append (parameters.Substring (1, parameters.Length - 2)); - else - sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1)); - sig.Append (']'); - } else { - sig.Append (mb.Name.Substring (accessor_end + 1)); - } - } else { - if (mb.Name == ".ctor") - sig.Append (RemoveGenericArity (mb.DeclaringType.Name)); - else { - sig.Append (mb.Name); - -#if GMCS_SOURCE - if (TypeManager.IsGenericMethod (mb)) { - Type[] args = mb.GetGenericArguments (); - sig.Append ('<'); - for (int i = 0; i < args.Length; i++) { - if (i > 0) - sig.Append (','); - sig.Append (CSharpName (args [i])); - } - sig.Append ('>'); - } -#endif - } + return false; + } - sig.Append (parameters); - } + public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent) + { +// TypeParameter tparam = LookupTypeParameter (type); +// TypeParameter pparam = LookupTypeParameter (parent); + + if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) { + if (type == parent) + return true; - if (show_accessor && accessor_end > 0) { - sig.Append ('.'); - sig.Append (mb.Name.Substring (0, accessor_end)); + throw new NotImplementedException ("net"); +// return tparam.IsSubclassOf (parent); } - return sig.ToString (); - } + do { + if (IsInstantiationOfSameGenericType (type, parent)) + return true; - public static string GetMethodName (MethodInfo m) - { -#if GMCS_SOURCE - if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m)) - return m.Name; - - return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length); -#else - return m.Name; -#endif - } + type = type.BaseType; + } while (type != null); - static public string CSharpSignature (EventInfo ei) - { - return CSharpName (ei.DeclaringType) + "." + ei.Name; + return false; } // - // Looks up a type, and aborts if it is not found. This is used - // by predefined types required by the compiler + // Checks whether `type' is a subclass or nested child of `base_type'. // - public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required) + public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type) { - Expression expr; - if (RootContext.StdLib) { - Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true); - expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null); - } else { - if (!required) - Report.DisableReporting (); - - TypeLookupExpression tle = new TypeLookupExpression (ns_name + "." + name); - expr = tle.ResolveAsTypeTerminal (RootContext.ToplevelTypes, false); - - if (!required) - Report.EnableReporting (); - } - - if (expr == null) { - if (required) { - Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", - ns_name, name); - } - return null; - } + do { + if (IsFamilyAccessible (type, base_type)) + return true; - Type t = expr.Type; - if (RootContext.StdLib || t == null || !required) - return t; - - // TODO: All predefined imported types have to have correct signature - if (t.Module != CodeGen.Module.Builder) - return t; - - DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName); - if (ds is Delegate) { - if (type_kind == Kind.Delegate) - return t; - } else { - TypeContainer tc = (TypeContainer)ds; - if (tc.Kind == type_kind) - return t; - } + // Handle nested types. + type = type.DeclaringType; + } while (type != null); - Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly", - ns_name, name); - return null; + return false; } - static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args) + // + // Checks whether `type' is a nested child of `parent'. + // + public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent) { - const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly; - - MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null); - if (members != null) { - for (int i = 0; i < members.Length; ++i) { - MemberInfo member = members [i]; - if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) { - MethodBase mb = member as MethodBase; - if (mb == null) - continue; - - AParametersCollection pd = TypeManager.GetParameterData (mb); - if (IsEqual (pd.Types, args)) - return member; - } - if (mt == MemberTypes.Field) { - FieldInfo fi = member as FieldInfo; - if (fi == null) - continue; - - if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0])) - continue; + if (type == null) + return false; - return member; - } + type = type.GetDefinition (); // DropGenericTypeArguments (type); + parent = parent.GetDefinition (); // DropGenericTypeArguments (parent); - if (mt == MemberTypes.Property) { - PropertyInfo pi = member as PropertyInfo; - if (pi == null) - continue; + if (IsEqual (type, parent)) + return false; - if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0])) - continue; + type = type.DeclaringType; + while (type != null) { + if (IsEqual (type.GetDefinition (), parent)) + return true; - return member; - } - } + type = type.DeclaringType; } - string method_args = null; - if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) - method_args = "(" + TypeManager.CSharpName (args) + ")"; - - Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible", - TypeManager.CSharpName (t), name, method_args); - - return null; + return false; } - // - // Returns the ConstructorInfo for "args" - // - public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args) + public static bool IsSpecialType (TypeSpec t) { - return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args); + return t == arg_iterator_type || t == typed_reference_type; } // - // Returns the MethodInfo for a method named `name' defined - // in type `t' which takes arguments of types `args' + // Checks whether `invocationAssembly' is same or a friend of the assembly // - public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args) - { - return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args); - } - - public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args) - { - return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args); - } - - public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args) - { - return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args); - } - - /// - /// The types have to be initialized after the initial - /// population of the type has happened (for example, to - /// bootstrap the corlib.dll - /// - public static bool InitCoreTypes () + public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly) { - object_type = CoreLookupType ("System", "Object", Kind.Class, true); - system_object_expr.Type = object_type; - value_type = CoreLookupType ("System", "ValueType", Kind.Class, true); - system_valuetype_expr.Type = value_type; - attribute_type = CoreLookupType ("System", "Attribute", Kind.Class, true); - - int32_type = CoreLookupType ("System", "Int32", Kind.Struct, true); - int64_type = CoreLookupType ("System", "Int64", Kind.Struct, true); - uint32_type = CoreLookupType ("System", "UInt32", Kind.Struct, true); - uint64_type = CoreLookupType ("System", "UInt64", Kind.Struct, true); - byte_type = CoreLookupType ("System", "Byte", Kind.Struct, true); - sbyte_type = CoreLookupType ("System", "SByte", Kind.Struct, true); - short_type = CoreLookupType ("System", "Int16", Kind.Struct, true); - ushort_type = CoreLookupType ("System", "UInt16", Kind.Struct, true); - - ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator", Kind.Interface, true); - ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable", Kind.Interface, true); - idisposable_type = CoreLookupType ("System", "IDisposable", Kind.Interface, true); - - // HACK: DefineType immediately resolves iterators (very wrong) - generic_ienumerator_type = CoreLookupType ("System.Collections.Generic", "IEnumerator`1", Kind.Interface, false); - - char_type = CoreLookupType ("System", "Char", Kind.Struct, true); - string_type = CoreLookupType ("System", "String", Kind.Class, true); - float_type = CoreLookupType ("System", "Single", Kind.Struct, true); - double_type = CoreLookupType ("System", "Double", Kind.Struct, true); - decimal_type = CoreLookupType ("System", "Decimal", Kind.Struct, true); - bool_type = CoreLookupType ("System", "Boolean", Kind.Struct, true); - intptr_type = CoreLookupType ("System", "IntPtr", Kind.Struct, true); - uintptr_type = CoreLookupType ("System", "UIntPtr", Kind.Struct, true); - - multicast_delegate_type = CoreLookupType ("System", "MulticastDelegate", Kind.Class, true); - delegate_type = CoreLookupType ("System", "Delegate", Kind.Class, true); - - enum_type = CoreLookupType ("System", "Enum", Kind.Class, true); - array_type = CoreLookupType ("System", "Array", Kind.Class, true); - void_type = CoreLookupType ("System", "Void", Kind.Struct, true); - type_type = CoreLookupType ("System", "Type", Kind.Class, true); - exception_type = CoreLookupType ("System", "Exception", Kind.Class, true); - - runtime_field_handle_type = CoreLookupType ("System", "RuntimeFieldHandle", Kind.Struct, true); - runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle", Kind.Struct, true); - - param_array_type = CoreLookupType ("System", "ParamArrayAttribute", Kind.Class, true); - out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute", Kind.Class, true); - - return Report.Errors == 0; - } + if (assembly == null) + throw new ArgumentNullException ("assembly"); - // - // Initializes optional core types - // - public static void InitOptionalCoreTypes () - { - void_ptr_type = GetPointerType (void_type); - char_ptr_type = GetPointerType (char_type); + // TODO: This can happen for constants used at assembly level and + // predefined members + // But there is no way to test for it for now, so it could be abused + // elsewhere too. + if (invocationAssembly == null) + invocationAssembly = CodeGen.Assembly.Builder; - // - // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate - // types cache with incorrect accessiblity when any of optional types is internal. - // - internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute", Kind.Class, false); + if (invocationAssembly == assembly) + return true; - runtime_argument_handle_type = CoreLookupType ("System", "RuntimeArgumentHandle", Kind.Struct, false); - asynccallback_type = CoreLookupType ("System", "AsyncCallback", Kind.Delegate, false); - iasyncresult_type = CoreLookupType ("System", "IAsyncResult", Kind.Interface, false); - typed_reference_type = CoreLookupType ("System", "TypedReference", Kind.Struct, false); - arg_iterator_type = CoreLookupType ("System", "ArgIterator", Kind.Struct, false); - mbr_type = CoreLookupType ("System", "MarshalByRefObject", Kind.Class, false); + bool value; + if (assembly_internals_vis_attrs.TryGetValue (assembly, out value)) + return value; - // - // Optional attributes, used for error reporting only - // - obsolete_attribute_type = CoreLookupType ("System", "ObsoleteAttribute", Kind.Class, false); - if (obsolete_attribute_type != null) { - Class c = TypeManager.LookupClass (obsolete_attribute_type); - if (c != null) - c.DefineMembers (); + object[] attrs = assembly.GetCustomAttributes (typeof (InternalsVisibleToAttribute), false); + if (attrs.Length == 0) { + assembly_internals_vis_attrs.Add (assembly, false); + return false; } - dllimport_type = CoreLookupType ("System.Runtime.InteropServices", "DllImportAttribute", Kind.Class, false); - methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "MethodImplAttribute", Kind.Class, false); -#if !NET_2_0 - marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices", "MarshalAsAttribute", Kind.Class, false); -#endif - in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute", Kind.Class, false); - indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices", "IndexerNameAttribute", Kind.Class, false); - conditional_attribute_type = CoreLookupType ("System.Diagnostics", "ConditionalAttribute", Kind.Class, false); - cls_compliant_attribute_type = CoreLookupType ("System", "CLSCompliantAttribute", Kind.Class, false); - security_attr_type = CoreLookupType ("System.Security.Permissions", "SecurityAttribute", Kind.Class, false); - required_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RequiredAttributeAttribute", Kind.Class, false); - guid_attr_type = CoreLookupType ("System.Runtime.InteropServices", "GuidAttribute", Kind.Class, false); - assembly_culture_attribute_type = CoreLookupType ("System.Reflection", "AssemblyCultureAttribute", Kind.Class, false); - assembly_version_attribute_type = CoreLookupType ("System.Reflection", "AssemblyVersionAttribute", Kind.Class, false); - comimport_attr_type = CoreLookupType ("System.Runtime.InteropServices", "ComImportAttribute", Kind.Class, false); - coclass_attr_type = CoreLookupType ("System.Runtime.InteropServices", "CoClassAttribute", Kind.Class, false); - attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute", Kind.Class, false); - default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute", Kind.Class, false); - - // New in .NET 2.0 - default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute", Kind.Class, false); - type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute", Kind.Class, false); - generic_ilist_type = CoreLookupType ("System.Collections.Generic", "IList`1", Kind.Interface, false); - generic_icollection_type = CoreLookupType ("System.Collections.Generic", "ICollection`1", Kind.Interface, false); - generic_ienumerable_type = CoreLookupType ("System.Collections.Generic", "IEnumerable`1", Kind.Interface, false); - generic_nullable_type = CoreLookupType ("System", "Nullable`1", Kind.Struct, false); + bool is_friend = false; - // - // Optional types which are used as types and for member lookup - // - default_member_type = CoreLookupType ("System.Reflection", "DefaultMemberAttribute", Kind.Class, false); - runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false); - decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "DecimalConstantAttribute", Kind.Class, false); - struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "StructLayoutAttribute", Kind.Class, false); - field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "FieldOffsetAttribute", Kind.Class, false); + AssemblyName this_name = CodeGen.Assembly.Name; + if (this_name == null) + return false; - // New in .NET 2.0 - fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute", Kind.Class, false); + byte [] this_token = this_name.GetPublicKeyToken (); + foreach (InternalsVisibleToAttribute attr in attrs) { + if (attr.AssemblyName == null || attr.AssemblyName.Length == 0) + continue; + + AssemblyName aname = null; + try { + aname = new AssemblyName (attr.AssemblyName); + } catch (FileLoadException) { + } catch (ArgumentException) { + } - // New in .NET 3.5 - extension_attribute_type = CoreLookupType ("System.Runtime.CompilerServices", "ExtensionAttribute", Kind.Class, false); - expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", Kind.Class, false); - - if (!RootContext.StdLib) { - // - // HACK: When building Mono corlib mcs uses loaded mscorlib which - // has different predefined types and this method sets mscorlib types - // to be same to avoid any type check errors. - // - - Type type = typeof (Type); - Type [] system_4_type_arg = { type, type, type, type }; - - MethodInfo set_corlib_type_builders = - typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod ( - "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null, - system_4_type_arg, null); - - if (set_corlib_type_builders != null) { - object[] args = new object [4]; - args [0] = object_type; - args [1] = value_type; - args [2] = enum_type; - args [3] = void_type; + if (aname == null || aname.Name != this_name.Name) + continue; + + byte [] key_token = aname.GetPublicKeyToken (); + if (key_token != null) { + if (this_token.Length == 0) { + // Same name, but assembly is not strongnamed + Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report); + break; + } - set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args); - } else { - Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method", - TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)), - TypeManager.CSharpName (system_4_type_arg)); + if (!CompareKeyTokens (this_token, key_token)) + continue; } + + is_friend = true; + break; } - system_string_expr.Type = string_type; - system_boolean_expr.Type = bool_type; - system_decimal_expr.Type = decimal_type; - system_single_expr.Type = float_type; - system_double_expr.Type = double_type; - system_sbyte_expr.Type = sbyte_type; - system_byte_expr.Type = byte_type; - system_int16_expr.Type = short_type; - system_uint16_expr.Type = ushort_type; - system_int32_expr.Type = int32_type; - system_uint32_expr.Type = uint32_type; - system_int64_expr.Type = int64_type; - system_uint64_expr.Type = uint64_type; - system_char_expr.Type = char_type; - system_void_expr.Type = void_type; + assembly_internals_vis_attrs.Add (assembly, is_friend); + return is_friend; + } - // - // These are only used for compare purposes - // - anonymous_method_type = typeof (AnonymousMethodBody); - null_type = typeof (NullLiteral); + static bool CompareKeyTokens (byte [] token1, byte [] token2) + { + for (int i = 0; i < token1.Length; i++) + if (token1 [i] != token2 [i]) + return false; + + return true; } - const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance; + static void Error_FriendAccessNameNotMatching (string other_name, Report Report) + { + Report.Error (281, + "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it", + other_name, CodeGen.Assembly.Name.FullName); + } - /// - /// This is the "old", non-cache based FindMembers() function. We cannot use - /// the cache here because there is no member name argument. - /// - public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) + public static TypeSpec GetElementType (TypeSpec t) { -#if MS_COMPATIBLE && GMCS_SOURCE - if (t.IsGenericType) - t = t.GetGenericTypeDefinition (); -#endif + return ((ElementTypeSpec)t).Element; + } - DeclSpace decl = (DeclSpace) builder_to_declspace [t]; + /// + /// This method is not implemented by MS runtime for dynamic types + /// + public static bool HasElementType (TypeSpec t) + { + return t is ElementTypeSpec; + } - // - // `builder_to_declspace' contains all dynamic types. - // - if (decl != null) { - MemberList list; - Timer.StartTimer (TimerType.FindMembers); - list = decl.FindMembers (mt, bf, filter, criteria); - Timer.StopTimer (TimerType.FindMembers); - return list; - } + static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat; - // - // We have to take care of arrays specially, because GetType on - // a TypeBuilder array will return a Type, not a TypeBuilder, - // and we can not call FindMembers on this type. - // - if ( -#if MS_COMPATIBLE && GMCS_SOURCE - !t.IsGenericType && -#endif - t.IsSubclassOf (TypeManager.array_type)) - return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria)); - -#if GMCS_SOURCE - if (t is GenericTypeParameterBuilder) { - TypeParameter tparam = (TypeParameter) builder_to_type_param [t]; - - Timer.StartTimer (TimerType.FindMembers); - MemberList list = tparam.FindMembers ( - mt, bf | BindingFlags.DeclaredOnly, filter, criteria); - Timer.StopTimer (TimerType.FindMembers); - return list; + // This is a custom version of Convert.ChangeType() which works + // with the TypeBuilder defined types when compiling corlib. + public static object ChangeType (object value, TypeSpec targetType, out bool error) + { + IConvertible convert_value = value as IConvertible; + + if (convert_value == null){ + error = true; + return null; } -#endif - + // - // Since FindMembers will not lookup both static and instance - // members, we emulate this behaviour here. + // We cannot rely on build-in type conversions as they are + // more limited than what C# supports. + // See char -> float/decimal/double conversion // - if ((bf & instance_and_static) == instance_and_static){ - MemberInfo [] i_members = t.FindMembers ( - mt, bf & ~BindingFlags.Static, filter, criteria); - - int i_len = i_members.Length; - if (i_len == 1){ - MemberInfo one = i_members [0]; - - // - // If any of these are present, we are done! - // - if ((one is Type) || (one is EventInfo) || (one is FieldInfo)) - return new MemberList (i_members); + error = false; + try { + if (targetType == TypeManager.bool_type) + return convert_value.ToBoolean (nf_provider); + if (targetType == TypeManager.byte_type) + return convert_value.ToByte (nf_provider); + if (targetType == TypeManager.char_type) + return convert_value.ToChar (nf_provider); + if (targetType == TypeManager.short_type) + return convert_value.ToInt16 (nf_provider); + if (targetType == TypeManager.int32_type) + return convert_value.ToInt32 (nf_provider); + if (targetType == TypeManager.int64_type) + return convert_value.ToInt64 (nf_provider); + if (targetType == TypeManager.sbyte_type) + return convert_value.ToSByte (nf_provider); + + if (targetType == TypeManager.decimal_type) { + if (convert_value.GetType () == typeof (char)) + return (decimal) convert_value.ToInt32 (nf_provider); + return convert_value.ToDecimal (nf_provider); } - - MemberInfo [] s_members = t.FindMembers ( - mt, bf & ~BindingFlags.Instance, filter, criteria); - - int s_len = s_members.Length; - if (i_len > 0 || s_len > 0) - return new MemberList (i_members, s_members); - else { - if (i_len > 0) - return new MemberList (i_members); - else - return new MemberList (s_members); + + if (targetType == TypeManager.double_type) { + if (convert_value.GetType () == typeof (char)) + return (double) convert_value.ToInt32 (nf_provider); + return convert_value.ToDouble (nf_provider); } - } - return new MemberList (t.FindMembers (mt, bf, filter, criteria)); - } + if (targetType == TypeManager.float_type) { + if (convert_value.GetType () == typeof (char)) + return (float)convert_value.ToInt32 (nf_provider); + return convert_value.ToSingle (nf_provider); + } + if (targetType == TypeManager.string_type) + return convert_value.ToString (nf_provider); + if (targetType == TypeManager.ushort_type) + return convert_value.ToUInt16 (nf_provider); + if (targetType == TypeManager.uint32_type) + return convert_value.ToUInt32 (nf_provider); + if (targetType == TypeManager.uint64_type) + return convert_value.ToUInt64 (nf_provider); + if (targetType == TypeManager.object_type) + return value; + + error = true; + } catch { + error = true; + } + return null; + } /// - /// This method is only called from within MemberLookup. It tries to use the member - /// cache if possible and falls back to the normal FindMembers if not. The `used_cache' - /// flag tells the caller whether we used the cache or not. If we used the cache, then - /// our return value will already contain all inherited members and the caller don't need - /// to check base classes and interfaces anymore. + /// Utility function that can be used to probe whether a type + /// is managed or not. /// - private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, - string name, out bool used_cache) + public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc) { - MemberCache cache; + while (t.IsPointer) + t = GetElementType (t); - // - // If this is a dynamic type, it's always in the `builder_to_declspace' hash table - // and we can ask the DeclSpace for the MemberCache. - // -#if MS_COMPATIBLE - if (t.Assembly == CodeGen.Assembly.Builder) { - if (t.IsGenericParameter) { - TypeParameter tparam = (TypeParameter) builder_to_type_param[t]; + if (IsUnmanagedType (t)) + return true; - used_cache = true; - if (tparam.MemberCache == null) - return new MemberInfo[0]; + ctx.Report.SymbolRelatedToPreviousError (t); + ctx.Report.Error (208, loc, + "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'", + CSharpName (t)); - return tparam.MemberCache.FindMembers ( - mt, bf, name, FilterWithClosure_delegate, null); - } + return false; + } + + // + // Returns whether the array of memberinfos contains the given method + // + public static bool ArrayContainsMethod (List array, MethodSpec new_method, bool ignoreDeclType) + { + AParametersCollection new_args = new_method.Parameters; - if (t.IsGenericType && !t.IsGenericTypeDefinition) - t = t.GetGenericTypeDefinition (); -#else - if (t is TypeBuilder) { -#endif - DeclSpace decl = (DeclSpace) builder_to_declspace [t]; - cache = decl.MemberCache; - - // - // If this DeclSpace has a MemberCache, use it. - // - - if (cache != null) { - used_cache = true; - return cache.FindMembers ( - mt, bf, name, FilterWithClosure_delegate, null); - } + foreach (MethodSpec method in array) { + if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType) + continue; - // If there is no MemberCache, we need to use the "normal" FindMembers. - // Note, this is a VERY uncommon route! + if (method.Name != new_method.Name) + continue; - MemberList list; - Timer.StartTimer (TimerType.FindMembers); - list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly, - FilterWithClosure_delegate, name); - Timer.StopTimer (TimerType.FindMembers); - used_cache = false; - return (MemberInfo []) list; - } + if (!TypeSpecComparer.Override.IsEqual (method.ReturnType, new_method.ReturnType)) + continue; - // - // We have to take care of arrays specially, because GetType on - // a TypeBuilder array will return a Type, not a TypeBuilder, - // and we can not call FindMembers on this type. - // - if (t.IsArray) { - used_cache = true; - return TypeHandle.ArrayType.MemberCache.FindMembers ( - mt, bf, name, FilterWithClosure_delegate, null); - } + AParametersCollection old_args = method.Parameters; + int old_count = old_args.Count; + int i; -#if GMCS_SOURCE - if (t is GenericTypeParameterBuilder) { - TypeParameter tparam = (TypeParameter) builder_to_type_param [t]; + if (new_args.Count != old_count) + continue; - used_cache = true; - if (tparam.MemberCache == null) - return new MemberInfo [0]; + for (i = 0; i < old_count; i++) { + if (!TypeSpecComparer.Override.IsEqual (old_args.Types[i], new_args.Types[i])) + break; + } + if (i != old_count) + continue; - return tparam.MemberCache.FindMembers ( - mt, bf, name, FilterWithClosure_delegate, null); - } -#endif - - if (IsGenericType (t) && (mt == MemberTypes.NestedType)) { - // - // This happens if we're resolving a class'es base class and interfaces - // in TypeContainer.DefineType(). At this time, the types aren't - // populated yet, so we can't use the cache. - // - MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly, - FilterWithClosure_delegate, name); - used_cache = false; - return info; + return true; } - // - // This call will always succeed. There is exactly one TypeHandle instance per - // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return - // the corresponding MemberCache. - // - cache = TypeHandle.GetMemberCache (t); - - used_cache = true; - return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null); + return false; } - - public static bool IsBuiltinType (Type t) +#region Generics + // This method always return false for non-generic compiler, + // while Type.IsGenericParameter is returned if it is supported. + public static bool IsGenericParameter (TypeSpec type) { - t = TypeToCoreType (t); - if (t == object_type || t == string_type || t == int32_type || t == uint32_type || - t == int64_type || t == uint64_type || t == float_type || t == double_type || - t == char_type || t == short_type || t == decimal_type || t == bool_type || - t == sbyte_type || t == byte_type || t == ushort_type || t == void_type) - return true; - else - return false; + return type.IsGenericParameter; } - // - // This is like IsBuiltinType, but lacks decimal_type, we should also clean up - // the pieces in the code where we use IsBuiltinType and special case decimal_type. - // - public static bool IsPrimitiveType (Type t) + public static bool IsGenericType (TypeSpec type) { - return (t == int32_type || t == uint32_type || - t == int64_type || t == uint64_type || t == float_type || t == double_type || - t == char_type || t == short_type || t == bool_type || - t == sbyte_type || t == byte_type || t == ushort_type); + return type.IsGeneric; } - public static bool IsDelegateType (Type t) + // TODO: Implement correctly + public static bool ContainsGenericParameters (TypeSpec type) { -#if GMCS_SOURCE - if (t.IsGenericParameter) - return false; -#endif - - if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type) - return false; - - t = DropGenericTypeArguments (t); - return IsSubclassOf (t, TypeManager.delegate_type); + return type.GetMetaInfo ().ContainsGenericParameters; } - - public static bool IsEnumType (Type t) + + public static bool IsEqual (TypeSpec a, TypeSpec b) { - t = DropGenericTypeArguments (t); - return t.BaseType == TypeManager.enum_type; + return a == b && !(a is InternalType); } - public static bool IsBuiltinOrEnum (Type t) + public static TypeSpec[] GetTypeArguments (TypeSpec t) { - if (IsBuiltinType (t)) - return true; - - if (IsEnumType (t)) - return true; + // TODO: return empty array !! + return t.TypeArguments; + } - return false; + /// + /// Check whether `type' and `parent' are both instantiations of the same + /// generic type. Note that we do not check the type parameters here. + /// + public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent) + { + return type == parent || type.MemberDefinition == parent.MemberDefinition; } - public static bool IsAttributeType (Type t) + public static bool IsNullableType (TypeSpec t) { - return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type); + return generic_nullable_type == t.GetDefinition (); } - - static Stack unmanaged_enclosing_types = new Stack (4); +#endregion // - // Whether a type is unmanaged. This is used by the unsafe code (25.2) - // - public static bool IsUnmanagedType (Type t) - { - // Avoid infloops in the case of: unsafe struct Foo { Foo *x; } - if (unmanaged_enclosing_types.Contains (t)) - return true; - - // builtins that are not unmanaged types - if (t == TypeManager.object_type || t == TypeManager.string_type) - return false; - - if (IsGenericType (t) || IsGenericParameter (t)) - return false; - - if (IsBuiltinOrEnum (t)) - return true; - - // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it. - if (t.IsPointer) - return true; - - // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)] - if (t.IsArray) - return false; - - if (!IsValueType (t)) - return false; - -#if GMCS_SOURCE - for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) { - if (p.IsGenericTypeDefinition) - return false; - } -#endif - - unmanaged_enclosing_types.Push (t); - - bool retval = true; - - if (t is TypeBuilder) { - TypeContainer tc = LookupTypeContainer (t); - if (tc.Fields != null){ - foreach (FieldBase f in tc.Fields){ - // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked. - if ((f.ModFlags & Modifiers.STATIC) != 0) - continue; - if (f.MemberType == null) - continue; - if (!IsUnmanagedType (f.MemberType)){ - Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name); - retval = false; - } - } - } - } else { - FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - foreach (FieldInfo f in fields){ - if (!IsUnmanagedType (f.FieldType)){ - Report.SymbolRelatedToPreviousError (f); - retval = false; - } - } - } - - unmanaged_enclosing_types.Pop (); - - return retval; - } - - // - // Null is considered to be a reference type - // - public static bool IsReferenceType (Type t) - { - if (TypeManager.IsGenericParameter (t)) { - GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t); - if (constraints == null) - return false; - - return constraints.IsReferenceType; - } - - return !t.IsValueType; - } - - public static bool IsValueType (Type t) - { - return t.IsValueType || IsGenericParameter (t); - } - - public static bool IsInterfaceType (Type t) - { - TypeContainer tc = (TypeContainer) builder_to_declspace [t]; - if (tc == null) - return false; - - return tc.Kind == Kind.Interface; - } - - public static bool IsSubclassOf (Type type, Type base_type) - { - TypeParameter tparam = LookupTypeParameter (type); - TypeParameter pparam = LookupTypeParameter (base_type); - - if ((tparam != null) && (pparam != null)) { - if (tparam == pparam) - return true; - - return tparam.IsSubclassOf (base_type); - } - -#if MS_COMPATIBLE && GMCS_SOURCE - if (type.IsGenericType) - type = type.GetGenericTypeDefinition (); -#endif - - if (type.IsSubclassOf (base_type)) - return true; - - do { - if (IsEqual (type, base_type)) - return true; - - type = type.BaseType; - } while (type != null); - - return false; - } - - public static bool IsPrivateAccessible (Type type, Type parent) - { - if (type == null) - return false; - - if (type.Equals (parent)) - return true; - - return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent); - } - - public static bool IsFamilyAccessible (Type type, Type parent) - { - TypeParameter tparam = LookupTypeParameter (type); - TypeParameter pparam = LookupTypeParameter (parent); - - if ((tparam != null) && (pparam != null)) { - if (tparam == pparam) - return true; - - return tparam.IsSubclassOf (parent); - } - - do { - if (IsInstantiationOfSameGenericType (type, parent)) - return true; - - type = type.BaseType; - } while (type != null); - - return false; - } - - // - // Checks whether `type' is a subclass or nested child of `base_type'. - // - public static bool IsNestedFamilyAccessible (Type type, Type base_type) - { - do { - if (IsFamilyAccessible (type, base_type)) - return true; - - // Handle nested types. - type = type.DeclaringType; - } while (type != null); - - return false; - } - - // - // Checks whether `type' is a nested child of `parent'. - // - public static bool IsNestedChildOf (Type type, Type parent) - { - if (type == null) - return false; - - type = DropGenericTypeArguments (type); - parent = DropGenericTypeArguments (parent); - - if (IsEqual (type, parent)) - return false; - - type = type.DeclaringType; - while (type != null) { - if (IsEqual (type, parent)) - return true; - - type = type.DeclaringType; - } - - return false; - } - - // - // Checks whether `extern_type' is friend of the output assembly - // - public static bool IsThisOrFriendAssembly (Assembly assembly) - { - if (assembly == CodeGen.Assembly.Builder) - return true; - - if (assembly_internals_vis_attrs.Contains (assembly)) - return (bool)(assembly_internals_vis_attrs [assembly]); - - if (internals_visible_attr_type == null) - return false; - - object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false); - if (attrs.Length == 0) { - assembly_internals_vis_attrs.Add (assembly, false); - return false; - } - - bool is_friend = false; -#if GMCS_SOURCE - AssemblyName this_name = CodeGen.Assembly.Name; - byte [] this_token = this_name.GetPublicKeyToken (); - foreach (InternalsVisibleToAttribute attr in attrs) { - if (attr.AssemblyName == null || attr.AssemblyName.Length == 0) - continue; - - AssemblyName aname = null; - try { - aname = new AssemblyName (attr.AssemblyName); - } catch (FileLoadException) { - } catch (ArgumentException) { - } - - if (aname == null || aname.Name != this_name.Name) - continue; - - byte [] key_token = aname.GetPublicKeyToken (); - if (key_token != null) { - if (this_token.Length == 0) { - // Same name, but assembly is not strongnamed - Error_FriendAccessNameNotMatching (aname.FullName); - break; - } - - if (!CompareKeyTokens (this_token, key_token)) - continue; - } - - is_friend = true; - break; - } -#endif - assembly_internals_vis_attrs.Add (assembly, is_friend); - return is_friend; - } - -#if GMCS_SOURCE - static bool CompareKeyTokens (byte [] token1, byte [] token2) - { - for (int i = 0; i < token1.Length; i++) - if (token1 [i] != token2 [i]) - return false; - - return true; - } - - static void Error_FriendAccessNameNotMatching (string other_name) - { - Report.Error (281, "Friend access was granted to `" + other_name + - "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName + - "'. Try adding a reference to `" + other_name + - "' or change the output assembly name to match it"); - } -#endif - - // - // Do the right thing when returning the element type of an - // array type based on whether we are compiling corlib or not - // - public static Type GetElementType (Type t) - { - if (RootContext.StdLib) - return t.GetElementType (); - else - return TypeToCoreType (t.GetElementType ()); - } - - /// - /// This method is not implemented by MS runtime for dynamic types - /// - public static bool HasElementType (Type t) - { - return t.IsArray || t.IsPointer || t.IsByRef; - } - - public static Type GetEnumUnderlyingType (Type t) - { - t = DropGenericTypeArguments (t); - Enum e = LookupTypeContainer (t) as Enum; - if (e != null) - return e.UnderlyingType; - - // TODO: cache it ? - FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes); - if (fi == null) - return TypeManager.int32_type; - - return TypeToCoreType (fi.FieldType); - } - - /// - /// Gigantic work around for missing features in System.Reflection.Emit follows. - /// - /// - /// - /// Since System.Reflection.Emit can not return MethodBase.GetParameters - /// for anything which is dynamic, and we need this in a number of places, - /// we register this information here, and use it afterwards. - /// - static public void RegisterMethod (MethodBase mb, AParametersCollection ip) - { - method_params.Add (mb, ip); - } - - static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p) - { - method_params.Add (pb, p); - } - - static public AParametersCollection GetParameterData (MethodBase mb) - { - AParametersCollection pd = (AParametersCollection) method_params [mb]; - if (pd == null) { -#if MS_COMPATIBLE - if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) { - MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition (); - pd = GetParameterData (mi); - /* - if (mi.IsGenericMethod) - pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ()); - else - pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ()); - */ - method_params.Add (mb, pd); - return pd; - } - - if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) { - throw new InternalErrorException ("Parameters are not registered for method `{0}'", - TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name); - } - - pd = ParametersCollection.Create (mb); -#else - MethodBase generic = TypeManager.DropGenericMethodArguments (mb); - if (generic != mb) { - pd = TypeManager.GetParameterData (generic); - pd = ParametersCollection.Create (pd, mb); - } else { - pd = ParametersCollection.Create (mb); - } -#endif - method_params.Add (mb, pd); - } - return pd; - } - - public static AParametersCollection GetParameterData (PropertyInfo pi) - { - AParametersCollection pd = (AParametersCollection)method_params [pi]; - if (pd == null) { - if (pi is PropertyBuilder) - return Parameters.EmptyReadOnlyParameters; - - ParameterInfo [] p = pi.GetIndexParameters (); - if (p == null) - return Parameters.EmptyReadOnlyParameters; - - pd = ParametersCollection.Create (p, null); - method_params.Add (pi, pd); - } - - return pd; - } - - public static AParametersCollection GetDelegateParameters (Type t) - { - Delegate d = builder_to_declspace [t] as Delegate; - if (d != null) - return d.Parameters; - - MethodInfo invoke_mb = Delegate.GetInvokeMethod (t, t); - return GetParameterData (invoke_mb); - } - - static public void RegisterOverride (MethodBase override_method, MethodBase base_method) - { - if (!method_overrides.Contains (override_method)) - method_overrides [override_method] = base_method; - if (method_overrides [override_method] != base_method) - throw new InternalErrorException ("Override mismatch: " + override_method); - } - - static public bool IsOverride (MethodBase m) - { - m = DropGenericMethodArguments (m); - - return m.IsVirtual && - (m.Attributes & MethodAttributes.NewSlot) == 0 && - (m is MethodBuilder || method_overrides.Contains (m)); - } - - static public MethodBase TryGetBaseDefinition (MethodBase m) - { - m = DropGenericMethodArguments (m); - - return (MethodBase) method_overrides [m]; - } - - public static void RegisterConstant (FieldInfo fb, IConstant ic) - { - fields.Add (fb, ic); - } - - public static IConstant GetConstant (FieldInfo fb) - { - if (fb == null) - return null; - - return (IConstant)fields [fb]; - } - - public static void RegisterProperty (PropertyInfo pi, PropertyBase pb) - { - propertybuilder_to_property.Add (pi, pb); - } - - public static PropertyBase GetProperty (PropertyInfo pi) - { - return (PropertyBase)propertybuilder_to_property [pi]; - } - - static public void RegisterFieldBase (FieldBuilder fb, FieldBase f) - { - fieldbuilders_to_fields.Add (fb, f); - } - - // - // The return value can be null; This will be the case for - // auxiliary FieldBuilders created by the compiler that have no - // real field being declared on the source code - // - static public FieldBase GetField (FieldInfo fb) - { -#if GMCS_SOURCE - fb = GetGenericFieldDefinition (fb); -#endif - return (FieldBase) fieldbuilders_to_fields [fb]; - } - - static public MethodInfo GetAddMethod (EventInfo ei) - { - if (ei is MyEventBuilder) { - return ((MyEventBuilder)ei).GetAddMethod (true); - } - return ei.GetAddMethod (true); - } - - static public MethodInfo GetRemoveMethod (EventInfo ei) - { - if (ei is MyEventBuilder) { - return ((MyEventBuilder)ei).GetRemoveMethod (true); - } - return ei.GetRemoveMethod (true); - } - - static public void RegisterEventField (EventInfo einfo, EventField e) - { - if (events == null) - events = new Hashtable (); - - events.Add (einfo, e); - } - - static public EventField GetEventField (EventInfo ei) - { - if (events == null) - return null; - - return (EventField) events [ei]; - } - - public static bool CheckStructCycles (TypeContainer tc, Hashtable seen) - { - Hashtable hash = new Hashtable (); - return CheckStructCycles (tc, seen, hash); - } - - public static bool CheckStructCycles (TypeContainer tc, Hashtable seen, - Hashtable hash) - { - if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder)) - return true; - - // - // `seen' contains all types we've already visited. - // - if (seen.Contains (tc)) - return true; - seen.Add (tc, null); - - if (tc.Fields == null) - return true; - - foreach (FieldBase field in tc.Fields) { - if (field.FieldBuilder == null || field.FieldBuilder.IsStatic) - continue; - - Type ftype = field.FieldBuilder.FieldType; - TypeContainer ftc = LookupTypeContainer (ftype); - if (ftc == null) - continue; - - if (hash.Contains (ftc)) { - Report.Error (523, tc.Location, - "Struct member `{0}.{1}' of type `{2}' " + - "causes a cycle in the struct layout", - tc.Name, field.Name, ftc.Name); - return false; - } - - // - // `hash' contains all types in the current path. - // - hash.Add (tc, null); - - bool ok = CheckStructCycles (ftc, seen, hash); - - hash.Remove (tc); - - if (!ok) - return false; - - if (!seen.Contains (ftc)) - seen.Add (ftc, null); - } - - return true; - } - - /// - /// Given an array of interface types, expand and eliminate repeated ocurrences - /// of an interface. - /// - /// - /// - /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to - /// be IA, IB, IC. - /// - public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces) - { - ArrayList new_ifaces = new ArrayList (); - - foreach (TypeExpr iface in base_interfaces){ - Type itype = iface.Type; - - if (new_ifaces.Contains (itype)) - continue; - - new_ifaces.Add (itype); - - Type [] implementing = GetInterfaces (itype); - - foreach (Type imp in implementing){ - if (!new_ifaces.Contains (imp)) - new_ifaces.Add (imp); - } - } - Type [] ret = new Type [new_ifaces.Count]; - new_ifaces.CopyTo (ret, 0); - return ret; - } - - public static Type[] ExpandInterfaces (Type [] base_interfaces) - { - ArrayList new_ifaces = new ArrayList (); - - foreach (Type itype in base_interfaces){ - if (new_ifaces.Contains (itype)) - continue; - - new_ifaces.Add (itype); - - Type [] implementing = GetInterfaces (itype); - - foreach (Type imp in implementing){ - if (!new_ifaces.Contains (imp)) - new_ifaces.Add (imp); - } - } - Type [] ret = new Type [new_ifaces.Count]; - new_ifaces.CopyTo (ret, 0); - return ret; - } - - static PtrHashtable iface_cache = new PtrHashtable (); - - /// - /// This function returns the interfaces in the type `t'. Works with - /// both types and TypeBuilders. - /// - public static Type [] GetInterfaces (Type t) - { - Type [] cached = iface_cache [t] as Type []; - if (cached != null) - return cached; - - // - // The reason for catching the Array case is that Reflection.Emit - // will not return a TypeBuilder for Array types of TypeBuilder types, - // but will still throw an exception if we try to call GetInterfaces - // on the type. - // - // Since the array interfaces are always constant, we return those for - // the System.Array - // - - if (t.IsArray) - t = TypeManager.array_type; - - if ((t is TypeBuilder) || IsGenericType (t)) { - Type [] base_ifaces; - - if (t.BaseType == null) - base_ifaces = Type.EmptyTypes; - else - base_ifaces = GetInterfaces (t.BaseType); - Type[] type_ifaces; - if (IsGenericType (t)) -#if MS_COMPATIBLE && GMCS_SOURCE - type_ifaces = t.GetGenericTypeDefinition().GetInterfaces (); -#else - type_ifaces = t.GetInterfaces (); -#endif - else - type_ifaces = (Type []) builder_to_ifaces [t]; - if (type_ifaces == null || type_ifaces.Length == 0) - type_ifaces = Type.EmptyTypes; - - int base_count = base_ifaces.Length; - Type [] result = new Type [base_count + type_ifaces.Length]; - base_ifaces.CopyTo (result, 0); - type_ifaces.CopyTo (result, base_count); - - iface_cache [t] = result; - return result; -#if GMCS_SOURCE - } else if (t is GenericTypeParameterBuilder){ - Type[] type_ifaces = (Type []) builder_to_ifaces [t]; - if (type_ifaces == null || type_ifaces.Length == 0) - type_ifaces = Type.EmptyTypes; - - iface_cache [t] = type_ifaces; - return type_ifaces; -#endif - } else { - Type[] ifaces = t.GetInterfaces (); - iface_cache [t] = ifaces; - return ifaces; - } - } - - // - // gets the interfaces that are declared explicitly on t - // - public static Type [] GetExplicitInterfaces (TypeBuilder t) - { - return (Type []) builder_to_ifaces [t]; - } - - /// - /// The following is used to check if a given type implements an interface. - /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime. - /// - public static bool ImplementsInterface (Type t, Type iface) - { - Type [] interfaces; - - // - // FIXME OPTIMIZATION: - // as soon as we hit a non-TypeBuiler in the interface - // chain, we could return, as the `Type.GetInterfaces' - // will return all the interfaces implement by the type - // or its bases. - // - do { - interfaces = GetInterfaces (t); - - if (interfaces != null){ - foreach (Type i in interfaces){ - if (i == iface) - return true; - } - } - - t = t.BaseType; - } while (t != null); - - return false; - } - - static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat; - - // This is a custom version of Convert.ChangeType() which works - // with the TypeBuilder defined types when compiling corlib. - public static object ChangeType (object value, Type conversionType, out bool error) - { - IConvertible convert_value = value as IConvertible; - - if (convert_value == null){ - error = true; - return null; - } - - // - // NOTE 1: - // We must use Type.Equals() here since `conversionType' is - // the TypeBuilder created version of a system type and not - // the system type itself. You cannot use Type.GetTypeCode() - // on such a type - it'd always return TypeCode.Object. - // - // NOTE 2: - // We cannot rely on build-in type conversions as they are - // more limited than what C# supports. - // See char -> float/decimal/double conversion - // - - error = false; - try { - if (conversionType.Equals (typeof (Boolean))) - return (object)(convert_value.ToBoolean (nf_provider)); - if (conversionType.Equals (typeof (Byte))) - return (object)(convert_value.ToByte (nf_provider)); - if (conversionType.Equals (typeof (Char))) - return (object)(convert_value.ToChar (nf_provider)); - if (conversionType.Equals (typeof (DateTime))) - return (object)(convert_value.ToDateTime (nf_provider)); - - if (conversionType.Equals (decimal_type)) { - if (convert_value.GetType () == TypeManager.char_type) - return (decimal)convert_value.ToInt32 (nf_provider); - return convert_value.ToDecimal (nf_provider); - } - - if (conversionType.Equals (typeof (Double))) { - if (convert_value.GetType () == TypeManager.char_type) - return (double)convert_value.ToInt32 (nf_provider); - return convert_value.ToDouble (nf_provider); - } - - if (conversionType.Equals (typeof (Int16))) - return (object)(convert_value.ToInt16 (nf_provider)); - if (conversionType.Equals (int32_type)) - return (object)(convert_value.ToInt32 (nf_provider)); - if (conversionType.Equals (int64_type)) - return (object)(convert_value.ToInt64 (nf_provider)); - if (conversionType.Equals (typeof (SByte))) - return (object)(convert_value.ToSByte (nf_provider)); - - if (conversionType.Equals (typeof (Single))) { - if (convert_value.GetType () == TypeManager.char_type) - return (float)convert_value.ToInt32 (nf_provider); - return convert_value.ToSingle (nf_provider); - } - - if (conversionType.Equals (typeof (String))) - return (object)(convert_value.ToString (nf_provider)); - if (conversionType.Equals (typeof (UInt16))) - return (object)(convert_value.ToUInt16 (nf_provider)); - if (conversionType.Equals (typeof (UInt32))) - return (object)(convert_value.ToUInt32 (nf_provider)); - if (conversionType.Equals (typeof (UInt64))) - return (object)(convert_value.ToUInt64 (nf_provider)); - if (conversionType.Equals (typeof (Object))) - return (object)(value); - else - error = true; - } catch { - error = true; - } - return null; - } - - // - // When compiling with -nostdlib and the type is imported from an external assembly - // SRE uses "wrong" type and we have to convert it to the right compiler instance. - // - public static Type TypeToCoreType (Type t) - { - if (RootContext.StdLib || t.Module != typeof (object).Module) - return t; - - TypeCode tc = Type.GetTypeCode (t); - - switch (tc){ - case TypeCode.Boolean: - return TypeManager.bool_type; - case TypeCode.Byte: - return TypeManager.byte_type; - case TypeCode.SByte: - return TypeManager.sbyte_type; - case TypeCode.Char: - return TypeManager.char_type; - case TypeCode.Int16: - return TypeManager.short_type; - case TypeCode.UInt16: - return TypeManager.ushort_type; - case TypeCode.Int32: - return TypeManager.int32_type; - case TypeCode.UInt32: - return TypeManager.uint32_type; - case TypeCode.Int64: - return TypeManager.int64_type; - case TypeCode.UInt64: - return TypeManager.uint64_type; - case TypeCode.Single: - return TypeManager.float_type; - case TypeCode.Double: - return TypeManager.double_type; - case TypeCode.String: - return TypeManager.string_type; - case TypeCode.Decimal: - return TypeManager.decimal_type; - } - - if (t == typeof (void)) - return TypeManager.void_type; - if (t == typeof (object)) - return TypeManager.object_type; - if (t == typeof (System.Type)) - return TypeManager.type_type; - if (t == typeof (System.IntPtr)) - return TypeManager.intptr_type; - if (t == typeof (System.UIntPtr)) - return TypeManager.uintptr_type; -#if GMCS_SOURCE - if (t.IsArray) { - int dim = t.GetArrayRank (); - t = GetElementType (t); - return t.MakeArrayType (dim); - } - if (t.IsByRef) { - t = GetElementType (t); - return t.MakeByRefType (); - } - if (t.IsPointer) { - t = GetElementType (t); - return t.MakePointerType (); - } -#endif - return t; - } - - /// - /// Utility function that can be used to probe whether a type - /// is managed or not. - /// - public static bool VerifyUnManaged (Type t, Location loc) - { - if (IsUnmanagedType (t)) - return true; - - Report.Error (208, loc, "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'", - CSharpName (t)); - - return false; - } - - /// - /// Returns the name of the indexer in a given type. - /// - /// - /// The default is not always `Item'. The user can change this behaviour by - /// using the IndexerNameAttribute in the container. - /// For example, the String class indexer is named `Chars' not `Item' - /// - public static string IndexerPropertyName (Type t) - { - t = DropGenericTypeArguments (t); - if (t is TypeBuilder) { - TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t); - return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName; - } - - System.Attribute attr = System.Attribute.GetCustomAttribute ( - t, TypeManager.default_member_type); - if (attr != null){ - DefaultMemberAttribute dma = (DefaultMemberAttribute) attr; - return dma.MemberName; - } - - return TypeContainer.DefaultIndexerName; - } - - static MethodInfo declare_local_method = null; - - public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t) - { - if (declare_local_method == null){ - declare_local_method = typeof (ILGenerator).GetMethod ( - "DeclareLocal", - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, - new Type [] { typeof (Type), typeof (bool)}, - null); - if (declare_local_method == null){ - Report.RuntimeMissingSupport (Location.Null, "pinned local variables"); - return ig.DeclareLocal (t); - } - } - return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true }); - } - - private static bool IsSignatureEqual (Type a, Type b) - { - /// - /// Consider the following example (bug #77674): - /// - /// public abstract class A - /// { - /// public abstract T Foo (); - /// } - /// - /// public abstract class B : A - /// { - /// public override U Foo () - /// { return default (U); } - /// } - /// - /// Here, `T' and `U' are method type parameters from different methods - /// (A.Foo and B.Foo), so both `==' and Equals() will fail. - /// - /// However, since we're determining whether B.Foo() overrides A.Foo(), - /// we need to do a signature based comparision and consider them equal. - - if (a == b) - return true; - -#if GMCS_SOURCE - if (a.IsGenericParameter && b.IsGenericParameter && - (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) { - return a.GenericParameterPosition == b.GenericParameterPosition; - } -#endif - - if (a.IsArray && b.IsArray) { - if (a.GetArrayRank () != b.GetArrayRank ()) - return false; - - return IsSignatureEqual (a.GetElementType (), b.GetElementType ()); - } - - if (a.IsByRef && b.IsByRef) - return IsSignatureEqual (a.GetElementType (), b.GetElementType ()); - -#if GMCS_SOURCE - if (a.IsGenericType && b.IsGenericType) { - if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ()) - return false; - - Type[] aargs = a.GetGenericArguments (); - Type[] bargs = b.GetGenericArguments (); - - if (aargs.Length != bargs.Length) - return false; - - for (int i = 0; i < aargs.Length; i++) { - if (!IsSignatureEqual (aargs [i], bargs [i])) - return false; - } - - return true; - } -#endif - - return false; - } - - // - // Returns whether the array of memberinfos contains the given method - // - public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType) - { - Type [] new_args = TypeManager.GetParameterData (new_method).Types; - - foreach (MethodBase method in array) { - if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType) - continue; - - if (method.Name != new_method.Name) - continue; - - if (method is MethodInfo && new_method is MethodInfo && - !IsSignatureEqual ( - TypeToCoreType (((MethodInfo) method).ReturnType), - TypeToCoreType (((MethodInfo) new_method).ReturnType))) - continue; - - Type [] old_args = TypeManager.GetParameterData (method).Types; - int old_count = old_args.Length; - int i; - - if (new_args.Length != old_count) - continue; - - for (i = 0; i < old_count; i++){ - if (!IsSignatureEqual (old_args [i], new_args [i])) - break; - } - if (i != old_count) - continue; - - return true; - } - - return false; - } - - // - // We copy methods from `new_members' into `target_list' if the signature - // for the method from in the new list does not exist in the target_list - // - // The name is assumed to be the same. - // - public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members) - { - if (target_list == null){ - target_list = new ArrayList (); - - foreach (MemberInfo mi in new_members){ - if (mi is MethodBase) - target_list.Add (mi); - } - return target_list; - } - - MemberInfo [] target_array = new MemberInfo [target_list.Count]; - target_list.CopyTo (target_array, 0); - - foreach (MemberInfo mi in new_members){ - MethodBase new_method = (MethodBase) mi; - - if (!ArrayContainsMethod (target_array, new_method, true)) - target_list.Add (new_method); - } - return target_list; - } - -#region Generics - // - // Tracks the generic parameters. - // - static PtrHashtable builder_to_type_param; - - public static void AddTypeParameter (Type t, TypeParameter tparam) - { - if (!builder_to_type_param.Contains (t)) - builder_to_type_param.Add (t, tparam); - } - - public static TypeParameter LookupTypeParameter (Type t) - { - return (TypeParameter) builder_to_type_param [t]; - } - - // This method always return false for non-generic compiler, - // while Type.IsGenericParameter is returned if it is supported. - public static bool IsGenericParameter (Type type) - { -#if GMCS_SOURCE - return type.IsGenericParameter; -#else - return false; -#endif - } - - public static int GenericParameterPosition (Type type) - { -#if GMCS_SOURCE - return type.GenericParameterPosition; -#else - throw new InternalErrorException ("should not be called"); -#endif - } - - public static bool IsGenericType (Type type) - { -#if GMCS_SOURCE - return type.IsGenericType; -#else - return false; -#endif - } - - public static bool IsGenericTypeDefinition (Type type) - { -#if GMCS_SOURCE - return type.IsGenericTypeDefinition; -#else - return false; -#endif - } - - public static bool ContainsGenericParameters (Type type) - { -#if GMCS_SOURCE - return type.ContainsGenericParameters; -#else - return false; -#endif - } - - public static FieldInfo GetGenericFieldDefinition (FieldInfo fi) - { -#if GMCS_SOURCE - if (fi.DeclaringType.IsGenericTypeDefinition || - !fi.DeclaringType.IsGenericType) - return fi; - - Type t = fi.DeclaringType.GetGenericTypeDefinition (); - BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; - - // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken); - foreach (FieldInfo f in t.GetFields (bf)) - if (f.MetadataToken == fi.MetadataToken) - return f; -#endif - - return fi; - } - - public static bool IsEqual (Type a, Type b) - { - if (a.Equals (b)) { - // MS BCL returns true even if enum types are different - if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type) - return a.FullName == b.FullName; - - // Some types are never equal - if (a == TypeManager.null_type || a == TypeManager.anonymous_method_type) - return false; - - return true; - } - -#if GMCS_SOURCE - if (a.IsGenericParameter && b.IsGenericParameter) { - // TODO: needs more testing before cleaning up - //if (a.DeclaringMethod != b.DeclaringMethod && - // (a.DeclaringMethod == null || b.DeclaringMethod == null)) - // return false; - return a.GenericParameterPosition == b.GenericParameterPosition; - } - - if (a.IsArray && b.IsArray) { - if (a.GetArrayRank () != b.GetArrayRank ()) - return false; - return IsEqual (a.GetElementType (), b.GetElementType ()); - } - - if (a.IsByRef && b.IsByRef) - return IsEqual (a.GetElementType (), b.GetElementType ()); - - if (a.IsGenericType && b.IsGenericType) { - Type adef = a.GetGenericTypeDefinition (); - Type bdef = b.GetGenericTypeDefinition (); - - if (adef != bdef) - return false; - - if (adef.IsEnum && bdef.IsEnum) - return true; - - Type[] aargs = a.GetGenericArguments (); - Type[] bargs = b.GetGenericArguments (); - - if (aargs.Length != bargs.Length) - return false; - - for (int i = 0; i < aargs.Length; i++) { - if (!IsEqual (aargs [i], bargs [i])) - return false; - } - - return true; - } -#endif - - return false; - } - - public static bool IsEqual (Type[] a, Type[] b) - { - if (a == null || b == null || a.Length != b.Length) - return false; - - for (int i = 0; i < a.Length; ++i) { - if (a [i] == null || b [i] == null) { - if (a [i] == b [i]) - continue; - - return false; - } - - if (!IsEqual (a [i], b [i])) - return false; - } - - return true; - } - - public static Type DropGenericTypeArguments (Type t) - { -#if GMCS_SOURCE - if (!t.IsGenericType) - return t; - // Micro-optimization: a generic typebuilder is always a generic type definition - if (t is TypeBuilder) - return t; - return t.GetGenericTypeDefinition (); -#else - return t; -#endif - } - - public static MethodBase DropGenericMethodArguments (MethodBase m) - { -#if GMCS_SOURCE - if (m.IsGenericMethod) - m = ((MethodInfo) m).GetGenericMethodDefinition (); - - Type t = m.DeclaringType; - if (!t.IsGenericType || t.IsGenericTypeDefinition) - return m; - - t = t.GetGenericTypeDefinition (); - BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; - -#if MS_COMPATIBLE - // TODO: use CodeGen.Module.Builder.ResolveMethod () - return m; -#endif - - if (m is ConstructorInfo) { - foreach (ConstructorInfo c in t.GetConstructors (bf)) - if (c.MetadataToken == m.MetadataToken) - return c; - } else { - foreach (MethodBase mb in t.GetMethods (bf)) - if (mb.MetadataToken == m.MetadataToken) - return mb; - } -#endif - - return m; - } - - public static Type[] GetGenericArguments (MethodBase mi) - { -#if GMCS_SOURCE - return mi.GetGenericArguments (); -#else - return Type.EmptyTypes; -#endif - } - - public static Type[] GetTypeArguments (Type t) - { -#if GMCS_SOURCE - DeclSpace tc = LookupDeclSpace (t); - if (tc != null) { - if (!tc.IsGeneric) - return Type.EmptyTypes; - - TypeParameter[] tparam = tc.TypeParameters; - Type[] ret = new Type [tparam.Length]; - for (int i = 0; i < tparam.Length; i++) { - ret [i] = tparam [i].Type; - if (ret [i] == null) - throw new InternalErrorException (); - } - - return ret; - } else - return t.GetGenericArguments (); -#else - throw new InternalErrorException (); -#endif - } - - public static GenericConstraints GetTypeParameterConstraints (Type t) - { -#if GMCS_SOURCE - if (!t.IsGenericParameter) - throw new InvalidOperationException (); - - TypeParameter tparam = LookupTypeParameter (t); - if (tparam != null) - return tparam.GenericConstraints; - - return ReflectionConstraints.GetConstraints (t); -#else - throw new InternalErrorException (); -#endif - } - - public static bool HasGenericArguments (Type t) - { - return GetNumberOfTypeArguments (t) > 0; - } - - public static int GetNumberOfTypeArguments (Type t) - { -#if GMCS_SOURCE - if (t.IsGenericParameter) - return 0; - DeclSpace tc = LookupDeclSpace (t); - if (tc != null) - return tc.IsGeneric ? tc.CountTypeParameters : 0; - else - return t.IsGenericType ? t.GetGenericArguments ().Length : 0; -#else - return 0; -#endif - } - - /// - /// Check whether `type' and `parent' are both instantiations of the same - /// generic type. Note that we do not check the type parameters here. - /// - public static bool IsInstantiationOfSameGenericType (Type type, Type parent) - { - int tcount = GetNumberOfTypeArguments (type); - int pcount = GetNumberOfTypeArguments (parent); - - if (tcount != pcount) - return false; - - type = DropGenericTypeArguments (type); - parent = DropGenericTypeArguments (parent); - - return type.Equals (parent); - } - - /// - /// Whether `mb' is a generic method definition. - /// - public static bool IsGenericMethodDefinition (MethodBase mb) - { -#if GMCS_SOURCE - if (mb.DeclaringType is TypeBuilder) { - IMethodData method = (IMethodData) builder_to_method [mb]; - if (method == null) - return false; - - return method.GenericMethod != null; - } - - return mb.IsGenericMethodDefinition; -#else - return false; -#endif - } - - /// - /// Whether `mb' is a generic method. - /// - public static bool IsGenericMethod (MethodBase mb) - { -#if GMCS_SOURCE - return mb.IsGenericMethod; -#else - return false; -#endif - } - - public static bool IsNullableType (Type t) - { -#if GMCS_SOURCE - return generic_nullable_type == DropGenericTypeArguments (t); -#else - return false; -#endif - } - - public static bool IsNullableTypeOf (Type t, Type nullable) - { -#if GMCS_SOURCE - if (!IsNullableType (t)) - return false; - - return GetTypeArguments (t) [0] == nullable; -#else - return false; -#endif - } - - public static bool IsNullableValueType (Type t) - { -#if GMCS_SOURCE - if (!IsNullableType (t)) - return false; - - return GetTypeArguments (t) [0].IsValueType; -#else - return false; -#endif - } -#endregion - -#region MemberLookup implementation - - // - // Whether we allow private members in the result (since FindMembers - // uses NonPublic for both protected and private), we need to distinguish. - // - - internal class Closure { - internal bool private_ok; - - // Who is invoking us and which type is being queried currently. - internal Type invocation_type; - internal Type qualifier_type; - - // The assembly that defines the type is that is calling us - internal Assembly invocation_assembly; - internal IList almost_match; - - private bool CheckValidFamilyAccess (bool is_static, MemberInfo m) - { - if (invocation_type == null) - return false; - - if (is_static && qualifier_type == null) - // It resolved from a simple name, so it should be visible. - return true; - - if (IsNestedChildOf (invocation_type, m.DeclaringType)) - return true; - - for (Type t = invocation_type; t != null; t = t.DeclaringType) { - if (!IsFamilyAccessible (t, m.DeclaringType)) - continue; - - // Although a derived class can access protected members of its base class - // it cannot do so through an instance of the base class (CS1540). - // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type - if (is_static || qualifier_type == null || - IsInstantiationOfSameGenericType (t, qualifier_type) || - IsFamilyAccessible (qualifier_type, t)) - return true; - } - - if (almost_match != null) - almost_match.Add (m); - - return false; - } - - // - // This filter filters by name + whether it is ok to include private - // members in the search - // - internal bool Filter (MemberInfo m, object filter_criteria) - { - // - // Hack: we know that the filter criteria will always be in the - // `closure' // fields. - // - - if ((filter_criteria != null) && (m.Name != (string) filter_criteria)) - return false; - - if (((qualifier_type == null) || (qualifier_type == invocation_type)) && - (invocation_type != null) && - IsPrivateAccessible (m.DeclaringType, invocation_type)) - return true; - - // - // Ugly: we need to find out the type of `m', and depending - // on this, tell whether we accept or not - // - if (m is MethodBase){ - MethodBase mb = (MethodBase) m; - MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask; - - if (ma == MethodAttributes.Public) - return true; - - if (ma == MethodAttributes.PrivateScope) - return false; - - if (ma == MethodAttributes.Private) - return private_ok || - IsPrivateAccessible (invocation_type, m.DeclaringType) || - IsNestedChildOf (invocation_type, m.DeclaringType); - - if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) { - if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) - return true; - } else { - if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem) - return false; - } - - // Family, FamORAssem or FamANDAssem - return CheckValidFamilyAccess (mb.IsStatic, m); - } - - if (m is FieldInfo){ - FieldInfo fi = (FieldInfo) m; - FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask; - - if (fa == FieldAttributes.Public) - return true; - - if (fa == FieldAttributes.PrivateScope) - return false; - - if (fa == FieldAttributes.Private) - return private_ok || - IsPrivateAccessible (invocation_type, m.DeclaringType) || - IsNestedChildOf (invocation_type, m.DeclaringType); - - if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) { - if ((fa == FieldAttributes.Assembly) || - (fa == FieldAttributes.FamORAssem)) - return true; - } else { - if ((fa == FieldAttributes.Assembly) || - (fa == FieldAttributes.FamANDAssem)) - return false; - } - - // Family, FamORAssem or FamANDAssem - return CheckValidFamilyAccess (fi.IsStatic, m); - } - - // - // EventInfos and PropertyInfos, return true because they lack - // permission information, so we need to check later on the methods. - // - return true; - } - } - - static Closure closure = new Closure (); - static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter); - - // - // Looks up a member called `name' in the `queried_type'. This lookup - // is done by code that is contained in the definition for `invocation_type' - // through a qualifier of type `qualifier_type' (or null if there is no qualifier). + // Looks up a member called `name' in the `queried_type'. This lookup + // is done by code that is contained in the definition for `invocation_type' + // through a qualifier of type `qualifier_type' (or null if there is no qualifier). // // `invocation_type' is used to check whether we're allowed to access the requested // member wrt its protection level. @@ -3009,475 +947,31 @@ namespace Mono.CSharp { // Returns an array of a single element for everything but Methods/Constructors // that might return multiple matches. // - public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type, - Type queried_type, MemberTypes mt, - BindingFlags original_bf, string name, IList almost_match) + public static IList MemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type, + TypeSpec queried_type, MemberKind mt, + BindingRestriction opt, string name, int arity, IList almost_match) { Timer.StartTimer (TimerType.MemberLookup); - MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type, - queried_type, mt, original_bf, name, almost_match); + var retval = RealMemberLookup (invocation_type, qualifier_type, + queried_type, mt, opt, name, arity, almost_match); Timer.StopTimer (TimerType.MemberLookup); return retval; } - static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type, - Type queried_type, MemberTypes mt, - BindingFlags original_bf, string name, IList almost_match) - { - BindingFlags bf = original_bf; - - ArrayList method_list = null; - Type current_type = queried_type; - bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0; - bool skip_iface_check = true, used_cache = false; - bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type); - - closure.invocation_type = invocation_type; - closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null; - closure.qualifier_type = qualifier_type; - closure.almost_match = almost_match; - - // This is from the first time we find a method - // in most cases, we do not actually find a method in the base class - // so we can just ignore it, and save the arraylist allocation - MemberInfo [] first_members_list = null; - bool use_first_members_list = false; - - do { - MemberInfo [] list; - - // - // `NonPublic' is lame, because it includes both protected and - // private methods, so we need to control this behavior by - // explicitly tracking if a private method is ok or not. - // - // The possible cases are: - // public, private and protected (internal does not come into the - // equation) - // - if ((invocation_type != null) && - ((invocation_type == current_type) || - IsNestedChildOf (invocation_type, current_type)) || - always_ok_flag) - bf = original_bf | BindingFlags.NonPublic; - else - bf = original_bf; - - closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0; - - Timer.StopTimer (TimerType.MemberLookup); - - list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache); - - Timer.StartTimer (TimerType.MemberLookup); - - // - // When queried for an interface type, the cache will automatically check all - // inherited members, so we don't need to do this here. However, this only - // works if we already used the cache in the first iteration of this loop. - // - // If we used the cache in any further iteration, we can still terminate the - // loop since the cache always looks in all base classes. - // - - if (used_cache) - searching = false; - else - skip_iface_check = false; - - if (current_type == TypeManager.object_type) - searching = false; - else { - current_type = current_type.BaseType; - - // - // This happens with interfaces, they have a null - // basetype. Look members up in the Object class. - // - if (current_type == null) { - current_type = TypeManager.object_type; - searching = true; - } - } - - if (list.Length == 0) - continue; - - // - // Events and types are returned by both `static' and `instance' - // searches, which means that our above FindMembers will - // return two copies of the same. - // - if (list.Length == 1 && !(list [0] is MethodBase)){ - return list; - } - - // - // Multiple properties: we query those just to find out the indexer - // name - // - if (list [0] is PropertyInfo) - return list; - - // - // We found an event: the cache lookup returns both the event and - // its private field. - // - if (list [0] is EventInfo) { - if ((list.Length == 2) && (list [1] is FieldInfo)) - return new MemberInfo [] { list [0] }; - - return list; - } - - // - // We found methods, turn the search into "method scan" - // mode. - // - - if (first_members_list != null) { - if (use_first_members_list) { - method_list = CopyNewMethods (method_list, first_members_list); - use_first_members_list = false; - } - - method_list = CopyNewMethods (method_list, list); - } else { - first_members_list = list; - use_first_members_list = true; - mt &= (MemberTypes.Method | MemberTypes.Constructor); - } - } while (searching); - - if (use_first_members_list) - return first_members_list; - - if (method_list != null && method_list.Count > 0) { - return (MemberInfo []) method_list.ToArray (typeof (MemberInfo)); - } - // - // This happens if we already used the cache in the first iteration, in this case - // the cache already looked in all interfaces. - // - if (skip_iface_check) - return null; - - // - // Interfaces do not list members they inherit, so we have to - // scan those. - // - if (!queried_type.IsInterface) - return null; - - if (queried_type.IsArray) - queried_type = TypeManager.array_type; - - Type [] ifaces = GetInterfaces (queried_type); - if (ifaces == null) - return null; - - foreach (Type itype in ifaces){ - MemberInfo [] x; - - x = MemberLookup (null, null, itype, mt, bf, name, null); - if (x != null) - return x; - } - - return null; - } - - const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | - BindingFlags.DeclaredOnly; - - // Currently is designed to work with external types only - public static PropertyInfo GetPropertyFromAccessor (MethodBase mb) - { - if (!mb.IsSpecialName) - return null; - - string name = mb.Name; - if (name.Length < 5) - return null; - - if (name [3] != '_') - return null; - - if (name.StartsWith ("get") || name.StartsWith ("set")) { - MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers, - Type.FilterName, name.Substring (4)); - - if (pi == null) - return null; - - // This can happen when property is indexer (it can have same name but different parameters) - foreach (PropertyInfo p in pi) { - foreach (MethodInfo p_mi in p.GetAccessors (true)) { - if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb))) - return p; - } - } - } - - return null; - } - - // Currently is designed to work with external types only - public static MemberInfo GetEventFromAccessor (MethodBase mb) - { - if (!mb.IsSpecialName) - return null; - - string name = mb.Name; - if (name.Length < 5) - return null; - - if (name.StartsWith ("add_")) - return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers); - - if (name.StartsWith ("remove_")) - return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers); - - return null; - } - - // Tests whether external method is really special - public static bool IsSpecialMethod (MethodBase mb) - { - if (!mb.IsSpecialName) - return false; - - IMethodData md = TypeManager.GetMethod (mb); - if (md != null) - return (md is AbstractPropertyEventMethod || md is Operator); - - PropertyInfo pi = GetPropertyFromAccessor (mb); - if (pi != null) - return IsValidProperty (pi); - - if (GetEventFromAccessor (mb) != null) - return true; - - string name = mb.Name; - if (name.StartsWith ("op_")) - return Operator.GetName (name) != null; - - return false; - } - - // Tests whether imported property is valid C# property. - // TODO: It seems to me that we should do a lot of sanity tests before - // we accept property as C# property - static bool IsValidProperty (PropertyInfo pi) + static IList RealMemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type, + TypeSpec queried_type, MemberKind mt, + BindingRestriction bf, string name, int arity, IList almost_match) { - MethodInfo get_method = pi.GetGetMethod (true); - MethodInfo set_method = pi.GetSetMethod (true); - int g_count = 0; - int s_count = 0; - if (get_method != null && set_method != null) { - g_count = get_method.GetParameters ().Length; - s_count = set_method.GetParameters ().Length; - if (g_count + 1 != s_count) - return false; - } else if (get_method != null) { - g_count = get_method.GetParameters ().Length; - } else if (set_method != null) { - s_count = set_method.GetParameters ().Length; - } - - // - // DefaultMemberName and indexer name has to match to identify valid C# indexer - // - if ((s_count > 1 || g_count > 0) && TypeManager.default_member_type != null) { - object[] o = pi.DeclaringType.GetCustomAttributes (TypeManager.default_member_type, false); - if (o.Length == 0) - return false; - - DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0]; - if (dma.MemberName != pi.Name) - return false; - if (get_method != null && "get_" + dma.MemberName != get_method.Name) - return false; - if (set_method != null && "set_" + dma.MemberName != set_method.Name) - return false; + MemberFilter filter = new MemberFilter (name, arity, mt, null, null); + if ((bf & BindingRestriction.AccessibleOnly) != 0) { + filter.InvocationType = invocation_type ?? InternalType.FakeInternalType; } - return true; - } - -#endregion - + return MemberCache.FindMembers (queried_type, filter, bf); + } } -/// -/// There is exactly one instance of this class per type. -/// -public sealed class TypeHandle : IMemberContainer { - public readonly IMemberContainer BaseType; - - readonly int id = ++next_id; - static int next_id = 0; - - static TypeHandle () - { - Reset (); - } - - /// - /// Lookup a TypeHandle instance for the given type. If the type doesn't have - /// a TypeHandle yet, a new instance of it is created. This static method - /// ensures that we'll only have one TypeHandle instance per type. - /// - private static TypeHandle GetTypeHandle (Type t) - { - TypeHandle handle = (TypeHandle) type_hash [t]; - if (handle != null) - return handle; - - handle = new TypeHandle (t); - type_hash.Add (t, handle); - return handle; - } - - public static MemberCache GetMemberCache (Type t) - { - return GetTypeHandle (t).MemberCache; - } - - public static void CleanUp () - { - type_hash = null; - } - - public static void Reset () - { - type_hash = new PtrHashtable (); - } - - /// - /// Returns the TypeHandle for TypeManager.object_type. - /// - public static IMemberContainer ObjectType { - get { - if (object_type != null) - return object_type; - - object_type = GetTypeHandle (TypeManager.object_type); - - return object_type; - } - } - - /// - /// Returns the TypeHandle for TypeManager.array_type. - /// - public static TypeHandle ArrayType { - get { - if (array_type != null) - return array_type; - - array_type = GetTypeHandle (TypeManager.array_type); - - return array_type; - } - } - - private static PtrHashtable type_hash; - - private static TypeHandle object_type = null; - private static TypeHandle array_type = null; - - private Type type; - private string full_name; - private bool is_interface; - private MemberCache member_cache; - private MemberCache base_cache; - - private TypeHandle (Type type) - { - this.type = type; - full_name = type.FullName != null ? type.FullName : type.Name; - if (type.BaseType != null) { - base_cache = TypeManager.LookupMemberCache (type.BaseType); - BaseType = base_cache.Container; - } else if (type.IsInterface) - base_cache = TypeManager.LookupBaseInterfacesCache (type); - this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type); - this.member_cache = new MemberCache (this); - } - - // IMemberContainer methods - - public string Name { - get { - return full_name; - } - } - - public Type Type { - get { - return type; - } - } - - public MemberCache BaseCache { - get { - return base_cache; - } - } - - public bool IsInterface { - get { - return is_interface; - } - } - - public MemberList GetMembers (MemberTypes mt, BindingFlags bf) - { - MemberInfo [] members; - -#if GMCS_SOURCE - if (type is GenericTypeParameterBuilder) - return MemberList.Empty; -#endif - - if (mt == MemberTypes.Event) - members = type.GetEvents (bf | BindingFlags.DeclaredOnly); - else - members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly, - null, null); - - if (members.Length == 0) - return MemberList.Empty; - - Array.Reverse (members); - return new MemberList (members); - } - - // IMemberFinder methods - - public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name, - MemberFilter filter, object criteria) - { - return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria)); - } - - public MemberCache MemberCache { - get { - return member_cache; - } - } - - public override string ToString () - { - if (BaseType != null) - return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")"; - else - return "TypeHandle (" + id + "," + Name + ")"; - } -} }