2004-10-24 Marek Safar <marek.safar@seznam.cz>
authorMarek Safar <marek.safar@gmail.com>
Sat, 23 Oct 2004 22:10:25 +0000 (22:10 -0000)
committerMarek Safar <marek.safar@gmail.com>
Sat, 23 Oct 2004 22:10:25 +0000 (22:10 -0000)
Fixed bugs #63705, #67130
* decl.cs (MemberCache.MemberCache): Add parameter to distinguish
imported and defined interfaces.
(CacheEntry, EntryType): Changed to protected internal.

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

* typemanager.cs (LookupInterfaceContainer): New method.
Fills member container from base interfaces.

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

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

index f265e7ea828edede0f099b19e2b5e8684c81baf0..2522683ccde08aca4ef27bc0122aea2c5cbb7f7b 100755 (executable)
@@ -1,3 +1,16 @@
+2004-10-24  Marek Safar  <marek.safar@seznam.cz>
+
+       Fixed bugs #63705, #67130
+       * decl.cs (MemberCache.MemberCache): Add parameter to distinguish
+       imported and defined interfaces.
+       (CacheEntry, EntryType): Changed to protected internal.
+
+       * class.cs (TypeContainer.DoDefineMembers): Setup cache for
+       interfaces too.
+
+       * typemanager.cs (LookupInterfaceContainer): New method.
+       Fills member container from base interfaces.
+
 2004-10-20  Marek Safar  <marek.safar@seznam.cz>
 
        * class.cs (MethodCore.CheckBase): Add errors 505, 533, 544,
index 11307b7890c9c4790224c8557b16dd291370aab2..2795ef6704ef72ff552986260d7b838e2419b47c 100755 (executable)
@@ -1315,10 +1315,8 @@ namespace Mono.CSharp {
                        if (TypeBuilder.BaseType != null)
                                parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
 
-                       // TODO:
-                       //if (TypeBuilder.IsInterface) {
-                       //      parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
-                       //}
+                       if (TypeBuilder.IsInterface)
+                               parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
 
                        if (IsTopLevel) {
                                if ((ModFlags & Modifiers.NEW) != 0)
@@ -1399,7 +1397,7 @@ namespace Mono.CSharp {
 
 #if CACHE
                        if (!(this is ClassPart))
-                               member_cache = new MemberCache (this);
+                               member_cache = new MemberCache (this, false);
 #endif
 
                        if (parts != null) {
@@ -2986,7 +2984,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;
index 1a2c46c2c28643998cfa2733bcbbc868d87c6c8c..bdee3c366a71d03ac77937640baeaa84c353a83c 100755 (executable)
@@ -402,7 +402,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;
@@ -1262,7 +1262,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Create a new MemberCache for the given IMemberContainer `container'.
                /// </summary>
-               public MemberCache (IMemberContainer container)
+               public MemberCache (IMemberContainer container, bool setup_inherited_interfaces)
                {
                        this.Container = container;
 
@@ -1279,8 +1279,8 @@ namespace Mono.CSharp {
                                if (Container.ParentContainer != null)
                                        parent = Container.ParentContainer.MemberCache;
                                else
-                                       parent = TypeHandle.ObjectType.MemberCache;
-                               member_hash = SetupCacheForInterface (parent);
+                                       parent = null;
+                               member_hash = SetupCacheForInterface (parent, setup_inherited_interfaces);
                        } else if (Container.ParentContainer != null)
                                member_hash = SetupCache (Container.ParentContainer.MemberCache);
                        else
@@ -1306,11 +1306,13 @@ namespace Mono.CSharp {
                Hashtable SetupCache (MemberCache parent)
                {
                        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 ();
-                        }
+                       }
                                 
                        return hash;
                }
@@ -1341,9 +1343,13 @@ namespace Mono.CSharp {
                ///   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 SetupCacheForInterface (MemberCache parent, bool deep_setup)
                {
                        Hashtable hash = SetupCache (parent);
+
+                       if (!deep_setup)
+                               return hash;
+
                        TypeExpr [] ifaces = TypeManager.GetInterfaces (Container.Type);
 
                        foreach (TypeExpr iface in ifaces) {
@@ -1367,8 +1373,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.
-                       AddMembers (MemberTypes.Constructor, container);
-                       AddMembers (MemberTypes.Field, container);
+                       if (!container.IsInterface) {
+                               AddMembers (MemberTypes.Constructor, container);
+                               AddMembers (MemberTypes.Field, container);
+                       }
                        AddMembers (MemberTypes.Method, container);
                        AddMembers (MemberTypes.Property, container);
                        AddMembers (MemberTypes.Event, container);
@@ -1518,7 +1526,7 @@ namespace Mono.CSharp {
                ///   number to speed up the searching process.
                /// </summary>
                [Flags]
-               protected enum EntryType {
+               protected internal enum EntryType {
                        None            = 0x000,
 
                        Instance        = 0x001,
@@ -1541,7 +1549,7 @@ namespace Mono.CSharp {
                        MaskType        = Constructor|Event|Field|Method|Property|NestedType
                }
 
-               protected struct CacheEntry {
+               protected internal struct CacheEntry {
                        public readonly IMemberContainer Container;
                        public readonly EntryType EntryType;
                        public readonly MemberInfo Member;
index b22e183c504fb45c0c5e3cc059491333da94df22..358266661f95f6eae45d1d8874c8432075b235ed 100755 (executable)
@@ -490,6 +490,54 @@ public class TypeManager {
                return builder_to_declspace [t] as TypeContainer;
        }
        
+       /// <summary>
+       /// Fills member container from base interfaces
+       /// </summary>
+       public static IMemberContainer LookupInterfaceContainer (Type[] types)
+       {
+               if (types == null)
+                       return null;
+
+               IMemberContainer complete = null;
+               foreach (Type t in types) {
+                       IMemberContainer one_type_cont = null;
+                       if (t is TypeBuilder) {
+                               one_type_cont = builder_to_declspace [t] as IMemberContainer;
+                       } else
+                               one_type_cont = TypeHandle.GetTypeHandle (t);
+
+                       if (complete == null) {
+                               complete = one_type_cont;
+                               continue;
+                       }
+
+                       // We need to avoid including same member more than once
+                       foreach (DictionaryEntry de in one_type_cont.MemberCache.Members) {
+                               object o = complete.MemberCache.Members [de.Key];
+                               if (o == null) {
+                                       complete.MemberCache.Members.Add (de.Key, de.Value);
+                                       continue;
+                               }
+
+                               ArrayList al_old = (ArrayList)o;
+                               ArrayList al_new = (ArrayList)de.Value;
+
+                               foreach (MemberCache.CacheEntry ce in al_new) {
+                                       bool exist = false;
+                                       foreach (MemberCache.CacheEntry ce_old in al_old) {
+                                               if (ce.Member == ce_old.Member) {
+                                                       exist = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!exist)
+                                               al_old.Add (ce);
+                               }
+                       }
+               }
+               return complete;
+       }
+
        public static IMemberContainer LookupMemberContainer (Type t)
        {
                if (t is TypeBuilder) {
@@ -2640,8 +2688,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)
@@ -2843,7 +2893,7 @@ public sealed class TypeHandle : IMemberContainer {
                if (type.BaseType != null)
                        BaseType = GetTypeHandle (type.BaseType);
                this.is_interface = type.IsInterface;
-               this.member_cache = new MemberCache (this);
+               this.member_cache = new MemberCache (this, true);
        }
 
        // IMemberContainer methods