Skip to content

Commit 7536ebf

Browse files
authored
[Clang][SemaCXX] Fix bug where unexpanded lambda captures where assumed to have size 1 (#101385)
Fixes #63677
1 parent c24fb45 commit 7536ebf

File tree

4 files changed

+33
-4
lines changed

4 files changed

+33
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ Bug Fixes to C++ Support
185185
- Clang now correctly recognizes the correct context for parameter
186186
substitutions in concepts, so it doesn't incorrectly complain of missing
187187
module imports in those situations. (#GH60336)
188+
- Fix init-capture packs having a size of one before being instantiated. (#GH63677)
188189

189190
Bug Fixes to AST Handling
190191
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,8 @@ namespace {
14471447
}
14481448

14491449
void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
1450-
if (Old->isParameterPack()) {
1450+
if (Old->isParameterPack() &&
1451+
(NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
14511452
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
14521453
for (auto *New : NewDecls)
14531454
SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14340,14 +14340,14 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1434014340
OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
1434114341
RetainExpansion, NumExpansions))
1434214342
return ExprError();
14343+
assert(!RetainExpansion && "Should not need to retain expansion after a "
14344+
"capture since it cannot be extended");
1434314345
if (Expand) {
1434414346
for (unsigned I = 0; I != *NumExpansions; ++I) {
1434514347
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
1434614348
SubstInitCapture(SourceLocation(), std::nullopt);
1434714349
}
14348-
}
14349-
if (!Expand || RetainExpansion) {
14350-
ForgetPartiallySubstitutedPackRAII Forget(getDerived());
14350+
} else {
1435114351
SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
1435214352
Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
1435314353
}

clang/test/SemaCXX/lambda-pack-expansion.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,30 @@ int h(Ts... ts) {
4141
}
4242

4343
}
44+
45+
namespace GH63677 {
46+
47+
template<typename>
48+
void f() {
49+
[]<typename... Ts>() -> void {
50+
[...us = Ts{}]{
51+
(Ts(us), ...);
52+
};
53+
}.template operator()<int, int>();
54+
}
55+
56+
template void f<int>();
57+
58+
template <class>
59+
inline constexpr auto fun =
60+
[]<class... Ts>(Ts... ts) {
61+
return [... us = (Ts&&) ts]<class Fun>(Fun&& fn) mutable {
62+
return static_cast<Fun&&>(fn)(static_cast<Ts&&>(us)...);
63+
};
64+
};
65+
66+
void f() {
67+
[[maybe_unused]] auto s = fun<int>(1, 2, 3, 4);
68+
}
69+
70+
}

0 commit comments

Comments
 (0)