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 @@ -460,6 +460,12 @@ void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { Outer.add(POE->getSyntacticForm(), Flags); } + void VisitCXXNewExpr(const CXXNewExpr *CNE) { + Outer.add(CNE->getOperatorNew(), Flags); + } + void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE) { + Outer.add(CDE->getOperatorDelete(), Flags); + } }; Visitor(*this, Flags).Visit(S); } 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 @@ -238,6 +238,11 @@ llvm::DenseMap ResultIndex; auto AddResultDecl = [&](const NamedDecl *D) { + // FIXME: C++ global operator new/delete are implicitly declared in every + // TU, these functions have invalid source location. In case where users + // provide these function definitions (to replace the default ones), + // getCanonicalDecl may return the implicit version, which will be dropped + // becase of the invalid source location. D = llvm::cast(D->getCanonicalDecl()); auto Loc = makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath); 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 @@ -559,6 +559,37 @@ }; )cpp"; EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)"); + + Flags.push_back("--target=x86_64-pc-linux-gnu"); + Code = R"cpp( + struct X { + static void *operator new(unsigned long); + }; + auto* k = [[new]] X(); + )cpp"; + EXPECT_DECLS("CXXNewExpr", "static void *operator new(unsigned long)"); + Code = R"cpp( + void *operator new(unsigned long); + auto* k = [[new]] int(); + )cpp"; + EXPECT_DECLS("CXXNewExpr", "void *operator new(unsigned long)"); + + Code = R"cpp( + struct X { + static void operator delete(void *) noexcept; + }; + void k(X* x) { + [[delete]] x; + } + )cpp"; + EXPECT_DECLS("CXXDeleteExpr", "static void operator delete(void *) noexcept"); + Code = R"cpp( + void operator delete(void *) noexcept; + void k(int* x) { + [[delete]] x; + } + )cpp"; + EXPECT_DECLS("CXXDeleteExpr", "void operator delete(void *) noexcept"); } TEST_F(TargetDeclTest, DependentExprs) {