forked from OSchip/llvm-project
69 lines
2.0 KiB
C++
69 lines
2.0 KiB
C++
// This tests that the symmetric transfer at the final suspend point could happen successfully.
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s
|
|
|
|
#include "Inputs/coroutine.h"
|
|
|
|
struct Task {
|
|
struct promise_type {
|
|
struct FinalAwaiter {
|
|
bool await_ready() const noexcept { return false; }
|
|
template <typename PromiseType>
|
|
std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {
|
|
return h.promise().continuation;
|
|
}
|
|
void await_resume() noexcept {}
|
|
};
|
|
Task get_return_object() noexcept {
|
|
return std::coroutine_handle<promise_type>::from_promise(*this);
|
|
}
|
|
std::suspend_always initial_suspend() noexcept { return {}; }
|
|
FinalAwaiter final_suspend() noexcept { return {}; }
|
|
void unhandled_exception() noexcept {}
|
|
void return_value(int x) noexcept {
|
|
_value = x;
|
|
}
|
|
std::coroutine_handle<> continuation;
|
|
int _value;
|
|
};
|
|
|
|
Task(std::coroutine_handle<promise_type> handle) : handle(handle) {}
|
|
~Task() {
|
|
if (handle)
|
|
handle.destroy();
|
|
}
|
|
|
|
struct Awaiter {
|
|
std::coroutine_handle<promise_type> handle;
|
|
Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {}
|
|
bool await_ready() const noexcept { return false; }
|
|
std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept {
|
|
handle.promise().continuation = continuation;
|
|
return handle;
|
|
}
|
|
int await_resume() noexcept {
|
|
int ret = handle.promise()._value;
|
|
handle.destroy();
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
auto operator co_await() {
|
|
auto handle_ = handle;
|
|
handle = nullptr;
|
|
return Awaiter(handle_);
|
|
}
|
|
|
|
private:
|
|
std::coroutine_handle<promise_type> handle;
|
|
};
|
|
|
|
Task task0() {
|
|
co_return 43;
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} void @_Z5task0v.resume
|
|
// This checks we are still in the scope of the current function.
|
|
// CHECK-NOT: {{^}}}
|
|
// CHECK: musttail call fastcc void
|
|
// CHECK-NEXT: ret void
|