Skip to content

Commit

Permalink
[coroutines] Fix co_return statement for initializer list arguments
Browse files Browse the repository at this point in the history
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
  • Loading branch information
EricWF committed Oct 6, 2016
1 parent 4fa098a commit 9813131
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaCoroutine.cpp
Expand Up @@ -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();
Expand Down
24 changes: 19 additions & 5 deletions clang/test/SemaCXX/coroutines.cpp
Expand Up @@ -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 {
Expand All @@ -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};
Expand All @@ -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() {
Expand All @@ -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'}}
Expand Down

0 comments on commit 9813131

Please sign in to comment.