Author: Younan Zhang Date: 2025-10-23T09:24:04Z New Revision: cd6e913d00cf91b7bbac205351e967a68cd14797
URL: https://github.com/llvm/llvm-project/commit/cd6e913d00cf91b7bbac205351e967a68cd14797 DIFF: https://github.com/llvm/llvm-project/commit/cd6e913d00cf91b7bbac205351e967a68cd14797.diff LOG: [Clang] Handle TemplateTemplateParmDecl in concept cache (#164777) 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 Added: Modified: clang/lib/Sema/SemaConcept.cpp clang/test/SemaTemplate/concepts.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a1163e904dc1b..94dc7aac6b171 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)); +} + +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
