https://gcc.gnu.org/g:074a89e4c5f9b237176626d464fcc494389905f6

commit r14-11716-g074a89e4c5f9b237176626d464fcc494389905f6
Author: Arsen Arsenović <ar...@aarsen.me>
Date:   Thu Jul 18 18:16:49 2024 +0200

    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.
    
    (cherry picked from commit 1a37d6b732506f8c3f9e9452c9dc6a456f25397b)

Diff:
---
 gcc/cp/coroutines.cc                       |  7 +++++++
 gcc/testsuite/g++.dg/coroutines/pr111728.C | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 882831ce2ec9..200789e89102 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 000000000000..c1fee4b36a10
--- /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);
+}

Reply via email to