Index: clang/lib/CodeGen/CGCoroutine.cpp =================================================================== --- clang/lib/CodeGen/CGCoroutine.cpp +++ clang/lib/CodeGen/CGCoroutine.cpp @@ -275,9 +275,9 @@ void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { ++CurCoro.Data->CoreturnCount; const Expr *RV = S.getOperand(); - if (RV && RV->getType()->isVoidType()) { - // Make sure to evaluate the expression of a co_return with a void - // expression for side effects. + if (RV && RV->getType()->isVoidType() && !isa(RV)) { + // Make sure to evaluate the non initlist expression of a co_return + // with a void expression for side effects. RunCleanupsScope cleanupScope(*this); EmitIgnoredExpr(RV); } Index: clang/test/CodeGenCoroutines/coro-return-voidtype-initlist.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCoroutines/coro-return-voidtype-initlist.cpp @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++1z -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s + +namespace std { +template struct b { b(int, a); }; +template struct d { c *operator->(); }; +template struct e {}; +} // namespace std +enum f {}; +namespace std { +namespace experimental { +template struct coroutine_traits : g {}; +template struct coroutine_handle; +template <> struct coroutine_handle<> {}; +template struct coroutine_handle : coroutine_handle<> { + static coroutine_handle from_address(void *); +}; +struct h { + int await_ready(); + void await_suspend(coroutine_handle<>); + void await_resume(); +}; +} // namespace experimental +} // namespace std +template using i = std::experimental::coroutine_handle<>; +template auto ah(ag) { return ag().ah(0); } +template struct k; +struct l { + struct m { + int await_ready(); + template + void await_suspend(std::experimental::coroutine_handle); + void await_resume(); + }; + std::experimental::h initial_suspend(); + m final_suspend(); + template auto await_transform(ag) { return ah(ag()); } +}; +template struct n : l { + k get_return_object(); + void return_value(am); + void unhandled_exception(); +}; +struct o { + using ap = i<>; + o(ap); + int await_ready(); +}; +template struct k { + using promise_type = n; + using ap = i<>; + ap ar; + struct p : o { + using at = o; + p(ap q) : at(q) {} + void await_suspend(std::experimental::coroutine_handle<>); + }; + struct r : p { + r(ap q) : p(q) {} + am await_resume(); + }; + auto ah(int) { return r(ar); } +}; +template +auto ax(std::e, av>, aw) -> k>; +struct s { + s(int); +}; +struct K; +f j; +struct t { + std::d bh(); + std::d bi; +}; +template struct M { + using bm = int; + static k bh(); + static k>> bo(); +}; +template k M::bh() { bo; } + +// CHECK-LABEL: _ZN1MIiE2boEv( +template k>> M::bo() { + std::e> bu; + s bw(0); +// CHECK: _ZN1nISt1bISt1eIi1sEEE12return_valueES4_(%struct.n* %__promise) + co_return{0, co_await ax(bu, bw)}; +} +template struct u { + template + k by(int *, unsigned long, std::e, unsigned long, f, + int *, int *); +}; +template +template +k u::by(int *, unsigned long, std::e, unsigned long, + f, int *, int *) { + M::bh; +} +struct K { + template + k by(unsigned long, std::e, unsigned long, f, int *, + int *); + template + k by(unsigned long, const std::e &, unsigned long, f, int *, + int *); +}; +template +k K::by(unsigned long, const std::e &, unsigned long, f p4, int *, + int *) { + std::e cj; + by(0, cj, 0, p4, 0, 0); +} +template +k K::by(unsigned long, std::e v, unsigned long, f p4, + int *, int *) { + static_cast *>(0)->by(0, 0, v, 0, p4, 0, 0); +} +using namespace std; +d t::bh() { + e cm; + auto cn = [&] { bi->by(0, cm, 0, j, 0, 0); }; + cn(); +}