https://gcc.gnu.org/g:7b7ad3f4b2455072f42e7884b93fd96ebb920bc8

commit r15-3453-g7b7ad3f4b2455072f42e7884b93fd96ebb920bc8
Author: Arsen Arsenović <ar...@aarsen.me>
Date:   Tue Sep 3 17:14:13 2024 +0200

    coros: mark .CO_YIELD as LEAF [PR106973]
    
    We rely on .CO_YIELD calls being followed by an assignment (optionally)
    and then a switch/if in the same basic block.  This implies that a
    .CO_YIELD can never end a block.  However, since a call to .CO_YIELD is
    still a call, if the function containing it calls setjmp, GCC thinks
    that the .CO_YIELD can introduce abnormal control flow, and generates an
    edge for the call.
    
    We know this is not the case; .CO_YIELD calls get removed quite early on
    and have no effect, and result in no other calls, so .CO_YIELD can be
    considered a leaf function, preventing generating an edge when calling
    it.
    
    PR c++/106973 - coroutine generator and setjmp
    
            PR c++/106973
    
    gcc/ChangeLog:
    
            * internal-fn.def (CO_YIELD): Mark as ECF_LEAF.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/pr106973.C: New test.

Diff:
---
 gcc/internal-fn.def                        |  2 +-
 gcc/testsuite/g++.dg/coroutines/pr106973.C | 22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 75b527b1ab0..23b4ab02b30 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -569,7 +569,7 @@ DEF_INTERNAL_FN (DIVMOD, ECF_CONST | ECF_LEAF, NULL)
 
 /* For coroutines.  */
 DEF_INTERNAL_FN (CO_ACTOR, ECF_NOTHROW | ECF_LEAF, NULL)
-DEF_INTERNAL_FN (CO_YIELD, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (CO_YIELD, ECF_NOTHROW | ECF_LEAF, NULL)
 DEF_INTERNAL_FN (CO_SUSPN, ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (CO_FRAME, ECF_PURE | ECF_NOTHROW | ECF_LEAF, NULL)
 
diff --git a/gcc/testsuite/g++.dg/coroutines/pr106973.C 
b/gcc/testsuite/g++.dg/coroutines/pr106973.C
new file mode 100644
index 00000000000..6db6cbc7711
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr106973.C
@@ -0,0 +1,22 @@
+// https://gcc.gnu.org/PR106973
+// { dg-require-effective-target indirect_jumps }
+#include <coroutine>
+#include <setjmp.h>
+
+struct generator;
+struct generator_promise {
+  generator get_return_object();
+  std::suspend_always initial_suspend();
+  std::suspend_always final_suspend() noexcept;
+  std::suspend_always yield_value(int);
+  void unhandled_exception();
+};
+
+struct generator {
+  using promise_type = generator_promise;
+};
+jmp_buf foo_env;
+generator foo() {
+  setjmp(foo_env);
+  co_yield 1;
+}

Reply via email to