diff options
| author | Gor Nishanov <GorNishanov@gmail.com> | 2017-03-09 03:09:43 +0000 |
|---|---|---|
| committer | Gor Nishanov <GorNishanov@gmail.com> | 2017-03-09 03:09:43 +0000 |
| commit | 6dcb0eb301c72ba2628d2e292a91cae09244faa8 (patch) | |
| tree | 24e9c584bd0387d86e2c0063947028f8d9ad1b4b /clang/test/SemaCXX/coroutines.cpp | |
| parent | 84a2dadceeb9013a5df995e81cbbebe47b1dd045 (diff) | |
| download | bcm5719-llvm-6dcb0eb301c72ba2628d2e292a91cae09244faa8.tar.gz bcm5719-llvm-6dcb0eb301c72ba2628d2e292a91cae09244faa8.zip | |
[coroutines] Build and pass coroutine_handle to await_suspend
Summary:
This patch adds passing a coroutine_handle object to await_suspend calls.
It builds the coroutine_handle using coroutine_handle<PromiseType>::from_address(__builtin_coro_frame()).
(a revision of https://reviews.llvm.org/D26316 that for some reason refuses to apply via arc patch)
Reviewers: GorNishanov
Subscribers: mehdi_amini, cfe-commits, EricWF
Differential Revision: https://reviews.llvm.org/D30769
llvm-svn: 297356
Diffstat (limited to 'clang/test/SemaCXX/coroutines.cpp')
| -rw-r--r-- | clang/test/SemaCXX/coroutines.cpp | 80 |
1 files changed, 53 insertions, 27 deletions
diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index ea16b005c79..9ff42a46d77 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -16,42 +16,40 @@ void no_coroutine_traits_bad_arg_return() { // expected-error@-1 {{use of undeclared identifier 'a'}} } +void no_coroutine_traits() { + co_await 4; // expected-error {{std::experimental::coroutine_traits type was not found; include <experimental/coroutine>}} +} + +namespace std { +namespace experimental { +template <typename... T> +struct coroutine_traits; // expected-note {{declared here}} +}} // namespace std::experimental + +template<typename Promise> struct coro {}; +template <typename Promise, typename... Ps> +struct std::experimental::coroutine_traits<coro<Promise>, Ps...> { + using promise_type = Promise; +}; struct awaitable { bool await_ready(); - void await_suspend(); // FIXME: coroutine_handle + template <typename F> void await_suspend(F); void await_resume(); } a; struct suspend_always { bool await_ready() { return false; } - void await_suspend() {} + template <typename F> void await_suspend(F); void await_resume() {} }; struct suspend_never { bool await_ready() { return true; } - void await_suspend() {} + template <typename F> void await_suspend(F); void await_resume() {} }; -void no_coroutine_traits() { - co_await a; // expected-error {{need to include <experimental/coroutine>}} -} - -namespace std { -namespace experimental { -template <typename... T> -struct coroutine_traits; // expected-note {{declared here}} -} -} - -template<typename Promise> struct coro {}; -template <typename Promise, typename... Ps> -struct std::experimental::coroutine_traits<coro<Promise>, Ps...> { - using promise_type = Promise; -}; - void no_specialization() { co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}} } @@ -86,13 +84,6 @@ template <typename... T> struct std::experimental::coroutine_traits<void, void_tag, T...> { using promise_type = promise_void; }; -namespace std { -namespace experimental { -template <typename Promise = void> -struct coroutine_handle; -} -} - // FIXME: This diagnostic is terrible. void undefined_promise() { // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<void>::promise_type' (aka 'promise') is an incomplete type}} co_await a; @@ -119,6 +110,25 @@ struct promise_void { void return_void(); }; +void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include <experimental/coroutine> before defining a coroutine}} + //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} + co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} + +namespace std { +namespace experimental { +template <class PromiseType = void> +struct coroutine_handle { + static coroutine_handle from_address(void *); +}; +template <> +struct coroutine_handle<void> { + template <class PromiseType> + coroutine_handle(coroutine_handle<PromiseType>); + static coroutine_handle from_address(void *); +}; +}} // namespace std::experimental + void yield() { co_yield 0; co_yield {"foo", 1, 2}; @@ -520,3 +530,19 @@ template<> struct std::experimental::coroutine_traits<int, int, const char**> int main(int, const char**) { co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}} } + +struct good_promise_2 { + float get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); +}; +template<> struct std::experimental::coroutine_handle<good_promise_2> {}; + +template<> struct std::experimental::coroutine_traits<float> +{ using promise_type = good_promise_2; }; + +float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}} + //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} + co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} |

