OSDN Git Service

gcc:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Feb 2001 11:45:16 +0000 (11:45 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Feb 2001 11:45:16 +0000 (11:45 +0000)
* invoke.texi (-fdump-class-layout): Document.
(-fdump-translation-unit): Use `=' as filename separator.
cp:
Fix specification and implementation bugs in V3 ABI
construction vtables.
* cp-tree.h (flag_dump_class_layout): New flag.
(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P): Remove.
(BINFO_LOST_PRIMARY_P): New flag.
(SET_BINFO_NEW_VTABLE_MARKED): Adjust asserts.
(BINFO_PRIMARY_MARKED_P): Rename to ...
(BINFO_PRIMARY_P): ... here.
(binfo_via_virtual): New prototype.
* decl2.c (flag_dump_class_layout): New flag.
(cxx_decode_option): Set it. Adjust -fdump-translation-unit to
use `=' as a file name separator.
* init.c (dfs_initialize_vtbl_ptrs): Walk into virtual primary
bases.
(build_vtbl_address): If this is a virtual primary base, then
get the vtbl of what it is ultimately primary for.
* search.c (dfs_skip_nonprimary_vbases_unmarkedp): Adjust
for BINFO_PRIMARY_P.
(dfs_skip_nonprimary_vbases_markedp): Likewise.
(get_shared_vbase_if_not_primary): Likewise.
(dfs_get_pure_virtuals): Likewise.
(expand_upcast_fixups): Likewise.
(fixup_virtual_upcast_offsets): Likewise.
(dfs_find_vbase_instance): Likewise.
(find_vbase_instance): Likewise.
(binfo_from_vbase): Adjust comment to reflect reality.
(binfo_via_virtual): New function.
* class.c (VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P): New macros
for binfo walking during VTT construction.
(dfs_mark_primary_bases): Remove.
(force_canonical_binfo_r): New function.
(force_canonical_binfo): New function.
(mark_primary_virtual_base): New function.
(mark_primary_bases): Walk in inheritance graph order, use
mark_primary_virtual_base.
(determine_primary_base): Use some more intermediate variables.
(dfs_find_final_overrider): Don't check for overriding along a
virtual path.
(dfs_modify_vtables): Walk into primary virtual bases too.
(walk_subobject_offsets): Adjust for BINFO_PRIMARY_P.
(build_base_fields): Likewise.
(dfs_set_offset_for_unshared_vbases): Likewise.
(layout_virtual_bases): Likewise.
(end_of_class): Likewise.
(finish_struct_1): Call dump_class_hierarchy, if requested.
(dfs_get_primary_binfo): Use BINFO_TYPE for binfos.
(dump_class_hierarchy_r): Add stream parameter. Emit more information.
(dump_class_hierarchy): Add file parameter. Append to file, if
required.
(finish_vtbls): Adjust accumulate_vtbl_inits call.
Use canonical base for virtual bases.
(build_vtt): Add more comments. Adjust build_vtt_inits call.
(build_vtt_inits): Remove VIRTUAL_VTTS_P parm.
Only set BINFO_VPTR_INDEX on top level. Use VTT_TOP_LEVEL_P,
VTT_MARKED_BINFO_P for binfo walking. Use canonical vbase for
virtual VTTs.
(dfs_build_secondary_vptr_vtt_inits): Extract VTT_TOP_LEVEL_P
from DATA.  We want virtual primary bases and all bases via virtual.
Only set BINFO_VPTR_INDEX for top level. Look up from a primary
virtual base when not a construction vtable.
(dfs_ctor_vtable_bases_queue_p): New DFS predicate.
(build_ctor_vtbl_group): Adjust accumulate_vtbl_inits call.
Use canonical bases when processing virtual bases.
(accumulate_vtbl_inits): We're interested in any base via a
virtual path.
(dfs_accumulate_vtbl_inits): If this is a primary virtual base
within a construction vtable, determine what is being overridden.
(build_vtbl_initializer): Add more comments
(add_vcall_offset_vtbl_entries_1): Adjust comment.
(build_rtti_vtbl_entries): Check if the base has lost its
primary.
testsuite:
* g++.old-deja/g++.abi/primary2.C: New test.
* g++.old-deja/g++.abi/primary3.C: New test.
* g++.old-deja/g++.abi/primary4.C: New test.
* g++.old-deja/g++.abi/primary5.C: New test.
* g++.old-deja/g++.abi/vtable3.h: New test.
* g++.old-deja/g++.abi/vtable3a.C: New test.
* g++.old-deja/g++.abi/vtable3b.C: New test.
* g++.old-deja/g++.abi/vtable3c.C: New test.
* g++.old-deja/g++.abi/vtable3d.C: New test.
* g++.old-deja/g++.abi/vtable3e.C: New test.
* g++.old-deja/g++.abi/vtable3f.C: New test.
* g++.old-deja/g++.abi/vtable3g.C: New test.
* g++.old-deja/g++.abi/vtable3h.C: New test.
* g++.old-deja/g++.abi/vtable3i.C: New test.
* g++.old-deja/g++.abi/vtable3j.C: New test.
* g++.old-deja/g++.oliva/thunk1.C: Remove XFAIL.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39455 138bc75d-0d04-0410-961f-82ee72b054a4

25 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/search.c
gcc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.abi/primary2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/primary3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/primary4.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/primary5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3.h [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C

index 2ce8ac7..0046ae1 100644 (file)
@@ -1,3 +1,8 @@
+2001-02-05  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * invoke.texi (-fdump-class-layout): Document.
+       (-fdump-translation-unit): Use `=' as filename separator.
+
 2001-02-05  Mark Mitchell  <mark@codesourcery.com>
 
        * Makefile.in (s-mlib): Don't build multilibs if
index 6011b76..04d64a0 100644 (file)
@@ -1,3 +1,77 @@
+2001-02-05  Nathan Sidwell  <nathan@codesourcery.com>
+
+       Fix specification and implementation bugs in V3 ABI
+       construction vtables.
+       * cp-tree.h (flag_dump_class_layout): New flag.
+       (BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P): Remove.
+       (BINFO_LOST_PRIMARY_P): New flag.
+       (SET_BINFO_NEW_VTABLE_MARKED): Adjust asserts.
+       (BINFO_PRIMARY_MARKED_P): Rename to ...
+       (BINFO_PRIMARY_P): ... here.
+       (binfo_via_virtual): New prototype.
+       * decl2.c (flag_dump_class_layout): New flag.
+       (cxx_decode_option): Set it. Adjust -fdump-translation-unit to
+       use `=' as a file name separator.
+       * init.c (dfs_initialize_vtbl_ptrs): Walk into virtual primary
+       bases.
+       (build_vtbl_address): If this is a virtual primary base, then
+       get the vtbl of what it is ultimately primary for.
+       * search.c (dfs_skip_nonprimary_vbases_unmarkedp): Adjust
+       for BINFO_PRIMARY_P.
+       (dfs_skip_nonprimary_vbases_markedp): Likewise.
+       (get_shared_vbase_if_not_primary): Likewise.
+       (dfs_get_pure_virtuals): Likewise.
+       (expand_upcast_fixups): Likewise.
+       (fixup_virtual_upcast_offsets): Likewise.
+       (dfs_find_vbase_instance): Likewise.
+       (find_vbase_instance): Likewise.
+       (binfo_from_vbase): Adjust comment to reflect reality.
+       (binfo_via_virtual): New function.
+       * class.c (VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P): New macros
+       for binfo walking during VTT construction.
+       (dfs_mark_primary_bases): Remove.
+       (force_canonical_binfo_r): New function.
+       (force_canonical_binfo): New function.
+       (mark_primary_virtual_base): New function.
+       (mark_primary_bases): Walk in inheritance graph order, use
+       mark_primary_virtual_base.
+       (determine_primary_base): Use some more intermediate variables.
+       (dfs_find_final_overrider): Don't check for overriding along a
+       virtual path.
+       (dfs_modify_vtables): Walk into primary virtual bases too.
+       (walk_subobject_offsets): Adjust for BINFO_PRIMARY_P.
+       (build_base_fields): Likewise.
+       (dfs_set_offset_for_unshared_vbases): Likewise.
+       (layout_virtual_bases): Likewise.
+       (end_of_class): Likewise.
+       (finish_struct_1): Call dump_class_hierarchy, if requested.
+       (dfs_get_primary_binfo): Use BINFO_TYPE for binfos.
+       (dump_class_hierarchy_r): Add stream parameter. Emit more information.
+       (dump_class_hierarchy): Add file parameter. Append to file, if
+       required.
+       (finish_vtbls): Adjust accumulate_vtbl_inits call.
+       Use canonical base for virtual bases.
+       (build_vtt): Add more comments. Adjust build_vtt_inits call.
+       (build_vtt_inits): Remove VIRTUAL_VTTS_P parm.
+       Only set BINFO_VPTR_INDEX on top level. Use VTT_TOP_LEVEL_P,
+       VTT_MARKED_BINFO_P for binfo walking. Use canonical vbase for
+       virtual VTTs.
+       (dfs_build_secondary_vptr_vtt_inits): Extract VTT_TOP_LEVEL_P
+       from DATA.  We want virtual primary bases and all bases via virtual.
+       Only set BINFO_VPTR_INDEX for top level. Look up from a primary
+       virtual base when not a construction vtable.
+       (dfs_ctor_vtable_bases_queue_p): New DFS predicate.
+       (build_ctor_vtbl_group): Adjust accumulate_vtbl_inits call.
+       Use canonical bases when processing virtual bases.
+       (accumulate_vtbl_inits): We're interested in any base via a
+       virtual path.
+       (dfs_accumulate_vtbl_inits): If this is a primary virtual base
+       within a construction vtable, determine what is being overridden.
+       (build_vtbl_initializer): Add more comments
+       (add_vcall_offset_vtbl_entries_1): Adjust comment.
+       (build_rtti_vtbl_entries): Check if the base has lost its
+       primary.
+
 2001-02-05  Mark Mitchell  <mark@codesourcery.com>
 
        * Makefile.in (g++spec.o): Adjust use of DRIVER_DEFINES.
index 423fb32..376260b 100644 (file)
@@ -111,8 +111,6 @@ static tree get_basefndecls PARAMS ((tree, tree));
 static int build_primary_vtable PARAMS ((tree, tree));
 static int build_secondary_vtable PARAMS ((tree, tree));
 static tree dfs_finish_vtbls PARAMS ((tree, void *));
-static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
-                                              tree));
 static void finish_vtbls PARAMS ((tree));
 static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
 static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
