From: Iain Sandoe Date: Mon, 9 Jun 2025 10:26:01 +0000 (+0100) Subject: c++,coroutines: Handle await expressions in assume attributes. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=892892b455ba8be6a0bf373f338b251876ec4623;p=thirdparty%2Fgcc.git c++,coroutines: Handle await expressions in assume attributes. 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. (cherry picked from commit 4ff09eb3422c525d514c869c7e0366fd5b40b561) --- diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 17eed9d2559..0443f5170ed 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -3496,6 +3496,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 an await-expression"); + *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..d007386f6bc --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/assume.C @@ -0,0 +1,40 @@ +// { dg-additional-options "-fsyntax-only -Wattributes" } + +#include + +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 an await-expression} } + [[assume ((h(),co_await awaitable{11}))]]; // { dg-warning {assumption ignored because it contains an await-expression} } + co_return; +}