[clang] [Clang] GH93099 (PR #110238)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 27 03:26:48 PDT 2024
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 <zyn7109 at 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
More information about the cfe-commits
mailing list