@@ -171,8 +169,8 @@ static void layout_vtable_decl PARAMS ((tree, int));
 static tree dfs_find_final_overrider PARAMS ((tree, void *));
 static tree find_final_overrider PARAMS ((tree, tree, tree));
 static int make_new_vtable PARAMS ((tree, tree));
-static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
-extern void dump_class_hierarchy PARAMS ((tree));
+static void dump_class_hierarchy_r PARAMS ((FILE *, tree, tree, int));
+extern void dump_class_hierarchy PARAMS ((const char *, tree));
 static tree build_vtable PARAMS ((tree, tree, tree));
 static void initialize_vtable PARAMS ((tree, tree));
 static void initialize_array PARAMS ((tree, tree));
@@ -182,20 +180,25 @@ static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
 static void layout_empty_base PARAMS ((tree, tree, splay_tree));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
+static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
+                                              tree));
 static void set_vindex PARAMS ((tree, tree, int *));
 static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
 static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
                                                        vtbl_init_data *));
-static tree dfs_mark_primary_bases PARAMS ((tree, void *));
+static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree));
+static void force_canonical_binfo PARAMS ((tree, tree, tree, tree));
 static void mark_primary_bases PARAMS ((tree));
+static tree mark_primary_virtual_base PARAMS ((tree, tree, tree));
 static void clone_constructors_and_destructors PARAMS ((tree));
 static tree build_clone PARAMS ((tree, tree));
 static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
 static tree copy_virtuals PARAMS ((tree));
 static void build_ctor_vtbl_group PARAMS ((tree, tree));
 static void build_vtt PARAMS ((tree));
-static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
 static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
+static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data));
 static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
 static tree get_matching_base PARAMS ((tree, tree));
 static tree dfs_get_primary_binfo PARAMS ((tree, void*));
@@ -208,6 +211,13 @@ static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
 static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
                                                    splay_tree_key k2));
 
+
+/* Macros for dfs walking during vtt construction. See
+   dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
+   and dfs_fixup_binfo_vtbls.  */
+#define VTT_TOP_LEVEL_P(node) TREE_UNSIGNED(node)
+#define VTT_MARKED_BINFO_P(node) TREE_USED(node)
+
 /* Variables shared between class.c and call.c.  */
 
 #ifdef GATHER_STATISTICS
@@ -1719,92 +1729,142 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
     }
 }
 
-/* Called via dfs_walk from mark_primary_bases.  Sets
-   BINFO_PRIMARY_MARKED_P for BINFO, if appropriate.  */
+/* Binfo FROM is within a virtual heirarchy which is being reseated to
+   TO. Move primary information from FROM to TO, and recursively traverse
+   into FROM's bases. The heirarchy is dominated by TYPE.  MAPPINGS is an
+   assoc list of binfos that have already been reseated.  */
 
-static tree
-dfs_mark_primary_bases (binfo, data)
-     tree binfo;
-     void *data;
+static void
+force_canonical_binfo_r (to, from, type, mappings)
+     tree to;
+     tree from;
+     tree type;
+     tree mappings;
 {
-  tree base_binfo;
+  int i, n_baseclasses = BINFO_N_BASETYPES (from);
+  
+  BINFO_INDIRECT_PRIMARY_P (to)
+          = BINFO_INDIRECT_PRIMARY_P (from);
+  BINFO_INDIRECT_PRIMARY_P (from) = 0;
+  if (BINFO_PRIMARY_P (from))
+    {
+      tree primary = BINFO_PRIMARY_BASE_OF (from);
+      tree assoc;
+      
+      /* We might have just moved the primary base too, see if it's on our
+         mappings.  */
+      assoc = purpose_member (primary, mappings);
+      if (assoc)
+        primary = TREE_VALUE (assoc);
+      BINFO_PRIMARY_BASE_OF (to) = primary;
+      BINFO_PRIMARY_BASE_OF (from) = NULL_TREE;
+    }
+  my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)), 20010104);
+  mappings = tree_cons (from, to, mappings);
+  for (i = 0; i != n_baseclasses; i++)
+    {
+      tree from_binfo = BINFO_BASETYPE (from, i);
+      tree to_binfo = BINFO_BASETYPE (to, i);
+      
+      if (TREE_VIA_VIRTUAL (from_binfo))
+        {
+          tree shared_binfo = binfo_for_vbase (BINFO_TYPE (from_binfo), type);
+          
+          if (shared_binfo == from_binfo)
+            force_canonical_binfo (to_binfo, from_binfo, type, mappings);
+        }
+      else
+        force_canonical_binfo_r (to_binfo, from_binfo, type, mappings);
+    }
+}
 
-  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
-    return NULL_TREE;
+/* FROM is the canonical binfo for a virtual base. It is being reseated to
+   make TO the canonical binfo, within the heirarchy dominated by TYPE.
+   MAPPINGS is an assoc list of binfos that have already been reseated.
+   Adjust any non-virtual bases within FROM, and also move any virtual bases
+   which are canonical.  This complication arises because selecting primary
+   bases walks in inheritance graph order, but we don't share binfos for
+   virtual bases, hence we can fill in the primaries for a virtual base,
+   and then discover that a later base requires the virtual as its
+   primary.  */
 
-  base_binfo = get_primary_binfo (binfo);
+static void
+force_canonical_binfo (to, from, type, mappings)
+     tree to;
+     tree from;
+     tree type;
+     tree mappings;
+{
+  tree assoc = purpose_member (BINFO_TYPE (to),
+                              CLASSTYPE_VBASECLASSES (type));
+  TREE_VALUE (assoc) = to;
+  force_canonical_binfo_r (to, from, type, mappings);
+}
 
-  if (TREE_VIA_VIRTUAL (base_binfo))
-    {
-      tree shared_binfo;
-      tree type;
+/* Make BASE_BINFO the primary virtual base of BINFO within the hierarchy
+   dominated by TYPE. Returns BASE_BINFO, if it can be made so, NULL
+   otherwise (because something else has already made it primary).  */
 
-      type = (tree) data;
-      shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+static tree
+mark_primary_virtual_base (binfo, base_binfo, type)
+     tree binfo;
+     tree base_binfo;
+     tree type;
+{
+  tree shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+  tree delta;
 
-      /* If this virtual base is not already primary somewhere else in
-        the hiearchy, then we'll be using this copy.  */
-      if (!BINFO_PRIMARY_MARKED_P (shared_binfo))
-       {
-         /* Make sure the CLASSTYPE_VBASECLASSES list contains the
-            primary copy; it's the one that really exists.  */
-         if (base_binfo != shared_binfo)
-           TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
-                                       CLASSTYPE_VBASECLASSES (type)))
-             = base_binfo;
-       }
-      else
-       base_binfo = NULL_TREE;
+  if (BINFO_PRIMARY_P (shared_binfo))
+    {
+      /* It's already allocated in the hierarchy. BINFO won't have a
+         primary base in this hierachy, even though the complete object
+         BINFO is for, would do.  */
+      BINFO_LOST_PRIMARY_P (binfo) = 1;
+      
+      return NULL_TREE;
     }
+     
+  /* We need to make sure that the assoc list
+     CLASSTYPE_VBASECLASSES of TYPE, indicates this particular
+     primary BINFO for the virtual base, as this is the one
+     that'll really exist.  */
+  if (base_binfo != shared_binfo)
+    force_canonical_binfo (base_binfo, shared_binfo, type, NULL);
 
