c++: new (nothrow) array cleanup [PR104007]
authorJason Merrill <jason@redhat.com>
Mon, 17 Jan 2022 22:08:03 +0000 (17:08 -0500)
committerJason Merrill <jason@redhat.com>
Tue, 18 Jan 2022 17:42:52 +0000 (12:42 -0500)
For this testcase, the cleanup that is supposed to happen if initialization
throws was wrongly being run on the normal control path as well.  This turns
out to be because the EH-only handling in gimple_push_cleanup didn't apply
to conditional cleanups such as we have for nothrow new, since we check
whether the result is non-null before proceeding with the initialization.

PR c++/104007

gcc/ChangeLog:

* gimplify.cc (gimple_push_cleanup): Handle eh_only in conditional
context.

gcc/testsuite/ChangeLog:

* g++.dg/eh/new2.C: New test.

gcc/gimplify.cc
gcc/testsuite/g++.dg/eh/new2.C [new file with mode: 0644]

index ab9874a..bf2f60c 100644 (file)
@@ -6885,6 +6885,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
          cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
          gimplify_stmt (&cleanup, &cleanup_stmts);
          wce = gimple_build_wce (cleanup_stmts);
+         gimple_wce_set_cleanup_eh_only (wce, eh_only);
 
          gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
          gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
diff --git a/gcc/testsuite/g++.dg/eh/new2.C b/gcc/testsuite/g++.dg/eh/new2.C
new file mode 100644 (file)
index 0000000..d4a1abf
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/104007
+// { dg-do run }
+
+extern "C" void abort();
+#include <new>
+
+struct S { ~S() { abort(); } };
+int main() {
+  new (std::nothrow) S[1];
+}