diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -61,7 +61,7 @@ // We only need declarations, because we don't count references. IndexOpts.SystemSymbolFilter = index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly; - IndexOpts.IndexFunctionLocals = false; + IndexOpts.IndexFunctionLocals = true; if (IsIndexMainAST) { // We only collect refs when indexing main AST. CollectorOpts.RefFilter = RefKind::All; diff --git a/clang-tools-extra/clangd/index/IndexAction.cpp b/clang-tools-extra/clangd/index/IndexAction.cpp --- a/clang-tools-extra/clangd/index/IndexAction.cpp +++ b/clang-tools-extra/clangd/index/IndexAction.cpp @@ -212,6 +212,7 @@ index::IndexingOptions IndexOpts; IndexOpts.SystemSymbolFilter = index::IndexingOptions::SystemSymbolFilterKind::All; + IndexOpts.IndexFunctionLocals = true; Opts.CollectIncludePath = true; if (Opts.Origin == SymbolOrigin::Unknown) Opts.Origin = SymbolOrigin::Static; diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -223,6 +223,13 @@ if (!IsMainFileOnly && ND.isInAnonymousNamespace()) return false; + // Index all virtual and overridding methods. + if (const auto *CXXMD = llvm::dyn_cast(&ND)) + if (CXXMD->isVirtual() || !CXXMD->overridden_methods().empty()) + return true; + // For function local symbols, index only classes. + if (ND.getParentFunctionOrMethod()) + return isa(ND); // We want most things but not "local" symbols such as symbols inside // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl. // FIXME: Need a matcher for ExportDecl in order to include symbols declared diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -72,7 +72,7 @@ struct LocalClass {}; int local_var; })cpp"; - EXPECT_THAT(getSymbols(TU, "l"), IsEmpty()); + EXPECT_THAT(getSymbols(TU, "l"), ElementsAre(QName("LocalClass"))); EXPECT_THAT(getSymbols(TU, "p"), IsEmpty()); } diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp --- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -138,6 +138,13 @@ namespace nx { class X{}; auto f() { int Local; } // auto ensures function body is parsed. + auto foo() { + class LocalBase { + virtual void LocalVirtual(); + void LocalConcrete(); + int BaseMember; + }; + } struct { int x; } var; } )", @@ -154,6 +161,11 @@ EXPECT_TRUE(shouldCollect("InAnonymous", /*Qualified=*/false)); EXPECT_TRUE(shouldCollect("g")); + // Locals. + EXPECT_TRUE(shouldCollect("LocalBase", /*Qualified=*/false)); + EXPECT_TRUE(shouldCollect("LocalVirtual", /*Qualified=*/false)); + EXPECT_FALSE(shouldCollect("LocalConcrete", /*Qualified=*/false)); + EXPECT_FALSE(shouldCollect("BaseMember", /*Qualified=*/false)); EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false)); } diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -1637,14 +1637,28 @@ template struct $5^TemplateBase {}; struct $5[[Child3]] : public TemplateBase {}; + + // Local classes. + void LocationFunction() { + struct $0[[LocalClass1]] : Base { + void $1[[Foo]]() override; + }; + struct $6^LocalBase { + virtual void $7^Bar(); + }; + struct $6[[LocalClass2]]: LocalBase { + void $7[[Bar]]() override; + }; + } )cpp"; Annotations Code(Test); auto TU = TestTU::withCode(Code.code()); auto AST = TU.build(); - for (StringRef Label : {"0", "1", "2", "3", "4", "5"}) { + auto Index = TU.index(); + for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) { for (const auto &Point : Code.points(Label)) { - EXPECT_THAT(findImplementations(AST, Point, TU.index().get()), + EXPECT_THAT(findImplementations(AST, Point, Index.get()), UnorderedPointwise(DeclRange(), Code.ranges(Label))) << Code.code() << " at " << Point << " for Label " << Label; }