diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -782,6 +782,8 @@ (`#63903 `_) - Fix constraint checking of non-generic lambdas. (`#63181 `_) +- Fix init-capture packs having a size of one before being instantiated + (`#63677 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1270,7 +1270,8 @@ } void transformedLocalDecl(Decl *Old, ArrayRef NewDecls) { - if (Old->isParameterPack()) { + if (Old->isParameterPack() && + (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) { SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old); for (auto *New : NewDecls) SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg( diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13340,14 +13340,14 @@ OldVD->getInit()->getSourceRange(), Unexpanded, Expand, RetainExpansion, NumExpansions)) return ExprError(); + assert(!RetainExpansion && "Should not need to retain expansion after a " + "capture since it cannot be extended"); if (Expand) { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); SubstInitCapture(SourceLocation(), std::nullopt); } - } - if (!Expand || RetainExpansion) { - ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + } else { SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions); Result.EllipsisLoc = ExpansionTL.getEllipsisLoc(); } diff --git a/clang/test/SemaCXX/lambda-pack-expansion.cpp b/clang/test/SemaCXX/lambda-pack-expansion.cpp --- a/clang/test/SemaCXX/lambda-pack-expansion.cpp +++ b/clang/test/SemaCXX/lambda-pack-expansion.cpp @@ -21,3 +21,30 @@ take_by_ref(x); } } + +namespace GH63677 { + +template +void f() { + []() -> void { + [...us = Ts{}]{ + (Ts(us), ...); + }; + }.template operator()(); +} + +template void f(); + +template +inline constexpr auto fun = + [](Ts... ts) { + return [... us = (Ts&&) ts](Fun&& fn) mutable { + return static_cast(fn)(static_cast(us)...); + }; + }; + +void f() { + [[maybe_unused]] auto s = fun(1, 2, 3, 4); +} + +}