Index: clangd/index/SymbolCollector.cpp =================================================================== --- clangd/index/SymbolCollector.cpp +++ clangd/index/SymbolCollector.cpp @@ -290,6 +290,15 @@ index::IndexDataConsumer::ASTNodeInfo ASTNode) { assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set."); assert(CompletionAllocator && CompletionTUInfo); + // A declaration created for a friend declaration should not be used as the + // canonical declaration in the index. + if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) { + // If OrigD is an object of a friend declaration, skip it. + if (ASTNode.OrigD->getFriendObjectKind() != + Decl::FriendObjectKind::FOK_None) + return true; + D = ASTNode.OrigD; + } const NamedDecl *ND = llvm::dyn_cast(D); if (!ND) return true; Index: unittests/clangd/SymbolCollectorTests.cpp =================================================================== --- unittests/clangd/SymbolCollectorTests.cpp +++ unittests/clangd/SymbolCollectorTests.cpp @@ -812,6 +812,29 @@ QName("nx::Kind"), QName("nx::Kind_Fine"))); } +TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) { + Annotations Header(R"( + namespace nx { + class $z[[Z]] {}; + class X { + friend class Y; + friend class Z; + friend void foo(); + }; + class $y[[Y]] {}; + void $foo[[foo]]() {} + } + )"); + runSymbolCollector(Header.code(), /*Main=*/""); + + EXPECT_THAT(Symbols, + UnorderedElementsAre( + QName("nx"), QName("nx::X"), + AllOf(QName("nx::Y"), DeclRange(Header.range("y"))), + AllOf(QName("nx::Z"), DeclRange(Header.range("z"))), + AllOf(QName("nx::foo"), DeclRange(Header.range("foo"))))); +} + } // namespace } // namespace clangd } // namespace clang