Author: Oleksandr T. Date: 2025-11-06T22:55:36+02:00 New Revision: bb6d2bea6495b044a0773598916eba801f8d38fc
URL: https://github.com/llvm/llvm-project/commit/bb6d2bea6495b044a0773598916eba801f8d38fc DIFF: https://github.com/llvm/llvm-project/commit/bb6d2bea6495b044a0773598916eba801f8d38fc.diff LOG: [Clang] fix confusing diagnostics for lambdas with init-captures inside braced initializers (#166180) Fixes #163498 --- This PR addresses the issue of confusing diagnostics for lambdas with init-captures appearing inside braced initializers. Cases such as: ```cpp S s{[a(42), &] {}}; ``` were misparsed as C99 array designators, producing unrelated diagnostics, such as `use of undeclared identifier 'a'`, and `expected ']'` --- https://github.com/llvm/llvm-project/blob/bb9bd5f263226840194b28457ddf9861986db51f/clang/lib/Parse/ParseInit.cpp#L470 https://github.com/llvm/llvm-project/blob/bb9bd5f263226840194b28457ddf9861986db51f/clang/lib/Parse/ParseInit.cpp#L74 https://github.com/llvm/llvm-project/blob/bb9bd5f263226840194b28457ddf9861986db51f/clang/include/clang/Parse/Parser.h#L4652-L4655 https://github.com/llvm/llvm-project/blob/24c22b7de620669aed9da28de323309c44a58244/clang/lib/Parse/ParseExprCXX.cpp#L871-L879 The tentative parser now returns `Incomplete` for partially valid lambda introducers, preserving the `lambda` interpretation and allowing the proper diagnostic to be issued later. --- Clang now correctly recognizes such constructs as malformed lambda introducers and emits the expected diagnostic — for example, “capture-default must be first” — consistent with direct initialization cases such as: ```cpp S s([a(42), &] {}); ``` Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Parse/ParseExprCXX.cpp clang/test/Parser/lambda-misplaced-capture-default.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 34c0d73d4a129..e8339fa13ffba 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -514,6 +514,7 @@ Bug Fixes to C++ Support - Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092) - Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753) - Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560) +- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 74f87a8cb63c3..7a5d28caf8521 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -772,9 +772,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Produce a diagnostic if we're not tentatively parsing; otherwise track // that our parse has failed. - auto Invalid = [&](llvm::function_ref<void()> Action) { + auto Result = [&](llvm::function_ref<void()> Action, + LambdaIntroducerTentativeParse State = + LambdaIntroducerTentativeParse::Invalid) { if (Tentative) { - *Tentative = LambdaIntroducerTentativeParse::Invalid; + *Tentative = State; return false; } Action(); @@ -824,7 +826,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, break; } - return Invalid([&] { + return Result([&] { Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare); }); } @@ -861,7 +863,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, ConsumeToken(); Kind = LCK_StarThis; } else { - return Invalid([&] { + return Result([&] { Diag(Tok.getLocation(), diag::err_expected_star_this_capture); }); } @@ -875,8 +877,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // or the start of a capture (in the "&" case) with the rest of the // capture missing. Both are an error but a misplaced capture-default // is more likely if we don't already have a capture default. - return Invalid( - [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); }); + return Result( + [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); }, + LambdaIntroducerTentativeParse::Incomplete); } else { TryConsumeToken(tok::ellipsis, EllipsisLocs[0]); @@ -899,14 +902,13 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, Id = Tok.getIdentifierInfo(); Loc = ConsumeToken(); } else if (Tok.is(tok::kw_this)) { - return Invalid([&] { + return Result([&] { // FIXME: Suggest a fixit here. Diag(Tok.getLocation(), diag::err_this_captured_by_reference); }); } else { - return Invalid([&] { - Diag(Tok.getLocation(), diag::err_expected_capture); - }); + return Result( + [&] { Diag(Tok.getLocation(), diag::err_expected_capture); }); } TryConsumeToken(tok::ellipsis, EllipsisLocs[2]); diff --git a/clang/test/Parser/lambda-misplaced-capture-default.cpp b/clang/test/Parser/lambda-misplaced-capture-default.cpp index d65b875102da7..4f5bd6d7fa5e9 100644 --- a/clang/test/Parser/lambda-misplaced-capture-default.cpp +++ b/clang/test/Parser/lambda-misplaced-capture-default.cpp @@ -36,3 +36,12 @@ template <typename... Args> void Test(Args... args) { [... xs = &args, &] {}; // expected-error {{capture default must be first}} } } // namespace misplaced_capture_default_pack + +namespace GH163498 { +struct S { + template <class T> S(T) {} +}; +void t() { + S s{[a(42), &] {}}; // expected-error {{capture default must be first}} +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
