From 694b942a179f5fbaee882a5e619e5bbaf64b4d11 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Arsen=20Arsenovi=C4=87?= Date: Wed, 28 Aug 2024 21:59:18 +0200 Subject: [PATCH] c++/coro: prevent ICV_STATEMENT diagnostics in temp promotion [PR116502] If such a diagnostic is necessary, it has already been emitted, otherwise, it is not correct and emitting it here is inactionable by the user, and bogus. PR c++/116502 gcc/cp/ChangeLog: * coroutines.cc (maybe_promote_temps): Convert temporary initializers to void without complaining. gcc/testsuite/ChangeLog: * g++.dg/coroutines/maybe-unused-1.C: New test. * g++.dg/coroutines/pr116502.C: New test. (cherry picked from commit 05e4f07cad1eacf869c10622cae2a9cdee3b6a7a) --- gcc/cp/coroutines.cc | 12 +++++-- .../g++.dg/coroutines/maybe-unused-1.C | 33 +++++++++++++++++++ gcc/testsuite/g++.dg/coroutines/pr116502.C | 33 +++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/maybe-unused-1.C create mode 100644 gcc/testsuite/g++.dg/coroutines/pr116502.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index e0e312265c10..de160bad1a20 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -3323,7 +3323,13 @@ maybe_promote_temps (tree *stmt, void *d) to run the initializer. If the initializer is a conditional expression, we need to collect and declare any promoted variables nested within it. DTORs for such - variables must be run conditionally too. */ + variables must be run conditionally too. + + Since here we're synthetically processing code here, we've already + emitted any Wunused-result warnings. Below, however, we call + finish_expr_stmt, which will convert its operand to void, and could + result in such a diagnostic being emitted. To avoid that, convert to + void ahead of time. */ if (t->var) { tree var = t->var; @@ -3333,7 +3339,7 @@ maybe_promote_temps (tree *stmt, void *d) if (TREE_CODE (t->init) == COND_EXPR) process_conditional (t, vlist); else - finish_expr_stmt (t->init); + finish_expr_stmt (convert_to_void (t->init, ICV_STATEMENT, tf_none)); if (tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error)) { tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var); @@ -3352,7 +3358,7 @@ maybe_promote_temps (tree *stmt, void *d) if (TREE_CODE (t->init) == COND_EXPR) process_conditional (t, vlist); else - finish_expr_stmt (t->init); + finish_expr_stmt (convert_to_void (t->init, ICV_STATEMENT, tf_none)); if (expr_list) { if (TREE_CODE (expr_list) != STATEMENT_LIST) diff --git a/gcc/testsuite/g++.dg/coroutines/maybe-unused-1.C b/gcc/testsuite/g++.dg/coroutines/maybe-unused-1.C new file mode 100644 index 000000000000..68d59d83e8eb --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/maybe-unused-1.C @@ -0,0 +1,33 @@ +// https://gcc.gnu.org/PR116502 +#include + +struct SuspendNever { + bool await_ready() noexcept; + void await_suspend(std::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct Coroutine; + +struct PromiseType { + Coroutine get_return_object(); + SuspendNever initial_suspend(); + SuspendNever final_suspend() noexcept; + void return_void(); + void unhandled_exception(); +}; + +struct Coroutine { + using promise_type = PromiseType; +}; + +struct Awaiter { + bool await_ready(); + void await_suspend(std::coroutine_handle<>); + [[nodiscard]] int& await_resume(); +}; + +Coroutine foo() +{ + co_await Awaiter {}; // { dg-warning "Wunused-result" } +} diff --git a/gcc/testsuite/g++.dg/coroutines/pr116502.C b/gcc/testsuite/g++.dg/coroutines/pr116502.C new file mode 100644 index 000000000000..95cc0bc8a983 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr116502.C @@ -0,0 +1,33 @@ +// https://gcc.gnu.org/PR116502 +#include + +struct SuspendNever { + bool await_ready() noexcept; + void await_suspend(std::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct Coroutine; + +struct PromiseType { + Coroutine get_return_object(); + SuspendNever initial_suspend(); + SuspendNever final_suspend() noexcept; + void return_void(); + void unhandled_exception(); +}; + +struct Coroutine { + using promise_type = PromiseType; +}; + +struct Awaiter { + bool await_ready(); + void await_suspend(std::coroutine_handle<>); + [[nodiscard]] int& await_resume(); +}; + +Coroutine foo() +{ + (void)co_await Awaiter {}; +} -- 2.47.2