hokein created this revision.
hokein added a reviewer: ilya-biryukov.
Herald added subscribers: kadircet, arphaman, jkorous, MaskRay, ioeric.

The previous solution (checking the AST) is not a reliable way to
determine whether a declaration is explicitly referenced by the source
code, we are still missing a few cases.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D55191

Files:
  clangd/XRefs.cpp
  unittests/clangd/XRefsTests.cpp

Index: unittests/clangd/XRefsTests.cpp
===================================================================
--- unittests/clangd/XRefsTests.cpp
+++ unittests/clangd/XRefsTests.cpp
@@ -1225,6 +1225,53 @@
   }
 }
 
+TEST(FindReferences, ExplicitSymbols) {
+  const char *Tests[] = {
+      R"cpp(
+      struct Foo { Foo* [self]() const; };
+      void f() {
+        if (Foo* T = foo.[^self]()) {} // Foo member call expr.
+      }
+      )cpp",
+
+      R"cpp(
+      struct Foo { Foo(int); };
+      Foo f() {
+        int [b];
+        return [^b]; // Foo constructor expr.
+      }
+      )cpp",
+
+      R"cpp(
+      struct Foo {};
+      void g(Foo);
+      Foo [f]();
+      void call() {
+        g([^f]());  // Foo constructor expr.
+      }
+      )cpp",
+
+      R"cpp(
+      void [foo](int);
+      void [foo](double);
+
+      namespace ns {
+      using [fo^o];
+      }
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    Annotations T(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    std::vector<Matcher<Location>> ExpectedLocations;
+    for (const auto &R : T.ranges())
+      ExpectedLocations.push_back(RangeIs(R));
+    EXPECT_THAT(findReferences(AST, T.point()),
+                ElementsAreArray(ExpectedLocations))
+        << Test;
+  }
+}
+
 TEST(FindReferences, NeedsIndex) {
   const char *Header = "int foo();";
   Annotations Main("int main() { [[f^oo]](); }");
Index: clangd/XRefs.cpp
===================================================================
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -139,30 +139,30 @@
                       SourceLocation Loc,
                       index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
     if (Loc == SearchedLocation) {
-      // Check whether the E has an implicit AST node (e.g. ImplicitCastExpr).
-      auto hasImplicitExpr = [](const Expr *E) {
-        if (!E || E->child_begin() == E->child_end())
+      // Check whether the give ND is explicitly referenced by the written
+      // identifier at Loc in the source code.
+      auto IsWrittenInCode = [this](const NamedDecl *ND, SourceLocation Loc) {
+        if (!ND)
           return false;
-        // Use the first child is good enough for most cases -- normally the
-        // expression returned by handleDeclOccurence contains exactly one
-        // child expression.
-        const auto *FirstChild = *E->child_begin();
-        return isa<ExprWithCleanups>(FirstChild) ||
-               isa<MaterializeTemporaryExpr>(FirstChild) ||
-               isa<CXXBindTemporaryExpr>(FirstChild) ||
-               isa<ImplicitCastExpr>(FirstChild);
+        auto &SM = AST.getSourceManager();
+        auto FileIDAndOffset = SM.getDecomposedLoc(Loc);
+        auto Code = SM.getBufferData(FileIDAndOffset.first);
+        auto IdentifierLength =
+            clang::Lexer::MeasureTokenLength(Loc, SM, AST.getLangOpts());
+        StringRef WrittenName =
+            Code.substr(FileIDAndOffset.second, IdentifierLength);
+        return WrittenName == ND->getDeclName().getAsString();
       };
-
-      bool IsExplicit = !hasImplicitExpr(ASTNode.OrigE);
+      bool WrittenInCode = IsWrittenInCode(dyn_cast<NamedDecl>(D), Loc);
       // Find and add definition declarations (for GoToDefinition).
       // We don't use parameter `D`, as Parameter `D` is the canonical
       // declaration, which is the first declaration of a redeclarable
       // declaration, and it could be a forward declaration.
       if (const auto *Def = getDefinition(D)) {
-        Decls[Def] |= IsExplicit;
+        Decls[Def] |= WrittenInCode;
       } else {
         // Couldn't find a definition, fall back to use `D`.
-        Decls[D] |= IsExplicit;
+        Decls[D] |= WrittenInCode;
       }
     }
     return true;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to