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

Reply via email to