llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Oleksandr T. (a-tarasyuk)

<details>
<summary>Changes</summary>

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), &amp;] {}};
```

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), &amp;] {});
```

---
Full diff: https://github.com/llvm/llvm-project/pull/166180.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+1) 
- (modified) clang/lib/Parse/ParseExprCXX.cpp (+25-17) 
- (modified) clang/test/Parser/lambda-misplaced-capture-default.cpp (+9) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 92fc9381a5868..63faf46895989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -496,6 +496,7 @@ Bug Fixes to C++ Support
   nontrivial member when another member has an initializer. (#GH81774)
 - 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 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..03ae727168df0 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -772,9 +772,10 @@ 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) {
     if (Tentative) {
-      *Tentative = LambdaIntroducerTentativeParse::Invalid;
+      *Tentative = State;
       return false;
     }
     Action();
@@ -824,9 +825,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
           break;
         }
 
-        return Invalid([&] {
-          Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
-        });
+        return Result(
+            [&] {
+              Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
+            },
+            LambdaIntroducerTentativeParse::Invalid);
       }
       ConsumeToken();
     }
@@ -861,9 +864,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
         ConsumeToken();
         Kind = LCK_StarThis;
       } else {
-        return Invalid([&] {
-          Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
-        });
+        return Result(
+            [&] {
+              Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
+            },
+            LambdaIntroducerTentativeParse::Invalid);
       }
     } else if (Tok.is(tok::kw_this)) {
       Kind = LCK_This;
@@ -875,8 +880,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 +905,16 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer 
&Intro,
         Id = Tok.getIdentifierInfo();
         Loc = ConsumeToken();
       } else if (Tok.is(tok::kw_this)) {
-        return Invalid([&] {
-          // FIXME: Suggest a fixit here.
-          Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
-        });
+        return Result(
+            [&] {
+              // FIXME: Suggest a fixit here.
+              Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
+            },
+            LambdaIntroducerTentativeParse::Invalid);
       } else {
-        return Invalid([&] {
-          Diag(Tok.getLocation(), diag::err_expected_capture);
-        });
+        return Result(
+            [&] { Diag(Tok.getLocation(), diag::err_expected_capture); },
+            LambdaIntroducerTentativeParse::Invalid);
       }
 
       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}}
+}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/166180
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to