2004-11-16 Martin Baulig <martin@ximian.com>
authorMartin Baulig <martin@novell.com>
Tue, 16 Nov 2004 03:17:29 +0000 (03:17 -0000)
committerMartin Baulig <martin@novell.com>
Tue, 16 Nov 2004 03:17:29 +0000 (03:17 -0000)
This is based on a patch from Marek Safar, see bug #69082.
Fixes bugs #63705 and #67130.

* typemanager.cs (TypeManager.LookupInterfaceCache): New public
method; create a MemberCache for an interface type and cache the
result.

* decl.cs (IMemberContainer.ParentContainer): Removed.
(IMemberContainer.ParentCache): New property.
(MemberCache.SetupCacheForInterface): Removed.
(MemberCache..ctor): Added .ctor which takes a `Type[]'; use this
to create a cache for an interface's "parent".

* class.cs (TypeContainer.DoDefineMembers): Setup cache for
interfaces too.

svn path=/trunk/mcs/; revision=36157

mcs/gmcs/ChangeLog
mcs/gmcs/class.cs
mcs/gmcs/decl.cs
mcs/gmcs/generic.cs
mcs/gmcs/typemanager.cs

index bfd255a0c6893909494e9c87187ebccdb823b343..3d13fa52c36c05a9f67bf8144a7714f88f8b0f1d 100755 (executable)
@@ -1,3 +1,21 @@
+2004-11-16  Martin Baulig  <martin@ximian.com>
+
+       This is based on a patch from Marek Safar, see bug #69082.
+       Fixes bugs #63705 and #67130.
+
+       * typemanager.cs (TypeManager.LookupInterfaceCache): New public
+       method; create a MemberCache for an interface type and cache the
+       result.
+
+       * decl.cs (IMemberContainer.ParentContainer): Removed.
+       (IMemberContainer.ParentCache): New property.
+       (MemberCache.SetupCacheForInterface): Removed.
+       (MemberCache..ctor): Added .ctor which takes a `Type[]'; use this
+       to create a cache for an interface's "parent".
+
+       * class.cs (TypeContainer.DoDefineMembers): Setup cache for
+       interfaces too.
+
 2004-11-15  Martin Baulig  <martin@ximian.com>
 
        * decl.cs (MemberName.GetPartialName): Removed, use GetTypeName() instead.
