https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127691
Bug ID: 127691
Summary: [coroutines] Both branches of ternary operator is
evaluated with nested co_await's
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: daklishch at gmail dot com
Target Milestone: ---
The following snippet
```
#include <coroutine>
struct Task {
struct promise_type {
int value = 0;
Task get_return_object() { return {
std::coroutine_handle<promise_type>::from_promise(*this) }; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_value(int v) { value = v; }
void unhandled_exception() { }
};
std::coroutine_handle<promise_type> handle;
~Task() { handle.destroy(); }
bool await_ready() { return true; }
void await_suspend(std::coroutine_handle<>) { }
int&& await_resume() { return static_cast<int&&>(handle.promise().value); }
};
struct Try {
int* value;
Try(int&& v) : value(&v) { }
bool await_ready() { return true; }
void await_suspend(std::coroutine_handle<>) { }
int await_resume() { return *value; }
};
int a_calls = 0;
int b_calls = 0;
Task a() { ++a_calls; co_return 1; }
Task b() { ++b_calls; co_return 2; }
int a_foo() { ++a_calls; return 1; }
int b_foo() { ++b_calls; return 2; }
Task test(bool flag)
{
int v = co_await Try { flag ? co_await a() : co_await b() };
co_return v;
}
int main()
{
auto t = test(true);
__builtin_printf("result=%d a_calls=%d b_calls=%d\n",
t.handle.promise().value, a_calls, b_calls);
}
```
produces `result=1 a_calls=1 b_calls=1`, evidently evaluating both branches of
the ternary instead of only the selected one.
CE link: https://godbolt.org/z/69Kfr7WPq