Index: clangd/XRefs.cpp =================================================================== --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -361,7 +361,7 @@ class ReferenceFinder : public index::IndexDataConsumer { public: struct Reference { - const Decl *Target; + const Decl *CanonicalTarget; SourceLocation Loc; index::SymbolRoleSet Role; }; @@ -370,22 +370,23 @@ const std::vector &TargetDecls) : AST(AST) { for (const Decl *D : TargetDecls) - Targets.insert(D); + CanonicalTargets.insert(D->getCanonicalDecl()); } std::vector take() && { std::sort(References.begin(), References.end(), [](const Reference &L, const Reference &R) { - return std::tie(L.Loc, L.Target, L.Role) < - std::tie(R.Loc, R.Target, R.Role); + return std::tie(L.Loc, L.CanonicalTarget, L.Role) < + std::tie(R.Loc, R.CanonicalTarget, R.Role); }); // We sometimes see duplicates when parts of the AST get traversed twice. - References.erase(std::unique(References.begin(), References.end(), - [](const Reference &L, const Reference &R) { - return std::tie(L.Target, L.Loc, L.Role) == - std::tie(R.Target, R.Loc, R.Role); - }), - References.end()); + References.erase( + std::unique(References.begin(), References.end(), + [](const Reference &L, const Reference &R) { + return std::tie(L.CanonicalTarget, L.Loc, L.Role) == + std::tie(R.CanonicalTarget, R.Loc, R.Role); + }), + References.end()); return std::move(References); } @@ -394,15 +395,16 @@ ArrayRef Relations, SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override { + assert(D->isCanonicalDecl() && "expect D to be a canonical declaration"); const SourceManager &SM = AST.getSourceManager(); Loc = SM.getFileLoc(Loc); - if (SM.isWrittenInMainFile(Loc) && Targets.count(D)) + if (SM.isWrittenInMainFile(Loc) && CanonicalTargets.count(D)) References.push_back({D, Loc, Roles}); return true; } private: - llvm::SmallSet Targets; + llvm::SmallSet CanonicalTargets; std::vector References; const ASTContext &AST; }; Index: unittests/clangd/XRefsTests.cpp =================================================================== --- unittests/clangd/XRefsTests.cpp +++ unittests/clangd/XRefsTests.cpp @@ -1113,37 +1113,45 @@ const char *Tests[] = { R"cpp(// Local variable int main() { - int $foo[[foo]]; - $foo[[^foo]] = 2; - int test1 = $foo[[foo]]; + int [[foo]]; + [[^foo]] = 2; + int test1 = [[foo]]; } )cpp", R"cpp(// Struct namespace ns1 { - struct $foo[[Foo]] {}; + struct [[Foo]] {}; } // namespace ns1 int main() { - ns1::$foo[[Fo^o]]* Params; + ns1::[[Fo^o]]* Params; + } + )cpp", + + R"cpp(// Forward declaration + class [[Foo]]; + class [[Foo]] {} + int main() { + [[Fo^o]] foo; } )cpp", R"cpp(// Function - int $foo[[foo]](int) {} + int [[foo]](int) {} int main() { - auto *X = &$foo[[^foo]]; - $foo[[foo]](42) + auto *X = &[[^foo]]; + [[foo]](42) } )cpp", R"cpp(// Field struct Foo { - int $foo[[foo]]; - Foo() : $foo[[foo]](0) {} + int [[foo]]; + Foo() : [[foo]](0) {} }; int main() { Foo f; - f.$foo[[f^oo]] = 1; + f.[[f^oo]] = 1; } )cpp", @@ -1152,29 +1160,29 @@ int Foo::[[foo]]() {} int main() { Foo f; - f.^foo(); + f.[[^foo]](); } )cpp", R"cpp(// Typedef - typedef int $foo[[Foo]]; + typedef int [[Foo]]; int main() { - $foo[[^Foo]] bar; + [[^Foo]] bar; } )cpp", R"cpp(// Namespace - namespace $foo[[ns]] { + namespace [[ns]] { struct Foo {}; } // namespace ns - int main() { $foo[[^ns]]::Foo foo; } + int main() { [[^ns]]::Foo foo; } )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("foo")) + for (const auto &R : T.ranges()) ExpectedLocations.push_back(RangeIs(R)); EXPECT_THAT(findReferences(AST, T.point()), ElementsAreArray(ExpectedLocations))