[clang-tools-extra] r373318 - [clangd] Handle template arguments in findExplicitReferences

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 1 03:02:24 PDT 2019


Author: ibiryukov
Date: Tue Oct  1 03:02:23 2019
New Revision: 373318

URL: http://llvm.org/viewvc/llvm-project?rev=373318&view=rev
Log:
[clangd] Handle template arguments in findExplicitReferences

Reviewers: kadircet

Reviewed By: kadircet

Subscribers: MaskRay, jkorous, arphaman, usaxena95, cfe-commits

Tags: #clang

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

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

Modified: clang-tools-extra/trunk/clangd/FindTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FindTarget.cpp?rev=373318&r1=373317&r2=373318&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/FindTarget.cpp (original)
+++ clang-tools-extra/trunk/clangd/FindTarget.cpp Tue Oct  1 03:02:23 2019
@@ -22,6 +22,7 @@
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeLocVisitor.h"
@@ -565,6 +566,34 @@ public:
     return true;
   }
 
+  // We re-define Traverse*, since there's no corresponding Visit*.
+  // TemplateArgumentLoc is the only way to get locations for references to
+  // template template parameters.
+  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) {
+    switch (A.getArgument().getKind()) {
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      reportReference(ReferenceLoc{A.getTemplateQualifierLoc(),
+                                   A.getTemplateNameLoc(),
+                                   {A.getArgument()
+                                        .getAsTemplateOrTemplatePattern()
+                                        .getAsTemplateDecl()}},
+                      DynTypedNode::create(A.getArgument()));
+      break;
+    case TemplateArgument::Declaration:
+      break; // FIXME: can this actually happen in TemplateArgumentLoc?
+    case TemplateArgument::Integral:
+    case TemplateArgument::Null:
+    case TemplateArgument::NullPtr:
+      break; // no references.
+    case TemplateArgument::Pack:
+    case TemplateArgument::Type:
+    case TemplateArgument::Expression:
+      break; // Handled by VisitType and VisitExpression.
+    };
+    return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);
+  }
+
   bool VisitDecl(Decl *D) {
     visitNode(DynTypedNode::create(*D));
     return true;
@@ -623,15 +652,19 @@ private:
     auto Ref = explicitReference(N);
     if (!Ref)
       return;
+    reportReference(*Ref, N);
+  }
+
+  void reportReference(const ReferenceLoc &Ref, DynTypedNode N) {
     // Our promise is to return only references from the source code. If we lack
     // location information, skip these nodes.
     // Normally this should not happen in practice, unless there are bugs in the
     // traversals or users started the traversal at an implicit node.
-    if (Ref->NameLoc.isInvalid()) {
+    if (Ref.NameLoc.isInvalid()) {
       dlog("invalid location at node {0}", nodeToString(N));
       return;
     }
-    Out(*Ref);
+    Out(Ref);
   }
 
   llvm::function_ref<void(ReferenceLoc)> Out;

Modified: clang-tools-extra/trunk/clangd/unittests/FindTargetTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/FindTargetTests.cpp?rev=373318&r1=373317&r2=373318&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/FindTargetTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/FindTargetTests.cpp Tue Oct  1 03:02:23 2019
@@ -750,6 +750,39 @@ TEST_F(FindExplicitReferencesTest, All)
             }
         )cpp",
            "0: targets = {I}\n"},
+          // Template template parameters.
+          {R"cpp(
+            template <class T> struct vector {};
+
+            template <template<class> class TT, template<class> class ...TP>
+            void foo() {
+              $0^TT<int> x;
+              $1^foo<$2^TT>();
+              $3^foo<$4^vector>()
+              $5^foo<$6^TP...>();
+            }
+        )cpp",
+           "0: targets = {TT}\n"
+           "1: targets = {foo}\n"
+           "2: targets = {TT}\n"
+           "3: targets = {foo}\n"
+           "4: targets = {vector}\n"
+           "5: targets = {foo}\n"
+           "6: targets = {TP}\n"},
+          // Non-type template parameters with declarations.
+          {R"cpp(
+            int func();
+            template <int(*)()> struct wrapper {};
+
+            template <int(*FuncParam)()>
+            void foo() {
+              $0^wrapper<$1^func> w;
+              $2^FuncParam();
+            }
+        )cpp",
+           "0: targets = {wrapper<&func>}\n"
+           "1: targets = {func}\n"
+           "2: targets = {FuncParam}\n"},
       };
 
   for (const auto &C : Cases) {




More information about the cfe-commits mailing list