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 ();
+}