The C++ standard says that if an exception is thrown during initialization of a class, any fully-constructed subobjects are destroyed. We already handled that properly for objects initialized via constructor, but we weren't handling it properly for aggregate initialization. This patch adds the necessary EH cleanups for during initialization; conveniently, just using push_eh_cleanup works here because we were already doing push/pop_stmt_list around the initialization as a whole.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 7d32708956095f3ddb6698fee9fa092f649d72d4
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Oct 20 15:00:49 2011 -0400

    	PR c++/41449
    	* typeck2.c (split_nonconstant_init_1): Handle EH cleanup of
    	initialized subobjects.

diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 3accab6..580f669 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -567,6 +567,13 @@ split_nonconstant_init_1 (tree dest, tree init)
 	      code = build2 (INIT_EXPR, inner_type, sub, value);
 	      code = build_stmt (input_location, EXPR_STMT, code);
 	      add_stmt (code);
+	      if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+		{
+		  code = (build_special_member_call
+			  (sub, complete_dtor_identifier, NULL, inner_type,
+			   LOOKUP_NORMAL, tf_warning_or_error));
+		  finish_eh_cleanup (code);
+		}
 
 	      num_split_elts++;
 	    }
diff --git a/gcc/testsuite/g++.dg/eh/partial1.C b/gcc/testsuite/g++.dg/eh/partial1.C
new file mode 100644
index 0000000..db73177
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/partial1.C
@@ -0,0 +1,37 @@
+// PR c++/41449
+// { dg-do run }
+
+struct A
+{
+  A() {}
+  A(const A&) { throw 1; }
+};
+
+int bs;
+struct B
+{
+  B() { ++bs; }
+  B(const B&) { ++bs; }
+  ~B() { --bs; }
+};
+
+struct C
+{
+  B b1;
+  A a;
+  B b2;
+};
+
+int main()
+{
+  {
+    B b1, b2;
+    A a;
+
+    try {
+      C c = { b1, a, b2 };
+    } catch (...) {}
+  }
+  if (bs != 0)
+    __builtin_abort ();
+}

Reply via email to