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(FirstChild) || - isa(FirstChild) || - isa(FirstChild) || - isa(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(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; 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> 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]](); }");