Hi Jason, There was some discussion of this in the PR116775 comments. In the end I have matched what clang does in this circumstance, since that seems reasonable - and we may ignore the attributes as needed. tested on x86-64-darwin, powerpc64le-linux, OK for trunk? thanks Iain
--- 8< --- Here we have an expression that is not evaluated but is still seen as potentially-evaluated. We handle this by determining if the operand has side-effects, producing a warning that the assume has been ignored and eliding it. gcc/cp/ChangeLog: * coroutines.cc (analyze_expression_awaits): Elide assume attributes containing await expressions, since these have side effects. Emit a diagnostic that this has been done. gcc/testsuite/ChangeLog: * g++.dg/coroutines/assume.C: New test. --- gcc/cp/coroutines.cc | 13 ++++++++ gcc/testsuite/g++.dg/coroutines/assume.C | 40 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 gcc/testsuite/g++.dg/coroutines/assume.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index bbdc33abc0e..21b1d85b02c 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -3587,6 +3587,19 @@ analyze_expression_awaits (tree *stmt, int *do_subtree, void *d) } *do_subtree = 0; } + else if (!fn && CALL_EXPR_IFN (*stmt) == IFN_ASSUME) + { + tree expr = CALL_EXPR_ARG (*stmt, 0); + if (TREE_SIDE_EFFECTS (expr)) + { + location_t loc_e = cp_expr_location (expr); + location_t loc_s = cp_expr_location (*stmt); + location_t loc_n = make_location (loc_e, loc_s, loc_s); + warning_at (loc_n, OPT_Wattributes,"assumption ignored" + " because it contains possible side-effects"); + *stmt = build_empty_stmt (loc_n); + } + } } break; case CO_YIELD_EXPR: diff --git a/gcc/testsuite/g++.dg/coroutines/assume.C b/gcc/testsuite/g++.dg/coroutines/assume.C new file mode 100644 index 00000000000..ad979b4956e --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/assume.C @@ -0,0 +1,40 @@ +// { dg-additional-options "-fsyntax-only -Wattributes" } + +#include <coroutine> + +struct awaitable { + awaitable (int n) : delay{n} {} + + constexpr bool await_ready () const noexcept { return false; } + auto await_suspend (std::coroutine_handle<> h) const { + __builtin_abort (); + return false; + } + int await_resume() const noexcept { + return delay; + } + + int delay; +}; + +struct Task { + struct promise_type { + promise_type() = default; + Task get_return_object() { return {}; } + std::suspend_never initial_suspend() { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + void unhandled_exception() {} + void return_void () {} + awaitable yield_value (int v) { return {v}; } + }; +}; + +int h () { return 5; } + +Task foo() noexcept { + int x = 5; + [[assume (x == 5)]]; + [[assume (co_await awaitable{10})]]; // { dg-warning {assumption ignored because it contains possible side-effects} } + [[assume ((h(),co_await awaitable{11}))]]; // { dg-warning {assumption ignored because it contains possible side-effects} } + co_return; +} -- 2.39.2 (Apple Git-143)