-  if (base_binfo)
-    BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
-
-  return NULL_TREE;
+  delta = size_diffop (BINFO_OFFSET (binfo), BINFO_OFFSET (base_binfo));
+  if (!integer_zerop (delta))
+    {
+      propagate_binfo_offsets (base_binfo, delta);
+      BINFO_OFFSET (base_binfo) = BINFO_OFFSET (binfo);
+    }
+  return base_binfo;
 }
 
-/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
-   dominated by BINFO that are primary bases.  */
+/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
+   dominated by TYPE that are primary bases.  */
 
 static void
 mark_primary_bases (type)
      tree type;
 {
-  tree vbases;
-
-  /* Mark the TYPE_BINFO hierarchy.  We need to mark primary bases in
-     pre-order to deal with primary virtual bases.  (The virtual base
-     would be skipped if it were not marked as primary, and that
-     requires getting to dfs_mark_primary_bases before
-     dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
-     virtual base.)  */
-  dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
-                dfs_skip_nonprimary_vbases_unmarkedp, type);
-
-  /* Now go through the virtual base classes in inheritance graph
-     order.  Any that are not already primary will need to be
-     allocated in TYPE, and so we need to mark their primary bases.  */
-  for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases))
+  tree binfo;
+  
+  /* Walk the bases in inheritance graph order.  */
+  for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
     {
-      tree vbase;
-
-      /* Make sure that only BINFOs appear on this list.
-        Historically, the TREE_CHAIN was used for other purposes, and
-        we want to make sure that none of those uses remain.  */
-      my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402);
+      tree base_binfo;
+      
+      if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+        /* Not a dynamic base. */
+        continue;
 
-      if (!TREE_VIA_VIRTUAL (vbases))
-       continue;
+      base_binfo = get_primary_binfo (binfo);
 
-      vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
-      if (BINFO_PRIMARY_MARKED_P (vbase))
-       /* This virtual base was already included in the hierarchy, so
-          there's nothing to do here.  */
-       continue;
+      if (TREE_VIA_VIRTUAL (base_binfo))
+        base_binfo = mark_primary_virtual_base (binfo, base_binfo, type);
 
-      /* Now, walk its bases.  */
-      dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
-                    dfs_skip_nonprimary_vbases_unmarkedp, type);
+      if (base_binfo)
+        BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
     }
 }
 
@@ -1892,32 +1952,33 @@ determine_primary_base (t, vfuns_p)
   if (!TYPE_VFIELD (t))
     CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
 
-  /* Mark the indirect primary bases.  */
+  /* Find the indirect primary bases - those virtual bases which are primary
+     bases of something else in this hierarchy.  */
   for (vbases = CLASSTYPE_VBASECLASSES (t);
        vbases;
        vbases = TREE_CHAIN (vbases)) 
     {
-      tree binfo = TREE_VALUE (vbases);
+      tree vbase_binfo = TREE_VALUE (vbases);
 
-      /* See if this virtual base is an indirect primary base.  If so,
-        it must be either a primary base or an indirect primary base
-        in one of the direct bases.  */
+      /* See if this virtual base is an indirect primary base.  To be so,
+         it must be a primary base within the hierarchy of one of our
+         direct bases.  */
       for (i = 0; i < n_baseclasses; ++i) 
        {
-         tree basetype;
+         tree basetype = TYPE_BINFO_BASETYPE (t, i);
          tree v;
 
-         basetype = TYPE_BINFO_BASETYPE (t, i);
          for (v = CLASSTYPE_VBASECLASSES (basetype); 
               v; 
               v = TREE_CHAIN (v))
            {
-             tree b = TREE_VALUE (v);
-             if ((BINFO_PRIMARY_MARKED_P (b)
-                  || BINFO_INDIRECT_PRIMARY_P (b))
-                 && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+             tree base_vbase = TREE_VALUE (v);
+             
+             if (BINFO_PRIMARY_P (base_vbase)
+                 && same_type_p (BINFO_TYPE (base_vbase),
+                                 BINFO_TYPE (vbase_binfo)))
                {
-                 BINFO_INDIRECT_PRIMARY_P (binfo) = 1;
+                 BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
                  break;
                }
            }
@@ -1925,7 +1986,7 @@ determine_primary_base (t, vfuns_p)
          /* If we've discovered that this virtual base is an indirect
             primary base, then we can move on to the next virtual
             base.  */
-         if (BINFO_INDIRECT_PRIMARY_P (binfo))
+         if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo))
            break;
        }
     }
@@ -1957,10 +2018,12 @@ determine_primary_base (t, vfuns_p)
                  candidate = base_binfo;
                  break;
                }
-             /* If this was an indirect primary base, it's still our
-                primary base -- unless there's another nearly-empty
-                virtual base that isn't an indirect primary base.  */
-             else if (!candidate)
+
+             /* If this is an indirect primary base, it still could be
+                our primary base -- unless we later find there's another
+                nearly-empty virtual base that isn't an indirect
+                primary base.  */
+             if (!candidate)
                candidate = base_binfo;
            }
        }
@@ -2516,12 +2579,6 @@ dfs_find_final_overrider (binfo, data)
            if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
              {
                base = ffod->declaring_base;
-               while (BINFO_PRIMARY_MARKED_P (base))
-                 {
-                   BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
-                   base = BINFO_INHERITANCE_CHAIN (base);
-                 }
-               BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
                break;
              }
 
@@ -2748,9 +2805,11 @@ dfs_modify_vtables (binfo, data)
      tree binfo;
      void *data;
 {
-  if (/* There's no need to modify the vtable for a primary base;
-        we're not going to use that vtable anyhow.  */
-      !BINFO_PRIMARY_MARKED_P (binfo)
+  if (/* There's no need to modify the vtable for a non-virtual
+         primary base; we're not going to use that vtable anyhow
+         (virtual primary bases can become non-primary in a
+         class derivation of this one.) */
+      (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
       /* Similarly, a base without a vtable needs no modification.  */
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
@@ -3734,7 +3793,7 @@ check_subobject_offset (type, offset, offsets)
 
 /* Walk through all the subobjects of TYPE (located at OFFSET).  Call
    F for every subobject, passing it the type, offset, and table of
-   OFFSETS.  If VBASES_P is non-zero, then even non-virtual primary
+   OFFSETS.  If VBASES_P is non-zero, then even virtual non-primary
    bases should be traversed; otherwise, they are ignored.  If F
    returns a non-zero value, the traversal ceases, and that value is
    returned.  Otherwise, returns zero.  */
@@ -3766,7 +3825,7 @@ walk_subobject_offsets (type, f, offset, offsets, vbases_p)
 
          if (!vbases_p 
              && TREE_VIA_VIRTUAL (binfo) 
-             && !BINFO_PRIMARY_MARKED_P (binfo))
+             && !BINFO_PRIMARY_P (binfo))
            continue;
 
          r = walk_subobject_offsets (BINFO_TYPE (binfo),
@@ -4085,7 +4144,7 @@ build_base_fields (rli, empty_p, offsets)
         base class, but a non-primary virtual base is allocated
         later, in layout_virtual_bases.  */
       if (TREE_VIA_VIRTUAL (base_binfo) 
-         && !BINFO_PRIMARY_MARKED_P (base_binfo))
+         && !BINFO_PRIMARY_P (base_binfo))
        continue;
 
       build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
@@ -4649,7 +4708,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
   /* If this is a virtual base, make sure it has the same offset as
      the shared copy.  If it's a primary base, then we know it's
      correct.  */
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
     {
       tree t = (tree) data;
       tree vbase;
@@ -4713,7 +4772,7 @@ layout_virtual_bases (t, offsets)
       else
        vbase = TREE_VALUE (vbases);
 
-      if (!BINFO_PRIMARY_MARKED_P (vbase))
+      if (!BINFO_PRIMARY_P (vbase))
        {
          /* This virtual base is not a primary base of any class in the
             hierarchy, so we have to add space for it.  */
@@ -4824,7 +4883,7 @@ end_of_class (t, include_virtuals_p)
 
       if (!include_virtuals_p
          && TREE_VIA_VIRTUAL (base_binfo) 
-         && !BINFO_PRIMARY_MARKED_P (base_binfo))
+         && !BINFO_PRIMARY_P (base_binfo))
        continue;
 
       offset = size_binop (PLUS_EXPR, 
@@ -5143,6 +5202,11 @@ finish_struct_1 (t)
   layout_class_type (t, &empty, &vfuns,
                     &new_virtuals, &overridden_virtuals);
 
+  if (flag_dump_class_layout)
+    dump_class_hierarchy (*flag_dump_class_layout
+                          ? flag_dump_class_layout : NULL,
+                          t);
+  
   /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
      might need to know it for setting up the offsets in the vtable
      (or in thunks) below.  */
@@ -5277,6 +5341,7 @@ finish_struct_1 (t)
   /* Make the rtl for any new vtables we have created, and unmark
      the base types we marked.  */
   finish_vtbls (t);
+  
   /* Build the VTT for T.  */
   build_vtt (t);
 
@@ -6587,7 +6652,7 @@ dfs_get_primary_binfo (binfo, data)
   tree primary_base = (tree) data;
 
   if (TREE_VIA_VIRTUAL (binfo) 
-      && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base)))
+      && same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (primary_base)))
     return binfo;
   
   return NULL_TREE;
@@ -6598,7 +6663,7 @@ dfs_get_primary_binfo (binfo, data)
    primary.  In particular if the resulting BINFO is a virtual base,
    and it occurs elsewhere in the hierarchy, then this occurrence may
    not actually be a primary base in the complete object.  Check
-   BINFO_PRIMARY_MARKED_P to be sure.  */
+   BINFO_PRIMARY_P to be sure.  */
 
 tree
 get_primary_binfo (binfo)
@@ -6645,38 +6710,68 @@ get_primary_binfo (binfo)
    the top level; it is incremented recursively.  */
 
 static void
-dump_class_hierarchy_r (t, binfo, indent)
+dump_class_hierarchy_r (stream, t, binfo, indent)
+     FILE *stream;
      tree t;
      tree binfo;
      int indent;
 {
   int i;
 
-  fprintf (stderr, "%*s0x%lx (%s) ", indent, "",
+  fprintf (stream, "%*s0x%lx (%s) ", indent, "",
           (unsigned long) binfo,
           type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
-  fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
+  fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
           tree_low_cst (BINFO_OFFSET (binfo), 0));
+  if (is_empty_class (BINFO_TYPE (binfo)))
+    fprintf (stream, " empty");
+  else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
+    fprintf (stream, " nearly-empty");
   if (TREE_VIA_VIRTUAL (binfo))
-    fprintf (stderr, " virtual");
-  if (BINFO_PRIMARY_MARKED_P (binfo)
-      || (TREE_VIA_VIRTUAL (binfo) 
-         && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo), 
-                                                     t))))
-    fprintf (stderr, " primary");
-  fprintf (stderr, "\n");
+    {
+      tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
+      
+      if (canonical == binfo)
+        fprintf (stream, " virtual-canonical");
+      else
+        fprintf (stream, " virtual-non-canonical");
+    }
+  if (BINFO_PRIMARY_P (binfo))
+    fprintf (stream, " primary-for 0x%lx (%s)",
+             (unsigned long)BINFO_PRIMARY_BASE_OF (binfo),
+             type_as_string (BINFO_PRIMARY_BASE_OF (binfo), TFF_PLAIN_IDENTIFIER));
+  if (BINFO_LOST_PRIMARY_P (binfo))
+    fprintf (stream, " lost-primary");
+  fprintf (stream, "\n");
 
   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
