Skip to content

Commit b97e99f

Browse files
committed
[Clang] fix confusing diagnostics for lambdas with init-captures inside braced initializers
1 parent 9cf51a7 commit b97e99f

File tree

3 files changed

+35
-17
lines changed

3 files changed

+35
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ Bug Fixes to C++ Support
496496
nontrivial member when another member has an initializer. (#GH81774)
497497
- Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092)
498498
- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
499+
- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
499500

500501
Bug Fixes to AST Handling
501502
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseExprCXX.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -772,9 +772,10 @@ 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) {
776777
if (Tentative) {
777-
*Tentative = LambdaIntroducerTentativeParse::Invalid;
778+
*Tentative = State;
778779
return false;
779780
}
780781
Action();
@@ -824,9 +825,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
824825
break;
825826
}
826827

827-
return Invalid([&] {
828-
Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
829-
});
828+
return Result(
829+
[&] {
830+
Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
831+
},
832+
LambdaIntroducerTentativeParse::Invalid);
830833
}
831834
ConsumeToken();
832835
}
@@ -861,9 +864,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
861864
ConsumeToken();
862865
Kind = LCK_StarThis;
863866
} else {
864-
return Invalid([&] {
865-
Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
866-
});
867+
return Result(
868+
[&] {
869+
Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
870+
},
871+
LambdaIntroducerTentativeParse::Invalid);
867872
}
868873
} else if (Tok.is(tok::kw_this)) {
869874
Kind = LCK_This;
@@ -875,8 +880,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
875880
// or the start of a capture (in the "&" case) with the rest of the
876881
// capture missing. Both are an error but a misplaced capture-default
877882
// is more likely if we don't already have a capture default.
878-
return Invalid(
879-
[&] { Diag(Tok.getLocation(), diag::err_capture_default_first); });
883+
return Result(
884+
[&] { Diag(Tok.getLocation(), diag::err_capture_default_first); },
885+
LambdaIntroducerTentativeParse::Incomplete);
880886
} else {
881887
TryConsumeToken(tok::ellipsis, EllipsisLocs[0]);
882888

@@ -899,14 +905,16 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
899905
Id = Tok.getIdentifierInfo();
900906
Loc = ConsumeToken();
901907
} else if (Tok.is(tok::kw_this)) {
902-
return Invalid([&] {
903-
// FIXME: Suggest a fixit here.
904-
Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
905-
});
908+
return Result(
909+
[&] {
910+
// FIXME: Suggest a fixit here.
911+
Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
912+
},
913+
LambdaIntroducerTentativeParse::Invalid);
906914
} else {
907-
return Invalid([&] {
908-
Diag(Tok.getLocation(), diag::err_expected_capture);
909-
});
915+
return Result(
916+
[&] { Diag(Tok.getLocation(), diag::err_expected_capture); },
917+
LambdaIntroducerTentativeParse::Invalid);
910918
}
911919

912920
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)