Issue |
147150
|
Summary |
`CoyieldExpr` doesn't contain the original AST `-ast-print` returns invalid source.
|
Labels |
new issue
|
Assignees |
|
Reporter |
hanickadot
|
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.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs