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

Reply via email to