}
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)
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
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;
}
expr = build (COND_EXPR, target_type, null_test,
build1 (NOP_EXPR, target_type, integer_zero_node),
expr);
-
+
return expr;
}
--- /dev/null
+// 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;
+}