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 @@ -596,8 +596,30 @@ } void VisitMemberExpr(const MemberExpr *E) { + auto NameLocation = E->getMemberNameInfo().getLoc(); + // If E is the destructor call, then NameLocation would point to the + // location of the tilde, i.e. + // + // Foo f; + // f.~/*something*/Foo(); + // ^ + // f.~Foo(); + // ^ + // + // When renaming, this would cause incorrect behavior. We consider the + // location of the type name to be the right one (this is also the + // location used to trigger the rename itself, triggering rename with + // cursor at `~` won't work. + // + // Foo f; + // f.~/*something*/Foo(); + // ^ + // f.~Foo(); + // ^ + if (llvm::dyn_cast(E->getMemberDecl())) + NameLocation = E->getEndLoc(); Refs.push_back(ReferenceLoc{E->getQualifierLoc(), - E->getMemberNameInfo().getLoc(), + NameLocation, /*IsDecl=*/false, {E->getFoundDecl()}}); } diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -265,6 +265,22 @@ } )cpp", + // Destructor. + R"cpp( + class [[F^oo]] { + public: + ~[[^Foo]](); + }; + + [[Foo^]]::~[[^Foo]]() {} + + int main() { + [[Fo^o]] f; + f.~/*something*/[[^Foo]](); + f.~[[^Foo]](); + } + )cpp", + // CXXConstructor initializer list. R"cpp( class Baz {};