X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Ftypemanager.cs;h=308faf58212b6d1db024b322a0a3047d32450a89;hb=e0df8328d11d79623c1b0369cf15544b26a18db0;hp=50e504c5165a64fbc9734a5d43e89d1b20f22290;hpb=38f320d19a29a3e7d6a92cdb0b3ebec149d7c1a7;p=mono.git diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs index 50e504c5165..308faf58212 100644 --- a/mcs/mcs/typemanager.cs +++ b/mcs/mcs/typemanager.cs @@ -31,7 +31,7 @@ using System.Diagnostics; namespace Mono.CSharp { -public class TypeManager { +public partial class TypeManager { // // A list of core types that the compiler requires or uses // @@ -70,7 +70,9 @@ public class TypeManager { static public Type iasyncresult_type; static public Type asynccallback_type; static public Type intptr_type; + static public Type uintptr_type; static public Type monitor_type; + static public Type interlocked_type; static public Type runtime_field_handle_type; static public Type runtime_argument_handle_type; static public Type attribute_type; @@ -90,6 +92,8 @@ public class TypeManager { static public Type conditional_attribute_type; static public Type in_attribute_type; static public Type out_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; @@ -112,15 +116,10 @@ public class TypeManager { static internal Type compiler_generated_attr_type; static internal Type fixed_buffer_attr_type; static internal Type default_charset_type; + static internal Type internals_visible_attr_type; + static internal Type type_forwarder_attr_type; #endif - // - // An empty array of types - // - static public Type [] NoTypes; - static public TypeExpr [] NoTypeExprs; - - // // Expressions representing the internal types. Used during declaration // definition. @@ -189,13 +188,14 @@ public class TypeManager { static public MethodInfo int_array_get_lower_bound_int; static public MethodInfo int_array_get_upper_bound_int; static public MethodInfo void_array_copyto_array_int; + static public MethodInfo int_interlocked_compare_exchange; static public PropertyInfo ienumerator_getcurrent; // // The attribute constructors. // static public ConstructorInfo object_ctor; - static public ConstructorInfo cons_param_array_attribute; + static private ConstructorInfo cons_param_array_attribute; static public ConstructorInfo void_decimal_ctor_five_args; static public ConstructorInfo void_decimal_ctor_int_arg; static public ConstructorInfo unverifiable_code_ctor; @@ -251,7 +251,13 @@ public class TypeManager { public static Hashtable AllClsTopLevelTypes; static Hashtable fieldbuilders_to_fields; + static Hashtable propertybuilder_to_property; static Hashtable fields; + static Hashtable events; + +#if GMCS_SOURCE + static PtrHashtable assembly_internals_vis_attrs; +#endif struct Signature { public string name; @@ -264,6 +270,7 @@ public class TypeManager { builder_to_declspace = null; builder_to_member_cache = null; builder_to_ifaces = null; + builder_to_type_param = null; indexer_arguments = null; method_params = null; builder_to_method = null; @@ -273,7 +280,12 @@ public class TypeManager { events = null; priv_fields_events = null; type_hash = null; - + propertybuilder_to_property = null; + +#if GMCS_SOURCE + assembly_internals_vis_attrs = null; +#endif + TypeHandle.CleanUp (); } @@ -287,7 +299,7 @@ public class TypeManager { if (!(mi is MethodBase)) return false; - + if (mi.Name != sig.name) return false; @@ -361,17 +373,23 @@ public class TypeManager { 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 (); indexer_arguments = new PtrHashtable (); builder_to_ifaces = new PtrHashtable (); - NoTypes = new Type [0]; - NoTypeExprs = new TypeExpr [0]; - fieldbuilders_to_fields = new Hashtable (); + propertybuilder_to_property = new Hashtable (); fields = new Hashtable (); type_hash = new DoubleHash (); + +#if GMCS_SOURCE + assembly_internals_vis_attrs = new PtrHashtable (); +#endif + + // to uncover regressions + cons_param_array_attribute = null; } public static void AddUserType (DeclSpace ds) @@ -419,18 +437,32 @@ public class TypeManager { public static MemberCache LookupMemberCache (Type t) { +#if GMCS_SOURCE && MS_COMPATIBLE + if (t.IsGenericType && !t.IsGenericTypeDefinition) + t = t.GetGenericTypeDefinition (); +#endif + if (t is TypeBuilder) { IMemberContainer container = builder_to_declspace [t] as IMemberContainer; if (container != null) return container.MemberCache; } +#if GMCS_SOURCE + if (t is GenericTypeParameterBuilder) { + IMemberContainer container = builder_to_type_param [t] as IMemberContainer; + + if (container != null) + return container.MemberCache; + } +#endif + return TypeHandle.GetMemberCache (t); } public static MemberCache LookupBaseInterfacesCache (Type t) { - Type [] ifaces = t.GetInterfaces (); + Type [] ifaces = GetInterfaces (t); if (ifaces != null && ifaces.Length == 1) return LookupMemberCache (ifaces [0]); @@ -481,7 +513,11 @@ public class TypeManager { // public static Type GetReferenceType (Type t) { +#if GMCS_SOURCE + return t.MakeByRefType (); +#else return GetConstructedType (t, "&"); +#endif } // @@ -495,11 +531,56 @@ public class TypeManager { public static Type GetConstructedType (Type t, string dim) { object ret = null; - if (!type_hash.Lookup (t, dim, out ret)) { - ret = t.Module.GetType (t.ToString () + dim); + 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; } - return (Type) ret; + + if (dim == "&") { + ret = GetReferenceType (t); + type_hash.Insert (t, dim, ret); + return (Type) ret; + } + +#if GMCS_SOURCE + if (t.IsGenericParameter || t.IsGenericType) { + int pos = 0; + Type result = t; + while ((pos < dim.Length) && (dim [pos] == '[')) { + pos++; + + if (dim [pos] == ']') { + result = result.MakeArrayType (); + pos++; + + if (pos < dim.Length) + continue; + + type_hash.Insert (t, dim, result); + return result; + } + + int rank = 0; + while (dim [pos] == ',') { + pos++; rank++; + } + + if ((dim [pos] != ']') || (pos != dim.Length-1)) + break; + + result = result.MakeArrayType (rank + 1); + type_hash.Insert (t, dim, result); + return result; + } + } +#endif + + type_hash.Insert (t, dim, null); + return null; } public static Type GetNestedType (Type t, string name) @@ -541,7 +622,19 @@ public class TypeManager { /// static public string CSharpName (Type t) { - return Regex.Replace (t.FullName, + if (t == typeof(NullType)) + return "null"; + +#if GMCS_SOURCE + if (IsNullableType (t) && !t.IsGenericTypeDefinition) { + t = GetTypeArguments (t) [0]; + return CSharpName (t) + "?"; + } +#endif + + string name = GetFullName (t); + + return Regex.Replace (name, @"^System\." + @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" + @"Single|Double|Char|Decimal|Byte|SByte|Object|" + @@ -583,9 +676,9 @@ public class TypeManager { { PropertyInfo pi = mi as PropertyInfo; if (pi != null) { - MethodBase pmi = pi.GetGetMethod (); + MethodBase pmi = pi.GetGetMethod (true); if (pmi == null) - pmi = pi.GetSetMethod (); + pmi = pi.GetSetMethod (true); if (GetParameterData (pmi).Count > 0) mi = pmi; } @@ -594,6 +687,71 @@ public class TypeManager { : CSharpName (mi.DeclaringType) + '.' + mi.Name; } +#if GMCS_SOURCE + private static int GetFullName (Type t, StringBuilder sb) + { + int pos = 0; + + if (!t.IsGenericType) { + sb.Append (t.FullName); + return 0; + } + + if (t.DeclaringType != null) { + pos = GetFullName (t.DeclaringType, sb); + sb.Append ('.'); + sb.Append (RemoveGenericArity (t.Name)); + } else { + sb.Append (RemoveGenericArity (t.FullName)); + } + + 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; + } + + public static string GetFullName (Type t) + { + if (t.IsGenericParameter) + return t.Name; + if (!t.IsGenericType) + return t.FullName; + + 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 (); + } +#else + public static string GetFullName (Type t) + { + return t.FullName; + } +#endif + + public static string RemoveGenericArity (string from) + { + int i = from.IndexOf ('`'); + if (i > 0) + return from.Substring (0, i); + return from; + } + /// /// When we need to report accessors as well /// @@ -650,9 +808,23 @@ public class TypeManager { } else { if (mb.Name == ".ctor") sig.Append (mb.DeclaringType.Name); - else + 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 (args [i].Name); + } + sig.Append ('>'); + } +#endif + } + sig.Append (parameters); } @@ -664,6 +836,18 @@ public class TypeManager { return sig.ToString (); } + 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 + } + static public string CSharpSignature (EventInfo ei) { return CSharpName (ei.DeclaringType) + '.' + ei.Name; @@ -676,7 +860,7 @@ public class TypeManager { static Type CoreLookupType (string ns_name, string name) { Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true); - FullNamedExpression fne = ns.Lookup (RootContext.Tree.Types, name, Location.Null); + FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null); Type t = fne == null ? null : fne.Type; if (t == null) Report.Error (518, "The predefined type `" + name + "' is not defined or imported"); @@ -721,7 +905,7 @@ public class TypeManager { return GetMethod (t, name, args, false, report_errors); } - static MethodInfo GetMethod (Type t, string name, Type [] args) + public static MethodInfo GetMethod (Type t, string name, Type [] args) { return GetMethod (t, name, args, true); } @@ -730,10 +914,10 @@ public class TypeManager { /// Returns the PropertyInfo for a property named `name' defined /// in type `t' /// - static PropertyInfo GetProperty (Type t, string name) + public static PropertyInfo GetProperty (Type t, string name) { MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public | - BindingFlags.Instance, Type.FilterName, name); + BindingFlags.Instance, Type.FilterName, name); if (list.Count == 0) { Report.Error (-19, "Can not find the core property `" + name + "'"); return null; @@ -758,6 +942,9 @@ public class TypeManager { sig.name = ".ctor"; sig.args = args; + + if (t == null) + throw new InternalErrorException ("Core types haven't been initialized yet?"); list = FindMembers (t, MemberTypes.Constructor, instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly, @@ -778,7 +965,6 @@ public class TypeManager { public static void InitEnumUnderlyingTypes () { - int32_type = CoreLookupType ("System", "Int32"); int64_type = CoreLookupType ("System", "Int64"); uint32_type = CoreLookupType ("System", "UInt32"); @@ -787,6 +973,15 @@ public class TypeManager { sbyte_type = CoreLookupType ("System", "SByte"); short_type = CoreLookupType ("System", "Int16"); ushort_type = CoreLookupType ("System", "UInt16"); + + ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator"); + ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable"); + + idisposable_type = CoreLookupType ("System", "IDisposable"); + +#if GMCS_SOURCE + InitGenericCoreTypes (); +#endif } /// @@ -824,13 +1019,12 @@ public class TypeManager { runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle"); asynccallback_type = CoreLookupType ("System", "AsyncCallback"); iasyncresult_type = CoreLookupType ("System", "IAsyncResult"); - ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator"); - ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable"); - idisposable_type = CoreLookupType ("System", "IDisposable"); icloneable_type = CoreLookupType ("System", "ICloneable"); iconvertible_type = CoreLookupType ("System", "IConvertible"); + interlocked_type = CoreLookupType ("System.Threading", "Interlocked"); monitor_type = CoreLookupType ("System.Threading", "Monitor"); intptr_type = CoreLookupType ("System", "IntPtr"); + uintptr_type = CoreLookupType ("System", "UIntPtr"); attribute_type = CoreLookupType ("System", "Attribute"); attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute"); @@ -840,6 +1034,9 @@ public class TypeManager { param_array_type = CoreLookupType ("System", "ParamArrayAttribute"); in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute"); out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute"); +#if NET_2_0 + default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute"); +#endif typed_reference_type = CoreLookupType ("System", "TypedReference"); arg_iterator_type = CoreLookupType ("System", "ArgIterator"); mbr_type = CoreLookupType ("System", "MarshalByRefObject"); @@ -877,7 +1074,9 @@ public class TypeManager { compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute"); fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute"); default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute"); + internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute"); runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute"); + type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute"); #endif // // When compiling corlib, store the "real" types here. @@ -888,13 +1087,12 @@ public class TypeManager { system_type_type = typeof (System.Type); system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder); - Type [] void_arg = { }; system_int_array_get_length = GetMethod ( - system_array_type, "get_Length", void_arg); + system_array_type, "get_Length", Type.EmptyTypes); system_int_array_get_rank = GetMethod ( - system_array_type, "get_Rank", void_arg); + system_array_type, "get_Rank", Type.EmptyTypes); system_object_array_clone = GetMethod ( - system_array_type, "Clone", void_arg); + system_array_type, "Clone", Type.EmptyTypes); Type [] system_int_arg = { system_int32_type }; system_int_array_get_length_int = GetMethod ( @@ -1021,23 +1219,22 @@ public class TypeManager { // // Void arguments // - Type [] void_arg = { }; ienumerator_getcurrent = GetProperty ( ienumerator_type, "Current"); bool_movenext_void = GetMethod ( - ienumerator_type, "MoveNext", void_arg); + ienumerator_type, "MoveNext", Type.EmptyTypes); void_reset_void = GetMethod ( - ienumerator_type, "Reset", void_arg); + ienumerator_type, "Reset", Type.EmptyTypes); void_dispose_void = GetMethod ( - idisposable_type, "Dispose", void_arg); + idisposable_type, "Dispose", Type.EmptyTypes); int_get_offset_to_string_data = GetMethod ( - runtime_helpers_type, "get_OffsetToStringData", void_arg); + runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes); int_array_get_length = GetMethod ( - array_type, "get_Length", void_arg); + array_type, "get_Length", Type.EmptyTypes); int_array_get_rank = GetMethod ( - array_type, "get_Rank", void_arg); + array_type, "get_Rank", Type.EmptyTypes); ienumerable_getenumerator_void = GetMethod ( - ienumerable_type, "GetEnumerator", void_arg); + ienumerable_type, "GetEnumerator", Type.EmptyTypes); // // Int32 arguments @@ -1054,7 +1251,7 @@ public class TypeManager { // System.Array methods // object_array_clone = GetMethod ( - array_type, "Clone", void_arg); + array_type, "Clone", Type.EmptyTypes); Type [] array_int_arg = { array_type, int32_type }; void_array_copyto_array_int = GetMethod ( array_type, "CopyTo", array_int_arg); @@ -1091,8 +1288,7 @@ public class TypeManager { // // Attributes // - cons_param_array_attribute = GetConstructor (param_array_type, void_arg); - unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg); + unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes); default_member_ctor = GetConstructor (default_member_type, string_); Type[] short_arg = { short_type }; @@ -1104,20 +1300,39 @@ public class TypeManager { field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type [] { int32_type }); + // + // System.Threading.CompareExchange + // + Type[] compare_exchange_types = { + GetReferenceType (int32_type), int32_type, int32_type }; + int_interlocked_compare_exchange = GetMethod ( + interlocked_type, "CompareExchange", compare_exchange_types); + // // .NET 2.0 types // #if NET_2_0 compiler_generated_attr = new CustomAttributeBuilder ( - GetConstructor (compiler_generated_attr_type, void_arg), new object[0]); + GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]); Type[] type_int_arg = { type_type, int32_type }; fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg); #endif // Object - object_ctor = GetConstructor (object_type, void_arg); + object_ctor = GetConstructor (object_type, Type.EmptyTypes); +#if GMCS_SOURCE + InitGenericCodeHelpers (); +#endif + } + + static public ConstructorInfo ConsParamArrayAttribute { + get { + if (cons_param_array_attribute == null) + cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes); + return cons_param_array_attribute; + } } const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance; @@ -1129,6 +1344,11 @@ public class TypeManager { public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria) { +#if MS_COMPATIBLE && GMCS_SOURCE + if (t.IsGenericType && !t.IsGenericTypeDefinition) + t = t.GetGenericTypeDefinition (); +#endif + DeclSpace decl = (DeclSpace) builder_to_declspace [t]; // @@ -1147,9 +1367,25 @@ public class TypeManager { // a TypeBuilder array will return a Type, not a TypeBuilder, // and we can not call FindMembers on this type. // - if (TypeManager.IsSubclassOf (t, TypeManager.array_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; + } +#endif + // // Since FindMembers will not lookup both static and instance // members, we emulate this behaviour here. @@ -1195,20 +1431,14 @@ public class TypeManager { /// to check base classes and interfaces anymore. /// private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, - string name, out bool used_cache) + string name, out bool used_cache) { MemberCache cache; - // - // 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 == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) { - used_cache = true; - return TypeHandle.ArrayType.MemberCache.FindMembers ( - mt, bf, name, FilterWithClosure_delegate, null); - } +#if GMCS_SOURCE && MS_COMPATIBLE + if (t.IsGenericType && !t.IsGenericTypeDefinition) + t = t.GetGenericTypeDefinition(); +#endif // // If this is a dynamic type, it's always in the `builder_to_declspace' hash table @@ -1230,17 +1460,53 @@ public class TypeManager { // If there is no MemberCache, we need to use the "normal" FindMembers. // Note, this is a VERY uncommon route! - + 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; } + // + // 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) { // == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) { + used_cache = true; + return TypeHandle.ArrayType.MemberCache.FindMembers ( + mt, bf, name, FilterWithClosure_delegate, null); + } + +#if GMCS_SOURCE + if (t is GenericTypeParameterBuilder) { + TypeParameter tparam = (TypeParameter) builder_to_type_param [t]; + + MemberList list; + Timer.StartTimer (TimerType.FindMembers); + list = tparam.FindMembers (mt, bf & ~BindingFlags.DeclaredOnly, + FilterWithClosure_delegate, name); + Timer.StopTimer (TimerType.FindMembers); + used_cache = true; + return (MemberInfo []) list; + } +#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; + } + // // This call will always succeed. There is exactly one TypeHandle instance per // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return @@ -1254,6 +1520,7 @@ public class TypeManager { public static bool IsBuiltinType (Type t) { + 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 || @@ -1282,6 +1549,7 @@ public class TypeManager { public static bool IsDelegateType (Type t) { + t = DropGenericTypeArguments (t); if (t.IsSubclassOf (TypeManager.delegate_type)) return true; else @@ -1293,6 +1561,10 @@ public class TypeManager { if (builder_to_declspace [t] is Enum) return true; +#if MS_COMPATIBLE && GMCS_SOURCE + if (t.IsGenericParameter || t.IsGenericType) + return false; +#endif return t.IsEnum; } @@ -1307,6 +1579,16 @@ public class TypeManager { return false; } + public static bool IsNullType (Type t) + { + return t == null_type; + } + + public static bool IsAttributeType (Type t) + { + return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type); + } + static Stack unmanaged_enclosing_types = new Stack (4); // @@ -1322,6 +1604,9 @@ public class TypeManager { if (t == TypeManager.object_type || t == TypeManager.string_type) return false; + if (IsGenericType (t) || IsGenericParameter (t)) + return false; + if (IsBuiltinOrEnum (t)) return true; @@ -1336,11 +1621,18 @@ public class TypeManager { 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){ + if (t is TypeBuilder) { TypeContainer tc = LookupTypeContainer (t); if (tc.Fields != null){ foreach (FieldMember f in tc.Fields){ @@ -1373,10 +1665,7 @@ public class TypeManager { public static bool IsValueType (Type t) { - if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type)) - return true; - else - return false; + return t.IsValueType || IsGenericParameter (t); } public static bool IsInterfaceType (Type t) @@ -1390,8 +1679,26 @@ public class TypeManager { 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 (type.Equals (base_type)) + if (IsEqual (type, base_type)) return true; type = type.BaseType; @@ -1400,9 +1707,37 @@ public class TypeManager { return false; } - public static bool IsFamilyAccessible (Type type, Type base_type) + 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) { - return IsSubclassOf (type, base_type); + 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; } // @@ -1411,7 +1746,7 @@ public class TypeManager { public static bool IsNestedFamilyAccessible (Type type, Type base_type) { do { - if ((type == base_type) || type.IsSubclassOf (base_type)) + if (IsFamilyAccessible (type, base_type)) return true; // Handle nested types. @@ -1426,12 +1761,18 @@ public class TypeManager { // public static bool IsNestedChildOf (Type type, Type parent) { - if (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 (type == parent) + if (IsEqual (type, parent)) return true; type = type.DeclaringType; @@ -1440,6 +1781,81 @@ public class TypeManager { return false; } +#if GMCS_SOURCE + // + // Checks whether `extern_type' is friend of the output assembly + // + public static bool IsFriendAssembly (Assembly assembly) + { + if (assembly_internals_vis_attrs.Contains (assembly)) + return (bool)(assembly_internals_vis_attrs [assembly]); + + object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false); + if (attrs.Length == 0) { + assembly_internals_vis_attrs.Add (assembly, false); + return false; + } + + AssemblyName this_name = CodeGen.Assembly.Name; + byte [] this_token = this_name.GetPublicKeyToken (); + bool is_friend = false; + 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 == null) { + // Same name, but key token is null + Error_FriendAccessNameNotMatching (aname.FullName); + break; + } + + if (!CompareKeyTokens (this_token, key_token)) + continue; + } + + is_friend = true; + break; + } + + assembly_internals_vis_attrs.Add (assembly, is_friend); + return is_friend; + } + + 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"); + } +#else + public static bool IsFriendAssembly (Assembly assembly) + { + return false; + } +#endif + // // Do the right thing when returning the element type of an // array type based on whether we are compiling corlib or not @@ -1489,21 +1905,28 @@ public class TypeManager { static public void RegisterOverride (MethodBase override_method, MethodBase base_method) { - if (method_overrides.Contains (override_method)) { - if (method_overrides [override_method] != base_method) - throw new InternalErrorException ("Override mismatch: " + override_method); - return; - } - method_overrides [override_method] = 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]; + } + /// /// Returns the argument types for an indexer based on its PropertyInfo /// @@ -1519,12 +1942,12 @@ public class TypeManager { // If we're a PropertyBuilder and not in the // `indexer_arguments' hash, then we're a property and // not an indexer. - return NoTypes; + return Type.EmptyTypes; else { ParameterInfo [] pi = indexer.GetIndexParameters (); // Property, not an indexer. if (pi == null) - return NoTypes; + return Type.EmptyTypes; int c = pi.Length; Type [] types = new Type [c]; @@ -1549,6 +1972,16 @@ public class TypeManager { 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 bool RegisterFieldBase (FieldBuilder fb, FieldBase f) { if (fieldbuilders_to_fields.Contains (fb)) @@ -1565,11 +1998,12 @@ public class TypeManager { // static public FieldBase GetField (FieldInfo fb) { +#if GMCS_SOURCE + fb = GetGenericFieldDefinition (fb); +#endif return (FieldBase) fieldbuilders_to_fields [fb]; } - static Hashtable events; - static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove) { if (events == null) @@ -1698,20 +2132,42 @@ public class TypeManager { /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to /// be IA, IB, IC. /// - public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces) + public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces) { ArrayList new_ifaces = new ArrayList (); foreach (TypeExpr iface in base_interfaces){ - Type itype = iface.ResolveType (ec); - if (itype == null) - return null; + Type itype = iface.Type; + + if (new_ifaces.Contains (itype)) + continue; - if (!new_ifaces.Contains (itype)) - new_ifaces.Add (itype); + new_ifaces.Add (itype); - Type [] implementing = itype.GetInterfaces (); + 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); @@ -1721,7 +2177,7 @@ public class TypeManager { new_ifaces.CopyTo (ret, 0); return ret; } - + static PtrHashtable iface_cache = new PtrHashtable (); /// @@ -1730,7 +2186,6 @@ public class TypeManager { /// public static Type [] GetInterfaces (Type t) { - Type [] cached = iface_cache [t] as Type []; if (cached != null) return cached; @@ -1748,16 +2203,24 @@ public class TypeManager { if (t.IsArray) t = TypeManager.array_type; - if (t is TypeBuilder){ + if ((t is TypeBuilder) || IsGenericType (t)) { Type [] base_ifaces; if (t.BaseType == null) - base_ifaces = NoTypes; + base_ifaces = Type.EmptyTypes; else base_ifaces = GetInterfaces (t.BaseType); - Type [] type_ifaces = (Type []) builder_to_ifaces [t]; - if (type_ifaces == null) - type_ifaces = NoTypes; + 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]; @@ -1766,6 +2229,15 @@ public class TypeManager { 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; @@ -2006,6 +2478,7 @@ public class TypeManager { /// 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; @@ -2039,7 +2512,72 @@ public class TypeManager { } 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 // @@ -2052,7 +2590,8 @@ public class TypeManager { continue; if (method is MethodInfo && new_method is MethodInfo) - if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType) + if (!IsSignatureEqual (((MethodInfo) method).ReturnType, + ((MethodInfo) new_method).ReturnType)) continue; @@ -2064,7 +2603,7 @@ public class TypeManager { continue; for (i = 0; i < old_count; i++){ - if (old_args [i] != new_args [i]) + if (!IsSignatureEqual (old_args [i], new_args [i])) break; } if (i != old_count) @@ -2106,6 +2645,323 @@ public class TypeManager { 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; + + 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)) + return true; + +#if GMCS_SOURCE + if (a.IsGenericParameter && b.IsGenericParameter) { + 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) { + 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 (!IsEqual (aargs [i], bargs [i])) + return false; + } + + return true; + } +#endif + + return false; + } + + 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.IsGenericMethodDefinition) + return m; + if (m.IsGenericMethod) + return ((MethodInfo) m).GetGenericMethodDefinition (); + if (!m.DeclaringType.IsGenericType) + return m; + + Type t = m.DeclaringType.GetGenericTypeDefinition (); + BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; + +#if MS_COMPATIBLE + 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 (MethodInfo 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 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 + if (mb.DeclaringType is TypeBuilder) { + IMethodData method = (IMethodData) builder_to_method [mb]; + if (method == null) + return false; + + return method.GenericMethod != null; + } + + 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 @@ -2114,11 +2970,6 @@ public class TypeManager { // uses NonPublic for both protected and private), we need to distinguish. // - static internal bool FilterNone (MemberInfo m, object filter_criteria) - { - return true; - } - internal class Closure { internal bool private_ok; @@ -2139,18 +2990,19 @@ public class TypeManager { // It resolved from a simple name, so it should be visible. return true; - // A nested class has access to all the protected members visible to its parent. - if (qualifier_type != null && TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) + if (IsNestedChildOf (invocation_type, m.DeclaringType)) return true; - if (invocation_type == m.DeclaringType || invocation_type.IsSubclassOf (m.DeclaringType)) { + 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 || - qualifier_type == invocation_type || - qualifier_type.IsSubclassOf (invocation_type)) + if (is_static || qualifier_type == null || + IsInstantiationOfSameGenericType (t, qualifier_type) || + IsFamilyAccessible (qualifier_type, t)) return true; } @@ -2167,17 +3019,18 @@ public class TypeManager { internal bool Filter (MemberInfo m, object filter_criteria) { // - // Hack: we know that the filter criteria will always be in the `closure' - // fields. + // 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)) && - (m.DeclaringType == 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 @@ -2186,11 +3039,19 @@ public class TypeManager { 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 || invocation_type == m.DeclaringType || + return private_ok || + IsPrivateAccessible (invocation_type, m.DeclaringType) || IsNestedChildOf (invocation_type, m.DeclaringType); - if (invocation_assembly == mb.DeclaringType.Assembly) { + if (invocation_assembly == mb.DeclaringType.Assembly || + TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) { if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; } else { @@ -2198,43 +3059,44 @@ public class TypeManager { return false; } - if (ma == MethodAttributes.Family || - ma == MethodAttributes.FamANDAssem || - ma == MethodAttributes.FamORAssem) - return CheckValidFamilyAccess (mb.IsStatic, m); - - // Public. - return true; + // 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 || (invocation_type == m.DeclaringType) || + return private_ok || + IsPrivateAccessible (invocation_type, m.DeclaringType) || IsNestedChildOf (invocation_type, m.DeclaringType); - if (invocation_assembly == fi.DeclaringType.Assembly) { - if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamORAssem) + if ((invocation_assembly == fi.DeclaringType.Assembly) || + (invocation_assembly == null) || + TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) { + if ((fa == FieldAttributes.Assembly) || + (fa == FieldAttributes.FamORAssem)) return true; } else { - if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamANDAssem) + if ((fa == FieldAttributes.Assembly) || + (fa == FieldAttributes.FamANDAssem)) return false; } - if (fa == FieldAttributes.Family || - fa == FieldAttributes.FamANDAssem || - fa == FieldAttributes.FamORAssem) - return CheckValidFamilyAccess (fi.IsStatic, m); - - // Public. - return true; + // 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. + // EventInfos and PropertyInfos, return true because they lack + // permission information, so we need to check later on the methods. // return true; } @@ -2274,7 +3136,7 @@ public class TypeManager { // that might return multiple matches. // public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type, - Type queried_type, MemberTypes mt, + Type queried_type, MemberTypes mt, BindingFlags original_bf, string name, IList almost_match) { Timer.StartTimer (TimerType.MemberLookup); @@ -2394,8 +3256,7 @@ public class TypeManager { if ((list.Length == 2) && (list [1] is FieldInfo)) return new MemberInfo [] { list [0] }; - // Oooops - return null; + return list; } // @@ -2416,20 +3277,13 @@ public class TypeManager { mt &= (MemberTypes.Method | MemberTypes.Constructor); } } while (searching); - - if (use_first_members_list) { - foreach (MemberInfo mi in first_members_list) { - if (! (mi is MethodBase)) { - method_list = CopyNewMethods (method_list, first_members_list); - return (MemberInfo []) method_list.ToArray (typeof (MemberInfo)); - } - } - return (MemberInfo []) first_members_list; - } - if (method_list != null && method_list.Count > 0) - return (MemberInfo []) method_list.ToArray (typeof (MemberInfo)); - + 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. @@ -2468,7 +3322,7 @@ public class TypeManager { string name = mb.Name; if (name.StartsWith ("get_") || name.StartsWith ("set_")) return mb.DeclaringType.GetProperty (name.Substring (4)) != null; - + if (name.StartsWith ("add_")) return mb.DeclaringType.GetEvent (name.Substring (4)) != null; @@ -2480,7 +3334,7 @@ public class TypeManager { if (oname == name) return true; } - + foreach (string oname in Binary.oper_names) { if (oname == name) return true; @@ -2488,7 +3342,7 @@ public class TypeManager { } return false; } - + #endregion } @@ -2572,6 +3426,7 @@ public sealed class TypeHandle : IMemberContainer { 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; @@ -2579,12 +3434,17 @@ public sealed class TypeHandle : IMemberContainer { private TypeHandle (Type type) { this.type = type; +#if MS_COMPATIBLE && GMCS_SOURCE + if (type.IsGenericType) + this.type = this.type.GetGenericTypeDefinition (); +#endif + 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; + this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type); this.member_cache = new MemberCache (this); } @@ -2592,7 +3452,7 @@ public sealed class TypeHandle : IMemberContainer { public string Name { get { - return type.FullName; + return full_name; } } @@ -2617,6 +3477,12 @@ public sealed class TypeHandle : IMemberContainer { 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