Skip to content

Commit bb6d2be

Browse files
authored
[Clang] fix confusing diagnostics for lambdas with init-captures inside braced initializers (llvm#166180)
Fixes llvm#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), &] {}); ```
1 parent 6adf993 commit bb6d2be

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ Bug Fixes to C++ Support
514514
- Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092)
515515
- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
516516
- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)
517+
- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
517518

518519
Bug Fixes to AST Handling
519520
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseExprCXX.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -772,9 +772,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
772772

773773
// Produce a diagnostic if we're not tentatively parsing; otherwise track
774774
// that our parse has failed.
775-
auto Invalid = [&](llvm::function_ref<void()> Action) {
775+
auto Result = [&](llvm::function_ref<void()> Action,
776+
LambdaIntroducerTentativeParse State =
777+
LambdaIntroducerTentativeParse::Invalid) {
776778
if (Tentative) {
777-
*Tentative = LambdaIntroducerTentativeParse::Invalid;
779+
*Tentative = State;
778780
return false;
779781
}
780782
Action();
@@ -824,7 +826,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
824826
break;
825827
}
826828

827-
return Invalid([&] {
829+
return Result([&] {
828830
Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
829831
});
830832
}
@@ -861,7 +863,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
861863
ConsumeToken();
862864
Kind = LCK_StarThis;
863865
} else {
864-
return Invalid([&] {
866+
return Result([&] {
865867
Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
866868
});
867869
}
@@ -875,8 +877,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
875877
// or the start of a capture (in the "&" case) with the rest of the
876878
// capture missing. Both are an error but a misplaced capture-default
877879
// is more likely if we don't already have a capture default.
878-
return Invalid(
879-
[&] { Diag(Tok.getLocation(), diag::err_capture_default_first); });
880+
return Result(
881+
[&] { Diag(Tok.getLocation(), diag::err_capture_default_first); },
882+
LambdaIntroducerTentativeParse::Incomplete);
880883
} else {
881884
TryConsumeToken(tok::ellipsis, EllipsisLocs[0]);
882885

@@ -899,14 +902,13 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
899902
Id = Tok.getIdentifierInfo();
900903
Loc = ConsumeToken();
901904
} else if (Tok.is(tok::kw_this)) {
902-
return Invalid([&] {
905+
return Result([&] {
903906
// FIXME: Suggest a fixit here.
904907
Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
905908
});
906909
} else {
907-
return Invalid([&] {
908-
Diag(Tok.getLocation(), diag::err_expected_capture);
909-
});
910+
return Result(
911+
[&] { Diag(Tok.getLocation(), diag::err_expected_capture); });
910912
}
911913

912914
TryConsumeToken(tok::ellipsis, EllipsisLocs[2]);

clang/test/Parser/lambda-misplaced-capture-default.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,12 @@ template <typename... Args> void Test(Args... args) {
3636
[... xs = &args, &] {}; // expected-error {{capture default must be first}}
3737
}
3838
} // namespace misplaced_capture_default_pack
39+
40+
namespace GH163498 {
41+
struct S {
42+
template <class T> S(T) {}
43+
};
44+
void t() {
45+
S s{[a(42), &] {}}; // expected-error {{capture default must be first}}
46+
}
47+
}

0 commit comments

Comments
 (0)