diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -270,6 +270,15 @@ // Record the underlying decl instead, if allowed. D = USD->getTargetDecl(); Flags |= Rel::Underlying; // continue with the underlying decl. + } else if (const ObjCImplementationDecl *IID = + dyn_cast(D)) { + // Objective-C implementation should map back to its interface. + D = IID->getClassInterface(); + } else if (const ObjCCategoryImplDecl *CID = + dyn_cast(D)) { + // Objective-C category implementation should map back to its category + // declaration. + D = CID->getCategoryDecl(); } if (const Decl *Pat = getTemplatePattern(D)) { diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -239,10 +239,10 @@ // - implementation: @implementation MyClass ... @end // // Clang will consider the forward declaration to be the canonical declaration -// because it is first, but we actually want the class definition if it is -// available since that is what a programmer would consider the real definition -// to be. -const NamedDecl *getNonStandardCanonicalDecl(const NamedDecl *D) { +// because it is first. We actually want the class definition if it is +// available since that is what a programmer would consider the primary +// declaration to be. +const NamedDecl *getPreferredDecl(const NamedDecl *D) { D = llvm::cast(D->getCanonicalDecl()); // Prefer Objective-C class definitions over the forward declaration. @@ -268,7 +268,7 @@ llvm::DenseMap ResultIndex; auto AddResultDecl = [&](const NamedDecl *D) { - D = getNonStandardCanonicalDecl(D); + D = getPreferredDecl(D); auto Loc = makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath); if (!Loc) diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -608,6 +608,24 @@ )cpp"; EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo"); + Code = R"cpp( + @interface Foo + @end + @implementation [[Foo]] + @end + )cpp"; + EXPECT_DECLS("ObjCImplementationDecl", "@interface Foo"); + + Code = R"cpp( + @interface Foo + @end + @interface Foo (Ext) + @end + @implementation [[Foo]] (Ext) + @end + )cpp"; + EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)"); + Code = R"cpp( @protocol Foo @end