From 98131319364b2e0d2c0a9e64e385906158be8128 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 6 Oct 2016 21:23:38 +0000 Subject: [PATCH] [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 --- clang/lib/Sema/SemaCoroutine.cpp | 2 +- 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 f9c3970..323878e 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(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 dd94123..dc3980c 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 struct std::experimental::coroutine_traits { using promise_type = promise; }; +template +struct std::experimental::coroutine_traits +{ 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'}} -- 2.7.4