Patchwork C++ PATCH for c++/41449 (EH cleanup of partially-aggregate-initialized objects)

login
register
mail settings
Submitter Jason Merrill
Date Oct. 20, 2011, 7:17 p.m.
Message ID <4EA073DC.8050406@redhat.com>
Download mbox | patch
Permalink /patch/120864/
State New
Headers show

Comments

Jason Merrill - Oct. 20, 2011, 7:17 p.m.
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.

Patch

commit 7d32708956095f3ddb6698fee9fa092f649d72d4
Author: Jason Merrill <jason@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 ();
+}