hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D123212

Files:
  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

Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -78,9 +78,17 @@
           "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;",
+       "template <template <typename> class T> class X {}; X<A> x;"},
+      {"namespace ns { template<typename T> struct ^A { ^A(T); }; } using "
+       "ns::^A;",
+       "A x(123);"},
       {
           "typedef bool ^Y; template <typename T> struct ^X {};",
           "X<Y> x;",
@@ -226,6 +234,7 @@
     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;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -229,6 +229,44 @@
     )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"});
+
+  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) {
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===================================================================
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -73,11 +73,23 @@
   }
 
   bool VisitTemplateSpecializationType(TemplateSpecializationType *TST) {
+    if (const auto *UTN = TST->getTemplateName().getAsUsingTemplateName()) {
+      add(UTN->getFoundDecl());
+      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 UsingTemplateName case.
+  bool TraverseTemplateName(TemplateName TN) {
+    if (const auto *UTN = TN.getAsUsingTemplateName())
+      add(UTN->getFoundDecl());
+    return Base::TraverseTemplateName(TN);
+  }
+
   bool VisitUsingType(UsingType *UT) {
     add(UT->getFoundDecl());
     return true;
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -384,11 +384,14 @@
       }
       void VisitDeducedTemplateSpecializationType(
           const DeducedTemplateSpecializationType *DTST) {
+        if (const auto *UTN = DTST->getTemplateName().getAsUsingTemplateName())
+          Outer.add(UTN->getFoundDecl(), 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);
@@ -440,6 +443,9 @@
         // class template specializations have a (specialized) CXXRecordDecl.
         else if (const CXXRecordDecl *RD = TST->getAsCXXRecordDecl())
           Outer.add(RD, Flags); // add(Decl) will despecialize if needed.
+        else if (const auto *UTN =
+                     TST->getTemplateName().getAsUsingTemplateName())
+          Outer.add(UTN->getFoundDecl(), Flags);
         else {
           // fallback: the (un-specialized) declaration from primary template.
           if (auto *TD = TST->getTemplateName().getAsTemplateDecl())
@@ -508,6 +514,9 @@
               Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) {
         report(TD, Flags);
       }
+      if (const auto *UTN =
+              Arg.getAsTemplateOrTemplatePattern().getAsUsingTemplateName())
+        add(UTN->getFoundDecl(), Flags);
     }
   }
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to