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

Reply via email to