aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2002-03-17 19:00:14 -0500
committerJason Merrill <jason@gcc.gnu.org>2002-03-17 19:00:14 -0500
commitf2606a975aaf67a44b96d8fd18ff13763c834c3c (patch)
tree1f2093f83283f0979882609633a42e2af9c6f460
parent94ea34195ba4f1db8cab2dbe935ec142a87e2d1f (diff)
downloadgcc-f2606a975aaf67a44b96d8fd18ff13763c834c3c.zip
gcc-f2606a975aaf67a44b96d8fd18ff13763c834c3c.tar.gz
gcc-f2606a975aaf67a44b96d8fd18ff13763c834c3c.tar.bz2
re PR c++/4460 (g++ 3.0.1 seg faults instead of throwing in a complicated inheritance hierarchy)
PR c++/4460 * class.c (build_base_path): Virtual base layout is fixed in in-charge [cd]tors. From-SVN: r50931
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c23
-rw-r--r--gcc/testsuite/g++.dg/eh/ctor2.C42
3 files changed, 63 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fd306a7..d27a93b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2002-03-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/4460
+ * class.c (build_base_path): Virtual base layout is fixed in
+ in-charge [cd]tors.
+
2002-03-17 Neil Booth <neil@daikokuya.demon.co.uk>
* cp-lang.c (LANG_HOOKS_PARSE_FILE): Redefine.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ae8b34e..8923916 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -290,12 +290,9 @@ build_base_path (code, expr, binfo, nonnull)
}
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
- if (fixed_type_p < 0)
- /* Virtual base layout is not fixed, even in ctors and dtors. */
- fixed_type_p = 0;
- if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
+ if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
-
+
if (!want_pointer)
expr = build_unary_op (ADDR_EXPR, expr, 0);
else if (!nonnull)
@@ -303,7 +300,7 @@ build_base_path (code, expr, binfo, nonnull)
offset = BINFO_OFFSET (binfo);
- if (v_binfo && !fixed_type_p)
+ if (v_binfo && fixed_type_p <= 0)
{
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
@@ -324,7 +321,17 @@ build_base_path (code, expr, binfo, nonnull)
size_diffop (offset, BINFO_OFFSET (v_binfo)));
if (!integer_zerop (offset))
- offset = build (code, ptrdiff_type_node, v_offset, offset);
+ v_offset = build (code, ptrdiff_type_node, v_offset, offset);
+
+ if (fixed_type_p < 0)
+ /* Negative fixed_type_p means this is a constructor or destructor;
+ virtual base layout is fixed in in-charge [cd]tors, but not in
+ base [cd]tors. */
+ offset = build (COND_EXPR, ptrdiff_type_node,
+ build (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
+ v_offset,
+ BINFO_OFFSET (binfo));
else
offset = v_offset;
}
@@ -351,7 +358,7 @@ build_base_path (code, expr, binfo, nonnull)
expr = build (COND_EXPR, target_type, null_test,
build1 (NOP_EXPR, target_type, integer_zero_node),
expr);
-
+
return expr;
}
diff --git a/gcc/testsuite/g++.dg/eh/ctor2.C b/gcc/testsuite/g++.dg/eh/ctor2.C
new file mode 100644
index 0000000..e2ebad7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/ctor2.C
@@ -0,0 +1,42 @@
+// PR c++/4460
+// Test that the cleanup for fully-constructed subobjects when a
+// constructor throws gets the right address for a virtual base.
+
+// { dg-do run }
+
+int r;
+void *p;
+
+struct VBase
+{
+ virtual void f () {}
+ VBase() { p = this; }
+ ~VBase() { if (p != this) r = 1; }
+};
+
+struct StreamBase
+{
+ virtual ~StreamBase() {}
+};
+
+struct Stream : public virtual VBase, public StreamBase
+{
+ Stream() {}
+ virtual ~Stream() {}
+};
+
+struct DerivedStream : public Stream
+{
+ DerivedStream() { throw 1; }
+};
+
+int main() {
+
+ try
+ {
+ DerivedStream str;
+ }
+ catch (...) { }
+
+ return r;
+}