cp-tree.h (BINFO_PRIMARY_MARKED_P): Change definition.
authorMark Mitchell <mitchell@dumbledore.codesourcery.com>
Tue, 11 Jan 2000 01:55:37 +0000 (01:55 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 11 Jan 2000 01:55:37 +0000 (01:55 +0000)
* cp-tree.h (BINFO_PRIMARY_MARKED_P): Change definition.
(BINFO_VBASE_PRIMARY_P): New macro.
(BINFO_VIRTUALS): Add to documentation.
(SET_BINFO_PRIMARY_MARKED_P): Remove.
(CLEAR_BINFO_PRIMARY_MARKED_P): Likewise.
(dfs_mark_primary_bases_queue_p): Likewise.
(dfs_unmarked_real_bases_queue_p): New function.
(dfs_marked_real_bases_queue_p): Likewise.
* search.c (dfs_mark_primary_bases): Adjust.
(mark_primary_bases): Likewise.
(get_shared_vbase_if_not_primary): New function.
(dfs_unmarked_real_bases_queue_p): Likewise.
(dfs_marked_real_bases_queue_p): Likewise.
(dfs_get_pure_virtuals): Simplify.
(get_pure_virtuals): Likewise.

From-SVN: r31312

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/search.c

index 8778233ccb3f7445817201c91fa45688391ae706..c4566981e36dc6d5c8fcafe084bc109bbf531d40 100644 (file)
@@ -1,3 +1,21 @@
+2000-01-10  Mark Mitchell  <mitchell@dumbledore.codesourcery.com>
+
+       * cp-tree.h (BINFO_PRIMARY_MARKED_P): Change definition.
+       (BINFO_VBASE_PRIMARY_P): New macro.
+       (BINFO_VIRTUALS): Add to documentation.
+       (SET_BINFO_PRIMARY_MARKED_P): Remove.
+       (CLEAR_BINFO_PRIMARY_MARKED_P): Likewise.
+       (dfs_mark_primary_bases_queue_p): Likewise.
+       (dfs_unmarked_real_bases_queue_p): New function.
+       (dfs_marked_real_bases_queue_p): Likewise.
+       * search.c (dfs_mark_primary_bases): Adjust.
+       (mark_primary_bases): Likewise.
+       (get_shared_vbase_if_not_primary): New function.
+       (dfs_unmarked_real_bases_queue_p): Likewise.
+       (dfs_marked_real_bases_queue_p): Likewise.
+       (dfs_get_pure_virtuals): Simplify.
+       (get_pure_virtuals): Likewise.
+       
 2000-01-10  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * lex.c: Include tm_p.h.
index 801298d6fca872a5d619ca5639b1b5f48d27b143..269c398166a130eec72ec1cece56915d80376faf 100644 (file)
@@ -72,8 +72,8 @@ Boston, MA 02111-1307, USA.  */
           or FIELD_DECL).
       NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
       SCOPE_PARTIAL_P (in SCOPE_STMT)
-   5: Not used.
-   6: Not used.
+   5: BINFO_PRIMARY_MARKED_P (in BINFO)
+   6: BINFO_VBASE_PRIMARY_P (in BINFO)
 
    Usage of TYPE_LANG_FLAG_?:
    0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE).
