X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Ftypemanager.cs;h=843e41083c1fbd39fe0df266e3068f519442da1d;hb=8db26e413f57a689ff42b659e045b8228143274c;hp=8d7dab4345296061a602858f81b9ae2d2f9e2fb8;hpb=371ed2b6661e9138177e2305e8b4be8ec5e9ce2b;p=mono.git diff --git a/mcs/gmcs/typemanager.cs b/mcs/gmcs/typemanager.cs index 8d7dab43452..843e41083c1 100755 --- a/mcs/gmcs/typemanager.cs +++ b/mcs/gmcs/typemanager.cs @@ -63,27 +63,40 @@ public class TypeManager { static public Type ienumerator_type; static public Type ienumerable_type; static public Type idisposable_type; + static public Type iconvertible_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 monitor_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 dllimport_type; static public Type unverifiable_code_type; static public Type methodimpl_attr_type; static public Type marshal_as_attr_type; + static public Type new_constraint_attr_type; static public Type param_array_type; static public Type guid_attr_type; static public Type void_ptr_type; static public Type indexer_name_type; static public Type exception_type; + static public Type activator_type; static public Type invalid_operation_exception_type; - static public object obsolete_attribute_type; - static public object conditional_attribute_type; + static public Type obsolete_attribute_type; + static public Type conditional_attribute_type; static public Type in_attribute_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 generic_ienumerator_type; + static public Type generic_ienumerable_type; // // An empty array of types @@ -135,7 +148,10 @@ public class TypeManager { static public MethodInfo string_concat_string_string; static public MethodInfo string_concat_string_string_string; static public MethodInfo string_concat_string_string_string_string; + static public MethodInfo string_concat_string_dot_dot_dot; static public MethodInfo string_concat_object_object; + static public MethodInfo string_concat_object_object_object; + static public MethodInfo string_concat_object_dot_dot_dot; static public MethodInfo string_isinterneted_string; static public MethodInfo system_type_get_type_from_handle; static public MethodInfo object_getcurrent_void; @@ -157,6 +173,7 @@ 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 activator_create_instance; // // The attribute constructors. @@ -206,6 +223,11 @@ public class TypeManager { // static PtrHashtable builder_to_ifaces; + // + // Tracks the generic parameters. + // + static PtrHashtable builder_to_type_param; + // // Maps MethodBase.RuntimeTypeHandle to a Type array that contains // the arguments to the method @@ -225,16 +247,16 @@ public class TypeManager { static Hashtable method_internal_params; // - // Keeps track of attribute types + // Keeps track of methods // - static Hashtable builder_to_attr; + static Hashtable builder_to_method; // - // Keeps track of methods + // Contains all public types from referenced assemblies. + // This member is used only if CLS Compliance verification is required. // - - static Hashtable builder_to_method; + public static Hashtable all_imported_types; struct Signature { public string name; @@ -254,13 +276,12 @@ public class TypeManager { method_arguments = null; indexer_arguments = null; method_internal_params = null; - builder_to_attr = null; builder_to_method = null; + builder_to_type_param = null; fields = null; references = null; negative_hits = null; - attr_to_allowmult = null; builder_to_constant = null; fieldbuilders_to_fields = null; events = null; @@ -350,12 +371,12 @@ public class TypeManager { typecontainers = new Hashtable (); builder_to_declspace = new PtrHashtable (); - builder_to_attr = new PtrHashtable (); builder_to_method = new PtrHashtable (); method_arguments = new PtrHashtable (); method_internal_params = new PtrHashtable (); indexer_arguments = new PtrHashtable (); builder_to_ifaces = new PtrHashtable (); + builder_to_type_param = new PtrHashtable (); NoTypes = new Type [0]; NoTypeExprs = new TypeExpr [0]; @@ -449,14 +470,24 @@ public class TypeManager { builder_to_declspace.Add (t, i); } - public static void AddMethod (MethodBuilder builder, MethodData method) + public static void AddMethod (MethodBase builder, IMethodData method) { builder_to_method.Add (builder, method); } - public static void RegisterAttrType (Type t, TypeContainer tc) + public static IMethodData GetMethod (MethodBase builder) { - builder_to_attr.Add (t, tc); + return (IMethodData) builder_to_method [builder]; + } + + public static void AddTypeParameter (Type t, TypeParameter tparam, TypeExpr[] ifaces) + { + if (!builder_to_type_param.Contains (t)) { + builder_to_type_param.Add (t, tparam); + + if (ifaces != null) + builder_to_ifaces [t] = ifaces; + } } /// @@ -485,6 +516,13 @@ public class TypeManager { return container; } + if (t is GenericTypeParameterBuilder) { + IMemberContainer container = builder_to_type_param [t] as IMemberContainer; + + if (container != null) + return container; + } + return TypeHandle.GetTypeHandle (t); } @@ -503,9 +541,30 @@ public class TypeManager { return builder_to_declspace [t] as Enum; } - public static TypeContainer LookupAttr (Type t) + public static Class LookupClass (Type t) { - return (TypeContainer) builder_to_attr [t]; + return (Class) builder_to_declspace [t]; + } + + public static TypeParameter LookupTypeParameter (Type t) + { + return (TypeParameter) builder_to_type_param [t]; + } + + public static bool HasConstructorConstraint (Type t) + { + if (!t.IsGenericParameter) + throw new InvalidOperationException (); + + TypeParameter tparam = LookupTypeParameter (t); + if (tparam != null) + return tparam.HasConstructorConstraint; + else { + object[] attrs = t.GetCustomAttributes ( + TypeManager.new_constraint_attr_type, false); + + return attrs.Length > 0; + } } /// @@ -527,6 +586,11 @@ public class TypeManager { assemblies = n; } + public static Assembly [] GetAssemblies () + { + return assemblies; + } + /// /// Registers a module builder to lookup types from /// @@ -541,6 +605,12 @@ public class TypeManager { modules = n; } + public static Module[] Modules { + get { + return modules; + } + } + static Hashtable references = new Hashtable (); // @@ -735,19 +805,38 @@ public class TypeManager { } } } else { - foreach (Assembly a in assemblies){ - foreach (Type t in a.GetTypes ()){ + Hashtable cache = new Hashtable (); + cache.Add ("", null); + foreach (Assembly a in assemblies) { + foreach (Type t in a.GetExportedTypes ()) { string ns = t.Namespace; - - // t.Namespace returns null for - if (ns == ""|| ns == null) + if (ns == null || cache.Contains (ns)) continue; + Namespace.LookupNamespace (ns, true); + cache.Add (ns, null); } } } } + /// + /// Fills static table with exported types from all referenced assemblies. + /// This information is required for CLS Compliance tests. + /// + public static void LoadAllImportedTypes () + { + if (!CodeGen.Assembly.IsClsCompliant) + return; + + all_imported_types = new Hashtable (); + foreach (Assembly a in assemblies) { + foreach (Type t in a.GetExportedTypes ()) { + all_imported_types [t.FullName] = t; + } + } + } + public static bool NamespaceClash (string name, Location loc) { if (Namespace.LookupNamespace (name, false) == null) @@ -762,6 +851,9 @@ public class TypeManager { /// static public string CSharpName (Type t) { + if (t.FullName == null) + return t.Name; + return Regex.Replace (t.FullName, @"^System\." + @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" + @@ -791,15 +883,32 @@ public class TypeManager { /// static public string GetFullNameSignature (MemberInfo mi) { - string n = mi.Name; - if (n == ".ctor") - n = mi.DeclaringType.Name; + return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name; + } - return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n; + static public string GetFullNameSignature (MethodBase mb) + { + string name = mb.Name; + if (name == ".ctor") + name = mb.DeclaringType.Name; + + if (mb.IsSpecialName) { + if (name.StartsWith ("get_") || name.StartsWith ("set_")) { + name = name.Remove (0, 4); + } + + if (name == "Item") + name = "this"; + } + + return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name; } static public string GetFullName (Type t) { + if (t.FullName == null) + return t.Name; + string name = t.FullName.Replace ('+', '.'); DeclSpace tc = LookupDeclSpace (t); @@ -852,7 +961,7 @@ public class TypeManager { /// static public string CSharpSignature (MethodBase mb) { - string sig = "("; + StringBuilder sig = new StringBuilder ("("); // // FIXME: We should really have a single function to do @@ -863,15 +972,25 @@ public class TypeManager { if (iparams == null) iparams = new ReflectionParameters (mb); + // Is property + if (mb.IsSpecialName && iparams.Count == 0) + return GetFullNameSignature (mb); + for (int i = 0; i < iparams.Count; i++) { if (i > 0) { - sig += ", "; + sig.Append (", "); } - sig += iparams.ParameterDesc(i); + sig.Append (iparams.ParameterDesc (i)); } - sig += ")"; + sig.Append (")"); + + // Is indexer + if (mb.IsSpecialName && iparams.Count == 1) { + sig.Replace ('(', '['); + sig.Replace (')', ']'); + } - return GetFullNameSignature (mb) + sig; + return GetFullNameSignature (mb) + sig.ToString (); } /// @@ -884,7 +1003,7 @@ public class TypeManager { if (t == null){ Report.Error (518, "The predefined type `" + name + "' is not defined or imported"); - Environment.Exit (0); + Environment.Exit (1); } return t; @@ -1004,6 +1123,7 @@ public class TypeManager { type_type = CoreLookupType ("System.Type"); runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle"); + runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle"); runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers"); default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute"); runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle"); @@ -1013,6 +1133,7 @@ public class TypeManager { ienumerable_type = CoreLookupType ("System.Collections.IEnumerable"); idisposable_type = CoreLookupType ("System.IDisposable"); icloneable_type = CoreLookupType ("System.ICloneable"); + iconvertible_type = CoreLookupType ("System.IConvertible"); monitor_type = CoreLookupType ("System.Threading.Monitor"); intptr_type = CoreLookupType ("System.IntPtr"); @@ -1021,8 +1142,12 @@ public class TypeManager { dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute"); methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute"); marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute"); + new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute"); param_array_type = CoreLookupType ("System.ParamArrayAttribute"); in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute"); + typed_reference_type = CoreLookupType ("System.TypedReference"); + arg_iterator_type = CoreLookupType ("System.ArgIterator"); + mbr_type = CoreLookupType ("System.MarshalByRefObject"); // // Sigh. Remove this before the release. Wonder what versions of Mono @@ -1037,6 +1162,7 @@ public class TypeManager { indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute"); exception_type = CoreLookupType ("System.Exception"); + activator_type = CoreLookupType ("System.Activator"); invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException"); // @@ -1044,6 +1170,16 @@ public class TypeManager { // obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute"); conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute"); + cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute"); + struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute"); + field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute"); + + // + // Generic types + // + generic_ienumerator_type = CoreLookupType ("System.Collections.Generic.IEnumerator`1"); + generic_ienumerable_type = CoreLookupType ("System.Collections.Generic.IEnumerable`1"); + // // When compiling corlib, store the "real" types here. @@ -1149,10 +1285,19 @@ public class TypeManager { Type [] string_string_string_string = { string_type, string_type, string_type, string_type }; string_concat_string_string_string_string = GetMethod ( string_type, "Concat", string_string_string_string); + Type[] params_string = { TypeManager.LookupType ("System.String[]") }; + string_concat_string_dot_dot_dot = GetMethod ( + string_type, "Concat", params_string); Type [] object_object = { object_type, object_type }; string_concat_object_object = GetMethod ( string_type, "Concat", object_object); + Type [] object_object_object = { object_type, object_type, object_type }; + string_concat_object_object_object = GetMethod ( + string_type, "Concat", object_object_object); + Type[] params_object = { TypeManager.LookupType ("System.Object[]") }; + string_concat_object_dot_dot_dot = GetMethod ( + string_type, "Concat", params_object); Type [] string_ = { string_type }; string_isinterneted_string = GetMethod ( @@ -1256,6 +1401,10 @@ public class TypeManager { // Object object_ctor = GetConstructor (object_type, void_arg); + // Activator + Type [] type_arg = { type_type }; + activator_create_instance = GetMethod ( + activator_type, "CreateInstance", type_arg); } const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance; @@ -1332,9 +1481,8 @@ public class TypeManager { /// our return value will already contain all inherited members and the caller don't need /// to check base classes and interfaces anymore. /// - private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, - string name, int num_type_arguments, - out bool used_cache) + private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, + string name, out bool used_cache) { // // We have to take care of arrays specially, because GetType on @@ -1366,6 +1514,7 @@ 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); @@ -1373,7 +1522,19 @@ public class TypeManager { FilterWithClosure_delegate, name); Timer.StopTimer (TimerType.FindMembers); used_cache = false; - return list; + return (MemberInfo []) list; + } + + 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 = false; + return (MemberInfo []) list; } // @@ -1398,6 +1559,11 @@ public class TypeManager { return false; } + public static bool IsBuiltinType (TypeContainer tc) + { + return IsBuiltinType (tc.TypeBuilder); + } + // // 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. @@ -1452,6 +1618,11 @@ public class TypeManager { return ds.IsGeneric; } + public static bool HasGenericArguments (Type t) + { + return GetNumberOfTypeArguments (t) > 0; + } + public static int GetNumberOfTypeArguments (Type t) { DeclSpace tc = LookupDeclSpace (t); @@ -1480,36 +1651,6 @@ public class TypeManager { } else return t.GetGenericArguments (); } - - public static bool CheckGeneric (Type t, int num_type_arguments) - { - if (num_type_arguments < 0) - return true; - - DeclSpace tc = LookupDeclSpace (t); - - if (tc != null) { - if (!tc.IsGeneric) - return num_type_arguments == 0; - - if (num_type_arguments == 0) - return false; - - if (num_type_arguments != tc.CountTypeParameters) - return false; - } else { - if (!t.HasGenericArguments) - return num_type_arguments == 0; - - if (num_type_arguments == 0) - return false; - - if (num_type_arguments != t.GetGenericArguments ().Length) - return false; - } - - return true; - } // // Whether a type is unmanaged. This is used by the unsafe code (25.2) @@ -1529,12 +1670,15 @@ public class TypeManager { if (t is TypeBuilder){ TypeContainer tc = LookupTypeContainer (t); + if (tc.Fields != null){ foreach (Field f in tc.Fields){ if (f.FieldBuilder.IsStatic) continue; if (!IsUnmanagedType (f.FieldBuilder.FieldType)) return false; } + } else + return true; } else { FieldInfo [] fields = t.GetFields (); @@ -1716,6 +1860,14 @@ public class TypeManager { return false; } + public static bool IsSubclassOf (Type type, Type parent) + { + if (type.IsGenericInstance && !parent.IsGenericInstance) + type = type.GetGenericTypeDefinition (); + + return type.IsSubclassOf (parent); + } + // // Checks whether `type' is a subclass or nested child of `parent'. // @@ -1779,39 +1931,6 @@ public class TypeManager { } } - static Hashtable attr_to_allowmult; - - public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow) - { - if (attr_to_allowmult == null) - attr_to_allowmult = new PtrHashtable (); - - if (attr_to_allowmult.Contains (attr_type)) - return; - - attr_to_allowmult.Add (attr_type, allow); - - } - - public static bool AreMultipleAllowed (Type attr_type) - { - if (!(attr_type is TypeBuilder)) { - System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type); - - foreach (System.Attribute tmp in attrs) - if (tmp is AttributeUsageAttribute) { - return ((AttributeUsageAttribute) tmp).AllowMultiple; - } - - return false; - } - - if (attr_to_allowmult == null) - return false; - - return (bool) attr_to_allowmult [attr_type]; - } - static Hashtable builder_to_constant; public static void RegisterConstant (FieldBuilder fb, Const c) @@ -1873,20 +1992,24 @@ public class TypeManager { /// static public Type [] GetArgumentTypes (MethodBase mb) { - if (method_arguments.Contains (mb)) - return (Type []) method_arguments [mb]; - else { + object t = method_arguments [mb]; + if (t != null) + return (Type []) t; + ParameterInfo [] pi = mb.GetParameters (); int c = pi.Length; - Type [] types = new Type [c]; + Type [] types; + if (c == 0) { + types = NoTypes; + } else { + types = new Type [c]; for (int i = 0; i < c; i++) types [i] = pi [i].ParameterType; - + } method_arguments.Add (mb, types); return types; } - } /// /// Returns the argument types for an indexer based on its PropertyInfo @@ -2044,6 +2167,64 @@ public class TypeManager { return true; } + 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 is Struct) || IsBuiltinType (tc)) + 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 (Field field in tc.Fields) { + if (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. @@ -2117,6 +2298,13 @@ public class TypeManager { iface_cache [t] = result; return result; + } else if (t is GenericTypeParameterBuilder){ + TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t]; + if (type_ifaces == null) + type_ifaces = NoTypeExprs; + + iface_cache [t] = type_ifaces; + return type_ifaces; } else { Type [] ifaces = t.GetInterfaces (); if (ifaces.Length == 0) @@ -2332,6 +2520,8 @@ public class TypeManager { return TypeManager.object_type; if (t == typeof (System.Type)) return TypeManager.type_type; + if (t == typeof (System.IntPtr)) + return TypeManager.intptr_type; return t; } } @@ -2405,15 +2595,27 @@ public class TypeManager { return "Item"; } - public static void MakePinned (LocalBuilder builder) - { - // - // FIXME: Flag the "LocalBuilder" type as being - // pinned. Figure out API. - // + 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.Warning (-24, new Location (-1), + "This version of the runtime does not support making pinned local variables. " + + "This code may cause errors on a runtime with a moving GC"); + return ig.DeclareLocal (t); + } + } + return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true }); } - // // Returns whether the array of memberinfos contains the given method // @@ -2456,7 +2658,7 @@ public class TypeManager { // // The name is assumed to be the same. // - public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members) + public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members) { if (target_list == null){ target_list = new ArrayList (); @@ -2480,17 +2682,10 @@ public class TypeManager { return target_list; } - [Flags] - public enum MethodFlags { - IsObsolete = 1, - IsObsoleteError = 1 << 1, - ShouldIgnore = 1 << 2 - } - - static public bool IsGenericMethod (MethodInfo mb) + static public bool IsGenericMethod (MethodBase mb) { if (mb.DeclaringType is TypeBuilder) { - MethodData method = (MethodData) builder_to_method [mb]; + IMethodData method = (IMethodData) builder_to_method [mb]; if (method == null) return false; @@ -2500,101 +2695,65 @@ public class TypeManager { return mb.IsGenericMethodDefinition; } - // - // Returns the TypeManager.MethodFlags for this method. - // This emits an error 619 / warning 618 if the method is obsolete. - // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned. - // - static public MethodFlags GetMethodFlags (MethodBase mb, Location loc) - { - MethodFlags flags = 0; - - if (mb.DeclaringType is TypeBuilder){ - MethodData method = (MethodData) builder_to_method [mb]; - if (method == null) { - // FIXME: implement Obsolete attribute on Property, - // Indexer and Event. - return 0; - } - - return method.GetMethodFlags (loc); - } - - if (mb.HasGenericParameters) { - MethodBase generic = mb.GetGenericMethodDefinition (); - - return GetMethodFlags (generic, loc); - } - - object [] attrs = mb.GetCustomAttributes (true); - foreach (object ta in attrs){ - if (!(ta is System.Attribute)){ - Console.WriteLine ("Unknown type in GetMethodFlags: " + ta); - continue; - } - System.Attribute a = (System.Attribute) ta; - if (a.TypeId == TypeManager.obsolete_attribute_type){ - ObsoleteAttribute oa = (ObsoleteAttribute) a; - - string method_desc = TypeManager.CSharpSignature (mb); - - if (oa.IsError) { - Report.Error (619, loc, "Method `" + method_desc + - "' is obsolete: `" + oa.Message + "'"); - return MethodFlags.IsObsoleteError; - } else - Report.Warning (618, loc, "Method `" + method_desc + - "' is obsolete: `" + oa.Message + "'"); - - flags |= MethodFlags.IsObsolete; - - continue; - } - - // - // Skip over conditional code. - // - if (a.TypeId == TypeManager.conditional_attribute_type){ - ConditionalAttribute ca = (ConditionalAttribute) a; - - if (RootContext.AllDefines [ca.ConditionString] == null) - flags |= MethodFlags.ShouldIgnore; - } - } - - return flags; - } - #region MemberLookup implementation // // Whether we allow private members in the result (since FindMembers // uses NonPublic for both protected and private), we need to distinguish. // - static bool closure_private_ok; - // + static internal bool FilterNone (MemberInfo m, object filter_criteria) + { + return true; + } + + internal class Closure { + internal bool private_ok; + // Who is invoking us and which type is being queried currently. - // - static Type closure_invocation_type; - static Type closure_qualifier_type; - static int closure_num_type_arguments; + internal Type invocation_type; + internal Type qualifier_type; - // // The assembly that defines the type is that is calling us - // - static Assembly closure_invocation_assembly; + internal Assembly invocation_assembly; + internal IList almost_match; - static internal bool FilterNone (MemberInfo m, object filter_criteria) + private bool CheckValidFamilyAccess (bool is_static, MemberInfo m) { + if (invocation_type == null) + return false; + + Debug.Assert (IsSubclassOrNestedChildOf (invocation_type, m.DeclaringType)); + + if (is_static) + 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)) + return true; + + if (invocation_type == m.DeclaringType + || invocation_type.IsSubclassOf (m.DeclaringType)) { + // 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 (qualifier_type == null + || qualifier_type == invocation_type + || qualifier_type.IsSubclassOf (invocation_type)) 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 // - static internal bool FilterWithClosure (MemberInfo m, object filter_criteria) + internal bool Filter (MemberInfo m, object filter_criteria) { // // Hack: we know that the filter criteria will always be in the `closure' @@ -2604,11 +2763,8 @@ public class TypeManager { if ((filter_criteria != null) && (m.Name != (string) filter_criteria)) return false; - if (m is Type) - return TypeManager.CheckGeneric ((Type) m, closure_num_type_arguments); - - if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) && - (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type)) + if (((qualifier_type == null) || (qualifier_type == invocation_type)) && + (invocation_type != null) && IsEqual (m.DeclaringType, invocation_type)) return true; // @@ -2620,22 +2776,22 @@ public class TypeManager { MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask; if (ma == MethodAttributes.Private) - return closure_private_ok || - IsEqual (closure_invocation_type, m.DeclaringType) || - IsNestedChildOf (closure_invocation_type, m.DeclaringType); + return private_ok || + IsEqual (invocation_type, m.DeclaringType) || + IsNestedChildOf (invocation_type, m.DeclaringType); // // FamAndAssem requires that we not only derivate, but we are on the // same assembly. // if (ma == MethodAttributes.FamANDAssem){ - if (closure_invocation_assembly != mb.DeclaringType.Assembly) + if (invocation_assembly != mb.DeclaringType.Assembly) return false; } // Assembly and FamORAssem succeed if we're in the same assembly. if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){ - if (closure_invocation_assembly == mb.DeclaringType.Assembly) + if (invocation_assembly == mb.DeclaringType.Assembly) return true; } @@ -2645,17 +2801,18 @@ public class TypeManager { // Family and FamANDAssem require that we derive. if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){ - if (closure_invocation_type == null) + if (invocation_type == null) return false; - if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType)) + if (!IsSubclassOrNestedChildOf (invocation_type, mb.DeclaringType)) return false; // Although a derived class can access protected members of its base class // it cannot do so through an instance of the base class (CS1540). - if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) && - (closure_qualifier_type != null) && - closure_invocation_type.IsSubclassOf (closure_qualifier_type)) + if (!mb.IsStatic && (invocation_type != qualifier_type) && + (qualifier_type != null) && + invocation_type.IsSubclassOf (qualifier_type) && + !TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) return false; return true; @@ -2670,22 +2827,22 @@ public class TypeManager { FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask; if (fa == FieldAttributes.Private) - return closure_private_ok || - IsEqual (closure_invocation_type, m.DeclaringType) || - IsNestedChildOf (closure_invocation_type, m.DeclaringType); + return private_ok || + IsEqual (invocation_type, m.DeclaringType) || + IsNestedChildOf (invocation_type, m.DeclaringType); // // FamAndAssem requires that we not only derivate, but we are on the // same assembly. // if (fa == FieldAttributes.FamANDAssem){ - if (closure_invocation_assembly != fi.DeclaringType.Assembly) + if (invocation_assembly != fi.DeclaringType.Assembly) return false; } // Assembly and FamORAssem succeed if we're in the same assembly. if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){ - if (closure_invocation_assembly == fi.DeclaringType.Assembly) + if (invocation_assembly == fi.DeclaringType.Assembly) return true; } @@ -2695,17 +2852,18 @@ public class TypeManager { // Family and FamANDAssem require that we derive. if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){ - if (closure_invocation_type == null) + if (invocation_type == null) return false; - if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType)) + if (!IsSubclassOrNestedChildOf (invocation_type, fi.DeclaringType)) return false; // Although a derived class can access protected members of its base class // it cannot do so through an instance of the base class (CS1540). - if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) && - (closure_qualifier_type != null) && - closure_invocation_type.IsSubclassOf (closure_qualifier_type)) + if (!fi.IsStatic && (invocation_type != qualifier_type) && + (qualifier_type != null) && + invocation_type.IsSubclassOf (qualifier_type) && + !TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) return false; return true; @@ -2717,12 +2875,14 @@ public class TypeManager { // // EventInfos and PropertyInfos, return true because they lack permission - // informaiton, so we need to check later on the methods. + // information, so we need to check later on the methods. // return true; } + } - static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure); + static Closure closure = new Closure (); + static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter); static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone); // @@ -2750,19 +2910,19 @@ public class TypeManager { // is allowed to access (using the specified `qualifier_type' if given); only use // BindingFlags.NonPublic to bypass the permission check. // + // The 'almost_match' argument is used for reporting error CS1540. + // // 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, int num_type_arguments, - MemberTypes mt, BindingFlags original_bf, - string name) + Type queried_type, MemberTypes mt, + BindingFlags original_bf, string name, IList almost_match) { Timer.StartTimer (TimerType.MemberLookup); MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type, - queried_type, num_type_arguments, - mt, original_bf, name); + queried_type, mt, original_bf, name, almost_match); Timer.StopTimer (TimerType.MemberLookup); @@ -2770,9 +2930,8 @@ public class TypeManager { } static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type, - Type queried_type, int num_type_arguments, - MemberTypes mt, BindingFlags original_bf, - string name) + Type queried_type, MemberTypes mt, + BindingFlags original_bf, string name, IList almost_match) { BindingFlags bf = original_bf; @@ -2782,11 +2941,10 @@ public class TypeManager { bool skip_iface_check = true, used_cache = false; bool always_ok_flag = false; - closure_invocation_type = invocation_type; - closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null; - closure_qualifier_type = qualifier_type; - - closure_num_type_arguments = num_type_arguments; + 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; // // If we are a nested class, we always have access to our container @@ -2794,7 +2952,7 @@ public class TypeManager { // if (invocation_type != null){ string invocation_name = invocation_type.FullName; - if (invocation_name.IndexOf ('+') != -1){ + if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){ string container = queried_type.FullName + "+"; int container_length = container.Length; @@ -2807,8 +2965,14 @@ public class TypeManager { } } + // 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 { - MemberList list; + MemberInfo [] list; // // `NonPublic' is lame, because it includes both protected and @@ -2827,12 +2991,12 @@ public class TypeManager { else bf = original_bf; - closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0; + closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0; Timer.StopTimer (TimerType.MemberLookup); - list = MemberLookup_FindMembers (current_type, mt, bf, name, - num_type_arguments, out used_cache); + list = MemberLookup_FindMembers ( + current_type, mt, bf, name, out used_cache); Timer.StartTimer (TimerType.MemberLookup); @@ -2863,7 +3027,7 @@ public class TypeManager { current_type = TypeManager.object_type; } - if (list.Count == 0) + if (list.Length == 0) continue; // @@ -2871,8 +3035,8 @@ public class TypeManager { // searches, which means that our above FindMembers will // return two copies of the same. // - if (list.Count == 1 && !(list [0] is MethodBase)){ - return (MemberInfo []) list; + if (list.Length == 1 && !(list [0] is MethodBase)){ + return list; } // @@ -2880,14 +3044,14 @@ public class TypeManager { // name // if (list [0] is PropertyInfo) - return (MemberInfo []) list; + return list; // // We found an event: the cache lookup returns both the event and // its private field. // if (list [0] is EventInfo) { - if ((list.Count == 2) && (list [1] is FieldInfo)) + if ((list.Length == 2) && (list [1] is FieldInfo)) return new MemberInfo [] { list [0] }; // Oooops @@ -2899,10 +3063,31 @@ public class TypeManager { // mode. // - method_list = CopyNewMethods (method_list, list); - mt &= (MemberTypes.Method | MemberTypes.Constructor); + 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) { + 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)); } @@ -2930,8 +3115,7 @@ public class TypeManager { foreach (TypeExpr itype in ifaces){ MemberInfo [] x; - x = MemberLookup (null, null, itype.Type, num_type_arguments, - mt, bf, name); + x = MemberLookup (null, null, itype.Type, mt, bf, name, null); if (x != null) return x; } @@ -3089,15 +3273,17 @@ 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 TypeHandle (Type type) { this.type = type; + full_name = type.FullName != null ? type.FullName : type.Name; if (type.BaseType != null) BaseType = GetTypeHandle (type.BaseType); - this.is_interface = type.IsInterface; + this.is_interface = type.IsInterface || type.IsGenericParameter; this.member_cache = new MemberCache (this); } @@ -3105,7 +3291,7 @@ public sealed class TypeHandle : IMemberContainer { public string Name { get { - return type.FullName; + return full_name; } } @@ -3130,6 +3316,8 @@ public sealed class TypeHandle : IMemberContainer { public MemberList GetMembers (MemberTypes mt, BindingFlags bf) { MemberInfo [] members; + if (type is GenericTypeParameterBuilder) + return MemberList.Empty; if (mt == MemberTypes.Event) members = type.GetEvents (bf | BindingFlags.DeclaredOnly); else @@ -3145,7 +3333,7 @@ public sealed class TypeHandle : IMemberContainer { public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name, MemberFilter filter, object criteria) { - return member_cache.FindMembers (mt, bf, name, filter, criteria); + return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria)); } public MemberCache MemberCache {