Index: clangd/XRefs.cpp =================================================================== --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -14,6 +14,16 @@ using namespace llvm; namespace { +bool IsDefinition(const Decl* D) { + if (const auto *TD = dyn_cast(D)) + return TD->isThisDeclarationADefinition(); + else if (const auto *VD = dyn_cast(D)) + return VD->isThisDeclarationADefinition(); + else if (const auto *FD = dyn_cast(D)) + return FD->isThisDeclarationADefinition(); + return false; +} + /// Finds declarations locations that a given source location refers to. class DeclarationAndMacrosFinder : public index::IndexDataConsumer { std::vector Decls; @@ -50,8 +60,20 @@ ArrayRef Relations, FileID FID, unsigned Offset, index::IndexDataConsumer::ASTNodeInfo ASTNode) override { - if (isSearchedLocation(FID, Offset)) - Decls.push_back(D); + if (isSearchedLocation(FID, Offset)) { + // 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. + auto Def = std::find_if(D->redecls_begin(), D->redecls_end(), + [](const Decl *D) { return IsDefinition(D); }); + if (Def != D->redecls_end()) { + Decls.push_back(*Def); + } else { + // Couldn't find a definition, fall back to use `D`. + Decls.push_back(D); + } + } return true; } Index: unittests/clangd/XRefsTests.cpp =================================================================== --- unittests/clangd/XRefsTests.cpp +++ unittests/clangd/XRefsTests.cpp @@ -203,6 +203,18 @@ #define MACRO 2 #undef macro )cpp", + + R"cpp(// Forward class declaration + class Foo; + [[class Foo {}]]; + F^oo* foo(); + )cpp", + + R"cpp(// Function declaration + void foo(); + void g() { f^oo(); } + [[void foo() {}]] + )cpp", }; for (const char *Test : Tests) { Annotations T(Test);