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 @@ -125,6 +125,13 @@ [Foo [[x]]:2 [[^y]]:4]; } )cpp", + R"cpp( // Label + int main() { + goto [[^theLabel]]; + [[theLabel]]: + return 1; + } + )cpp", }; for (const char *Test : Tests) { Annotations T(Test); diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -144,6 +144,18 @@ Parent, ParentDC, Roles, Relations, E); } + bool VisitGotoStmt(GotoStmt *S) { + return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent, + ParentDC, + unsigned(SymbolRole::NameReference)); + } + + bool VisitLabelStmt(LabelStmt *S) { + if (IndexCtx.shouldIndexFunctionLocalSymbols()) + return IndexCtx.handleDecl(S->getDecl()); + return true; + } + bool VisitMemberExpr(MemberExpr *E) { SourceLocation Loc = E->getMemberLoc(); if (Loc.isInvalid()) diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp --- a/clang/unittests/Index/IndexTests.cpp +++ b/clang/unittests/Index/IndexTests.cpp @@ -218,6 +218,28 @@ EXPECT_THAT(Index->Symbols, Not(Contains(QName("bar")))); } +TEST(IndexTest, IndexLabels) { + std::string Code = R"cpp( + int main() { + goto theLabel; + theLabel: + return 1; + } + )cpp"; + auto Index = std::make_shared(); + IndexingOptions Opts; + Opts.IndexFunctionLocals = true; + tooling::runToolOnCode(std::make_unique(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, + Contains(AllOf(QName("theLabel"), WrittenAt(Position(3, 16)), + DeclAt(Position(4, 11))))); + + Opts.IndexFunctionLocals = false; + Index->Symbols.clear(); + tooling::runToolOnCode(std::make_unique(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, Not(Contains(QName("theLabel")))); +} + TEST(IndexTest, IndexExplicitTemplateInstantiation) { std::string Code = R"cpp( template