[llvm-branch-commits] [clang-tools-extra] ed3b1f9 - [clangd] go-to-implementation on a base class jumps to all subclasses.

Haojian Wu via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jan 8 04:56:15 PST 2021


Author: Haojian Wu
Date: 2021-01-08T13:50:57+01:00
New Revision: ed3b1f906115a0dcd2542fa294d0382a42eb177d

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

LOG: [clangd] go-to-implementation on a base class jumps to all subclasses.

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

Added: 
    

Modified: 
    clang-tools-extra/clangd/XRefs.cpp
    clang-tools-extra/clangd/XRefs.h
    clang-tools-extra/clangd/unittests/XRefsTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index c7ec401c6479..ebe03e74a4a7 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -292,13 +292,14 @@ const NamedDecl *getPreferredDecl(const NamedDecl *D) {
   return D;
 }
 
-std::vector<LocatedSymbol> findOverrides(llvm::DenseSet<SymbolID> IDs,
-                                         const SymbolIndex *Index,
-                                         llvm::StringRef MainFilePath) {
+std::vector<LocatedSymbol> findImplementors(llvm::DenseSet<SymbolID> IDs,
+                                            RelationKind Predicate,
+                                            const SymbolIndex *Index,
+                                            llvm::StringRef MainFilePath) {
   if (IDs.empty())
     return {};
   RelationsRequest Req;
-  Req.Predicate = RelationKind::OverriddenBy;
+  Req.Predicate = Predicate;
   Req.Subjects = std::move(IDs);
   std::vector<LocatedSymbol> Results;
   Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
@@ -458,7 +459,8 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
     });
   }
 
-  auto Overrides = findOverrides(VirtualMethods, Index, MainFilePath);
+  auto Overrides = findImplementors(VirtualMethods, RelationKind::OverriddenBy,
+                                    Index, MainFilePath);
   Result.insert(Result.end(), Overrides.begin(), Overrides.end());
   return Result;
 }
@@ -1239,12 +1241,20 @@ std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
   }
   DeclRelationSet Relations =
       DeclRelation::TemplatePattern | DeclRelation::Alias;
-  llvm::DenseSet<SymbolID> VirtualMethods;
-  for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations))
-    if (const CXXMethodDecl *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND))
-      if (CXXMD->isVirtual())
-        VirtualMethods.insert(getSymbolID(ND));
-  return findOverrides(std::move(VirtualMethods), Index, *MainFilePath);
+  llvm::DenseSet<SymbolID> IDs;
+  RelationKind QueryKind;
+  for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) {
+    if (const auto *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
+      if (CXXMD->isVirtual()) {
+        IDs.insert(getSymbolID(ND));
+        QueryKind = RelationKind::OverriddenBy;
+      }
+    } else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
+      IDs.insert(getSymbolID(RD));
+      QueryKind = RelationKind::BaseOf;
+    }
+  }
+  return findImplementors(std::move(IDs), QueryKind, Index, *MainFilePath);
 }
 
 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,

diff  --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h
index eca174f59096..4c745eb9bc51 100644
--- a/clang-tools-extra/clangd/XRefs.h
+++ b/clang-tools-extra/clangd/XRefs.h
@@ -83,7 +83,9 @@ struct ReferencesResult {
   bool HasMore = false;
 };
 
-/// Returns implementations of the virtual function at a specified \p Pos.
+/// Returns implementations at a specified \p Pos:
+///   - overrides for a virtual method;
+///   - subclasses for a base class;
 std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
                                                const SymbolIndex *Index);
 

diff  --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 26e06dad9250..508634ec908a 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1611,11 +1611,11 @@ TEST(LocateSymbol, NearbyIdentifier) {
 
 TEST(FindImplementations, Inheritance) {
   llvm::StringRef Test = R"cpp(
-    struct Base {
+    struct $0^Base {
       virtual void F$1^oo();
       void C$4^oncrete();
     };
-    struct Child1 : Base {
+    struct $0[[Child1]] : Base {
       void $1[[Fo$3^o]]() override;
       virtual void B$2^ar();
       void Concrete();  // No implementations for concrete methods.
@@ -1625,7 +1625,7 @@ TEST(FindImplementations, Inheritance) {
       void $2[[Bar]]() override;
     };
     void FromReference() {
-      Base* B;
+      $0^Base* B;
       B->Fo$1^o();
       B->C$4^oncrete();
       &Base::Fo$1^o;
@@ -1633,12 +1633,16 @@ TEST(FindImplementations, Inheritance) {
       C1->B$2^ar();
       C1->Fo$3^o();
     }
+    // CRTP should work.
+    template<typename T>
+    struct $5^TemplateBase {};
+    struct $5[[Child3]] : public TemplateBase<Child3> {};
   )cpp";
 
   Annotations Code(Test);
   auto TU = TestTU::withCode(Code.code());
   auto AST = TU.build();
-  for (const std::string &Label : {"1", "2", "3", "4"}) {
+  for (StringRef Label : {"0", "1", "2", "3", "4", "5"}) {
     for (const auto &Point : Code.points(Label)) {
       EXPECT_THAT(findImplementations(AST, Point, TU.index().get()),
                   UnorderedPointwise(DeclRange(), Code.ranges(Label)))


        


More information about the llvm-branch-commits mailing list