Author: Kartik Ohlan Date: 2026-04-02T14:55:54Z New Revision: 87104ee51450e5c6417b80cfd9a0771c9a690a1c
URL: https://github.com/llvm/llvm-project/commit/87104ee51450e5c6417b80cfd9a0771c9a690a1c DIFF: https://github.com/llvm/llvm-project/commit/87104ee51450e5c6417b80cfd9a0771c9a690a1c.diff LOG: [Clang] [Sema] Diagnose returning an initializer list from a lambda with a return type of void (#188904) We previously didn’t diagnose attempts to return an initializer list from a lambda with an explicit return type of `void`. This patch fixes that. It also cleans up the error message so it actually says "lambda" instead of "block". Fixes #188661 Signed off by: Kartik Added: clang/test/SemaCXX/void-lambda-return-init.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaStmt.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7f6049b77fa7e..e36cffdd84647 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -392,6 +392,9 @@ Bug Fixes in This Version - Correctly diagnosing and no longer crashing when ``export module foo`` (without a semicolon) are the final tokens in a module file. (#GH187771) - Fixed a crash in duplicate attribute checking caused by comparing constant arguments with diff erent integer signedness. (#GH188259) +- Clang now emits an error when returning an initializer list from a lambda + with an explicit return type of void. The diagnostic now correctly refers + to "lambda" instead of "block". (#GH188661) - Fixed a crash on _BitInt(N) arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643) Bug Fixes to Compiler Builtins diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 603e91d598f79..eddf9c50033e1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7444,7 +7444,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..531147ef35b08 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3675,7 +3675,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, // initializer list, because it is not an expression (even // though we represent it as one). We still deduce 'void'. Diag(ReturnLoc, diag::err_lambda_return_init_list) - << RetValExp->getSourceRange(); + << RetValExp->getSourceRange(); + RetValExp = nullptr; } FnRetType = Context.VoidTy; @@ -3715,15 +3716,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 (isa_and_nonnull<InitListExpr>(RetValExp)) { + Diag(ReturnLoc, diag::err_return_block_has_expr) + << (CurLambda != 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) + << (CurLambda != 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}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
