Skip to content

Commit 500c436

Browse files
zyn0217aokblast
authored andcommitted
[Clang] Handle TemplateTemplateParmDecl in concept cache (llvm#164777)
We forgot to handle those in e9972de, hence the inconsistency across multiple instantiations. This is a regression on trunk, so no release note. Fixes llvm#164750
1 parent 691656f commit 500c436

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,28 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
385385
return inherited::TraverseStmt(E->getReplacement());
386386
}
387387

388+
bool TraverseTemplateName(TemplateName Template) {
389+
if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
390+
Template.getAsTemplateDecl());
391+
TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
392+
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
393+
TTP->getPosition()))
394+
return true;
395+
396+
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
397+
if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
398+
assert(Arg.getKind() == TemplateArgument::Pack &&
399+
"Missing argument pack");
400+
Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
401+
}
402+
assert(!Arg.getAsTemplate().isNull() &&
403+
"Null template template argument");
404+
UsedTemplateArgs.push_back(
405+
SemaRef.Context.getCanonicalTemplateArgument(Arg));
406+
}
407+
return inherited::TraverseTemplateName(Template);
408+
}
409+
388410
void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
389411
if (!Constraint.hasParameterMapping()) {
390412
for (const auto &List : TemplateArgs)

clang/test/SemaTemplate/concepts.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,3 +1573,62 @@ namespace GH162770 {
15731573
template<typename... Ts> auto comma = (..., Ts());
15741574
auto b = comma<check<e{}>>;
15751575
} // namespace GH162770
1576+
1577+
namespace GH164750 {
1578+
1579+
template <typename>
1580+
struct a;
1581+
template <typename>
1582+
struct b;
1583+
1584+
template <template <typename> typename c, typename d, typename>
1585+
concept e = !__is_convertible_to(c<d>*, b<d>*);
1586+
1587+
template <typename...>
1588+
struct f;
1589+
template <typename g, typename... h>
1590+
struct f<g, h...> {
1591+
g i;
1592+
};
1593+
1594+
template <typename, typename>
1595+
struct u;
1596+
template <typename j, template <typename> typename k, typename l>
1597+
requires e<k, j, l>
1598+
struct u<const k<j>*, l> {
1599+
u(const a<j>*);
1600+
};
1601+
template <typename j, template <typename> typename k, typename l>
1602+
struct u<const k<j>*, l> {
1603+
u(const b<j>*);
1604+
};
1605+
1606+
template <typename>
1607+
struct m;
1608+
template <typename n, typename... o>
1609+
struct m<n (*)(o...)> {
1610+
template <template <typename> typename j>
1611+
using p = j<o...>;
1612+
};
1613+
1614+
template <typename q, typename r>
1615+
struct s {
1616+
template <typename... p>
1617+
struct D {
1618+
using v = f<u<r, p>...>;
1619+
};
1620+
template <typename... t>
1621+
s(t... p1) : x(p1...) {}
1622+
m<q>::template p<D>::v x;
1623+
};
1624+
template <typename w, typename... t>
1625+
void fn1(w, t... p2) {
1626+
s<w, t...>(p2...);
1627+
}
1628+
int* fn2(int) { return nullptr; }
1629+
void fn3() {
1630+
fn1(fn2, static_cast<const a<int>*>(nullptr));
1631+
fn1(fn2, static_cast<const b<int>*>(nullptr));
1632+
}
1633+
1634+
}

0 commit comments

Comments
 (0)