1 // This tests that the symmetric transfer at the final suspend point could happen successfully. 2 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s 3 4 #include "Inputs/coroutine.h" 5 6 struct Task { 7 struct promise_type { 8 struct FinalAwaiter { await_readyTask::promise_type::FinalAwaiter9 bool await_ready() const noexcept { return false; } 10 template <typename PromiseType> await_suspendTask::promise_type::FinalAwaiter11 std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept { 12 return h.promise().continuation; 13 } await_resumeTask::promise_type::FinalAwaiter14 void await_resume() noexcept {} 15 }; get_return_objectTask::promise_type16 Task get_return_object() noexcept { 17 return std::coroutine_handle<promise_type>::from_promise(*this); 18 } initial_suspendTask::promise_type19 std::suspend_always initial_suspend() noexcept { return {}; } final_suspendTask::promise_type20 FinalAwaiter final_suspend() noexcept { return {}; } unhandled_exceptionTask::promise_type21 void unhandled_exception() noexcept {} return_valueTask::promise_type22 void return_value(int x) noexcept { 23 _value = x; 24 } 25 std::coroutine_handle<> continuation; 26 int _value; 27 }; 28 TaskTask29 Task(std::coroutine_handle<promise_type> handle) : handle(handle) {} ~TaskTask30 ~Task() { 31 if (handle) 32 handle.destroy(); 33 } 34 35 struct Awaiter { 36 std::coroutine_handle<promise_type> handle; AwaiterTask::Awaiter37 Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {} await_readyTask::Awaiter38 bool await_ready() const noexcept { return false; } await_suspendTask::Awaiter39 std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept { 40 handle.promise().continuation = continuation; 41 return handle; 42 } await_resumeTask::Awaiter43 int await_resume() noexcept { 44 int ret = handle.promise()._value; 45 handle.destroy(); 46 return ret; 47 } 48 }; 49 operator co_awaitTask50 auto operator co_await() { 51 auto handle_ = handle; 52 handle = nullptr; 53 return Awaiter(handle_); 54 } 55 56 private: 57 std::coroutine_handle<promise_type> handle; 58 }; 59 task0()60Task task0() { 61 co_return 43; 62 } 63 64 // CHECK-LABEL: define{{.*}} void @_Z5task0v.resume 65 // This checks we are still in the scope of the current function. 66 // CHECK-NOT: {{^}}} 67 // CHECK: musttail call fastcc void 68 // CHECK-NEXT: ret void 69