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 @@ -1838,6 +1838,20 @@ EXPECT_THAT(TU.headerSymbols(), Not(Contains(QName("X")))); } +TEST_F(SymbolCollectorTest, NoCrashOnObjCMethodCStyleParam) { + auto TU = TestTU::withCode(R"objc( + @interface Foo + - (void)fun:(bool)foo, bool bar; + @end + )objc"); + TU.ExtraArgs.push_back("-xobjective-c++"); + + TU.build(); + // We mostly care about not crashing. + EXPECT_THAT(TU.headerSymbols(), + UnorderedElementsAre(QName("Foo"), QName("Foo::fun:"))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3529,9 +3529,11 @@ Result.AddTypedTextChunk(""); } unsigned Idx = 0; + // The extra Idx < Sel.getNumArgs() check is needed due to legacy C-style + // method parameters. for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), PEnd = Method->param_end(); - P != PEnd; (void)++P, ++Idx) { + P != PEnd && Idx < Sel.getNumArgs(); (void)++P, ++Idx) { if (Idx > 0) { std::string Keyword; if (Idx > StartParameter)