Skip to content

Commit 0017e08

Browse files
committed
[Clang] Remove the wrong assumption when rebuilding SizeOfPackExprs for constraint normalization
In 463a4f1, we assumed that all the template argument packs are of size 1 when normalizing a constraint expression because I mistakenly thought those packs were obtained from their injected template parameters. This was wrong because we might be checking constraints when instantiating a friend declaration within a class template specialization, where the parent class template is specialized with non-dependent template arguments. In that sense, we shouldn't assume any pack size nor expand anything in such a scenario. Moreover, there are no intermediate (substituted but unexpanded) AST nodes for template template parameters, so we have to special-case their transformations by looking into the instantiation scope instead of extracting anything from template arguments.
1 parent 88823d0 commit 0017e08

File tree

2 files changed

+35
-17
lines changed

2 files changed

+35
-17
lines changed

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,23 +1736,13 @@ namespace {
17361736
SourceLocation RParenLoc,
17371737
std::optional<unsigned> Length,
17381738
ArrayRef<TemplateArgument> PartialArgs) {
1739-
if (SemaRef.CodeSynthesisContexts.back().Kind !=
1740-
Sema::CodeSynthesisContext::ConstraintNormalization)
1741-
return inherited::RebuildSizeOfPackExpr(OperatorLoc, Pack, PackLoc,
1742-
RParenLoc, Length, PartialArgs);
1743-
1744-
#ifndef NDEBUG
1745-
for (auto *Iter = TemplateArgs.begin(); Iter != TemplateArgs.end();
1746-
++Iter)
1747-
for (const TemplateArgument &TA : Iter->Args)
1748-
assert(TA.getKind() != TemplateArgument::Pack || TA.pack_size() == 1);
1749-
#endif
1750-
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(
1751-
SemaRef, /*NewSubstitutionIndex=*/0);
1752-
Decl *NewPack = TransformDecl(PackLoc, Pack);
1753-
if (!NewPack)
1754-
return ExprError();
1755-
1739+
Decl *NewPack = Pack;
1740+
if (SemaRef.CodeSynthesisContexts.back().Kind ==
1741+
Sema::CodeSynthesisContext::ConstraintNormalization) {
1742+
NewPack = TransformDecl(PackLoc, Pack);
1743+
if (!NewPack)
1744+
return ExprError();
1745+
}
17561746
return inherited::RebuildSizeOfPackExpr(OperatorLoc,
17571747
cast<NamedDecl>(NewPack), PackLoc,
17581748
RParenLoc, Length, PartialArgs);
@@ -1881,6 +1871,15 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
18811871
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
18821872

18831873
if (TTP->isParameterPack()) {
1874+
// We might not have an index for pack expansion when normalizing
1875+
// constraint expressions. In that case, resort to instantiation scopes
1876+
// for the transformed declarations.
1877+
if (SemaRef.ArgumentPackSubstitutionIndex == -1 &&
1878+
SemaRef.CodeSynthesisContexts.back().Kind ==
1879+
Sema::CodeSynthesisContext::ConstraintNormalization) {
1880+
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D),
1881+
TemplateArgs);
1882+
}
18841883
assert(Arg.getKind() == TemplateArgument::Pack &&
18851884
"Missing argument pack");
18861885
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);

clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,22 @@ class TTP;
702702
C v;
703703

704704
} // namespace GH93099
705+
706+
namespace GH115098 {
707+
708+
template <typename... Ts> struct c {
709+
template <typename T>
710+
requires(sizeof...(Ts) > 0)
711+
friend bool operator==(c, c);
712+
};
713+
714+
template <typename... Ts> struct d {
715+
template <typename T>
716+
requires(sizeof...(Ts) > 0)
717+
friend bool operator==(d, d);
718+
};
719+
720+
template struct c<int>;
721+
template struct d<int, int>;
722+
723+
} // namespace GH115098

0 commit comments

Comments
 (0)