69 lines · cpp
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 %s3 4#include "Inputs/coroutine.h"5 6struct Task {7 struct promise_type {8 struct FinalAwaiter {9 bool await_ready() const noexcept { return false; }10 template <typename PromiseType>11 std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {12 return h.promise().continuation;13 }14 void await_resume() noexcept {}15 };16 Task get_return_object() noexcept {17 return std::coroutine_handle<promise_type>::from_promise(*this);18 }19 std::suspend_always initial_suspend() noexcept { return {}; }20 FinalAwaiter final_suspend() noexcept { return {}; }21 void unhandled_exception() noexcept {}22 void return_value(int x) noexcept {23 _value = x;24 }25 std::coroutine_handle<> continuation;26 int _value;27 };28 29 Task(std::coroutine_handle<promise_type> handle) : handle(handle) {}30 ~Task() {31 if (handle)32 handle.destroy();33 }34 35 struct Awaiter {36 std::coroutine_handle<promise_type> handle;37 Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {}38 bool await_ready() const noexcept { return false; }39 std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept {40 handle.promise().continuation = continuation;41 return handle;42 }43 int await_resume() noexcept {44 int ret = handle.promise()._value;45 handle.destroy();46 return ret;47 }48 };49 50 auto operator co_await() {51 auto handle_ = handle;52 handle = nullptr;53 return Awaiter(handle_);54 }55 56private:57 std::coroutine_handle<promise_type> handle;58};59 60Task task0() {61 co_return 43;62}63 64// CHECK-LABEL: define{{.*}} void @_Z5task0v.resume65// This checks we are still in the scope of the current function.66// CHECK-NOT: {{^}}}67// CHECK: musttail call fastcc void68// CHECK-NEXT: ret void69