diff options
author | Arsen Arsenović <arsen@aarsen.me> | 2024-09-03 17:14:13 +0200 |
---|---|---|
committer | Arsen Arsenović <arsen@gcc.gnu.org> | 2024-09-04 16:46:34 +0200 |
commit | 7b7ad3f4b2455072f42e7884b93fd96ebb920bc8 (patch) | |
tree | a671a83ed3c5d751f72757826ff7c3e262098dbb /gcc | |
parent | 97e011a472e16ddab67d7374ee9c3db040b62798 (diff) | |
download | gcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.zip gcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.tar.gz gcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/internal-fn.def | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/coroutines/pr106973.C | 22 |
2 files changed, 23 insertions, 1 deletions
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 75b527b..23b4ab0 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 0000000..6db6cbc --- /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; +} |