aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-06-12 08:47:48 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-06-12 08:47:48 +0000
commit7bdcf888aaa78808dc2dd4e16e70458244a607be (patch)
tree8b3d53c05d660b1ff673c9a0fba8a13a8ecbd8ba /gcc
parent5a2dd36ccd1ee21ef038ce6f6775a422020787bd (diff)
downloadgcc-7bdcf888aaa78808dc2dd4e16e70458244a607be.zip
gcc-7bdcf888aaa78808dc2dd4e16e70458244a607be.tar.gz
gcc-7bdcf888aaa78808dc2dd4e16e70458244a607be.tar.bz2
re PR c++/3089 (ICE in dfs_accumulate_vtbl_inits)
cp: PR c++/3089 * class.c (dfs_accumulate_vtbl_inits): Always walk down the hierarchy looking for primary bases for a ctor vtable. Recursively call oneself, if we meet our primary via this route and haven't met it yet via inheritance graph order. testsuite: * g++.old-deja/g++.abi/vbase4.C: New test. From-SVN: r43248
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/class.c188
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vbase4.C165
4 files changed, 283 insertions, 82 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8d84da6..577038e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2001-06-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/3089
+ * class.c (dfs_accumulate_vtbl_inits): Always walk down the
+ hierarchy looking for primary bases for a ctor
+ vtable. Recursively call oneself, if we meet our primary via
+ this route and haven't met it yet via inheritance graph order.
+
2001-06-11 Mark Mitchell <mark@codesourcery.com>
* lang-options.h: Emit documentation for -fno-honor-std, not
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 499053c..a0cd2ce 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7409,7 +7409,7 @@ build_ctor_vtbl_group (binfo, t)
tree id;
tree vbase;
- /* See if we've already create this construction vtable group. */
+ /* See if we've already created this construction vtable group. */
id = mangle_ctor_vtbl_for_type (t, binfo);
if (IDENTIFIER_GLOBAL_VALUE (id))
return;
@@ -7525,91 +7525,118 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
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))
+ if (ctor_vtbl_p)
{
- /* 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 it should point to the ctor vtable for the
- base it is a primary for within the sub-hierarchy of RTTI_BINFO.
-
- 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))))
+ tree primary = binfo;
+ tree orig_primary = orig_binfo;
+
+ if (TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_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))
+ /* 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 it
+ should point to the ctor vtable for the base it is a
+ primary for within the sub-hierarchy of RTTI_BINFO.
+
+ 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. */
+
+ if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
+ size_diffop (BINFO_OFFSET (binfo),
+ BINFO_OFFSET (rtti_binfo))))
{
- 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;
+ /* 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. */
+
+ /* Walk down our until we either find the last
+ primary base or rtti_binfo. */
+ tree b = BINFO_PRIMARY_BASE_OF (binfo);
- /* First, look through the bases we are primary to for a virtual
- base. */
- for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ {
+ primary = b;
+ orig_primary = BINFO_PRIMARY_BASE_OF (orig_primary);
+ if (b == rtti_binfo)
+ break;
+ }
+ }
+ else
{
- last = b;
- if (TREE_VIA_VIRTUAL (b))
- break;
+ /* 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;
+ tree last, orig_last;
+
+ /* First, look through the bases we are primary to for a
+ virtual base. */
+ for (b = BINFO_PRIMARY_BASE_OF (binfo), orig_last = orig_binfo;
+ b;
+ b = BINFO_PRIMARY_BASE_OF (b))
+ {
+ last = b;
+ if (orig_last)
+ orig_last = BINFO_PRIMARY_BASE_OF (orig_last);
+ 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)))
+ {
+ my_friendly_assert (orig_last, 20010611);
+ primary = last;
+ orig_primary = orig_last;
+ }
}
- /* 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 (vtbl && TREE_CODE (vtbl) == TREE_LIST
+ && TREE_PURPOSE (vtbl) == rtti_binfo)
{
- 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);
+ if (primary == binfo)
+ /* We created this vtable because we met its primary base
+ earlier in the inheritance graph walk of
+ RTTI_BINFO. */
+ return inits;
}
+ else if (primary != binfo)
+ {
+ /* We're the primary of some binfo that we've not yet
+ met in the inheritance graph walk of RTTI_BINFO. We
+ must create that vtable now. */
+ inits = dfs_accumulate_vtbl_inits (primary, orig_primary,
+ rtti_binfo, t, l);
+ vtbl = BINFO_VTABLE (primary);
+ vtbl = TREE_VALUE (vtbl);
+ }
+ else
+ vtbl = NULL;
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
return inits;
-
+
if (!vtbl)
{
tree index;
@@ -7635,19 +7662,16 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
TREE_CONSTANT (vtbl) = 1;
}
- if (!ctor_vtbl_p)
- {
- /* For an ordinary vtable, set BINFO_VTABLE. */
- if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
- inits = NULL_TREE;
- else
- BINFO_VTABLE (binfo) = vtbl;
- }
- else
+ if (ctor_vtbl_p)
/* 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));
+ else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+ inits = NULL_TREE;
+ else
+ /* For an ordinary vtable, set BINFO_VTABLE. */
+ BINFO_VTABLE (binfo) = vtbl;
return inits;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index be457a8..a4dfba0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-06-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ * g++.old-deja/g++.abi/vbase4.C: New test.
+
2001-06-11 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* gcc.c-torture/execute/920501-8.x: New file, sprintf() does not
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C
new file mode 100644
index 0000000..116d79b
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C
@@ -0,0 +1,165 @@
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 9 Jun 2001 <nathan@codesourcery.com>
+
+// Bug 3089. We ICE'd in construction vtables.
+
+int failed;
+
+void fail (int val)
+{
+ if (!failed)
+ failed = val;
+}
+
+struct A
+{
+ virtual ~A();
+ A ();
+ virtual void check (void *whole, void *base);
+};
+
+A::A ()
+{
+ check (this, this);
+}
+A::~A ()
+{
+ check (this, this);
+}
+
+void A::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (1);
+ else if (this != base)
+ fail (2);
+}
+
+struct B
+{
+ virtual ~B ();
+ B ();
+ virtual void check (void *whole, void *base);
+};
+
+B::B ()
+{
+ check (this, this);
+}
+B::~B ()
+{
+ check (this, this);
+}
+void B::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (3);
+ else if (this != base)
+ fail (4);
+}
+
+struct C : virtual public B, virtual public A
+{
+ virtual ~C ();
+ C ();
+ virtual void check (void *whole, void *base);
+};
+C::C ()
+{
+ check (this, this);
+}
+C::~C ()
+{
+ check (this, this);
+}
+void C::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (5);
+ else if (this != base)
+ fail (6);
+ A::check (whole, static_cast <A *> (this));
+ B::check (whole, static_cast <B *> (this));
+}
+
+struct D : virtual public A
+{
+ virtual ~D ();
+ D ();
+ virtual void check (void *whole, void *base);
+};
+D::D ()
+{
+ check (this, this);
+}
+D::~D ()
+{
+ check (this, this);
+}
+void D::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (5);
+ else if (this != base)
+ fail (6);
+ A::check (whole, static_cast <A *> (this));
+}
+
+struct E : virtual public C, virtual public D
+{
+ virtual ~E ();
+ E ();
+ virtual void check (void *whole, void *base);
+};
+E::E ()
+{
+ check (this, this);
+}
+E::~E ()
+{
+ check (this, this);
+}
+void E::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (5);
+ else if (this != base)
+ fail (6);
+ C::check (whole, static_cast <C *> (this));
+ D::check (whole, static_cast <D *> (this));
+}
+
+struct F : virtual public E
+{
+ virtual ~F ();
+ F ();
+ virtual void check (void *whole, void *base);
+};
+F::F ()
+{
+ check (this, this);
+}
+F::~F ()
+{
+ check (this, this);
+}
+void F::check (void *whole, void *base)
+{
+ if (dynamic_cast <void *> (this) != whole)
+ fail (5);
+ else if (this != base)
+ fail (6);
+ E::check (whole, static_cast <F *> (this));
+}
+
+int main ()
+{
+ A a;
+ B b;
+ C c;
+ D d;
+ E e;
+ F f;
+
+ return failed;
+}