[clang] Fix crash and improve diagnostics for void lambda returns (PR #188904)
Kartik Ohlan via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 07:50:57 PDT 2026
https://github.com/Ko496-glitch updated https://github.com/llvm/llvm-project/pull/188904
>From ee5c7ba7f44d48561acf18887f7e795875e875fd Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <ko496 at drexel.edu>
Date: Thu, 26 Mar 2026 23:36:45 -0400
Subject: [PATCH 1/2] Issue 188661
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 ++-
clang/lib/Sema/SemaStmt.cpp | 17 +++++++------
.../test/SemaCXX/void-lambda-return-init.cpp | 25 +++++++++++++++++++
3 files changed, 37 insertions(+), 8 deletions(-)
create mode 100644 clang/test/SemaCXX/void-lambda-return-init.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0c25eb2443d5e..05efa47210384 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7426,7 +7426,8 @@ def err_illegal_decl_mempointer_in_nonclass
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
def err_nonfunction_block_type : Error<
"block pointer to non-function type is invalid">;
-def err_return_block_has_expr : Error<"void block should not return a value">;
+def err_return_block_has_expr : Error<
+ "void %select{block|lambda}0 should not return a value">;
def err_block_return_missing_expr : Error<
"non-void block should return a value">;
def err_func_def_incomplete_result : Error<
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index b74af55d1bea1..87414564c82d0 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3715,15 +3715,18 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
} else if (FnRetType->isVoidType()) {
- if (RetValExp && !isa<InitListExpr>(RetValExp) &&
- !(getLangOpts().CPlusPlus &&
- (RetValExp->isTypeDependent() ||
- RetValExp->getType()->isVoidType()))) {
- if (!getLangOpts().CPlusPlus &&
- RetValExp->getType()->isVoidType())
+ if (RetValExp && isa<InitListExpr>(RetValExp)) {
+ Diag(ReturnLoc, diag::err_return_block_has_expr)
+ << (getCurLambda() != nullptr);
+ RetValExp = nullptr;
+ } else if (RetValExp && !(getLangOpts().CPlusPlus &&
+ (RetValExp->isTypeDependent() ||
+ RetValExp->getType()->isVoidType()))) {
+ if (!getLangOpts().CPlusPlus && RetValExp->getType()->isVoidType())
Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
else {
- Diag(ReturnLoc, diag::err_return_block_has_expr);
+ Diag(ReturnLoc, diag::err_return_block_has_expr)
+ << (getCurLambda() != nullptr);
RetValExp = nullptr;
}
}
diff --git a/clang/test/SemaCXX/void-lambda-return-init.cpp b/clang/test/SemaCXX/void-lambda-return-init.cpp
new file mode 100644
index 0000000000000..d38ee1617691c
--- /dev/null
+++ b/clang/test/SemaCXX/void-lambda-return-init.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++20 -fblocks -fsyntax-only -verify %s
+
+void test_lambdas() {
+ (void) [] () -> void { return {}; }; // expected-error {{void lambda should not return a value}}
+ (void) [] () -> void { return {1}; }; // expected-error {{void lambda should not return a value}}
+ (void) [] () -> void { return {1, 2}; }; // expected-error {{void lambda should not return a value}}
+ (void) [] () -> void { return 42; }; // expected-error {{void lambda should not return a value}}
+ (void) [] () -> void { return double(32); }; // expected-error {{void lambda should not return a value}}
+
+ // Qualtype on void Lambda return
+ (void) [] () -> const void { return {1}; }; // expected-error {{void lambda should not return a value}}
+ (void) [] () -> volatile void { // expected-warning {{volatile-qualified return type 'volatile void' is deprecated}}
+ return {1, 2}; // expected-error {{void lambda should not return a value}}
+ };
+}
+
+void test_blocks() {
+ (void) ^ void { return {}; }; // expected-error {{void block should not return a value}}
+ (void) ^ void { return {1}; }; // expected-error {{void block should not return a value}}
+ (void) ^ void { return {1, 2}; }; // expected-error {{void block should not return a value}}
+ (void) ^ void { return 42; }; // expected-error {{void block should not return a value}}
+
+ // Qualtype on void Block return
+ (void) ^ const void { return {1}; }; // expected-error {{void block should not return a value}}
+}
>From 62c8a920b9c1bb45ea0bb25d1ec323399a32db3d Mon Sep 17 00:00:00 2001
From: kartikohlan <kartik7ohlan at gmail.com>
Date: Tue, 31 Mar 2026 10:30:09 -0400
Subject: [PATCH 2/2] Added the suggested fix
---
clang/docs/ReleaseNotes.rst | 12 +-----------
clang/lib/Sema/SemaStmt.cpp | 6 +++---
2 files changed, 4 insertions(+), 14 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bacf2761ca816..25afd43fb788a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,10 +282,6 @@ Improvements to Clang's diagnostics
- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
-- Fixed the Fix-It insertion point for ``expected ';' after alias declaration``
- when parsing alias declarations involving a token-split ``>>`` sequence
- (for example, ``using A = X<int>>;``). (#GH184425)
-
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
@@ -325,8 +321,7 @@ Bug Fixes in This Version
- Fixed an assertion failure caused by error recovery while extending a nested name specifier with results from ordinary lookup. (#GH181470)
- Fixed a crash when parsing ``#pragma clang attribute`` arguments for attributes that forbid arguments. (#GH182122)
- Fixed a bug with multiple-include optimization (MIOpt) state not being preserved in some cases during lexing, which could suppress header-guard mismatch diagnostics and interfere with include-guard optimization. (#GH180155)
-- Fixed a crash when normalizing constraints involving concept template parameters whose index coincided with non-concept template parameters in the same parameter mapping.
-- Fixed a crash caused by accessing dependent diagnostics of a non-dependent context.
+- Fixed a crash when returning an initializer list from a void lambda or block. The compiler now emits a proper error message that correctly says "lambda" instead of "block" when applicable. (#GH188661)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -359,8 +354,6 @@ Bug Fixes to C++ Support
- Fix initialization of GRO when GRO-return type mismatches, as part of CWG2563. (#GH98744)
- Fix an error using an initializer list with array new for a type that is not default-constructible. (#GH81157)
-- We no longer consider conversion operators when copy-initializing from the same type. This was non
- conforming and could lead to recursive constraint satisfaction checking. (#GH149443)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -383,8 +376,6 @@ Miscellaneous Clang Crashes Fixed
- Fixed an assertion when diagnosing address-space qualified ``new``/``delete`` in language-defined address spaces such as OpenCL ``__local``. (#GH178319)
- Fixed an assertion failure in ObjC++ ARC when binding a rvalue reference to reference with different lifetimes (#GH178524)
- Fixed a crash when subscripting a vector type with large unsigned integer values. (#GH180563)
-- Fixed a crash when evaluating ``__is_bitwise_cloneable`` on invalid record types. (#GH183707)
-- Fixed an assertion failure when casting a function pointer with a target with a non-default program address space. (#GH186210)
OpenACC Specific Changes
------------------------
@@ -426,7 +417,6 @@ RISC-V Support
^^^^^^^^^^^^^^
- Tenstorrent Ascalon D8 was renamed to Ascalon X. Use `tt-ascalon-x` with `-mcpu` or `-mtune`.
-- Intrinsics were added for the 'Zvabd` (RISC-V Integer Vector Absolute Difference) extension.
CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 87414564c82d0..2b29cafe45384 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3715,9 +3715,9 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
} else if (FnRetType->isVoidType()) {
- if (RetValExp && isa<InitListExpr>(RetValExp)) {
+ if (isa_and_nonnull<InitListExpr>(RetValExp)) {
Diag(ReturnLoc, diag::err_return_block_has_expr)
- << (getCurLambda() != nullptr);
+ << (CurLambda != nullptr);
RetValExp = nullptr;
} else if (RetValExp && !(getLangOpts().CPlusPlus &&
(RetValExp->isTypeDependent() ||
@@ -3726,7 +3726,7 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
else {
Diag(ReturnLoc, diag::err_return_block_has_expr)
- << (getCurLambda() != nullptr);
+ << (CurLambda != nullptr);
RetValExp = nullptr;
}
}
More information about the cfe-commits
mailing list