Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,8 @@ Bug Fixes to C++ Support
- Clang now uses the correct set of template argument lists when comparing the constraints of
out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
a class template. (#GH102320)
- 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 @@ -18843,7 +18843,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]);
LSI && !LSI->AfterParameterList)
--FSIndex;
assert(MaxFunctionScopesIndex <= FSIndex &&
"FunctionScopeIndexToStopAt should be no larger 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 @@ -8679,7 +8679,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
23 changes: 23 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,26 @@ void __trans_tmp_1() {
}

}

namespace GH47400 {

struct Foo {};

template <int, Foo> struct Arr {};

template <int> struct S {};

constexpr bool 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
}();
return true;
}

} // namespace GH47400
Loading