Skip to content

[Clang] Fix a DeclContext mismatch when parsing nested lambda parameters #112177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,12 @@ Bug Fixes to C++ Support
a class template. (#GH102320)
- Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460)
- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
and undeclared templates. (#GH107047, #GH49093)
and undeclared templates. (#GH107047), (#GH49093)
- Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded
parameter pack. (#GH109148)
- Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394)
- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
certain situations. (#GH47400), (#GH90896)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18865,7 +18865,17 @@ bool Sema::tryCaptureVariable(
// We need to sync up the Declaration Context with the
// FunctionScopeIndexToStopAt
if (FunctionScopeIndexToStopAt) {
assert(!FunctionScopes.empty() && "No function scopes to stop at?");
unsigned FSIndex = FunctionScopes.size() - 1;
// When we're parsing the lambda parameter list, the current DeclContext is
// NOT the lambda but its parent. So move away the current LSI before
// aligning DC and FunctionScopeIndexToStopAt.
if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]);
FSIndex && LSI && !LSI->AfterParameterList)
--FSIndex;
assert(MaxFunctionScopesIndex <= FSIndex &&
"FunctionScopeIndexToStopAt should be no greater than FSIndex into "
"FunctionScopes.");
while (FSIndex != MaxFunctionScopesIndex) {
DC = getLambdaAwareParentOfDeclContext(DC);
--FSIndex;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8686,7 +8686,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
while (isa_and_nonnull<CapturedDecl>(DC))
DC = DC->getParent();
assert(
CurrentLSI->CallOperator == DC &&
(CurrentLSI->CallOperator == DC || !CurrentLSI->AfterParameterList) &&
"The current call operator must be synchronized with Sema's CurContext");
#endif // NDEBUG

Expand Down
22 changes: 22 additions & 0 deletions clang/test/SemaCXX/lambda-capture-type-deduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,25 @@ void __trans_tmp_1() {
}

}

namespace GH47400 {

struct Foo {};

template <int, Foo> struct Arr {};

template <int> struct S {};

constexpr void foo() {
constexpr Foo f;
[&]<int is>() {
[&](Arr<is, f>) {}({}); // f constitutes an ODR-use
}.template operator()<42>();

constexpr int C = 1;
[] {
[](S<C>) { }({}); // ... while C doesn't
}();
}

} // namespace GH47400
Loading