On 7/29/24 8:18 AM, Arsen Arsenović wrote:
When register_local_var_uses iterates a BIND_EXPRs BIND_EXPR_VARS, it
fails to account for the fact that FUNCTION_DECLs might be present, and
later passes it to DECL_HAS_VALUE_EXPR_P.  This leads to a tree check
failure in DECL_HAS_VALUE_EXPR_P:

   tree check: expected var_decl or parm_decl or result_decl, have
   function_decl in register_local_var_uses

Much like types and namespaces, we don't need to check FUNCTION_DECLs.
Simply skip them.

If we only want variables (including parms), it seems better to check for them rather than "not all other things"?

PR c++/115906 - [coroutines] missing diagnostic and ICE when co_await used as 
default argument in function declaration

gcc/cp/ChangeLog:

        PR c++/115906
        * coroutines.cc (register_local_var_uses): Skip FUNCTION_DECLs.

gcc/testsuite/ChangeLog:

        PR c++/115906
        * g++.dg/coroutines/coro-function-decl.C: New test.
---
Tested on x86_64-pc-linux-gnu.

OK for trunk?

TIA, have a lovely day.

  gcc/cp/coroutines.cc                          |  1 +
  .../g++.dg/coroutines/coro-function-decl.C    | 19 +++++++++++++++++++
  2 files changed, 20 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/coroutines/coro-function-decl.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 2b16b4814d10..8cd619d7eaed 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -3928,6 +3928,7 @@ register_local_var_uses (tree *stmt, int *do_subtree, 
void *d)
/* Make sure that we only present vars to the tests below. */
          if (TREE_CODE (lvar) == TYPE_DECL
+             || TREE_CODE (lvar) == FUNCTION_DECL
              || TREE_CODE (lvar) == NAMESPACE_DECL)
            continue;
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-function-decl.C b/gcc/testsuite/g++.dg/coroutines/coro-function-decl.C
new file mode 100644
index 000000000000..86140569a76e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/coro-function-decl.C
@@ -0,0 +1,19 @@
+#include <coroutine>
+
+struct task
+{
+  struct promise_type
+  {
+    std::suspend_always initial_suspend () { return {}; }
+    std::suspend_always final_suspend () noexcept { return {}; }
+    void unhandled_exception () {}
+    task get_return_object () noexcept { return {}; }
+    void return_void () {}
+  };
+};
+
+task foo ()
+{
+  void bar ();
+  co_return;
+}

Reply via email to