Author: Kunal Dubey Date: 2026-08-31T14:57:55+02:00 New Revision: 09231ed02384f388ae5b87b9d89b804d8e94babf
URL: https://github.com/llvm/llvm-project/commit/09231ed02384f388ae5b87b9d89b804d8e94babf DIFF: https://github.com/llvm/llvm-project/commit/09231ed02384f388ae5b87b9d89b804d8e94babf.diff LOG: [clang] Delay dependent co_return promise calls (#218779) Avoiding selection of return_value or return_void while building co_return whose operand is type-dependent and keeping it unset until template init rebuild for a type allows dependent operations like co_return ctx.f(v) to use promise.return_void() instead of needing promise.return_value(). Fixes #218368 Added: Modified: clang/docs/ReleaseNotes.md clang/lib/Analysis/CFG.cpp clang/lib/Sema/SemaCoroutine.cpp clang/test/SemaCXX/coreturn.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 053a132e2408a..dd3dfdc5ad8d7 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -542,6 +542,10 @@ features cannot lower the translation-unit ABI level; using ``__is_constructible`` on a nested class template inside the definition of the containing class. (#GH215166) +- Fixed a bug where Clang incorrectly required `promise.return_value()` for a + dependent `co_return` operand that inits to `void`, instead of using + `promise.return_void()`. (#GH218368) + - Fixed merging of lambdas across modules in the case where neither lambda is imported from an AST file. (#GH214560) diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 5263114ebca28..5aaaf5a8c33a8 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -3432,8 +3432,9 @@ CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) { CoreturnStmt *CRS = cast<CoreturnStmt>(S); auto *B = Block; - if (CFGBlock *R = Visit(CRS->getPromiseCall())) - B = R; + if (Expr *PromiseCall = CRS->getPromiseCall()) + if (CFGBlock *R = Visit(PromiseCall)) + B = R; if (Expr *RV = CRS->getOperand()) if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV)) diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 627ed96522025..b46efba09500f 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1055,6 +1055,13 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, E = R.get(); } + // A type-dependent operand can init to either void or non-void. + // Delay selecting return_void or return_value until template init + // rebuilds the co_return statement with the operand type. + if (E && !isa<InitListExpr>(E) && E->isTypeDependent()) + return new (Context) + CoreturnStmt(Loc, E, /*PromiseCall=*/nullptr, IsImplicit); + VarDecl *Promise = FSI->CoroutinePromise; ExprResult PC; if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) { diff --git a/clang/test/SemaCXX/coreturn.cpp b/clang/test/SemaCXX/coreturn.cpp index 7069a1040db23..8fb2506848c3d 100644 --- a/clang/test/SemaCXX/coreturn.cpp +++ b/clang/test/SemaCXX/coreturn.cpp @@ -138,3 +138,29 @@ VoidTagReturnValue test11(bool b) { if (b) co_return 42; } // expected-warning {{non-void coroutine does not return a value in all control paths}} + +namespace dependent_void_coreturn { +struct coro { + struct promise_type { + coro get_return_object(); + suspend_never initial_suspend(); + suspend_never final_suspend() noexcept; + void unhandled_exception(); + void return_void(); + }; +}; + +struct Ctx { + template <typename T> + T &get(); + void f(int); +}; + +template <typename T> +coro f(Ctx &ctx) { + auto &v = ctx.get<T>(); + co_return ctx.f(v); +} + +void use(Ctx &ctx) { f<int>(ctx); } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
