aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-06-08 11:10:29 +0000
committerJason Merrill <jason@gcc.gnu.org>2001-06-08 07:10:29 -0400
commit85a9a0a28bd6f48e7e45386cbe6003ea3199f43b (patch)
treece04acf4b9d514f44b958d698c993174a3d3f80f /gcc
parent6a1447333f0c219f0efb334a463991b2af168572 (diff)
downloadgcc-85a9a0a28bd6f48e7e45386cbe6003ea3199f43b.zip
gcc-85a9a0a28bd6f48e7e45386cbe6003ea3199f43b.tar.gz
gcc-85a9a0a28bd6f48e7e45386cbe6003ea3199f43b.tar.bz2
re PR c++/3061 (kde2/artsd miscompilation (part 2))
PR c++/3061 * class.c (build_secondary_vtable): Use assert, rather than an error message. (dfs_fixup_binfo_vtbls): BINFO_VTABLE might be NULL. (dfs_accumulate_vtbl_inits): A lost primary virtual base may be between ORIG_BINFO and RTTI_BINFO, but neither of them. Don't set BINFO_VTABLE for a primary virtual base. Co-Authored-By: Jason Merrill <jason@redhat.com> From-SVN: r43006
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/class.c143
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable4.C27
4 files changed, 125 insertions, 58 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fb986e5..1fa95c8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2001-06-08 Nathan Sidwell <nathan@codesourcery.com>
+ Jason Merrill <jason_merrill@redhat.com>
+
+ PR c++/3061
+ * class.c (build_secondary_vtable): Use assert, rather than an error
+ message.
+ (dfs_fixup_binfo_vtbls): BINFO_VTABLE might be NULL.
+ (dfs_accumulate_vtbl_inits): A lost primary virtual base may
+ be between ORIG_BINFO and RTTI_BINFO, but neither of them.
+ Don't set BINFO_VTABLE for a primary virtual base.
+
2001-06-07 Mark Mitchell <mark@codesourcery.com>
* decl.c (duplicate_decls): Update source position information
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index cdd92b5..499053c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -768,7 +768,7 @@ copy_virtuals (binfo)
return copies;
}
-
+
/* Build the primary virtual function table for TYPE. If BINFO is
non-NULL, build the vtable starting with the initial approximation
that it is the same as the one which is the head of the association
@@ -866,20 +866,8 @@ build_secondary_vtable (binfo, for_type)
/* Make fresh virtual list, so we can smash it later. */
BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree binfo1 = binfo_for_vbase (BINFO_TYPE (binfo), for_type);
-
- /* XXX - This should never happen, if it does, the caller should
- ensure that the binfo is from for_type's binfos, not from any
- base type's. We can remove all this code after a while. */
- if (binfo1 != binfo)
- warning ("internal inconsistency: binfo offset error for rtti");
-
- offset = BINFO_OFFSET (binfo1);
- }
- else
- offset = BINFO_OFFSET (binfo);
+ my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605);
+ offset = BINFO_OFFSET (binfo);
/* In the new ABI, secondary vtables are laid out as part of the
same structure as the primary vtable. */
@@ -6744,12 +6732,12 @@ dfs_get_primary_binfo (binfo, data)
return NULL_TREE;
}
-/* Returns the binfo for the primary base of BINFO. Note that in a
- complex hierarchy the resulting BINFO may not actually *be*
- 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_P to be sure. */
+/* Returns the unshared binfo for the primary base of BINFO. Note
+ that in a complex hierarchy the resulting BINFO may not actually
+ *be* 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_P to be sure. */
tree
get_primary_binfo (binfo)
@@ -7397,7 +7385,8 @@ dfs_fixup_binfo_vtbls (binfo, data)
/* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */
- if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
+ if (BINFO_VTABLE (binfo)
+ && TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
&& (TREE_PURPOSE (BINFO_VTABLE (binfo))
== TREE_VALUE ((tree) data)))
BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
@@ -7543,41 +7532,80 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
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);
+ entry for the vtable, but it should point to the ctor vtable for the
+ base it is a primary for within the sub-hierarchy of RTTI_BINFO.
- 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);
- }
+ There are three possible cases:
+
+ 1) We are in the same place.
+ 2) We are a primary base within a lost primary virtual base of
+ RTTI_BINFO.
+ 3) We are not primary to anything else in RTTI_BINFO. */
+
+ tree primary = NULL_TREE;
+ if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
+ size_diffop (BINFO_OFFSET (binfo),
+ BINFO_OFFSET (rtti_binfo))))
+ {
+ /* Case 1: We're in the same place relative to RTTI_BINFO as we
+ were in the complete type, so we are primary either to
+ RTTI_BINFO or one of its secondary bases. */
+
+ tree b = BINFO_PRIMARY_BASE_OF (binfo);
+
+ /* Walk down our until we either find the last primary base or
+ rtti_binfo. */
+ for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ {
+ primary = b;
+ if (b == rtti_binfo)
+ break;
+ }
}
+ else
+ {
+ /* Case 2 or 3: We're not in the same place. We might still be
+ primary to something within a lost primary virtual base of
+ RTTI_BINFO. */
+
+ tree b = BINFO_PRIMARY_BASE_OF (binfo);
+ tree last;
+
+ /* First, look through the bases we are primary to for a virtual
+ base. */
+ for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ {
+ last = b;
+ if (TREE_VIA_VIRTUAL (b))
+ break;
+ }
+ /* If we run out of primary links, keep looking down our
+ inheritance chain; we might be an indirect primary of a
+ virtual base. */
+ if (b == NULL_TREE)
+ for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
+ if (TREE_VIA_VIRTUAL (b))
+ break;
+
+ /* If we found a virtual base B and it is a base of RTTI_BINFO, we
+ share our vtable with LAST, i.e. the derived-most base within
+ B of which we are a primary. Otherwise, we get our own. */
+ if (b && binfo_for_vbase (BINFO_TYPE (b),
+ BINFO_TYPE (rtti_binfo)))
+ primary = last;
+ }
+
+ if (primary)
+ {
+ vtbl = BINFO_VTABLE (primary);
+ /* If we haven't already been here for our primary derivation,
+ all bets are off. Especially for case 2 above, we need
+ the derived vtable to have been generated. */
+ my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST
+ && TREE_PURPOSE (vtbl) == rtti_binfo,
+ 20010126);
+ vtbl = TREE_VALUE (vtbl);
+ }
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
return inits;
@@ -7610,9 +7638,10 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
if (!ctor_vtbl_p)
{
/* For an ordinary vtable, set BINFO_VTABLE. */
- BINFO_VTABLE (binfo) = vtbl;
if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
- inits = NULL_TREE;
+ inits = NULL_TREE;
+ else
+ BINFO_VTABLE (binfo) = vtbl;
}
else
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 4acf6b6..ceb569c 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -292,7 +292,7 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
/* Return a thunk to FUNCTION. For a virtual thunk, DELTA is the
offset to this used to locate the vptr, and VCALL_INDEX is used to
look up the eventual subobject location. For a non-virtual thunk,
- DELTA is the offset to this and VCALL_INDEX is zero. */
+ DELTA is the offset to this and VCALL_INDEX is NULL. */
tree
make_thunk (function, delta, vcall_index)
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable4.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable4.C
new file mode 100644
index 0000000..8190c0e
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable4.C
@@ -0,0 +1,27 @@
+// Test for proper handling of extreme virtual inheritance.
+// Previously we failed to recognise that in the constructor vtable
+// for B_skel in C_skel, A_base was still primary to B_base, even though
+// not to B_skel.
+
+// From PR c++/3061.
+
+struct A_base {
+ virtual void foo() { }
+};
+class A_skel : virtual public A_base { };
+
+class B_base : virtual public A_base { };
+class B_skel : virtual public B_base, virtual public A_skel { };
+
+class C_base : virtual public B_base { };
+class C_skel : virtual public C_base, virtual public B_skel { };
+
+class D_base : virtual public C_base { };
+class D_skel : virtual public D_base, virtual public C_skel { };
+
+class D_impl : virtual public D_skel { };
+
+int main()
+{
+ D_impl i;
+}