-    dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+    dump_class_hierarchy_r (stream, t, BINFO_BASETYPE (binfo, i), indent + 2);
 }
 
 /* Dump the BINFO hierarchy for T.  */
 
 void
-dump_class_hierarchy (t)
+dump_class_hierarchy (name, t)
+     const char *name;
      tree t;
 {
-  dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+  FILE *stream = stderr;
+  
+  if (name)
+    {
+      static int append = 0;
+      
+      stream = fopen (name, append++ ? "a" : "w");
+      if (!stream)
+        error ("could not open dump file `%s'", name);
+      return;
+    }
+  fprintf (stream, "%s\n",
+           type_as_string (t, TFF_PLAIN_IDENTIFIER));
+  dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0);
+  fprintf (stream, "\n");
+  if (name)
+    fclose (stream);
 }
 
 /* Virtual function table initialization.  */
@@ -6703,10 +6798,17 @@ finish_vtbls (t)
         order.  */
       for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
        {
+         tree real_base;
+         
          if (!TREE_VIA_VIRTUAL (vbase))
            continue;
-
-         accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
+          
+          /* Although we walk in inheritance order, that might not get the
+             canonical base.  */
+          real_base = binfo_for_vbase (BINFO_TYPE (vbase), t);
+          
+         accumulate_vtbl_inits (real_base, real_base,
+                                TYPE_BINFO (t), t, list);
        }
 
       if (TYPE_BINFO_VTABLE (t))
@@ -6771,7 +6873,17 @@ initialize_array (decl, inits)
   DECL_CONTEXT (decl) = context;
 }
 
-/* Build the VTT (virtual table table) for T.  */
+/* Build the VTT (virtual table table) for T.
+   A class requires a VTT if it has virtual bases.
+   
+   This holds
+   1 - primary virtual pointer for complete object T
+   2 - secondary VTTs for each direct non-virtual base of T which requires a VTT
+   3 - secondary virtual pointers for each direct or indirect base of T which
+       has virtual bases or is reachable via a virtual path from T.
+   4 - secondary VTTs for each direct or indirect virtual base of T.
+   
+   Secondary VTTs look like complete object VTTs without part 4.  */
 
 static void
 build_vtt (t)
@@ -6789,8 +6901,7 @@ build_vtt (t)
   /* Build up the initializers for the VTT.  */
   inits = NULL_TREE;
   index = size_zero_node;
-  build_vtt_inits (TYPE_BINFO (t), t, /*virtual_vtts_p=*/1, 
-                  &inits, &index);
+  build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
 
   /* If we didn't need a VTT, we're done.  */
   if (!inits)
@@ -6835,16 +6946,17 @@ get_matching_base (binfo, t)
 }
 
 /* Recursively build the VTT-initializer for BINFO (which is in the
-   hierarchy dominated by T).  If VIRTUAL_VTTS_P is non-zero, then
-   sub-VTTs for virtual bases are included.  INITS points to the end
-   of the initializer list to date.  INDEX is the VTT index where the
-   next element will be placed.  */
+   hierarchy dominated by T).  INITS points to the end of the initializer
+   list to date.  INDEX is the VTT index where the next element will be
+   replaced.  Iff BINFO is the binfo for T, this is the top level VTT (i.e.
+   not a subvtt for some base of T).  When that is so, we emit the sub-VTTs
+   for virtual bases of T. When it is not so, we build the constructor
+   vtables for the BINFO-in-T variant.  */
 
 static tree *
-build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
+build_vtt_inits (binfo, t, inits, index)
      tree binfo;
      tree t;
-     int virtual_vtts_p;
      tree *inits;
      tree *index;
 {
@@ -6852,7 +6964,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
   tree b;
   tree init;
   tree secondary_vptrs;
-  int ctor_vtbl_p;
+  int top_level_p = same_type_p (TREE_TYPE (binfo), t);
 
   /* We only need VTTs for subobjects with virtual bases.  */
   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
@@ -6860,8 +6972,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
 
   /* We need to use a construction vtable if this is not the primary
      VTT.  */
-  ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
-  if (ctor_vtbl_p)
+  if (!top_level_p)
     {
       build_ctor_vtbl_group (binfo, t);
 
@@ -6875,7 +6986,11 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
     init = TREE_VALUE (init);
   *inits = build_tree_list (NULL_TREE, init);
   inits = &TREE_CHAIN (*inits);
-  BINFO_VPTR_INDEX (binfo) = *index;
+  if (top_level_p)
+    {
+      my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+      BINFO_VPTR_INDEX (binfo) = *index;
+    }
   *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
                       
   /* Recursively add the secondary VTTs for non-virtual bases.  */
@@ -6884,22 +6999,26 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
       b = BINFO_BASETYPE (binfo, i);
       if (!TREE_VIA_VIRTUAL (b))
        inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, 
-                                /*virtuals_vtts_p=*/0,
                                 inits, index);
     }
       
   /* Add secondary virtual pointers for all subobjects of BINFO with
-     either virtual bases or virtual functions overridden along a
-     virtual path between the declaration and D, except subobjects
-     that are non-virtual primary bases.  */
+     either virtual bases or reachable along a virtual path, except
+     subobjects that are non-virtual primary bases.  */
   secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
   TREE_TYPE (secondary_vptrs) = *index;
+  VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p;
+  VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
+  
   dfs_walk_real (binfo,
                 dfs_build_secondary_vptr_vtt_inits,
                 NULL,
-                dfs_unmarked_real_bases_queue_p,
+                dfs_ctor_vtable_bases_queue_p,
                 secondary_vptrs);
-  dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
+  VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
+  dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p,
+            secondary_vptrs);
+
   *index = TREE_TYPE (secondary_vptrs);
 
   /* The secondary vptrs come back in reverse order.  After we reverse
@@ -6914,7 +7033,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
     }
 
   /* Add the secondary VTTs for virtual bases.  */
-  if (virtual_vtts_p)
+  if (top_level_p)
     for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
       {
        tree vbase;
@@ -6923,18 +7042,29 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
          continue;
        
        vbase = binfo_for_vbase (BINFO_TYPE (b), t);
-       inits = build_vtt_inits (vbase, t, /*virtual_vtts_p=*/0, 
-                                inits, index);
+       inits = build_vtt_inits (vbase, t, inits, index);
       }
 
