<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56470>56470</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [bug] clang doesn't implement co_yield transformation correctly (can't defer to co_await support)
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          jacobsa
      </td>
    </tr>
</table>

<pre>
    In N4868, [[expr.yield]/1](https://timsong-cpp.github.io/cppwp/n4868/expr.yield#1) says that `co_yield`ing an expression `e` is equivalent to `co_await`ing the result of calling `yield_value(e)` on the coroutine's promise:

> A *yield-expression* shall appear only within a suspension context of a function ([expr.await]). Let *e* be the operand of the *yield-expression* and *p* be an lvalue naming the promise object of the enclosing coroutine ([dcl.fct.def.coroutine]), then the *yield-expression* is equivalent to the expression `co_­await` *p*`.yield_­value(`*e*`)`.

Here is a minimal program that attempts to make use of this property, by returning a type that the promise supports `co_await`ing from its `yield_value` method ([Compiler Explorer](https://godbolt.org/z/r1sar6sP1)):

```c++
#include <coroutine>

// A type that the promise supports awaiting.
struct SomeAwaitableType {};

struct MyTask{
  struct promise_type {
    MyTask get_return_object() { return {}; }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception();

    // We support co_await'ing objects of type SomeAwaitableType.
    std::suspend_always await_transform(SomeAwaitableType);

    // We support yielding ints, and reuse our support for co_await'ing
    // SomeAwaitableType to implement this.
    auto yield_value(int) { return SomeAwaitableType{}; }
  };
};

MyTask CoAwait() {
  co_await SomeAwaitableType();
}

MyTask CoYield() {
  co_yield 0;
}
```

Clang doesn't transform this correctly, instead giving an error about how `SomeAwaitableType` doesn't have an `await_ready` method:

```
<source>:27:3: error: no member named 'await_ready' in 'SomeAwaitableType'
  co_yield 0;
  ^~~~~~~~
```

It appears that the result of `co_yield` isn't correctly fed to `await_transform`, and is instead treated as if it's the output of a previous call to `await_transform`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJydVk1v4zYQ_TXyhVhBluI4PvjgOAm6QFsU6AJFTwYljWzuUqRKUk7cX99HUrId29ldFJAsmdS8mXnzxVLXh-VnxX6_e7h_SPI1S2aPuOitM-lBkKyT2VOSv0zD42HnXGeTYoUVXE60Vqvtp6rr0q1wu75MhcY6_r92eKqI-XIGlhfTJF8wyw-WuR13LLnPKr2Jm_eZUFvGFfMCZK3Qyu8TbiYso396seeSlGNOD4L8lQs3CLodMYj10jHdsIpL6VexGdA3EO0JPuBeeESAe4lKG907obA8t6wzuhWWvIvZU5KNv8UzW7EkXwWkTyfzsMTsDpoY7zriBqDywF7BhVCMM9vbjlTwo9LK0VuwjLOmV5UL3uUPI9nRE8_yImW_kvPqyOOXFOzUHRmuag_g_35gjP8Cz24QBJcy-M0Ub0eOBh-ZLr9S5UZAUpXU1n9zZGQwr65k2lQuralJT2wFS33CQFh9z6SryAVt7yKMQCbrPFk9jeEcfcBrTJxhf4wh1gd6wpuPZ3oesF_IkFfMGbwWLZfe6a3hbUw67hy1nbPempZ_I9Z7OjwPIqQAqHYH71t5QEa53qiQmMwdOooI5zzavuu0Adp1Sjb4hIm4dZ6F8LAlt9P1QPFat52QZNjzWye1IXOr3La6LrV0qTZb_PsXt5labu7tH9MQisVl1oKacFVJ_uivuJoXAqHuawSsWJ_iWTy_kw0akfQ_cDk4C08H9q0zPVLqT93Syu_wUtIXj5DMH5P5U1I8nisZvv7t8IXbb_6LsMrYsD4o27gRYNhmgwTbktvE8GxiLnsy0V3w7RC2k17mH0cA62pPVrGKFVpvFO3BPnLFCS43w-r_h-Py1Xe4RqgrNKXpraLO_QTsXoua9WqHopZUb6JcqKqHEO13ZHqBIWp_HQPEjvmYz30-RppsyHXP6lWg0h87FfA2Ds3INtq0MOYK5WetCyXh7RLKWV9vvn0ZCtXYm-NnUHPhyBXodcahtEXbSWpD10Fhn7nGe-y-nwqw4CLW117ditK7rL7K8CFR13oVbR_zaZQevbqh7CLGo8YL3L_jVL2BG9xj2Q2EsS2cA64lRxhqTRbZNQdhY3hjT0SbMEgcGZqiUNYRr9lW7Md5bQxCxEu0ErbTr77bXTuEnnfC3_F9mE5YjflkgHg49cWPWtk4j9cWCVKFrlWs8jl-CtzREP-i0NipLVHTGHzk2-z8XE8-hxd-8Qbv8--QiHjPnpP5retjbj-74XRgT430dE55fwDC0IoEHRlnDcyP553LyvOjL9YMQjRGxcFDBxGOpYaFgrHxANG7rh8OIBi-e6F7G05JH6Knk3pZ1ItiwSdOOElLTKqy32I2seoiX06ldmTtiMRdPACNDiFdKx7FcKRAiKD_WAhDzSOfJ72Ry4sJGA-ZlUbXeZFyPz4-YVTE_v8irO0JveRldn83zya75aLmUz5rZk3dVDNelk0xW1DWNFlOPCN6mEhekrTetyTPFb2yAIF3-DkRyzzL82w-nWZ3eZYtUshO6-KO8vvptM5mZXKXUcuFTL0dfjRPzDKYBKIsNqWwzp42Oc48W0WBSo-PTrTTZvmVV7q0fBJUL4Pp_wGLoao0">