[clang-tools-extra] 95f0f69 - [clangd] Handle the new Using TemplateName.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 20 06:42:34 PDT 2022


Author: Haojian Wu
Date: 2022-04-20T15:42:24+02:00
New Revision: 95f0f69441fb8b33528d25ba2b40e3fa703c6ea5

URL: https://github.com/llvm/llvm-project/commit/95f0f69441fb8b33528d25ba2b40e3fa703c6ea5
DIFF: https://github.com/llvm/llvm-project/commit/95f0f69441fb8b33528d25ba2b40e3fa703c6ea5.diff

LOG: [clangd] Handle the new Using TemplateName.

Add supports in FindTarget and IncludeCleaner. This would
improve AST-based features on a tempalte which is found via a using
declaration. For example, go-to-def on `vect^or<int> v;` gives us the
location of `using std::vector`, which was not previously.

Base on https://reviews.llvm.org/D123127

Differential Revision: https://reviews.llvm.org/D123212

Added: 
    

Modified: 
    clang-tools-extra/clangd/FindTarget.cpp
    clang-tools-extra/clangd/IncludeCleaner.cpp
    clang-tools-extra/clangd/unittests/FindTargetTests.cpp
    clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 404e852e179ca..dcdac55c26b70 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -384,11 +384,14 @@ struct TargetFinder {
       }
       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 @@ struct TargetFinder {
       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 @@ struct TargetFinder {
               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
index e6c8d9e76ed67..5b7f01d82fbac 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -79,11 +79,29 @@ class ReferencedLocationCrawler
   }
 
   bool VisitTemplateSpecializationType(TemplateSpecializationType *TST) {
-    add(TST->getTemplateName().getAsTemplateDecl()); // Primary template.
+    // Using templateName case is handled by the override TraverseTemplateName.
+    if (TST->getTemplateName().getKind() == TemplateName::UsingTemplate)
+      return true;
     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) {
+    VisitTemplateName(TN);
+    return Base::TraverseTemplateName(TN);
+  }
+  // A pseudo VisitTemplateName, dispatched by the above TraverseTemplateName!
+  bool VisitTemplateName(TemplateName TN) {
+    if (const auto *USD = TN.getAsUsingShadowDecl()) {
+      add(USD);
+      return true;
+    }
+    add(TN.getAsTemplateDecl()); // Primary template.
+    return true;
+  }
+
   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
index 7026f7fced3c9..c21114fa45b07 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -229,6 +229,45 @@ TEST_F(TargetDeclTest, UsingDecl) {
     )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias},
                {"void waldo()"});
+
+  Code = R"cpp(
+    namespace ns {
+    template<typename T> class S {};
+    }
+
+    using ns::S;
+
+    template<typename T>
+    using A = [[S]]<T>;
+  )cpp";
+  EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias},
+               {"template <typename T> class S"},
+               {"class S", Rel::TemplatePattern});
+
+  Code = R"cpp(
+    namespace ns {
+    template<typename T> class S {};
+    }
+
+    using ns::S;
+    template <template <typename> class T> class X {};
+    using B = X<[[S]]>;
+  )cpp";
+  EXPECT_DECLS("TemplateArgumentLoc", {"using ns::S", Rel::Alias},
+               {"template <typename T> class S"});
+
+  Code = R"cpp(
+    namespace ns {
+    template<typename T> class S { public: S(T); };
+    }
+
+    using ns::S;
+    [[S]] s(123);
+  )cpp";
+  Flags.push_back("-std=c++17"); // For CTAD feature.
+  EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
+               {"using ns::S", Rel::Alias}, {"template <typename T> class S"},
+               {"class S", Rel::TemplatePattern});
 }
 
 TEST_F(TargetDeclTest, BaseSpecifier) {

diff  --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index ffecea5713215..4a376a87297f9 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -79,9 +79,22 @@ TEST(IncludeCleaner, ReferencedLocations) {
           "using namespace ns;",
       },
       {
+          // Refs from UsingTypeLoc and implicit constructor!
           "struct ^A {}; using B = A; using ^C = B;",
           "C a;",
       },
+      {"namespace ns { template<typename T> class A {}; } using ns::^A;",
+       "A<int>* a;"},
+      {"namespace ns { template<typename T> class A {}; } using ns::^A;",
+       R"cpp(
+          template <template <typename> class T> class X {};
+          X<A> x;
+        )cpp"},
+      {R"cpp(
+          namespace ns { template<typename T> struct ^A { ^A(T); }; }
+          using ns::^A;
+       )cpp",
+       "A CATD(123);"},
       {
           "typedef bool ^Y; template <typename T> struct ^X {};",
           "X<Y> x;",
@@ -227,6 +240,7 @@ TEST(IncludeCleaner, ReferencedLocations) {
     TU.Code = T.MainCode;
     Annotations Header(T.HeaderCode);
     TU.HeaderCode = Header.code().str();
+    TU.ExtraArgs.push_back("-std=c++17");
     auto AST = TU.build();
 
     std::vector<Position> Points;


        


More information about the cfe-commits mailing list