-  dfs_walk (binfo, dfs_fixup_binfo_vtbls,
-           dfs_unmarked_real_bases_queue_p,
-           build_tree_list (t, binfo));
+  if (!top_level_p)
+    {
+      tree data = tree_cons (t, binfo, NULL_TREE);
+      VTT_TOP_LEVEL_P (data) = 0;
+      VTT_MARKED_BINFO_P (data) = 0;
+      
+      dfs_walk (binfo, dfs_fixup_binfo_vtbls,
+               dfs_ctor_vtable_bases_queue_p,
+               data);
+    }
 
   return inits;
 }
 
-/* Called from build_vtt_inits via dfs_walk.  */
+/* Called from build_vtt_inits via dfs_walk.  BINFO is the binfo
+   for the base in most derived. DATA is a TREE_LIST who's
+   TREE_CHAIN is the type of the base being
+   constructed whilst this secondary vptr is live.  The TREE_UNSIGNED
+   flag of DATA indicates that this is a constructor vtable.  The
+   TREE_TOP_LEVEL flag indicates that this is the primary VTT.  */
 
 static tree
 dfs_build_secondary_vptr_vtt_inits (binfo, data)
@@ -6945,10 +7075,12 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data)
   tree t;
   tree init;
   tree index;
+  int top_level_p;
 
   l = (tree) data;
   t = TREE_CHAIN (l);
-
+  top_level_p = VTT_TOP_LEVEL_P (l);
+  
   SET_BINFO_MARKED (binfo);
 
   /* We don't care about bases that don't have vtables.  */
@@ -6960,32 +7092,34 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data)
     return NULL_TREE;
 
   /* We're not interested in non-virtual primary bases.  */
-  if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+  if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo))
     return NULL_TREE;
 
-  /* If BINFO doesn't have virtual bases, then we have to look to see
-     whether or not any virtual functions were overidden along a
-     virtual path.  The point is that given:
-
-       struct V { virtual void f(); int i; };
-       struct C : public virtual V { void f (); };
-
-     when we constrct C we need a secondary vptr for V-in-C because we
-     don't know what the vcall offset for `f' should be.  If `V' ends
-     up in a different place in the complete object, then we'll need a
-     different vcall offset than that present in the normal V-in-C
-     vtable.  */
+  /* If BINFO has virtual bases or is reachable via a virtual path
+     from T, it'll have a secondary vptr.  */
   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
-      && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (get_matching_base (binfo, t)))
+      && !binfo_via_virtual (binfo, t))
     return NULL_TREE;
 
   /* Record the index where this secondary vptr can be found.  */
   index = TREE_TYPE (l);
-  BINFO_VPTR_INDEX (binfo) = index;
+  if (top_level_p)
+    {
+      my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+      BINFO_VPTR_INDEX (binfo) = index;
+    }
   TREE_TYPE (l) = size_binop (PLUS_EXPR, index, 
                              TYPE_SIZE_UNIT (ptr_type_node));
 
   /* Add the initializer for the secondary vptr itself.  */
+  if (top_level_p && TREE_VIA_VIRTUAL (binfo))
+    {
+      /* It's a primary virtual base, and this is not the construction
+         vtable. Find the base this is primary of in the inheritance graph,
+         and use that base's vtable now. */
+      while (BINFO_PRIMARY_BASE_OF (binfo))
+        binfo = BINFO_PRIMARY_BASE_OF (binfo);
+    }
   init = BINFO_VTABLE (binfo);
   if (TREE_CODE (init) == TREE_LIST)
     init = TREE_VALUE (init);
@@ -6994,7 +7128,34 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data)
   return NULL_TREE;
 }
 
-/* Called from build_vtt_inits via dfs_walk.  */
+/* dfs_walk_real predicate for building vtables. DATA is a TREE_LIST,
+   TREE_UNSIGNED indicates that a constructor vtable is being built.
+   TREE_USED indicates whether marked or unmarked bases should be walked.
+   TREE_PURPOSE is the TREE_TYPE that dominates the hierarchy.  */
+
+static tree
+dfs_ctor_vtable_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
+    {
+      tree type = TREE_PURPOSE ((tree) data);
+
+      /* This is a non-primary virtual base, get the shared version.  */
+      binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
+      if (VTT_TOP_LEVEL_P ((tree) data) && BINFO_PRIMARY_P (binfo))
+        return NULL_TREE;
+    }
+  if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
+    return NULL_TREE;
+  return binfo;
+}
+
+/* Called from build_vtt_inits via dfs_walk. After building constructor
+   vtables and generating the sub-vtt from them, we need to restore the
+   BINFO_VTABLES that were scribbled on.  DATA is a TREE_LIST whose
+   TREE_VALUE is the TREE_TYPE of the base whose sub vtt was generated.  */
 
 static tree
 dfs_fixup_binfo_vtbls (binfo, data)
@@ -7040,6 +7201,7 @@ build_ctor_vtbl_group (binfo, t)
   if (IDENTIFIER_GLOBAL_VALUE (id))
     return;
 
+  my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
   /* Build a version of VTBL (with the wrong type) for use in
      constructing the addresses of secondary vtables in the
      construction vtable group.  */
@@ -7047,19 +7209,23 @@ build_ctor_vtbl_group (binfo, t)
   list = build_tree_list (vtbl, NULL_TREE);
   accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
                         binfo, t, list);
-  for (vbase = TYPE_BINFO (TREE_TYPE (binfo)); 
+
+  /* Add the vtables for each of our virtual bases using the vbase in T
+     binfo.  */
+  for (vbase = TYPE_BINFO (BINFO_TYPE (binfo)); 
        vbase; 
        vbase = TREE_CHAIN (vbase))
     {
       tree b;
+      tree orig_base;
 
       if (!TREE_VIA_VIRTUAL (vbase))
        continue;
-
       b = binfo_for_vbase (BINFO_TYPE (vbase), t);
-      accumulate_vtbl_inits (b, vbase, binfo, t, list);
+      orig_base = binfo_for_vbase (BINFO_TYPE (vbase), BINFO_TYPE (binfo));
+      
+      accumulate_vtbl_inits (b, orig_base, binfo, t, list);
     }
-
   inits = TREE_VALUE (list);
 
   /* Figure out the type of the construction vtable.  */
@@ -7072,12 +7238,15 @@ build_ctor_vtbl_group (binfo, t)
   initialize_array (vtbl, inits);
 }
 
-/* Add the vtbl initializers for BINFO (and its non-primary,
-   non-virtual bases) to the list of INITS.  BINFO is in the hierarchy
-   dominated by T.  ORIG_BINFO must have the same type as BINFO, but
-   may be different from BINFO if we are building a construction
-   vtable.  RTTI_BINFO gives the object that should be used as the
-   complete object for BINFO.  */
+/* Add the vtbl initializers for BINFO (and its bases other than
+   non-virtual primaries) to the list of INITS.  BINFO is in the
+   hierarchy dominated by T.  RTTI_BINFO is the binfo within T of
+   the constructor the vtbl inits should be accumulated for. (If this
+   is the complete object vtbl then RTTI_BINFO will be TYPE_BINFO (T).)
+   ORIG_BINFO is the binfo for this object within BINFO_TYPE (RTTI_BINFO).
+   BINFO is the active base equivalent of ORIG_BINFO in the inheritance
+   graph of T. Both BINFO and ORIG_BINFO will have the same BINFO_TYPE,
+   but are not necessarily the same in terms of layout.  */
 
 static void
 accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
@@ -7088,22 +7257,17 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
      tree inits;
 {
   int i;
-  int ctor_vtbl_p;
+  int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
 
   my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
                                   BINFO_TYPE (orig_binfo)),
                      20000517);
 
-  /* This is a construction vtable if the RTTI type is not the most
-     derived type in the hierarchy.  */
-  ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
-
   /* If we're building a construction vtable, we're not interested in
      subobjects that don't require construction vtables.  */
   if (ctor_vtbl_p 
       && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
-      && !(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P 
-          (get_matching_base (binfo, BINFO_TYPE (rtti_binfo)))))
+      && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
     return;
 
   /* Build the initializers for the BINFO-in-T vtable.  */
@@ -7119,21 +7283,19 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
      and RTTI_BINFO simultaneously.  */
   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
     {
-      tree base_binfo;
-
-      base_binfo = BINFO_BASETYPE (binfo, i);
+      tree base_binfo = BINFO_BASETYPE (binfo, i);
+      
       /* Skip virtual bases.  */
       if (TREE_VIA_VIRTUAL (base_binfo))
        continue;
       accumulate_vtbl_inits (base_binfo,
                             BINFO_BASETYPE (orig_binfo, i),
-                            rtti_binfo,
-                            t,
+                            rtti_binfo, t,
                             inits);
     }
 }
 
