aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2024-07-18 18:16:49 +0200
committerThomas Koenig <tkoenig@gcc.gnu.org>2024-07-28 19:05:57 +0200
commit3109e8c991762031b108ae2a022472b989cbb465 (patch)
treec286edc060fcf5784140a67ff984eef65570463b
parent706ff59b9292cba61c36e9377fdaf5fa98da9d9e (diff)
downloadgcc-3109e8c991762031b108ae2a022472b989cbb465.zip
gcc-3109e8c991762031b108ae2a022472b989cbb465.tar.gz
gcc-3109e8c991762031b108ae2a022472b989cbb465.tar.bz2
cp/coroutines: do not rewrite parameters in unevaluated contexts
It is possible to use parameters of a parent function of a lambda in unevaluated contexts without capturing them. By not capturing them, we work around the usual mechanism we use to prevent rewriting captured parameters. Prevent this by simply skipping rewrites in unevaluated contexts. Those won't mind the value not being present anyway. This prevents an ICE during parameter substitution. In the testcase from the PR, the rewriting machinery finds a param in the body of the coroutine, which it did not previously encounter while processing the coroutine declaration, and that does not have a DECL_VALUE_EXPR, and fails. gcc/cp/ChangeLog: PR c++/111728 * coroutines.cc (rewrite_param_uses): Skip unevaluated subexpressions. gcc/testsuite/ChangeLog: PR c++/111728 * g++.dg/coroutines/pr111728.C: New test.
-rw-r--r--gcc/cp/coroutines.cc7
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr111728.C29
2 files changed, 36 insertions, 0 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index e8f028d..4ddd986 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -3755,6 +3755,13 @@ rewrite_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
return cp_walk_tree (&t, rewrite_param_uses, d, NULL);
}
+ if (unevaluated_p (TREE_CODE (*stmt)))
+ {
+ /* No odr-uses in unevaluated operands. */
+ *do_subtree = 0;
+ return NULL_TREE;
+ }
+
if (TREE_CODE (*stmt) != PARM_DECL)
return NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/coroutines/pr111728.C b/gcc/testsuite/g++.dg/coroutines/pr111728.C
new file mode 100644
index 0000000..c1fee4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr111728.C
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// https://gcc.gnu.org/PR111728
+#include <coroutine>
+struct promise;
+struct coroutine : std::coroutine_handle<promise>
+{
+ using promise_type = ::promise;
+ bool await_ready() { return false; }
+ void await_suspend(coroutine_handle h) {}
+ int await_resume() { return {} ;}
+};
+struct promise
+{
+ coroutine get_return_object() { return {coroutine::from_promise(*this)}; }
+ std::suspend_always initial_suspend() noexcept { return {}; }
+ std::suspend_always final_suspend() noexcept { return {}; }
+ void return_void() {}
+ void unhandled_exception() {}
+};
+coroutine
+write_fields() {
+ int static_buffer[10];
+ co_await [](auto)
+ -> coroutine
+ {
+ if (sizeof(static_buffer));
+ co_return;
+ }(0);
+}