<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/147150>147150</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
`CoyieldExpr` doesn't contain the original AST `-ast-print` returns invalid source.
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
hanickadot
</td>
</tr>
</table>
<pre>
Following code when parsed and emitted with `-ast-print` returns wrong result:
```c++
simple_coro<int> coro_test() {
co_yield 2001;
co_return 2010;
co_await my_awaitable{2061};
}
```
Result printed by clang is: (with fixed formatting
```c++
simple_coro<int> coro_test() {
co_yield __promise.yield_value(2001); // <-- ERROR HERE
co_return 2010;
co_await my_awaitable{2061};
}
```
Expected result:
```c++
simple_coro<int> coro_test() {
co_yield 2001;
co_return 2010;
co_await my_awaitable{2061};
}
```
Notice the `co_yield __promise.yield_value(1997);` it contains call to `__promise.yield_value` function, this helper AST is generated in `SemaCoroutine.cpp` in `Sema::ActOnCoyieldExpr`:
```c++
// Build yield_value call.
ExprResult Awaitable = buildPromiseCall(
*this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
if (Awaitable.isInvalid())
return ExprError();
// Build 'operator co_await' call.
Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
if (Awaitable.isInvalid())
return ExprError();
```
There is Operand slot inside `CoroutineSuspendExpr` which should contain original expression, but the function `BuildCoyieldExpr` is already getting modified AST.
Full source code to repeat the problem:
```c++
#include <coroutine>
struct my_awaitable {
int value;
bool await_ready() const {
return true;
}
void await_suspend(std::coroutine_handle<void>) {
}
int await_resume() const {
return value;
}
};
template <typename T> struct simple_coro {
struct promise_type {
T value{0};
constexpr auto initial_suspend() const noexcept {
return std::suspend_never{};
}
constexpr auto final_suspend() const noexcept {
return std::suspend_never{};
}
constexpr void return_value(int v) noexcept {
value = v;
}
constexpr auto yield_value(T v) noexcept {
value = v;
return std::suspend_always{};
}
std::coroutine_handle<promise_type> get_return_object() {
return std::coroutine_handle<promise_type>::from_promise(*this);
}
constexpr void unhandled_exception() const noexcept {
}
};
private:
std::coroutine_handle<promise_type> handle;
public:
constexpr simple_coro(std::coroutine_handle<promise_type> h) noexcept: handle{h} { }
constexpr ~simple_coro() noexcept {
handle.destroy();
}
constexpr int get() {
return handle.promise().value;
}
};
simple_coro<int> coro_test() {
co_yield 2001;
co_return 2010;
co_await my_awaitable{2061};
}
```
Maybe this is fine, but AFAIK clang is trying to represent the AST so the original source code is recoverable and this breaks it.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUV99v4joT_WvMy6gocYCUBx4oBX2r78d-avuOHGcgvmvsyHagvNy__WriEMLdtrt7tXelW0UqEPvMnOOTmYnwXu0N4oJNH9j0cSSaUFm3qIRR8osobRgVtjwvNlZre1JmD9KWCKcKDdTCeSxBmBLwoELAEk4qVMBmyZ3w4a52ygQ2S8BhaJzxcHLW7MGhb3Rg2ZIl7TVL4iUZf6ArWXp1qDVupXWWZSsCydZA37YBfWD8nvE5sJyWAki7PSvUJfAkSVnW_xiDAk_SZPCrOAkV4HCOH0ShkeUPPJmlLH-My-jDIKuY5FObM7SMsITiDFILswflWbYExu9b4jv1iiXsrDuIEJTZ_0x2223t7EF5HLfft0ehG2T8vmXN5yx7AMY3jG-AZau7O1g_PX1-gn-tn9Z_iyDr1xolSXFzmv-Eo_yfDUoihArJqN_UN53P86gvOVkFkNYEoYwHKbSGYAnl7c2zBHaNkUFZw_gKQqU8VKhrdLB8fgHlYY8GnSAZlSGcZzyIlXW2CcrgWNZ1G7O_RSpny6UMn83KtpHWr7UjZu_JDxdTPDRKlzDIrk1_3C4hkM7gy4uUwLJHKGjT_yOzldCajos20B_jSyJExPYYVo3b9FTpTO9Ytu6ZdBC09j9W0j_G-Y3MnH5cdzpTCLWjp6pPZ6z8J3MUWpURnq6YSecN4rB2zrrufjz_rwRgPLc1SW5dbyHG84EYbyjwuduxsu36ixJXAZ4HzK4p7zFck_2ptG4N_VKhQ3JTm6cpwWsbQBmvytbi_TE8N75Gc_EMnColK_CVbXR5cTVYp_bKCA34Wjv0vvNu0YT2ibn4mXBbRW99SFkI7VCUZ3IF1UA42FLtFJbk-XHMeNNoDd42TmJsJ8GCwxpFDFI7W2g8vGtqxjNlpG6IXraSF3osW0d4H1wjbytDX2KUCRA9151IYa2Gdt22zbsrSdIaH_pd_XkEd90ZqwvA0aqyQ_BRYcbvfSjj09qnt62EKTWybEUbKNlB5QO4gaQsLzn55oAfJ3XDp6t5fQlMlgEPtRahFSucazTigPBCdbgTalCjO3CWzLt7XV3b0sbrTZbMX7qw-UMyDBZvtomSg0A0wYIyKiihB_Jc2RiLrxLrcAPOknnHrdex27s1eERHa69B2x2R9lvRd-TnXx-7tUVE6ptJ6z6K_6fIsaTGukxl5_id1G5b1ctfwH6frNAncfYfs_3I5UPnkNn2GLpGvrXFbyhvm_-76XwbOa7bOXu4dOFhdZ5_50k1JuKX26he38k-9EqPN3gEaqeOIuBlwP0hkS43LlBNoZXska4pD8eqj4vNVxGGFqHhtVuZP1QsfyR20LO6xvv9NuAbNouCRLBxiT44e77txfM3cOmB6PvkDVLngw5weLDz8aDgXWEHJ_AjQ-cvmTn_K84FxgFQeSpIeGmqy83y07_7lwkI7kw9M_ZDhx5NbIk0L3rbfuw79LCBKg8OpT2ia7sdTQFttMKh-OJBhfGoXGTlPJuLES7SfJrmfDbJ01G1EPeY79KyKMQk46mUOz6bitmsuJ8USZ5NkpFa8IRPkzyZppNJmqbjsriXZTGVUpazSZpxNknwIJQea308jK3bj5T3DS7SSZ5Ok5EWBWrfvl9ybvAE7V2a-aaPI7egTXdFs_dskmjlg7_CBBU0LtoR5mbKKC16w3jeD-O3wpBY776DqjhvdeqNR43TiyqEml7k4qi4V6FqirG0B8Y3lEv37652NtatTcvAM77pKB4X_I8AAAD__1KquMk">