From f2606a975aaf67a44b96d8fd18ff13763c834c3c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 17 Mar 2002 19:00:14 -0500 Subject: 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 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/class.c | 23 ++++++++++++++-------- gcc/testsuite/g++.dg/eh/ctor2.C | 42 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/eh/ctor2.C 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 + + PR c++/4460 + * class.c (build_base_path): Virtual base layout is fixed in + in-charge [cd]tors. + 2002-03-17 Neil Booth * 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; +} -- cgit v1.1