-/* Called from finish_vtbls via dfs_walk when using the new ABI.
+/* Called from accumulate_vtbl_inits when using the new ABI.
    Accumulates the vtable initializers for all of the vtables into
    TREE_VALUE (DATA).  Returns the initializers for the BINFO vtable.  */
 
@@ -7146,10 +7308,57 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
      tree l;
 {
   tree inits = NULL_TREE;
+  tree vtbl = NULL_TREE;
+  int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+  if (ctor_vtbl_p
+      && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
+    {
+      /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary
+         virtual base.  If it is not the same primary in the hierarchy of T,
+         we'll need to generate a ctor vtable for it, to place at its
+         location in T.  If it is the same primary, we still need a VTT
+         entry for the vtable, but that must be the base it is a
+         primary for within the sub-hierarchy of RTTI_BINFO.  */
+      tree parent;
+      tree best_primary = NULL;
+      tree primary_for;
+      
+      my_friendly_assert (BINFO_PRIMARY_P (binfo), 20010131);
 
-  if (BINFO_NEW_VTABLE_MARKED (orig_binfo, t))
+      for (primary_for = BINFO_PRIMARY_BASE_OF (binfo);
+           primary_for;
+           primary_for = BINFO_PRIMARY_BASE_OF (primary_for))
+        {
+          for (parent = primary_for;
+               parent;
+               parent = BINFO_INHERITANCE_CHAIN (parent))
+             {
+               if (parent == rtti_binfo)
+                 {
+                   best_primary = primary_for;
+                   break;
+                 }
+             }
+           if (!parent)
+             break;
+        }
+      if (best_primary)
+        {
+          vtbl = BINFO_VTABLE (best_primary);
+          if (TREE_CODE (vtbl) == TREE_LIST)
+            {
+              my_friendly_assert (TREE_PURPOSE (vtbl) == rtti_binfo,
+                                  20010126);
+              vtbl = TREE_VALUE (vtbl);
+            }
+        }
+    }
+  else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
+    return inits;
+  
+  if (!vtbl)
     {
-      tree vtbl;
       tree index;
       int non_fn_entries;
 
@@ -7170,17 +7379,20 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
                          index);
       vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
       TREE_CONSTANT (vtbl) = 1;
+    }
 
+  if (!ctor_vtbl_p)
+    {
       /* For an ordinary vtable, set BINFO_VTABLE.  */
-      if (same_type_p (BINFO_TYPE (rtti_binfo), t))
-       BINFO_VTABLE (binfo) = vtbl;
-      /* For a construction vtable, we can't overwrite BINFO_VTABLE.
-        So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
-        straighten this out.  */
-      else
-       BINFO_VTABLE (binfo) = 
-         tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
+      BINFO_VTABLE (binfo) = vtbl;
+      if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+        inits = NULL_TREE;
     }
+  else
+    /* For a construction vtable, we can't overwrite BINFO_VTABLE.
+       So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
+       straighten this out.  */
+    BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
 
   return inits;
 }
@@ -7188,7 +7400,9 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
 /* Construct the initializer for BINFOs virtual function table.  BINFO
    is part of the hierarchy dominated by T.  If we're building a
    construction vtable, the ORIG_BINFO is the binfo we should use to
-   find the actual function pointers to put in the vtable.  Otherwise,
+   find the actual function pointers to put in the vtable - but they
+   can be overridden on the path to most-derived in the graph that
+   ORIG_BINFO belongs.  Otherwise,
    ORIG_BINFO should be the same as BINFO.  The RTTI_BINFO is the
    BINFO that should be indicated by the RTTI information in the
    vtable; it will be a base class of T, rather than T itself, if we
@@ -7200,9 +7414,9 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
    number of non-function entries in the vtable.  
 
    It might seem that this function should never be called with a
-   BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a
+   BINFO for which BINFO_PRIMARY_P holds, the vtable for such a
    base is always subsumed by a derived class vtable.  However, when
-   we are building construction vtables we do build vtables for
+   we are building construction vtables, we do build vtables for
    primary bases; we need these while the primary base is being
    constructed.  */
 
@@ -7489,7 +7703,7 @@ add_vcall_offset_vtbl_entries_r (binfo, vid)
     }
 }
 
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk.  */
+/* Called from build_vcall_offset_vtbl_entries_r.  */
 
 static void
 add_vcall_offset_vtbl_entries_1 (binfo, vid)
@@ -7579,7 +7793,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
       if (i != VARRAY_ACTIVE_SIZE (vid->fns))
        continue;
 
-      /* The FN comes from BASE.  So, we must caculate the adjustment
+      /* The FN comes from BASE.  So, we must calculate the adjustment
         from the virtual base that derived from BINFO to BASE.  */
       base = DECL_CONTEXT (fn);
       base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
@@ -7635,13 +7849,13 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
   /* To find the complete object, we will first convert to our most
      primary base, and then add the offset in the vtbl to that value.  */
   b = binfo;
-  while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
+  while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))
+         && !BINFO_LOST_PRIMARY_P (b))
     {
       tree primary_base;
 
       primary_base = get_primary_binfo (b);
-      if (!BINFO_PRIMARY_MARKED_P (primary_base))
-       break;
+      my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
       b = primary_base;
     }
   offset = size_diffop (BINFO_OFFSET (rtti_binfo), BINFO_OFFSET (b));
index 9077671..d473006 100644 (file)
@@ -60,7 +60,7 @@ Boston, MA 02111-1307, USA.  */
       TYPE_POLYMORHPIC_P (in _TYPE)
       ICS_THIS_FLAG (in _CONV)
       BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
-      BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (in BINFO)
+      BINFO_LOST_PRIMARY_P (in BINFO)
       TREE_PARMLIST (in TREE_LIST)
    3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
       BINFO_VTABLE_PATH_MARKED.
@@ -1158,6 +1158,10 @@ extern int flag_access_control;
 
 extern int flag_check_new;
 
+/* Nonnull if we want to dump class heirarchies. */
+
+extern const char *flag_dump_class_layout;
+
 \f
 /* C++ language-specific tree codes.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -1672,11 +1676,11 @@ struct lang_type
   (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
 
 /* Any subobject that needs a new vtable must have a vptr and must not
-   be a primary base (since it would then use the vtable from a
-   derived class.)  */
+   be a non-virtual primary base (since it would then use the vtable from a
+   derived class and never become non-primary.)  */
 #define SET_BINFO_NEW_VTABLE_MARKED(B, C)                               \
   (BINFO_NEW_VTABLE_MARKED (B, C) = 1,                                  \
-   my_friendly_assert (!BINFO_PRIMARY_MARKED_P (B), 20000517),          \
+   my_friendly_assert (!BINFO_PRIMARY_P (B) || TREE_VIA_VIRTUAL (B), 20000517),                 \
    my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE,  \
                       20000517))
 
@@ -1691,7 +1695,7 @@ struct lang_type
    class of a non-primary virtual base.  This flag is only valid for
    paths (given by BINFO_INHERITANCE_CHAIN) that really exist in the
    final object.  */
-#define BINFO_PRIMARY_MARKED_P(NODE) \
+#define BINFO_PRIMARY_P(NODE) \
   (BINFO_PRIMARY_BASE_OF (NODE) != NULL_TREE)
 
 /* The index in the VTT where this subobject's sub-VTT can be found.
@@ -1708,9 +1712,10 @@ struct lang_type
    immediate base.)  */
 #define BINFO_PRIMARY_BASE_OF(NODE) TREE_VEC_ELT ((NODE), 10)
 
-/* Nonzero if this binfo declares a virtual function which is
-   overridden along a virtual path.  */
-#define BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P(NODE) TREE_LANG_FLAG_2 (NODE)
+/* Nonzero if this binfo has lost its primary base binfo (because that
+   is a nearly-empty virtual base that has been taken by some other
+   base in the complete heirarchy.  */
+#define BINFO_LOST_PRIMARY_P(NODE) TREE_LANG_FLAG_2 (NODE)
 
 /* Nonzero if this binfo is an indirect primary base, i.e. a virtual
    base that is a primary base of some of other class in the
@@ -4248,6 +4253,7 @@ extern tree unmarked_vtable_pathp               PARAMS ((tree, void *));
 extern tree convert_pointer_to_vbase            PARAMS ((tree, tree));
 extern tree find_vbase_instance                 PARAMS ((tree, tree));
 extern tree binfo_for_vbase                     PARAMS ((tree, tree));
+extern tree binfo_via_virtual                   PARAMS ((tree, tree));
 extern void fixup_all_virtual_upcast_offsets    PARAMS ((tree));
 
 /* in semantics.c */
index 2c3dbc7..fff3956 100644 (file)
@@ -403,6 +403,10 @@ int flag_operator_names = 1;
 
 int flag_check_new;
 
+/* Nonnull if we want to dump class heirarchies.  */
+
+const char *flag_dump_class_layout;
+
 /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
    0: Old rules, set by -fno-for-scope.
