[clang] [Clang] Handle TemplateTemplateParmDecl in concept cache (PR #164777)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 23 02:04:08 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Younan Zhang (zyn0217)
<details>
<summary>Changes</summary>
We forgot to handle those in e9972debc, hence the inconsistency across multiple instantiations.
This is a regression on trunk, so no release note.
Fixes https://github.com/llvm/llvm-project/issues/164750
---
Full diff: https://github.com/llvm/llvm-project/pull/164777.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaConcept.cpp (+22)
- (modified) clang/test/SemaTemplate/concepts.cpp (+59)
``````````diff
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index f77fca2a69e00..741f796ea630f 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -385,6 +385,28 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
return inherited::TraverseStmt(E->getReplacement());
}
+ bool TraverseTemplateName(TemplateName Template) {
+ if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
+ Template.getAsTemplateDecl());
+ TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return true;
+
+ TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+ if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
+ }
+ assert(!Arg.getAsTemplate().isNull() &&
+ "Null template template argument");
+ UsedTemplateArgs.push_back(
+ SemaRef.Context.getCanonicalTemplateArgument(Arg));
+ }
+ return inherited::TraverseTemplateName(Template);
+ }
+
void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
if (!Constraint.hasParameterMapping()) {
for (const auto &List : TemplateArgs)
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 5b0f3d39d9648..becf5467a1b61 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1573,3 +1573,62 @@ namespace GH162770 {
template<typename... Ts> auto comma = (..., Ts());
auto b = comma<check<e{}>>;
} // namespace GH162770
+
+namespace GH164750 {
+
+template <typename>
+struct a;
+template <typename>
+struct b;
+
+template <template <typename> typename c, typename d, typename>
+concept e = !__is_convertible_to(c<d>*, b<d>*);
+
+template <typename...>
+struct f;
+template <typename g, typename... h>
+struct f<g, h...> {
+ g i;
+};
+
+template <typename, typename>
+struct u;
+template <typename j, template <typename> typename k, typename l>
+ requires e<k, j, l>
+struct u<const k<j>*, l> {
+ u(const a<j>*);
+};
+template <typename j, template <typename> typename k, typename l>
+struct u<const k<j>*, l> {
+ u(const b<j>*);
+};
+
+template <typename>
+struct m;
+template <typename n, typename... o>
+struct m<n (*)(o...)> {
+ template <template <typename> typename j>
+ using p = j<o...>;
+};
+
+template <typename q, typename r>
+struct s {
+ template <typename... p>
+ struct D {
+ using v = f<u<r, p>...>;
+ };
+ template <typename... t>
+ s(t... p1) : x(p1...) {}
+ m<q>::template p<D>::v x;
+};
+template <typename w, typename... t>
+void fn1(w, t... p2) {
+ s<w, t...>(p2...);
+}
+int* fn2(int) { return nullptr; }
+void fn3() {
+ fn1(fn2, static_cast<const a<int>*>(nullptr));
+ fn1(fn2, static_cast<const b<int>*>(nullptr));
+}
+
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/164777
More information about the cfe-commits
mailing list