https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575
Bug ID: 99575 Summary: [coroutines] unexpected move when co_awaiting a nonmoveable object Product: gcc Version: 10.2.1 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: lemourin at gmail dot com Target Milestone: --- ``` #if __has_include(<coroutine>) #include <coroutine> namespace stdx { using std::coroutine_handle; using std::noop_coroutine; using std::suspend_always; using std::suspend_never; } // namespace stdx #elif __has_include(<experimental/coroutine>) #include <experimental/coroutine> namespace stdx { using std::experimental::coroutine_handle; using std::experimental::noop_coroutine; using std::experimental::suspend_always; using std::experimental::suspend_never; } // namespace stdx #else #error "coroutines unsupported" #endif class Task { public: struct promise_type { Task get_return_object() { return Task{}; } stdx::suspend_always initial_suspend() { return {}; } stdx::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() {} void return_void() {} }; bool await_ready() const { return false; } void await_suspend(stdx::coroutine_handle<void> continuation) {} void await_resume() {} }; class NonMoveableTask { public: NonMoveableTask() = default; NonMoveableTask(const NonMoveableTask&) = delete; NonMoveableTask(NonMoveableTask&&) = delete; NonMoveableTask& operator=(const NonMoveableTask&) = delete; NonMoveableTask& operator=(NonMoveableTask&& other) = delete; bool await_ready() const { return false; } void await_suspend(stdx::coroutine_handle<void>) {} void await_resume() {} }; Task Foo(NonMoveableTask* task) { co_await* task; } int main() {} ``` The above code snippet does not compile with gcc with the following error log: ` move.cc: In function ‘Task Foo(NonMoveableTask*)’: move.cc:50:45: error: use of deleted function ‘NonMoveableTask::NonMoveableTask(NonMoveableTask&&)’ 50 | Task Foo(NonMoveableTask* task) { co_await* task; } | ^~~~ move.cc:40:3: note: declared here 40 | NonMoveableTask(NonMoveableTask&&) = delete; | ^~~~~~~~~~~~~~~ make: *** [<builtin>: move] Error 1 ` clang and msvc accept it. If the move constructor is available code compiled with gcc uses it and leaves `task` in a moved from state.