public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6333] c++: destroy retval on throwing cleanup in try [PR33799]
@ 2022-01-07 0:26 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-01-07 0:26 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:b10e031458d541f794dfaa08ba606487603a4bb6
commit r12-6333-gb10e031458d541f794dfaa08ba606487603a4bb6
Author: Jason Merrill <jason@redhat.com>
Date: Wed Jan 5 17:01:12 2022 -0500
c++: destroy retval on throwing cleanup in try [PR33799]
My earlier attempt to fix this bug didn't handle the case where both the
return and the throwing cleanup are within a try-block that catches and
discards the exception. Fixed by adding the retval cleanup to any
try-blocks as well as the function body. PR102191 pointed out that we also
weren't handling templates properly, so I moved the call out of the parser.
PR c++/33799
PR c++/102191
gcc/cp/ChangeLog:
* except.c (maybe_splice_retval_cleanup): Check
current_binding_level.
* semantics.c (do_poplevel): Call it here.
* parser.c (cp_parser_compound_statement): Not here.
gcc/testsuite/ChangeLog:
* g++.dg/eh/return1.C: Add temporary in try block case.
* g++.dg/cpp2a/constexpr-dtor11.C: New test.
Diff:
---
gcc/cp/except.c | 29 +++++++++-----
gcc/cp/parser.c | 3 --
gcc/cp/semantics.c | 2 +
gcc/testsuite/g++.dg/cpp2a/constexpr-dtor11.C | 12 ++++++
gcc/testsuite/g++.dg/eh/return1.C | 56 ++++++++++++++++++++++++---
5 files changed, 84 insertions(+), 18 deletions(-)
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 5c7eeff9035..bcd9f84431b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1294,26 +1294,35 @@ maybe_set_retval_sentinel ()
current_retval_sentinel, boolean_true_node);
}
-/* COMPOUND_STMT is the STATEMENT_LIST for the current function body. If
- current_retval_sentinel was set in this function, wrap the body in a
- CLEANUP_STMT to destroy the return value on throw. */
+/* COMPOUND_STMT is the STATEMENT_LIST for some block. If COMPOUND_STMT is the
+ current function body or a try block, and current_retval_sentinel was set in
+ this function, wrap the block in a CLEANUP_STMT to destroy the return value
+ on throw. */
void
maybe_splice_retval_cleanup (tree compound_stmt)
{
- /* If need_retval_cleanup set current_retval_sentinel, wrap the function body
- in a CLEANUP_STMT to handle destroying the return value. */
- if (!DECL_CONSTRUCTOR_P (current_function_decl)
+ /* If we need a cleanup for the return value, add it in at the same level as
+ pushdecl_outermost_localscope. And also in try blocks. */
+ bool function_body
+ = (current_binding_level->level_chain
+ && current_binding_level->level_chain->kind == sk_function_parms);
+
+ if ((function_body || current_binding_level->kind == sk_try)
+ && !DECL_CONSTRUCTOR_P (current_function_decl)
&& !DECL_DESTRUCTOR_P (current_function_decl)
&& current_retval_sentinel)
{
location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
-
- /* Add a DECL_EXPR for current_retval_sentinel. */
tree_stmt_iterator iter = tsi_start (compound_stmt);
tree retval = DECL_RESULT (current_function_decl);
- tree decl_expr = build_stmt (loc, DECL_EXPR, current_retval_sentinel);
- tsi_link_before (&iter, decl_expr, TSI_SAME_STMT);
+
+ if (function_body)
+ {
+ /* Add a DECL_EXPR for current_retval_sentinel. */
+ tree decl_expr = build_stmt (loc, DECL_EXPR, current_retval_sentinel);
+ tsi_link_before (&iter, decl_expr, TSI_SAME_STMT);
+ }
/* Skip past other decls, they can't contain a return. */
while (TREE_CODE (tsi_stmt (iter)) == DECL_EXPR)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6b91a0ce491..f40e707d47c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12751,9 +12751,6 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, in_statement_expr);
- if (function_body)
- maybe_splice_retval_cleanup (compound_stmt);
-
/* Consume the `}'. */
braces.require_close (parser);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 58f45e9c3e3..645654768e3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -624,6 +624,8 @@ do_poplevel (tree stmt_list)
{
tree block = NULL;
+ maybe_splice_retval_cleanup (stmt_list);
+
if (stmts_are_full_exprs_p ())
block = poplevel (kept_level_p (), 1, 0);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor11.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor11.C
new file mode 100644
index 00000000000..e371f89a10e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor11.C
@@ -0,0 +1,12 @@
+// PR c++/102191
+// { dg-do compile { target c++20 } }
+
+struct X {
+ struct A {
+ constexpr ~A() noexcept(false) { }
+ };
+
+ constexpr A operator()(auto...) { return {}; }
+};
+
+void f() { []() consteval { X{}(); }(); }
diff --git a/gcc/testsuite/g++.dg/eh/return1.C b/gcc/testsuite/g++.dg/eh/return1.C
index 5ef2f1dee85..ac2225405da 100644
--- a/gcc/testsuite/g++.dg/eh/return1.C
+++ b/gcc/testsuite/g++.dg/eh/return1.C
@@ -11,13 +11,16 @@ int c, d;
#define THROWS
#endif
+extern "C" int printf (const char *, ...);
+#define DEBUG // printf ("%p %s\n", this, __PRETTY_FUNCTION__)
+
struct X
{
- X(bool throws) : throws_(throws) { ++c; }
- X(const X& x) : throws_(x.throws_) { ++c; }
+ X(bool throws) : throws_(throws) { ++c; DEBUG; }
+ X(const X& x); // not defined
~X() THROWS
{
- ++d;
+ ++d; DEBUG;
if (throws_) { throw 1; }
}
private:
@@ -42,6 +45,40 @@ void h()
#endif
}
+X i()
+{
+ try {
+ X x(true);
+ return X(false);
+ } catch(...) {}
+ return X(false);
+}
+
+X j()
+{
+ try {
+ return X(true),X(false);
+ } catch(...) {}
+ return X(false);
+}
+
+template <class T>
+T k()
+{
+ try {
+ return T(true),T(false);
+ } catch (...) {}
+ return T(true),T(false);
+}
+
+X l() try { return X(true),X(false); }
+ catch (...) { return X(true),X(false); }
+
+template <class T>
+T m()
+ try { return T(true),T(false); }
+ catch (...) { return T(true),T(false); }
+
int main()
{
try { f(); }
@@ -53,6 +90,15 @@ int main()
try { h(); }
catch (...) {}
- if (c != d)
- throw;
+ try { i(); }
+ catch (...) {}
+
+ try { j(); } catch (...) {}
+
+ try { k<X>(); } catch (...) {}
+
+ try { l(); } catch (...) {}
+ try { m<X>(); } catch (...) {}
+
+ return c - d;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-01-07 0:26 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-07 0:26 [gcc r12-6333] c++: destroy retval on throwing cleanup in try [PR33799] Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).