@@ -647,13 +651,23 @@ cxx_decode_option (argc, argv)
        name_mangling_version 
          = read_integral_parameter (option_value, p - 2, name_mangling_version);
       else if ((option_value
-                = skip_leading_substring (p, "dump-translation-unit-")))
+                = skip_leading_substring (p, "dump-translation-unit=")))
        {
-         if (p[22] == '\0')
+         if (!*option_value)
            error ("no file specified with -fdump-translation-unit");
          else
            flag_dump_translation_unit = option_value;
        }
+      else if ((option_value
+                = skip_leading_substring (p, "dump-class-layout=")))
+       {
+         if (!*option_value)
+           error ("no file specified with -fdump-class-layout");
+         else
+           flag_dump_class_layout = option_value;
+       }
+      else if (!strcmp (p, "dump-class-layout"))
+       flag_dump_class_layout = ""; /* empty string for stderr */
       else 
        {
          int found = 0;
index 7cd6c57..e7d6293 100644 (file)
@@ -137,7 +137,7 @@ dfs_initialize_vtbl_ptrs (binfo, data)
      tree binfo;
      void *data;
 {
-  if (!BINFO_PRIMARY_MARKED_P (binfo) 
+  if ((!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
       tree base_ptr = TREE_VALUE ((tree) data);
@@ -802,16 +802,27 @@ static tree
 build_vtbl_address (binfo)
      tree binfo;
 {
+  tree binfo_for = binfo;
   tree vtbl;
 
+  if (BINFO_VPTR_INDEX (binfo) && TREE_VIA_VIRTUAL (binfo)
+      && BINFO_PRIMARY_P (binfo))
+    /* If this is a virtual primary base, then the vtable we want to store
+       is that for the base this is being used as the primary base of.  We
+       can't simply skip the initialization, because we may be expanding the
+       inits of a subobject constructor where the virtual base layout
+       can be different.  */
+    while (BINFO_PRIMARY_BASE_OF (binfo_for))
+      binfo_for = BINFO_PRIMARY_BASE_OF (binfo_for);
+
   /* Figure out what vtable BINFO's vtable is based on, and mark it as
      used.  */
-  vtbl = get_vtbl_decl_for_binfo (binfo);
+  vtbl = get_vtbl_decl_for_binfo (binfo_for);
   assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
-  vtbl = BINFO_VTABLE (binfo);
+  vtbl = BINFO_VTABLE (binfo_for);
   if (TREE_CODE (vtbl) == VAR_DECL)
     {
       vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
index c8cf526..1699c32 100644 (file)
@@ -2045,7 +2045,7 @@ dfs_skip_nonprimary_vbases_unmarkedp (binfo, data)
      tree binfo;
      void *data ATTRIBUTE_UNUSED;
 {
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
     /* This is a non-primary virtual base.  Skip it.  */
     return NULL_TREE;
 
@@ -2060,7 +2060,7 @@ dfs_skip_nonprimary_vbases_markedp (binfo, data)
      tree binfo;
      void *data ATTRIBUTE_UNUSED;
 {
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
     /* This is a non-primary virtual base.  Skip it.  */
     return NULL_TREE;
 
@@ -2078,7 +2078,7 @@ get_shared_vbase_if_not_primary (binfo, data)
      tree binfo;
      void *data;
 {
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
     {
       tree type = (tree) data;
 
@@ -2088,7 +2088,7 @@ get_shared_vbase_if_not_primary (binfo, data)
       /* 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_PRIMARY_MARKED_P (binfo))
+      if (BINFO_PRIMARY_P (binfo))
        return NULL_TREE;
     }
 
@@ -2152,7 +2152,7 @@ dfs_get_pure_virtuals (binfo, 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))
+  if (!BINFO_PRIMARY_P (binfo))
     {
       tree virtuals;
       
@@ -2455,7 +2455,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
   tree delta;
   HOST_WIDE_INT n;
 
-  while (BINFO_PRIMARY_MARKED_P (binfo))
+  while (BINFO_PRIMARY_P (binfo))
     {
       binfo = BINFO_INHERITANCE_CHAIN (binfo);
       if (TREE_VIA_VIRTUAL (binfo))
@@ -2593,7 +2593,7 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
       tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
       tree base_binfo = TREE_VEC_ELT (binfos, i);
       int is_not_base_vtable
-       = !BINFO_PRIMARY_MARKED_P (real_base_binfo);
+       = !BINFO_PRIMARY_P (real_base_binfo);
       if (! TREE_VIA_VIRTUAL (real_base_binfo))
        fixup_virtual_upcast_offsets (real_base_binfo, base_binfo,
                                      is_not_base_vtable, can_elide, addr,
@@ -2737,7 +2737,7 @@ dfs_find_vbase_instance (binfo, data)
 {
   tree base = TREE_VALUE ((tree) data);
 
-  if (BINFO_PRIMARY_MARKED_P (binfo)
+  if (BINFO_PRIMARY_P (binfo)
       && same_type_p (BINFO_TYPE (binfo), base))
     return binfo;
 
@@ -2755,7 +2755,7 @@ find_vbase_instance (base, type)
   tree instance;
 
   instance = binfo_for_vbase (base, type);
-  if (!BINFO_PRIMARY_MARKED_P (instance))
+  if (!BINFO_PRIMARY_P (instance))
     return instance;
 
   return dfs_walk (TYPE_BINFO (type), 
@@ -3249,8 +3249,8 @@ binfo_for_vtable (var)
   return main_binfo;
 }
 
-/* Returns the binfo of the first direct or indirect virtual base from
-   which BINFO is derived, or NULL if binfo is not via virtual.  */
+/* Returns the binfo of the first direct or indirect virtual base derived
+   from BINFO, or NULL if binfo is not via virtual.  */
 
 tree
 binfo_from_vbase (binfo)
@@ -3264,6 +3264,24 @@ binfo_from_vbase (binfo)
   return NULL_TREE;
 }
 
+/* Returns the binfo of the first direct or indirect virtual base derived
+   from BINFO up to the TREE_TYPE, LIMIT, or NULL if binfo is not
+   via virtual.  */
+
+tree
+binfo_via_virtual (binfo, limit)
+     tree binfo;
+     tree limit;
+{
+  for (; binfo && (!limit || !same_type_p (BINFO_TYPE (binfo), limit));
+       binfo = BINFO_INHERITANCE_CHAIN (binfo))
+    {
+      if (TREE_VIA_VIRTUAL (binfo))
+       return binfo;
+    }
+  return NULL_TREE;
+}
+
 /* Returns the BINFO (if any) for the virtual baseclass T of the class
    C from the CLASSTYPE_VBASECLASSES list.  */
 
index beec0e7..8052be1 100644 (file)
@@ -223,8 +223,8 @@ in the following sections.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{
--a  -ax  -d@var{letters}  -fdump-unnumbered -fdump-translation-unit-@var{file} @gol
--fpretend-float -fprofile-arcs  -ftest-coverage @gol
+-a  -ax  -d@var{letters}  -fdump-unnumbered -fdump-translation-unit=@var{file} @gol
+-fdump-class-layout=@var{file} -fpretend-float -fprofile-arcs  -ftest-coverage @gol
 -g  -g@var{level}  -gcoff  -gdwarf  -gdwarf-1  -gdwarf-1+  -gdwarf-2 @gol
 -ggdb  -gstabs  -gstabs+  -gxcoff  -gxcoff+ @gol
 -p  -pg  -print-file-name=@var{library}  -print-libgcc-file-name @gol
@@ -2679,10 +2679,15 @@ numbers and line number note output.  This makes it more feasible to
 use diff on debugging dumps for compiler invocations with different
 options, in particular with and without -g.
 
-@item -fdump-translation-unit-@var{file} (C and C++ only)
+@item -fdump-translation-unit=@var{file} (C and C++ only)
 Dump a representation of the tree structure for the entire translation
 unit to @var{file}.
 
+@item -fdump-class_layout=@var{file} (C++ only)
+@item -fdump-class_layout (C++ only)
+Dump a representation of each class's heirarchy to @var{file}, or
+@code{stderr} if not specified.
+
 @item -fpretend-float
 When running a cross-compiler, pretend that the target machine uses the
 same floating point format as the host machine.  This causes incorrect
index 60daf56..2cec5af 100644 (file)
@@ -1,3 +1,22 @@
+2001-02-05  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.abi/primary2.C: New test.
+       * g++.old-deja/g++.abi/primary3.C: New test.
+       * g++.old-deja/g++.abi/primary4.C: New test.
+       * g++.old-deja/g++.abi/primary5.C: New test.
+       * g++.old-deja/g++.abi/vtable3.h: New test.
+       * g++.old-deja/g++.abi/vtable3a.C: New test.
+       * g++.old-deja/g++.abi/vtable3b.C: New test.
+       * g++.old-deja/g++.abi/vtable3c.C: New test.
+       * g++.old-deja/g++.abi/vtable3d.C: New test.
+       * g++.old-deja/g++.abi/vtable3e.C: New test.
+       * g++.old-deja/g++.abi/vtable3f.C: New test.
+       * g++.old-deja/g++.abi/vtable3g.C: New test.
+       * g++.old-deja/g++.abi/vtable3h.C: New test.
+       * g++.old-deja/g++.abi/vtable3i.C: New test.
+       * g++.old-deja/g++.abi/vtable3j.C: New test.
+       * g++.old-deja/g++.oliva/thunk1.C: Remove XFAIL.
+
 2001-02-03  Jakub Jelinek  <jakub@redhat.com>
 
        * g++.old-deja/g++.other/anon6.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary2.C b/gcc/testsuite/g++.old-deja/g++.abi/primary2.C
new file mode 100644 (file)
index 0000000..795eb4d
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check primary bases are chosen correctly.
+
+struct A {virtual void Foo () {}};
+struct B : virtual A {};
+struct C : virtual B {};
+struct D : virtual B, virtual C {};
+
+int main ()
+{
+  D d;
+
+#if __GXX_ABI_VERSION >= 100
+  if (sizeof (D) != sizeof (A))
+    return 1;
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary3.C b/gcc/testsuite/g++.old-deja/g++.abi/primary3.C
new file mode 100644 (file)
index 0000000..ef245ef
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check primary bases are chosen correctly.
+
+struct A {virtual void Foo () {}};
+struct B1 : virtual A {};
+struct B2 : virtual A {};
+struct C : virtual B1, B2 {};
+struct D : virtual C {};
+
+int main ()
+{
+  C c;
+  D d;
+  
+  A *apc = &c;
+  B1 *b1pc = &c;
+  B2 *b2pc = &c;
+  
+  A *apd = &d;
+  B1 *b1pd = &d;
+  B2 *b2pd = &d;
+  
+#if __GXX_ABI_VERSION >= 100
+  if (static_cast <void *> (apc) != static_cast <void *> (b1pc))
+    return 1;
+  if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
+    return 2;
+  if (static_cast <void *> (apd) != static_cast <void *> (&d))
+    return 3;
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary4.C b/gcc/testsuite/g++.old-deja/g++.abi/primary4.C
new file mode 100644 (file)
index 0000000..d18f242
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check primary bases are chosen correctly.
+
+struct A { virtual void Foo () {}};
+
+struct B1 : virtual A {};
+struct B2 : virtual A {};
+
+struct C : virtual B1 {};
+
+struct D : virtual B1, B2, C {};
+
+int main ()
+{
+  D d;
+  A *ap = &d;
+  C *cp = &d;
+  
+#if __GXX_ABI_VERSION >= 100
+  if (static_cast <void *> (ap) != static_cast <void *> (cp))
+    return 1;
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary5.C b/gcc/testsuite/g++.old-deja/g++.abi/primary5.C
new file mode 100644 (file)
index 0000000..422e66e
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check primary bases are chosen correctly.
+
+struct A1
+{
+   virtual void Foo () {};
+};
+
+struct A : A1
+{
+};
+
+struct B : A
+{
+};
+
+struct C : virtual B
+{
+};
+
+struct D : virtual B, virtual C
+{
+};
+
+int main()
+{
+  D d;
+#if __GXX_ABI_VERSION >= 100
+  if (sizeof (D) != sizeof (A))
+    return 1;
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h b/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h
new file mode 100644 (file)
index 0000000..327d346
--- /dev/null
@@ -0,0 +1,181 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work. This is included from numerous test
+// files, which set the #defines necessary to specify the heirarchy.
+
+#include <typeinfo>
+#include <stdio.h>
+
+// XXX. vcall offsets are still broken, remove this define to re-enable
+// testing when fixed.
+#define NO_VCALL_TEST
+
+int fail;
+
+template <typename BASE, typename DERIVED>
+int Test (DERIVED *d, int expect)
+{
+  BASE *b = static_cast <BASE *> (d);
+  void *full_b = dynamic_cast <void *> (b);
+  void *full_d = dynamic_cast <void *> (d);
+  
+  if (full_b != full_d)
+    {
+      fail++;
+      fprintf (stderr, "base %s and derived %s have different full objects\n",
+              typeid (BASE).name (), typeid (DERIVED).name ());
+      return 1;
+    }
+
+  DERIVED *dynamic_d = dynamic_cast <DERIVED *> (b);
+  
+  if (dynamic_d != d)
+    {
+      fail++;
+      fprintf (stderr, "dynamic_cast from %s to %s failed\n",
+              typeid (BASE).name (), typeid (DERIVED).name ());
+      return 1;
+    }
+#ifndef NO_VCALL_TEST
+  b->Baz (static_cast <void *> (b));
+  
+  int res = b->Foo (static_cast <void *> (d));
+  
+  if (res != expect)
+    {
+      fail++;
+      fprintf (stderr, "%s::Foo returned %d, expected %d\n",
+              typeid (BASE).name (), res, expect);
+      return 1;
+    }
+#endif
+  return 0;
+}
+
+template <typename T>
+int Test (T *self, void *expected, int result)
+{
+  if (self != expected)
+    {
+      fail++;
+      fprintf (stderr, "%s::Foo wrong this pointer\n", typeid (T).name ());
+    }
+  return result;
+}
+
+struct A {
+#ifndef A_EMPTY
+  int a_m;
+#endif
+  virtual int Foo (void *p) {return Test (this, p, 1);}
+  virtual int Baz (void *p) {return Test (this, p, 1);}
+  A ();
+  ~A ();
+};
+
+struct B1: virtual A {
+#ifndef B1_EMPTY
+  int b1_m;
+#endif
+  virtual int Foo (void *p) {return Test (this, p, 2);}
+  B1();
+  ~B1();
+};
+
+struct B2: virtual A {
+#ifndef B2_EMPTY
+  int b2_m;
+#endif
+  virtual int Foo (void *p) {return Test (this, p, 3);}
+  B2();
+  ~B2();
+};
+
+struct Empty {};
+
+struct C : C_PARENTS {
+#ifndef C_EMPTY
+  int c_m;
+#endif
+  virtual int Foo (void *p) {return Test (this, p, 4);}
+  C();
+  ~C();
+};
+
+A::A ()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 1);
+}
+A::~A ()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 1);
+}
+
+B1::B1()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 2);
+  Test <B1> (this, 2);
+}
+B1::~B1()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 2);
+  Test <B1> (this, 2);
+}
+B2::B2()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 3);
+  Test <B2> (this, 3);
+}
+B2::~B2()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 3);
+  Test <B2> (this, 3);
+}
+C::C()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 4);
+  Test <C> (this, 4);
+}
+C::~C()
+{
+  fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+  Test <A> (this, 4);
+  Test <C> (this, 4);
+}
+
+struct D : C {};
+struct D1 : virtual C {};
+struct D2 : virtual A, virtual C {};
+
+int main()
+{
+  {
+    fprintf (stderr, "C\n");
+    C c;
+  }
+  {
+    fprintf (stderr, "D\n");
+    D d;
+  }
+  {
+    fprintf (stderr, "D1\n");
+    D1 d1;
+  }
+  {
+    fprintf (stderr, "D2\n");
+    D2 d2;
+  }
+  if (fail)
+    fprintf (stderr, "There are %d failings\n", fail);
+  else
+    fprintf (stderr, "Passed\n");
+  return fail ? 1 : 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C
new file mode 100644 (file)
index 0000000..99d3d0b
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C
new file mode 100644 (file)
index 0000000..4d4bd99
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C
new file mode 100644 (file)
index 0000000..2863ca5
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C
new file mode 100644 (file)
index 0000000..a3a2cbc
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define C_EMPTY
+#define C_PARENTS B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C
new file mode 100644 (file)
index 0000000..a1c8a9d
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_PARENTS B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C
new file mode 100644 (file)
index 0000000..7bcf40c
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS B1, virtual B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C
new file mode 100644 (file)
index 0000000..1ad70bc
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS virtual B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C
new file mode 100644 (file)
index 0000000..074bda4
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define A_EMPTY
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS virtual B1, virtual B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C
new file mode 100644 (file)
index 0000000..d6fc3a3
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS virtual B1, B2
+
+#include "vtable3.h"
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C
new file mode 100644 (file)
index 0000000..1af5225
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
+
+// Check constructor vtables work.
+
+#define B1_EMPTY
+#define B2_EMPTY
+#define C_EMPTY
+#define C_PARENTS virtual B1, virtual B2
+
+#include "vtable3.h"
index 5407e9e..225a1f9 100644 (file)
@@ -4,7 +4,6 @@
 // based on bug report by Fredrik Öhrström <d92-foh@nada.kth.se>
 
 // Special g++ Options: -fvtable-thunks
-// execution test - XFAIL *-*-*
 
 #include <cstdlib>