@@ -117,10 +117,13 @@ Boston, MA 02111-1307, USA.  */
    BINFO_VIRTUALS
      For a binfo, this is a TREE_LIST.  The TREE_PURPOSE of each node
      gives the amount by which to adjust the `this' pointer when
-     calling the function.  The TREE_VALUE is the declaration for the 
-     virtual function itself.  When CLASSTYPE_COM_INTERFACE_P does not
-     hold, the first entry does not have a TREE_VALUE; it is just an
-     offset.
+     calling the function.  If the method is an overriden version of a
+     base class method, then it is assumed that, prior to adjustment,
+     the this pointer points to an object of the base class.
+
+     The TREE_VALUE is the declaration for the virtual function
+     itself.  When CLASSTYPE_COM_INTERFACE_P does not hold, the first
+     entry does not have a TREE_VALUE; it is just an offset.
 
    DECL_ARGUMENTS
      For a VAR_DECL this is DECL_ANON_UNION_ELEMS.  */
@@ -1572,23 +1575,33 @@ struct lang_type
 #define SET_BINFO_PUSHDECLS_MARKED(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE)
 #define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
 
-/* Nonzero if this BINFO has been marked as a primary base class.  */
-#define BINFO_PRIMARY_MARKED_P(NODE)           \
-  (TREE_VIA_VIRTUAL (NODE)                     \
-   ? CLASSTYPE_MARKED5 (BINFO_TYPE (NODE))     \
-   : TREE_LANG_FLAG_5 (NODE))
+/* Nonzero if this BINFO is a primary base class.
+
+   In the TYPE_BINFO hierarchy, this flag is never set for a base
+   class of a non-primary virtual base because the copies of a
+   non-primary virtual base that appear in the TYPE_BINFO hierarchy do
+   not really exist.  Instead, it is the BINFOs in the
+   CLASSTYPE_VBASECLASSES list that are used.  In other words, this
+   flag is only valid for paths (given by BINFO_INHERITANCE_CHAIN)
+   that really exist in the final object.  
+
+   For example, consider:
+
+      struct A {};
+      struct B : public A { };
+      struct C : virtual public B { void f(); };
 
-/* Mark NODE as a primary base class.  */
-#define SET_BINFO_PRIMARY_MARKED_P(NODE)       \
-  (TREE_VIA_VIRTUAL (NODE)                     \
-   ? SET_CLASSTYPE_MARKED5 (BINFO_TYPE (NODE)) \
-   : (TREE_LANG_FLAG_5 (NODE) = 1))
+   `A' is the primary base class for `B'.  But, `B' is not a primary
+   base class for `C'.  So, in the copy of `A' that appears in the
+   TYPE_BINFO hierarcy for `C' does not have BINFO_PRIMARY_MARKED_P
+   set; the copy in the CLASSTYPE_VBASECLASSES list does have this
+   set.  */
+#define BINFO_PRIMARY_MARKED_P(NODE) TREE_LANG_FLAG_5 (NODE)
 
-/* Clear the primary base class mark.  */
-#define CLEAR_BINFO_PRIMARY_MARKED_P(NODE)             \
-  (TREE_VIA_VIRTUAL (NODE)                             \
-   ? CLEAR_CLASSTYPE_MARKED5 (BINFO_TYPE (NODE))       \
-   : (TREE_LANG_FLAG_5 (NODE) = 0))
+/* Nonzero if the virtual baseclass with the type given by this BINFO
+   is primary *somewhere* in the hierarchy.  This flag is only set on 
+   entries in the CLASSTYPE_VBASECLASSES list.  */
+#define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
 
 /* Used by various search routines.  */
 #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
@@ -3937,7 +3950,10 @@ extern tree dfs_unmark                          PROTO((tree, void *));
 extern tree dfs_vbase_unmark                    PROTO((tree, void *));
 extern tree markedp                             PROTO((tree, void *));
 extern tree unmarkedp                           PROTO((tree, void *));
-extern tree dfs_mark_primary_bases_queue_p      PROTO((tree, void *));
+extern tree dfs_skip_nonprimary_vbases_unmarkedp PROTO((tree, void *));
+extern tree dfs_skip_nonprimary_vbases_markedp  PROTO((tree, void *));
+extern tree dfs_unmarked_real_bases_queue_p     PROTO((tree, void *));
+extern tree dfs_marked_real_bases_queue_p       PROTO((tree, void *));
 extern void mark_primary_bases                  PROTO((tree));
 
 /* in semantics.c */
index c5ec089c1ee9c0b9da39778f2742483243e486f6..0637376b28017f2ea5f9c95b5d24157b84e16fd1 100644 (file)
@@ -151,6 +151,7 @@ static void setup_class_bindings PROTO ((tree, int));
 static int template_self_reference_p PROTO ((tree, tree));
 static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
 static tree dfs_mark_primary_bases PROTO((tree, void *));
+static tree get_shared_vbase_if_not_primary PROTO((tree, tree));
 
 /* Allocate a level of searching.  */
 
@@ -2111,22 +2112,71 @@ get_matching_virtual (binfo, fndecl, dtorp)
     }
 }
 
+/* A queue function for dfs_walk that skips any nonprimary virtual
+   bases and any already marked bases.  */
+
+tree
+dfs_skip_nonprimary_vbases_unmarkedp (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    /* This is a non-primary virtual base.  SKip it.  */
+    return NULL_TREE;
+
+  return unmarkedp (binfo, NULL);
+}
+
+/* A queue function for dfs_walk that skips any nonprimary virtual
+   bases and any unmarked bases.  */
+
+tree
+dfs_skip_nonprimary_vbases_markedp (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    /* This is a non-primary virtual base.  SKip it.  */
+    return NULL_TREE;
+
+  return markedp (binfo, NULL);
+}
+
 /* Called via dfs_walk from mark_primary_bases.  */
 
 static tree
 dfs_mark_primary_bases (binfo, data)
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 {
-  if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+  int i;
+  tree base_binfo;
+
+  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+  base_binfo = BINFO_BASETYPE (binfo, i);
+
+  if (!TREE_VIA_VIRTUAL (base_binfo))
+    /* Non-virtual base classes are easy.  */
+    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+  else
     {
-      int i;
+      tree shared_binfo;
 
-      i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-      SET_BINFO_PRIMARY_MARKED_P (BINFO_BASETYPE (binfo, i));
-    }
+      shared_binfo 
+       = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
 
-  SET_BINFO_MARKED (binfo);
+      /* If this virtual base is not already primary somewhere else in
+        the hiearchy, then we'll be using this copy.  */
+      if (!BINFO_VBASE_PRIMARY_P (shared_binfo)
+         && !BINFO_VBASE_MARKED (shared_binfo))
+       {
+         BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
+         BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+       }
+    }
 
   return NULL_TREE;
 }
@@ -2138,8 +2188,106 @@ void
 mark_primary_bases (type)
      tree type;
 {
-  dfs_walk (TYPE_BINFO (type), dfs_mark_primary_bases, unmarkedp, NULL);
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
+  tree vbase;
+
+  /* Mark the TYPE_BINFO hierarchy.  */
+  dfs_walk (TYPE_BINFO (type), dfs_mark_primary_bases, 
+           dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+  /* Now go through the virtual base classes.  Any that are not
+     already primary will need to be allocated in TYPE, and so we need
+     to mark their primary bases.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (type); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    {
+      if (BINFO_VBASE_PRIMARY_P (vbase))
+       /* This virtual base was already included in the hierarchy, so
+          there's nothing to do here.  */
+       continue;
+
+      /* Temporarily pretend that VBASE is primary so that its bases
+        will be walked; this is the real copy of VBASE.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 1;
+
+      /* Now, walk its bases.  */
+      dfs_walk (vbase, dfs_mark_primary_bases,
+               dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+      /* VBASE wasn't really primary.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 0;
+      /* And we don't want to allow it to *become* primary if it is a
+        base of some subsequent base class.  */
+      SET_BINFO_VBASE_MARKED (vbase);
+    }
+
+  /* Clear the VBASE_MARKED bits we set above.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (type); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    CLEAR_BINFO_VBASE_MARKED (vbase);
+}
+
+/* If BINFO is a non-primary virtual baseclass (in the hierarchy
+   dominated by TYPE), and no primary copy appears anywhere in the
+   hierarchy, return the shared copy.  If a primary copy appears
+   elsewhere, return NULL_TREE.  Otherwise, return BINFO itself; it is
+   either a non-virtual base or a primary virtual base.  */
+
+static tree
+get_shared_vbase_if_not_primary (binfo, type)
+     tree binfo;
+     tree type;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    {
+      /* This is a non-primary virtual base.  If there is no primary
+        version, get the shared version.  */
+      binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
+      if (BINFO_VBASE_PRIMARY_P (binfo))
+       return NULL_TREE;
+    }
+
+  return binfo;
+}
+
+/* A queue function to use with dfs_walk that prevents travel into any
+   nonprimary virtual base, or its baseclasses.  DATA should be the
+   type of the complete object, or a TREE_LIST whose TREE_PURPOSE is
+   the type of the complete object.  By using this function as a queue
+   function, you will walk over exactly those BINFOs that actually
+   exist in the complete object, including those for virtual base
+   classes.  If you SET_BINFO_MARKED for each binfo you process, you
+   are further guaranteed that you will walk into each virtual base
+   class exactly once.  */
+
+tree
+dfs_unmarked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree type = (tree) data;
+
+  if (TREE_CODE (type) == TREE_LIST)
+    type = TREE_PURPOSE (type);
+  binfo = get_shared_vbase_if_not_primary (binfo, type); 
+  return binfo ? unmarkedp (binfo, NULL) : NULL_TREE;
+}
+
+/* Like dfs_unmarked_real_bases_queue_p but walks only into things
+   that are marked, rather than unmarked.  */
+
+tree
+dfs_marked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree type = (tree) data;
+
+  if (TREE_CODE (type) == TREE_LIST)
+    type = TREE_PURPOSE (type);
+  binfo = get_shared_vbase_if_not_primary (binfo, type);
+  return binfo ? markedp (binfo, NULL) : NULL_TREE;
 }
 
 /* Called via dfs_walk from dfs_get_pure_virtuals.  */
@@ -2149,25 +2297,17 @@ dfs_get_pure_virtuals (binfo, data)
      tree binfo;
      void *data;
 {
+  tree type = (tree) data;
+
   /* We're not interested in primary base classes; the derived class
      of which they are a primary base will contain the information we
      need.  */
   if (!BINFO_PRIMARY_MARKED_P (binfo))
     {
-      tree type = (tree) data;
-      tree shared_binfo;
       tree virtuals;
       
-      /* If this is a virtual base class, then use the shared binfo
-        since that is the only place where BINFO_VIRTUALS is valid;
-        the various copies in the main hierarchy are not updated when
-        vtables are created.  */
-      shared_binfo = (TREE_VIA_VIRTUAL (binfo) 
-                     ? BINFO_FOR_VBASE (BINFO_TYPE (binfo), type)
-                     : binfo);
-
-      for (virtuals = skip_rtti_stuff (shared_binfo, 
-                                      BINFO_TYPE (shared_binfo), 
+      for (virtuals = skip_rtti_stuff (binfo, 
+                                      BINFO_TYPE (binfo), 
                                       NULL);
           virtuals;
           virtuals = TREE_CHAIN (virtuals))
@@ -2199,22 +2339,27 @@ get_pure_virtuals (type)
      (A primary base is not interesting because the derived class of
      which it is a primary base will contain vtable entries for the
      pure virtuals in the base class.  */
-  dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, unmarkedp, type);
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
+  dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, 
+           dfs_unmarked_real_bases_queue_p, type);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark, 
+           dfs_marked_real_bases_queue_p, type);
 
   /* Put the pure virtuals in dfs order.  */
   CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
 
-  for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
+  for (vbases = CLASSTYPE_VBASECLASSES (type); 
+       vbases; 
+       vbases = TREE_CHAIN (vbases))
     {
-      tree virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
+      tree virtuals;
 
-      while (virtuals)
+      for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
+          virtuals;
+          virtuals = TREE_CHAIN (virtuals))
        {
          tree base_fndecl = TREE_VALUE (virtuals);
          if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
            cp_error ("`%#D' needs a final overrider", base_fndecl);
-         virtuals = TREE_CHAIN (virtuals);
        }
     }
 }