re PR c++/4460 (g++ 3.0.1 seg faults instead of throwing in a complicated inheritance...
authorJason Merrill <jason@redhat.com>
Mon, 18 Mar 2002 00:00:14 +0000 (19:00 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 18 Mar 2002 00:00:14 +0000 (19:00 -0500)
        PR c++/4460
        * class.c (build_base_path): Virtual base layout is fixed in
        in-charge [cd]tors.

From-SVN: r50931

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/g++.dg/eh/ctor2.C [new file with mode: 0644]

index fd306a7..d27a93b 100644 (file)
@@ -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.
index ae8b34e..8923916 100644 (file)
@@ -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 (file)
index 0000000..e2ebad7
--- /dev/null
@@ -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;
+}