From bae8f7c203573bf75e6838551e5203b3ef8d01b8 Mon Sep 17 00:00:00 2001 From: letrec Date: Fri, 26 Jul 2024 22:25:10 +0800 Subject: [PATCH 1/3] add init capture packs to requires scope --- clang/include/clang/Sema/Sema.h | 4 +++ clang/lib/Sema/SemaConcept.cpp | 18 +++++++++---- clang/lib/Sema/SemaLambda.cpp | 9 +++++-- clang/lib/Sema/SemaTemplateVariadic.cpp | 17 ++++++++----- clang/test/SemaTemplate/concepts-lambda.cpp | 28 +++++++++++++++++++++ 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2ec6367eccea01..d8f903bc05eb65 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -14186,6 +14186,10 @@ class Sema final : public SemaBase { std::optional getNumArgumentsInExpansion( QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); + std::optional getNumArgumentsInExpansionFromUnexpanded( + llvm::ArrayRef Unexpanded, + const MultiLevelTemplateArgumentList &TemplateArgs); + /// Determine whether the given declarator contains any unexpanded /// parameter packs. /// diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 9e16b67284be45..49065af10b452e 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -712,8 +712,8 @@ bool Sema::addInstantiatedCapturesToScope( auto AddSingleCapture = [&](const ValueDecl *CapturedPattern, unsigned Index) { ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar(); - if (CapturedVar->isInitCapture()) - Scope.InstantiatedLocal(CapturedPattern, CapturedVar); + assert(CapturedVar->isInitCapture()); + Scope.InstantiatedLocal(CapturedPattern, CapturedVar); }; for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) { @@ -721,13 +721,21 @@ bool Sema::addInstantiatedCapturesToScope( Instantiated++; continue; } - const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar(); + ValueDecl *CapturedPattern = CapturePattern.getCapturedVar(); + + if (!CapturedPattern->isInitCapture()) { + continue; + } + if (!CapturedPattern->isParameterPack()) { AddSingleCapture(CapturedPattern, Instantiated++); } else { Scope.MakeInstantiatedLocalArgPack(CapturedPattern); - std::optional NumArgumentsInExpansion = - getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs); + SmallVector Unexpanded; + SemaRef.collectUnexpandedParameterPacks( + dyn_cast(CapturedPattern)->getInit(), Unexpanded); + auto NumArgumentsInExpansion = + getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs); if (!NumArgumentsInExpansion) continue; for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 601077e9f3334d..f39d35df56ed67 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -2389,11 +2389,10 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: if (!FDPattern) return; - SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL); - if (!ShouldAddDeclsFromParentScope) return; + FunctionDecl *OutermostFD = FD, *OutermostFDPattern = FDPattern; llvm::SmallVector, 4> ParentInstantiations; while (true) { @@ -2417,5 +2416,11 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: for (const auto &[FDPattern, FD] : llvm::reverse(ParentInstantiations)) { SemaRef.addInstantiatedParametersToScope(FD, FDPattern, Scope, MLTAL); SemaRef.addInstantiatedLocalVarsToScope(FD, FDPattern, Scope); + + if (isLambdaCallOperator(FD)) + SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL); } + + SemaRef.addInstantiatedCapturesToScope(OutermostFD, OutermostFDPattern, Scope, + MLTAL); } diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 3d4ccaf68c7007..d9886bd06fee4d 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -825,12 +825,9 @@ bool Sema::CheckParameterPacksForExpansion( return false; } -std::optional Sema::getNumArgumentsInExpansion( - QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) { - QualType Pattern = cast(T)->getPattern(); - SmallVector Unexpanded; - CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); - +std::optional Sema::getNumArgumentsInExpansionFromUnexpanded( + llvm::ArrayRef Unexpanded, + const MultiLevelTemplateArgumentList &TemplateArgs) { std::optional Result; for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { // Compute the depth and index for this parameter pack. @@ -878,6 +875,14 @@ std::optional Sema::getNumArgumentsInExpansion( return Result; } +std::optional Sema::getNumArgumentsInExpansion( + QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) { + QualType Pattern = cast(T)->getPattern(); + SmallVector Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); + return getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs); +} + bool Sema::containsUnexpandedParameterPacks(Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); switch (DS.getTypeSpecType()) { diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 252ef08549a486..9c5807bbabdcbf 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -251,3 +251,31 @@ void dependent_param() { L(0, 1)(1, 2)(1); } } // namespace dependent_param_concept + +namespace init_captures { +template struct V {}; + +void sink(V<0>, V<1>, V<2>, V<3>, V<4>) {} + +void init_capture_pack() { + auto L = [](auto... z) { + return [=](auto... y) { + return [... w = z, y...](auto) + requires requires { sink(w..., y...); } + {}; + }; + }; + L(V<0>{}, V<1>{}, V<2>{})(V<3>{}, V<4>{})(1); +} + +void dependent_capture_packs() { + auto L = [](auto... z) { + return [... w = z](auto... y) { + return [... c = w](auto) + requires requires { sink(c..., y...); } + {}; + }; + }; + L(V<0>{}, V<1>{}, V<2>{})(V<3>{}, V<4>{})(1); +} +} // namespace init_captures From cb94a47667d8d1eb1ec97503765b337cec9145e7 Mon Sep 17 00:00:00 2001 From: letrec Date: Fri, 26 Jul 2024 23:56:07 +0800 Subject: [PATCH 2/3] outer -> inner --- clang/lib/Sema/SemaLambda.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index f39d35df56ed67..b35cd81857ace7 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -2392,7 +2392,7 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: if (!ShouldAddDeclsFromParentScope) return; - FunctionDecl *OutermostFD = FD, *OutermostFDPattern = FDPattern; + FunctionDecl *InnermostFD = FD, *InnermostFDPattern = FDPattern; llvm::SmallVector, 4> ParentInstantiations; while (true) { @@ -2421,6 +2421,6 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL); } - SemaRef.addInstantiatedCapturesToScope(OutermostFD, OutermostFDPattern, Scope, + SemaRef.addInstantiatedCapturesToScope(InnermostFD, InnermostFDPattern, Scope, MLTAL); } From 9e631f1a02a24ee71d6537c6b8d0820228f54aa1 Mon Sep 17 00:00:00 2001 From: letrec Date: Sat, 27 Jul 2024 00:01:43 +0800 Subject: [PATCH 3/3] add a release note --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 286f319d41a23d..3a85d4c8ee4522 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -155,6 +155,7 @@ Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed a crash when an expression with a dependent ``__typeof__`` type is used as the operand of a unary operator. (#GH97646) +- Fixed incorrect pack expansion of init-capture references in requires expresssions. - Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191) Bug Fixes to AST Handling