From 709d1b30ab9e649fc3e2485c1fa11f2f203e9482 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 27 Oct 2016 07:30:31 +0000 Subject: [coroutines] Build fallthrough and set_exception statements. Summary: This patch adds semantic checking and building of the fall-through `co_return;` statement as well as the `p.set_exception(std::current_exception())` call for handling uncaught exceptions. The fall-through statement is built and checked according to: > [dcl.fct.def.coroutine]/4 > The unqualified-ids return_void and return_value are looked up in the scope of class P. If > both are found, the program is ill-formed. If the unqualified-id return_void is found, flowing > off the end of a coroutine is equivalent to a co_return with no operand. Otherwise, flowing off > the end of a coroutine results in undefined behavior. Similarly the `set_exception` call is only built when that unqualified-id is found in the scope of class P. Additionally this patch adds fall-through warnings for non-void returning coroutines. Since it's surprising undefined behavior I thought it would be important to add the warning right away. Reviewers: majnemer, GorNishanov, rsmith Subscribers: mehdi_amini, cfe-commits Differential Revision: https://reviews.llvm.org/D25349 llvm-svn: 285271 --- clang/test/SemaCXX/coroutines.cpp | 44 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'clang/test/SemaCXX/coroutines.cpp') diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index dc3980cef02..f170201a2bc 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -118,9 +118,6 @@ struct promise_void { void get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); - awaitable yield_value(int); - awaitable yield_value(yielded_thing); - not_awaitable yield_value(void()); void return_void(); }; @@ -313,6 +310,47 @@ coro bad_final_suspend() { // expected-error {{no member named 'a co_await a; } +struct bad_promise_6 { + coro get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void return_value(int) const; + void return_value(int); +}; +coro bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} + co_await a; +} + +struct bad_promise_7 { + coro get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void set_exception(int *); +}; +coro no_std_current_exc() { + // expected-error@-1 {{you need to include before defining a coroutine that implicitly uses 'set_exception'}} + co_await a; +} + +namespace std { +int *current_exception(); +} + +struct bad_promise_8 { + coro get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void set_exception(); // expected-note {{function not viable}} + void set_exception(int *) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}} + void set_exception(void *); // expected-note {{candidate function}} +}; +coro calls_set_exception() { + // expected-error@-1 {{call to unavailable member function 'set_exception'}} + co_await a; +} template<> struct std::experimental::coroutine_traits { using promise_type = promise; }; -- cgit v1.2.3