summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaCXX/coroutines.cpp
diff options
context:
space:
mode:
authorGor Nishanov <GorNishanov@gmail.com>2017-03-09 03:09:43 +0000
committerGor Nishanov <GorNishanov@gmail.com>2017-03-09 03:09:43 +0000
commit6dcb0eb301c72ba2628d2e292a91cae09244faa8 (patch)
tree24e9c584bd0387d86e2c0063947028f8d9ad1b4b /clang/test/SemaCXX/coroutines.cpp
parent84a2dadceeb9013a5df995e81cbbebe47b1dd045 (diff)
downloadbcm5719-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.cpp80
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}}
+}
OpenPOWER on IntegriCloud