2017-05-24 22:19:48 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
namespace std { namespace experimental { inline namespace coroutines_v1 {
|
|
|
|
|
|
|
|
template <typename R, typename...> struct coroutine_traits {
|
|
|
|
using promise_type = typename R::promise_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Promise = void> struct coroutine_handle;
|
|
|
|
|
|
|
|
template <> struct coroutine_handle<void> {
|
|
|
|
static coroutine_handle from_address(void *addr) noexcept {
|
|
|
|
coroutine_handle me;
|
|
|
|
me.ptr = addr;
|
|
|
|
return me;
|
|
|
|
}
|
|
|
|
void operator()() { resume(); }
|
2020-09-12 04:34:03 +08:00
|
|
|
void *address() const noexcept { return ptr; }
|
2017-05-24 22:19:48 +08:00
|
|
|
void resume() const { __builtin_coro_resume(ptr); }
|
|
|
|
void destroy() const { __builtin_coro_destroy(ptr); }
|
|
|
|
bool done() const { return __builtin_coro_done(ptr); }
|
|
|
|
coroutine_handle &operator=(decltype(nullptr)) {
|
|
|
|
ptr = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
|
|
|
|
coroutine_handle() : ptr(nullptr) {}
|
|
|
|
// void reset() { ptr = nullptr; } // add to P0057?
|
|
|
|
explicit operator bool() const { return ptr; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void *ptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Promise> struct coroutine_handle : coroutine_handle<> {
|
|
|
|
using coroutine_handle<>::operator=;
|
|
|
|
|
|
|
|
static coroutine_handle from_address(void *addr) noexcept {
|
|
|
|
coroutine_handle me;
|
|
|
|
me.ptr = addr;
|
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|
|
|
|
Promise &promise() const {
|
|
|
|
return *reinterpret_cast<Promise *>(
|
|
|
|
__builtin_coro_promise(ptr, alignof(Promise), false));
|
|
|
|
}
|
|
|
|
static coroutine_handle from_promise(Promise &promise) {
|
|
|
|
coroutine_handle p;
|
|
|
|
p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename _PromiseT>
|
|
|
|
bool operator==(coroutine_handle<_PromiseT> const& _Left,
|
|
|
|
coroutine_handle<_PromiseT> const& _Right) noexcept
|
|
|
|
{
|
|
|
|
return _Left.address() == _Right.address();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename _PromiseT>
|
|
|
|
bool operator!=(coroutine_handle<_PromiseT> const& _Left,
|
|
|
|
coroutine_handle<_PromiseT> const& _Right) noexcept
|
|
|
|
{
|
|
|
|
return !(_Left == _Right);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct suspend_always {
|
|
|
|
bool await_ready() { return false; }
|
|
|
|
void await_suspend(coroutine_handle<>) {}
|
|
|
|
void await_resume() {}
|
|
|
|
};
|
|
|
|
struct suspend_never {
|
[Coroutines] Ensure co_await promise.final_suspend() does not throw
Summary:
This patch addresses https://bugs.llvm.org/show_bug.cgi?id=46256
The spec of coroutine requires that the expression co_await promise.final_suspend() shall not be potentially-throwing.
To check this, we recursively look at every call (including Call, MemberCall, OperatorCall and Constructor) in all code
generated by the final suspend, and ensure that the callees are declared with noexcept. We also look at any returned data
type that requires explicit destruction, and check their destructors for noexcept.
This patch does not check declarations with dependent types yet, which will be done in future patches.
Updated all tests to add noexcept to the required functions, and added a dedicated test for this patch.
This patch might start to cause existing codebase fail to compile because most people may not have been strict in tagging
all the related functions noexcept.
Reviewers: lewissbaker, modocache, junparser
Reviewed By: modocache
Subscribers: arphaman, junparser, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82029
2020-06-16 07:27:41 +08:00
|
|
|
bool await_ready() noexcept { return true; }
|
|
|
|
void await_suspend(coroutine_handle<>) noexcept {}
|
|
|
|
void await_resume() noexcept {}
|
2017-05-24 22:19:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
}}}
|