https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/110238
Fixes #93099 >From 23a765ac6d8e455121346405332d2066dcc0861e Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Fri, 27 Sep 2024 18:23:47 +0800 Subject: [PATCH] [Clang] GH93099 --- clang/include/clang/Sema/Sema.h | 4 ++- clang/lib/Sema/SemaTemplateVariadic.cpp | 20 +++++++---- clang/lib/Sema/TreeTransform.h | 16 ++++++--- .../SemaTemplate/concepts-out-of-line-def.cpp | 34 +++++++++++++++++++ 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e1c3a99cfa167e..1fce74880026ce 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -14264,7 +14264,9 @@ class Sema final : public SemaBase { /// /// This is intended for use when transforming 'sizeof...(Arg)' in order to /// avoid actually expanding the pack where possible. - std::optional<unsigned> getFullyPackExpandedSize(TemplateArgument Arg); + std::optional<unsigned> + getFullyPackExpandedSize(TemplateArgument Arg, + const NamedDecl *&ParameterPack); /// Called when an expression computing the size of a parameter pack /// is parsed. diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 40522a07f6339c..79e2f1f610b11f 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1211,7 +1211,9 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( llvm_unreachable("Invalid TemplateArgument Kind!"); } -std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { +std::optional<unsigned> +Sema::getFullyPackExpandedSize(TemplateArgument Arg, + const NamedDecl *&ParameterPack) { assert(Arg.containsUnexpandedParameterPack()); // If this is a substituted pack, grab that pack. If not, we don't know @@ -1222,17 +1224,20 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { TemplateArgument Pack; switch (Arg.getKind()) { case TemplateArgument::Type: - if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>()) + if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>()) { Pack = Subst->getArgumentPack(); - else + ParameterPack = Subst->getReplacedParameter(); + } else return std::nullopt; break; case TemplateArgument::Expression: if (auto *Subst = - dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr())) + dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr())) { Pack = Subst->getArgumentPack(); - else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) { + ParameterPack = Subst->getParameterPack(); + } else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) { + ParameterPack = Subst->getParameterPack(); for (VarDecl *PD : *Subst) if (PD->isParameterPack()) return std::nullopt; @@ -1243,9 +1248,10 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { case TemplateArgument::Template: if (SubstTemplateTemplateParmPackStorage *Subst = - Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) + Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) { Pack = Subst->getArgumentPack(); - else + ParameterPack = Subst->getParameterPack(); + } else return std::nullopt; break; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 91cb980ee26b26..3a029e88e865df 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -15237,6 +15237,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { // Try to compute the result without performing a partial substitution. std::optional<unsigned> Result = 0; + NamedDecl *NewPack = E->getPack(); for (const TemplateArgument &Arg : PackArgs) { if (!Arg.isPackExpansion()) { Result = *Result + 1; @@ -15260,9 +15261,14 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { /*Uneval*/ true)) return true; + const NamedDecl *TransformedParameterPack = nullptr; // See if we can determine the number of arguments from the result. - std::optional<unsigned> NumExpansions = - getSema().getFullyPackExpandedSize(OutPattern.getArgument()); + std::optional<unsigned> NumExpansions = getSema().getFullyPackExpandedSize( + OutPattern.getArgument(), TransformedParameterPack); + if (TransformedParameterPack && !E->isPartiallySubstituted()) { + assert(PackArgs.size() == 1); + NewPack = const_cast<NamedDecl *>(TransformedParameterPack); + } if (!NumExpansions) { // No: we must be in an alias template expansion, and we're going to need // to actually expand the packs. @@ -15277,7 +15283,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { // substituting. if (Result) return getDerived().RebuildSizeOfPackExpr( - E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc(), + E->getOperatorLoc(), NewPack, E->getPackLoc(), E->getRParenLoc(), *Result, std::nullopt); TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(), @@ -15304,10 +15310,10 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { if (PartialSubstitution) return getDerived().RebuildSizeOfPackExpr( - E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc(), + E->getOperatorLoc(), NewPack, E->getPackLoc(), E->getRParenLoc(), std::nullopt, Args); - return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), NewPack, E->getPackLoc(), E->getRParenLoc(), Args.size(), std::nullopt); } diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index 5450d105a6f54a..8ca399a0f729a9 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -666,3 +666,37 @@ int foo() { } } // namespace eve + +namespace GH93099 { + +// Issues with sizeof...(expr) + +template <typename T = int> struct C { + template <int... N> + requires(sizeof...(N) > 0) + friend class NTTP; + + template <class... Tp> + requires(sizeof...(Tp) > 0) + friend class TP; + + template <template <typename> class... TTp> + requires(sizeof...(TTp) > 0) + friend class TTP; +}; + +template <int... N> + requires(sizeof...(N) > 0) +class NTTP; + +template <class... Tp> + requires(sizeof...(Tp) > 0) +class TP; + +template <template <typename> class... TTp> + requires(sizeof...(TTp) > 0) +class TTP; + +C v; + +} // namespace GH93099 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits