67 lines · cpp
1// This tests that the symmetric transfer at the final suspend point could happen successfully.2// Based on https://github.com/llvm/llvm-project/pull/85271#issuecomment-20075545323// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s4 5#include "Inputs/coroutine.h"6 7struct Task {8 struct promise_type {9 struct FinalAwaiter {10 bool await_ready() const noexcept { return false; }11 template <typename PromiseType>12 std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {13 return h.promise().continuation;14 }15 void await_resume() noexcept {}16 };17 Task get_return_object() noexcept {18 return std::coroutine_handle<promise_type>::from_promise(*this);19 }20 std::suspend_always initial_suspend() noexcept { return {}; }21 FinalAwaiter final_suspend() noexcept { return {}; }22 void unhandled_exception() noexcept {}23 void return_value(int x) noexcept {24 _value = x;25 }26 std::coroutine_handle<> continuation;27 int _value;28 };29 30 Task(std::coroutine_handle<promise_type> handle) : handle(handle), stuff(123) {}31 32 struct Awaiter {33 std::coroutine_handle<promise_type> handle;34 Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {}35 bool await_ready() const noexcept { return false; }36 std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept {37 handle.promise().continuation = continuation;38 return handle;39 }40 int await_resume() noexcept {41 int ret = handle.promise()._value;42 handle.destroy();43 return ret;44 }45 };46 47 auto operator co_await() {48 auto handle_ = handle;49 handle = nullptr;50 return Awaiter(handle_);51 }52 53private:54 std::coroutine_handle<promise_type> handle;55 int stuff;56};57 58Task task0() {59 co_return 43;60}61 62// CHECK-LABEL: define{{.*}} void @_Z5task0v.resume63// This checks we are still in the scope of the current function.64// CHECK-NOT: {{^}}}65// CHECK: musttail call fastcc void66// CHECK-NEXT: ret void67