diff options
| author | Eric Fiselier <eric@efcs.ca> | 2016-10-06 21:23:38 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2016-10-06 21:23:38 +0000 |
| commit | 98131319364b2e0d2c0a9e64e385906158be8128 (patch) | |
| tree | 76d668fba1fd86adc3f1ed387644ff78fa52242c | |
| parent | 4fa098a5c0223dab6ae10da6f01541e943cc0bbf (diff) | |
| download | bcm5719-llvm-98131319364b2e0d2c0a9e64e385906158be8128.tar.gz bcm5719-llvm-98131319364b2e0d2c0a9e64e385906158be8128.zip | |
[coroutines] Fix co_return statement for initializer list arguments
Summary:
Previously the statement `co_return {42}` would be transformed into `P.return_void()`, since the type of `{42}` is represented as `void` by Clang.
This patch fixes the bug by checking for `InitListExpr` arguments and transforming them accordingly.
Reviewers: majnemer, GorNishanov, rsmith
Subscribers: mehdi_amini, cfe-commits
Differential Revision: https://reviews.llvm.org/D25296
llvm-svn: 283495
| -rw-r--r-- | clang/lib/Sema/SemaCoroutine.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/coroutines.cpp | 24 |
2 files changed, 20 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index f9c3970e021..323878e2d57 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -362,7 +362,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) { // of scope, we should treat the operand as an xvalue for this overload // resolution. ExprResult PC; - if (E && !E->getType()->isVoidType()) { + if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) { PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E); } else { E = MakeFullDiscardedValueExpr(E).get(); diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index dd941237647..dc3980cef02 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -78,8 +78,13 @@ double bad_promise_type_2(int) { } struct promise; // expected-note 2{{forward declaration}} +struct promise_void; +struct void_tag {}; template <typename... T> struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; }; +template <typename... T> +struct std::experimental::coroutine_traits<void, void_tag, T...> +{ using promise_type = promise_void; }; namespace std { namespace experimental { @@ -106,10 +111,19 @@ struct promise { awaitable yield_value(int); // expected-note 2{{candidate}} awaitable yield_value(yielded_thing); // expected-note 2{{candidate}} not_awaitable yield_value(void()); // expected-note 2{{candidate}} - void return_void(); void return_value(int); // expected-note 2{{here}} }; +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(); +}; + void yield() { co_yield 0; co_yield {"foo", 1, 2}; @@ -126,10 +140,10 @@ void coreturn(int n) { if (n == 0) co_return 3; if (n == 1) - co_return {4}; + co_return {4}; // expected-warning {{braces around scalar initializer}} if (n == 2) co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}} - co_return; + co_return 42; } void mixed_yield() { @@ -142,11 +156,11 @@ void mixed_await() { return; // expected-error {{not allowed in coroutine}} } -void only_coreturn() { +void only_coreturn(void_tag) { co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}} } -void mixed_coreturn(bool b) { +void mixed_coreturn(void_tag, bool b) { if (b) // expected-warning@+1 {{'co_return' used in a function that uses neither}} co_return; // expected-note {{use of 'co_return'}} |

