[clang-tools-extra] [clangd] Handle template template parameters in TargetFinder::VisitDeducedTemplateSpecializationType (PR #228601)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 4 22:38:24 PDT 2026
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/228601
>From 210a5db3cca9cd0a0ba27b1d43a47ec990ff2350 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Fri, 2 Oct 2026 15:21:43 -0400
Subject: [PATCH] [clangd] Handle template template parameters in
TargetFinder::VisitDeducedTemplateSpecializationType
Fixes https://github.com/clangd/clangd/issues/1870
---
clang-tools-extra/clangd/FindTarget.cpp | 20 +++++++++++------
.../clangd/unittests/FindTargetTests.cpp | 22 +++++++++++++++++++
2 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 142776d0dfaa7..a3379d1337d62 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -397,14 +397,20 @@ struct TargetFinder {
if (const auto *USD = DTST->getTemplateName().getAsUsingShadowDecl())
Outer.add(USD, Flags);
- // FIXME: This is a workaround for https://llvm.org/PR42914,
- // which is causing DTST->getDeducedType() to be empty. We
- // fall back to the template pattern and miss the instantiation
- // even when it's known in principle. Once that bug is fixed,
- // the following code can be removed (the existing handling in
- // VisitDeducedType() is sufficient).
- if (auto *TD = DTST->getTemplateName().getAsTemplateDecl())
+ // Template template parameters have no templated decl, so they must
+ // refer to the parameter itself.
+ if (const auto *Parm =
+ DTST->getTemplateName().getAsTemplateTemplateParmDecl()) {
+ Outer.add(Parm, Flags);
+ } else if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) {
+ // FIXME: This is a workaround for https://llvm.org/PR42914,
+ // which is causing DTST->getDeducedType() to be empty. We
+ // fall back to the template pattern and miss the instantiation
+ // even when it's known in principle. Once that bug is fixed,
+ // the following code can be removed (the existing handling in
+ // VisitDeducedType() is sufficient).
Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern);
+ }
}
void VisitDependentNameType(const DependentNameType *DNT) {
if (Outer.Resolver) {
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 0c0ef1262141f..94837803cd64c 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -593,6 +593,16 @@ TEST_F(TargetDeclTest, ClassTemplate) {
EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
{"struct Test", Rel::TemplatePattern});
+ Code = R"cpp(
+ // Deduced specialization of a template template parameter
+ template <template<typename> class X>
+ void foo() {
+ [[X]] a;
+ }
+ )cpp";
+ EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
+ "template <typename> class X");
+
Code = R"cpp(
// Deduction guide
template <typename T>
@@ -604,6 +614,18 @@ TEST_F(TargetDeclTest, ClassTemplate) {
[[Test]](I, I) -> Test<typename I::type>;
)cpp";
EXPECT_DECLS("CXXDeductionGuideDecl", {"template <typename T> struct Test"});
+
+ Flags.push_back("-std=c++26"); // for pack indexing
+
+ Code = R"cpp(
+ // Deduced specialization of an indexed template template parameter pack
+ template <template <typename> class... X>
+ void foo() {
+ [[X]]...[0] a(1);
+ }
+ )cpp";
+ EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
+ "template <typename> class ...X");
}
TEST_F(TargetDeclTest, Concept) {
More information about the cfe-commits
mailing list