xref: /llvm-project/clang/test/CodeGenCoroutines/coro-symmetric-transfer-03.cpp (revision bf5f2354fa6e3f31a1acea75a229fee54359e279)
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()60 Task 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