diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -384,11 +384,14 @@ } void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *DTST) { + 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, - // this method can be removed (the existing handling in + // the following code can be removed (the existing handling in // VisitDeducedType() is sufficient). if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); @@ -419,6 +422,9 @@ VisitTemplateSpecializationType(const TemplateSpecializationType *TST) { // Have to handle these case-by-case. + if (const auto *UTN = TST->getTemplateName().getAsUsingShadowDecl()) + Outer.add(UTN, Flags); + // templated type aliases: there's no specialized/instantiated using // decl to point to. So try to find a decl for the underlying type // (after substitution), and failing that point to the (templated) using @@ -508,6 +514,9 @@ Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) { report(TD, Flags); } + if (const auto *USD = + Arg.getAsTemplateOrTemplatePattern().getAsUsingShadowDecl()) + add(USD, Flags); } } }; diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -75,11 +75,22 @@ } bool VisitTemplateSpecializationType(TemplateSpecializationType *TST) { + // Using templateName case is handled by the override TraverseTemplateName. + if (TST->getTemplateName().getKind() == TemplateName::UsingTemplate) + return true; add(TST->getTemplateName().getAsTemplateDecl()); // Primary template. add(TST->getAsCXXRecordDecl()); // Specialization return true; } + // There is no VisitTemplateName in RAV, thus we override the Traverse version + // to handle the Using TemplateName case. + bool TraverseTemplateName(TemplateName TN) { + if (const auto *USD = TN.getAsUsingShadowDecl()) + add(USD); + return Base::TraverseTemplateName(TN); + } + bool VisitUsingType(UsingType *UT) { add(UT->getFoundDecl()); return true; diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -229,6 +229,45 @@ )cpp"; EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias}, {"void waldo()"}); + + Code = R"cpp( + namespace ns { + template class S {}; + } + + using ns::S; + + template + using A = [[S]]; + )cpp"; + EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias}, + {"template class S"}, + {"class S", Rel::TemplatePattern}); + + Code = R"cpp( + namespace ns { + template class S {}; + } + + using ns::S; + template