Index: clang-tools-extra/trunk/clangd/index/SymbolCollector.h =================================================================== --- clang-tools-extra/trunk/clangd/index/SymbolCollector.h +++ clang-tools-extra/trunk/clangd/index/SymbolCollector.h @@ -134,9 +134,10 @@ void setIncludeLocation(const Symbol &S, SourceLocation); // Indexed macros, to be erased if they turned out to be include guards. llvm::DenseSet IndexedMacros; - // All refs collected from the AST. - // Only symbols declared in preamble (from #include) and referenced from the - // main file will be included. + // All refs collected from the AST. It includes: + // 1) symbols declared in the preamble and referenced from the main file ( + // which is not a header), or + // 2) symbols declared and referenced from the main file (which is a header) RefSlab::Builder Refs; // All relations collected from the AST. RelationSlab::Builder Relations; Index: clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp =================================================================== --- clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp +++ clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp @@ -314,10 +314,12 @@ if (IsOnlyRef && !CollectRef) return true; - // ND is the canonical (i.e. first) declaration. If it's in the main file, - // then no public declaration was visible, so assume it's main-file only. + // ND is the canonical (i.e. first) declaration. If it's in the main file + // (which is not a header), then no public declaration was visible, so assume + // it's main-file only. bool IsMainFileOnly = - SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())); + SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())) && + !ASTCtx->getLangOpts().IsHeaderFile; // In C, printf is a redecl of an implicit builtin! So check OrigD instead. if (ASTNode.OrigD->isImplicit() || !shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly)) Index: clang-tools-extra/trunk/clangd/unittests/SymbolCollectorTests.cpp =================================================================== --- clang-tools-extra/trunk/clangd/unittests/SymbolCollectorTests.cpp +++ clang-tools-extra/trunk/clangd/unittests/SymbolCollectorTests.cpp @@ -626,6 +626,33 @@ EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "c").ID, _)))); } + +TEST_F(SymbolCollectorTest, HeaderAsMainFile) { + CollectorOpts.RefFilter = RefKind::All; + Annotations Header(R"( + class $Foo[[Foo]] {}; + + void $Func[[Func]]() { + $Foo[[Foo]] fo; + } + )"); + // The main file is normal .cpp file, we shouldn't collect any refs of symbols + // which are not declared in the preamble. + TestFileName = testPath("foo.cpp"); + runSymbolCollector("", Header.code()); + EXPECT_THAT(Refs, UnorderedElementsAre()); + + // Run the .h file as main file, we should collect the refs. + TestFileName = testPath("foo.h"); + runSymbolCollector("", Header.code(), + /*ExtraArgs=*/{"-xobjective-c++-header"}); + EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"), QName("Func"))); + EXPECT_THAT(Refs, UnorderedElementsAre(Pair(findSymbol(Symbols, "Foo").ID, + HaveRanges(Header.ranges("Foo"))), + Pair(findSymbol(Symbols, "Func").ID, + HaveRanges(Header.ranges("Func"))))); +} + TEST_F(SymbolCollectorTest, RefsInHeaders) { CollectorOpts.RefFilter = RefKind::All; CollectorOpts.RefsInHeaders = true;