index 526de956bca71194cc6d7aaa94256e33fa01b4f6..2b119e6dc7f28e4aee62193d7630092de8725674 100755 (executable)
@@ -450,6 +450,7 @@ namespace Mono.CSharp {
 
                // The parent member container and our member cache
                IMemberContainer parent_container;
+               MemberCache parent_cache;
                MemberCache member_cache;
 
                public const string DefaultIndexerName = "Item";
@@ -1437,13 +1438,13 @@ namespace Mono.CSharp {
                        //
                        // We need to be able to use the member cache while we are checking/defining
                        //
-                       if (TypeBuilder.BaseType != null)
+                       if (TypeBuilder.BaseType != null) {
                                parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+                               parent_cache = parent_container.MemberCache;
+                       }
 
-                       // TODO:
-                       //if (TypeBuilder.IsInterface) {
-                       //      parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
-                       //}
+                       if (TypeBuilder.IsInterface)
+                               parent_cache = TypeManager.LookupInterfaceCache (this, TypeBuilder);
 
                        if (IsTopLevel) {
                                if ((ModFlags & Modifiers.NEW) != 0)
@@ -1586,7 +1587,7 @@ namespace Mono.CSharp {
 
                public MemberInfo FindMemberWithSameName (string name, bool ignore_methods)
                {
-                       return ParentContainer.MemberCache.FindMemberWithSameName (name, ignore_methods, null);
+                       return ParentCache.FindMemberWithSameName (name, ignore_methods, null);
                }
 
                /// <summary>
@@ -2292,7 +2293,7 @@ namespace Mono.CSharp {
                        type_bases = null;
                        OptAttributes = null;
                        ifaces = null;
-                       parent_container = null;
+                       parent_cache = null;
                        member_cache = null;
                }
 
@@ -2412,9 +2413,9 @@ namespace Mono.CSharp {
                /// </summary>
                void VerifyClsName ()
                {
-                       Hashtable parent_members = parent_container == null ? 
+                       Hashtable parent_members = parent_cache == null ? 
                                new Hashtable () :
-                               parent_container.MemberCache.GetPublicMembers ();
+                               parent_cache.GetPublicMembers ();
                        Hashtable this_members = new Hashtable ();
 
                        foreach (DictionaryEntry entry in defined_names) {
@@ -2528,9 +2529,9 @@ namespace Mono.CSharp {
                                return FindMembers (mt, new_bf, null, null);
                }
 
-               public virtual IMemberContainer ParentContainer {
+               public virtual MemberCache ParentCache {
                        get {
-                               return parent_container;
+                               return parent_cache;
                        }
                }
                
@@ -2709,9 +2710,9 @@ namespace Mono.CSharp {
                                interface_type, full, name, loc);
                }
 
-               public override IMemberContainer ParentContainer {
+               public override MemberCache ParentCache {
                        get {
-                               return PartialContainer.ParentContainer;
+                               return PartialContainer.ParentCache;
                        }
                }
        }
@@ -3125,7 +3126,7 @@ namespace Mono.CSharp {
                                return true;
 
                        // Is null for System.Object while compiling corlib and base interfaces
-                       if (Parent.ParentContainer == null) {
+                       if (Parent.ParentCache == null) {
                                if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
                                        Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
                                }
@@ -3149,7 +3150,7 @@ namespace Mono.CSharp {
                                                return false;
                                        }
                                } else {
-                                       if (parent_method.IsAbstract) {
+                                       if (parent_method.IsAbstract && !IsInterface) {
                                                Report.SymbolRelatedToPreviousError (parent_method);
                                                Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
                                                return false;
@@ -3953,7 +3954,7 @@ namespace Mono.CSharp {
 
                protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
                {
-                       MethodInfo mi = (MethodInfo) container.ParentContainer.MemberCache.FindMemberToOverride (
+                       MethodInfo mi = (MethodInfo) container.ParentCache.FindMemberToOverride (
                                container.TypeBuilder, Name, ParameterTypes, false);
 
                        if (mi == null)
@@ -6264,7 +6265,7 @@ namespace Mono.CSharp {
                // TODO: rename to Resolve......
                protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
                {
-                       PropertyInfo parent_property = container.ParentContainer.MemberCache.FindMemberToOverride (
+                       PropertyInfo parent_property = container.ParentCache.FindMemberToOverride (
                                container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
 
                        if (parent_property == null)
index c31f9f3b3e96b77639c43f22a1ac2f3b2bdd7a83..c57a6a8d04fa2aa77a5b8c0c1e90ec64495f2f0d 100755 (executable)
@@ -525,7 +525,7 @@ namespace Mono.CSharp {
                /// </summary>
                protected bool AddToContainer (MemberCore symbol, bool is_method, string fullname, string basename)
                {
-                       if (basename == Basename) {
+                       if (basename == Basename && !(this is Interface)) {
                                Report.SymbolRelatedToPreviousError (this);
                                Report.Error (542, "'{0}': member names cannot be the same as their enclosing type", symbol.Location, symbol.GetSignatureForError ());
                                return false;
@@ -1568,7 +1568,7 @@ namespace Mono.CSharp {
                ///   This is used when creating the member cache for a class to get all
                ///   members from the parent class.
                /// </summary>
-               IMemberContainer ParentContainer {
+               MemberCache ParentCache {
                        get;
                }
 
@@ -1619,7 +1619,7 @@ namespace Mono.CSharp {
                public readonly IMemberContainer Container;
                protected Hashtable member_hash;
                protected Hashtable method_hash;
-               
+
                /// <summary>
                ///   Create a new MemberCache for the given IMemberContainer `container'.
                /// </summary>
@@ -1630,20 +1630,10 @@ namespace Mono.CSharp {
                        Timer.IncrementCounter (CounterType.MemberCache);
                        Timer.StartTimer (TimerType.CacheInit);
 
-                       
-
                        // If we have a parent class (we have a parent class unless we're
                        // TypeManager.object_type), we deep-copy its MemberCache here.
-                       if (Container.IsInterface) {
-                               MemberCache parent;
-                               
-                               if (Container.ParentContainer != null)
-                                       parent = Container.ParentContainer.MemberCache;
-                               else
-                                       parent = TypeHandle.ObjectType.MemberCache;
-                               member_hash = SetupCacheForInterface (parent);
-                       } else if (Container.ParentContainer != null)
-                               member_hash = SetupCache (Container.ParentContainer.MemberCache);
+                       if (Container.ParentCache != null)
+                               member_hash = SetupCache (Container.ParentCache);
                        else
                                member_hash = new Hashtable ();
 
@@ -1661,6 +1651,24 @@ namespace Mono.CSharp {
                        Timer.StopTimer (TimerType.CacheInit);
                }
 
+               public MemberCache (IMemberContainer container, Type[] ifaces)
+               {
+                       this.Container = container;
+
+                       member_hash = new Hashtable ();
+                       if (ifaces == null)
+                               return;
+
+                       foreach (Type itype in ifaces) {
+                               IMemberContainer iface_container =
+                                       TypeManager.LookupMemberContainer (itype);
+
+                               MemberCache iface_cache = iface_container.MemberCache;
+
+                               AddHashtable (member_hash, iface_cache);
+                       }
+               }
+
                /// <summary>
                ///   Bootstrap this member cache by doing a deep-copy of our parent.
                /// </summary>
@@ -1668,6 +1676,9 @@ namespace Mono.CSharp {
                {
                        Hashtable hash = new Hashtable ();
 
+                       if (parent == null)
+                               return hash;
+
                        IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
                        while (it.MoveNext ()) {
                                hash [it.Key] = ((ArrayList) it.Value).Clone ();
@@ -1676,7 +1687,6 @@ namespace Mono.CSharp {
                        return hash;
                }
 
-
                /// <summary>
                ///   Add the contents of `new_hash' to `hash'.
                /// </summary>
@@ -1697,28 +1707,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   Bootstrap the member cache for an interface type.
-               ///   Type.GetMembers() won't return any inherited members for interface types,
-               ///   so we need to do this manually.  Interfaces also inherit from System.Object.
-               /// </summary>
-               Hashtable SetupCacheForInterface (MemberCache parent)
-               {
-                       Hashtable hash = SetupCache (parent);
-                       Type [] ifaces = TypeManager.GetInterfaces (Container.Type);
-
-                       foreach (Type itype in ifaces) {
-                               IMemberContainer iface_container =
-                                       TypeManager.LookupMemberContainer (itype);
-
-                               MemberCache iface_cache = iface_container.MemberCache;
-
-                               AddHashtable (hash, iface_cache);
-                       }
-
-                       return hash;
-               }
-
                /// <summary>
                ///   Add all members from class `container' to the cache.
                /// </summary>
@@ -1726,8 +1714,10 @@ namespace Mono.CSharp {
                {
                        // We need to call AddMembers() with a single member type at a time
                        // to get the member type part of CacheEntry.EntryType right.
+                       if (!container.IsInterface) {
                        AddMembers (MemberTypes.Constructor, container);
                        AddMembers (MemberTypes.Field, container);
+                       }
                        AddMembers (MemberTypes.Method, container);
                        AddMembers (MemberTypes.Property, container);
                        AddMembers (MemberTypes.Event, container);
@@ -1914,6 +1904,12 @@ namespace Mono.CSharp {
                                this.Member = member;
                                this.EntryType = GetEntryType (mt, bf);
                        }
+
+                       public override string ToString ()
+                       {
+                               return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,
+                                                     EntryType, Member);
+                       }
                }
 
                /// <summary>
index 61a1daa2a3d034030c141431c8354dfb3d7842f0..8e3baa2a0f1215432b69416b9f71761b4395f1a7 100644 (file)
@@ -663,7 +663,7 @@ namespace Mono.CSharp {
                        get { return Name; }
                }
 
-               IMemberContainer IMemberContainer.ParentContainer {
+               MemberCache IMemberContainer.ParentCache {
                        get { return null; }
                }
 
index d1c866d37fd8709de1747596b6f9ec28d7383745..3d0913d8ccf2f6aa11ee23e486032657a1e734f0 100755 (executable)
@@ -222,6 +222,8 @@ public class TypeManager {
 
        static PtrHashtable builder_to_declspace;
 
+       static PtrHashtable builder_to_member_cache;
+
        // <remarks>
        //   Tracks the interfaces implemented by typebuilders.  We only
        //   enter those who do implement or or more interfaces
@@ -277,6 +279,7 @@ public class TypeManager {
                typecontainers = null;
                user_types = null;
                builder_to_declspace = null;
+               builder_to_member_cache = null;
                builder_to_ifaces = null;
                method_arguments = null;
                indexer_arguments = null;
@@ -377,6 +380,7 @@ public class TypeManager {
                typecontainers = new Hashtable ();
                
                builder_to_declspace = new PtrHashtable ();
+               builder_to_member_cache = new PtrHashtable ();
                builder_to_method = new PtrHashtable ();
                method_arguments = new PtrHashtable ();
                method_internal_params = new PtrHashtable ();
@@ -508,7 +512,7 @@ public class TypeManager {
 
                return LookupTypeContainer (t);
        }
-       
+
        public static IMemberContainer LookupMemberContainer (Type t)
        {
                if (t is TypeBuilder) {
@@ -527,6 +531,17 @@ public class TypeManager {
                return TypeHandle.GetTypeHandle (t);
        }
 
+       public static MemberCache LookupInterfaceCache (IMemberContainer container, Type t)
+       {
+               MemberCache cache = builder_to_member_cache [t] as MemberCache;
+               if (cache != null)
+                       return cache;
+
+               cache = new MemberCache (container, GetInterfaces (t));
+               builder_to_member_cache.Add (t, cache);
+               return cache;
+       }
+
        public static TypeContainer LookupInterface (Type t)
        {
                TypeContainer tc = (TypeContainer) builder_to_declspace [t];
@@ -3166,8 +3181,10 @@ public class TypeManager {
                                // This happens with interfaces, they have a null
                                // basetype.  Look members up in the Object class.
                                //
-                               if (current_type == null)
+                               if (current_type == null) {
                                        current_type = TypeManager.object_type;
+                                       searching = true;
+                               }
                        }
                        
                        if (list.Length == 0)
@@ -3364,13 +3381,17 @@ public sealed class TypeHandle : IMemberContainer {
        private string full_name;
        private bool is_interface;
        private MemberCache member_cache;
+       private MemberCache parent_cache;
 
        private TypeHandle (Type type)
        {
                this.type = type;
                full_name = type.FullName != null ? type.FullName : type.Name;
-               if (type.BaseType != null)
+               if (type.BaseType != null) {
                        BaseType = GetTypeHandle (type.BaseType);
+                       parent_cache = BaseType.MemberCache;
+               } else if (type.IsInterface)
+                       parent_cache = TypeManager.LookupInterfaceCache (this, type);
                this.is_interface = type.IsInterface || type.IsGenericParameter;
                this.member_cache = new MemberCache (this);
        }
@@ -3389,9 +3410,9 @@ public sealed class TypeHandle : IMemberContainer {
                }
        }
 
-       public IMemberContainer ParentContainer {
+       public MemberCache ParentCache {
                get {
-                       return BaseType;
+                       return parent_cache;
                }
        }