https://github.com/b10902118 created https://github.com/llvm/llvm-project/pull/171860
For https://github.com/llvm/llvm-project/issues/169824. The main purpose is to complete call hierarchy and reference links. Local variables is marked at their init expression's beginning, which is intended for better understanding than marking at the end of the scope. Current limitation is that it assumes a BindTemporaryExpr will always lead to a destructor invocation, which is not true when the temporary is elided, say at return statement. >From 2f8c7ea7ba6c728a36021ef1609a18fcdf7a1695 Mon Sep 17 00:00:00 2001 From: Bill Tsui <[email protected]> Date: Thu, 11 Dec 2025 23:54:11 +0800 Subject: [PATCH] [clang][index] Index implicit destructor invocations from local vars and delete For https://github.com/llvm/llvm-project/issues/169824 The main purpose is to complete call hierarchy and reference links. Local variables is marked at their init expression's beginning, which is intended for better understanding than marking at the end of the scope. Current limitation is that it assumes a BindTemporaryExpr will always lead to a destructor invocation, which is not true when the temporary is elided, say at return statement. --- .../clangd/unittests/XRefsTests.cpp | 23 ++++++++++++++++--- clang/lib/Index/IndexBody.cpp | 17 ++++++++++++++ clang/lib/Index/IndexDecl.cpp | 11 +++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index 7ed08d7cce3d3..26cfeebbc1e02 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -110,7 +110,7 @@ TEST(HighlightsTest, All) { [[~]]Foo() {}; }; void foo() { - Foo f; + Foo [[f]]; f.[[^~]]Foo(); } )cpp", @@ -2242,15 +2242,32 @@ TEST(FindReferences, WithinAST) { class $def[[Foo]] {}; void func($(func)[[Fo^o]]<int>); )cpp", - R"cpp(// Not touching any identifiers. + R"cpp(// Destructor not referenced by static identifiers. struct Foo { $def(Foo)[[~]]Foo() {}; }; void foo() { - Foo f; + static Foo f; f.$(foo)[[^~]]Foo(); } )cpp", + R"cpp(// Destructor referenced by local varable. + struct Foo { + $def(Foo)[[^~]]Foo() {}; + }; + void foo() { + Foo $(foo)[[f]]; + } + )cpp", + R"cpp(// Destructor referenced by temporary. + struct Foo { + $def(Foo)[[^~]]Foo() {}; + }; + void foo(Foo f) { + $(foo)[[Foo]](); + foo($(foo)[[f]]); + } + )cpp", R"cpp(// Lambda capture initializer void foo() { int $def(foo)[[w^aldo]] = 42; diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp index 1979117d4695c..45fd1604816c4 100644 --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -161,12 +161,29 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { } bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { + QualType DT = E->getDestroyedType(); + if (!DT.isNull()) { + if (const auto *RecordTy = DT->getAsCXXRecordDecl()) { + if (const auto *Dtor = RecordTy->getDestructor()) { + IndexCtx.handleReference(Dtor, E->getExprLoc(), Parent, ParentDC); + } + } + } + if (E->isGlobalDelete() || !E->getOperatorDelete()) return true; return IndexCtx.handleReference(E->getOperatorDelete(), E->getBeginLoc(), Parent, ParentDC); } + bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); + if (Dtor) { + IndexCtx.handleReference(Dtor, E->getExprLoc(), Parent, ParentDC); + } + return true; + } + bool VisitLabelStmt(LabelStmt *S) { if (IndexCtx.shouldIndexFunctionLocalSymbols()) return IndexCtx.handleDecl(S->getDecl()); diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index df875e0b40079..eac857586b374 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -307,6 +307,17 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { gatherTemplatePseudoOverrides(D, Relations); TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); handleDeclarator(D); + // handle destructor reference for local variables + if (D->hasLocalStorage() && D->needsDestruction(D->getASTContext())) { + if (const auto *RecordTy = D->getType()->getAsCXXRecordDecl()) { + const auto *Dtor = RecordTy->getDestructor(); + const Expr *InitExpr = D->getInit(); + if (Dtor && InitExpr) { + IndexCtx.handleReference(Dtor, InitExpr->getExprLoc(), D, + D->getLexicalDeclContext()); + } + } + } IndexCtx.indexBody(D->getInit(), D); return true; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
