[kdevelop/kdevelop] plugins/clang: Detect final attribute on destructors
Martin Bednar <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 6c742b0664ebc2279d9798d2022062574ade363e by Martin Bednar, on behalf of Yin Zhijie.
Committed on 29/07/2026 at 11:45.
Pushed by bednar into branch 'master'.
Detect final attribute on destructors
M +18 -0 plugins/clang/tests/files/classfunctions.cpp
M +17 -0 plugins/clang/tests/files/functions.cpp
M +20 -0 plugins/clang/tests/test_navigationcontext.cpp
M +2 -1 plugins/clang/util/clangutils.cpp
https://invent.kde.org/kdevelop/kdevelop/-/commit/6c742b0664ebc2279d9798d2022062574ade363e
diff --git a/plugins/clang/tests/files/classfunctions.cpp b/plugins/clang/tests/files/classfunctions.cpp
index 2b1fc90a2b..c3db33cb78 100644
--- a/plugins/clang/tests/files/classfunctions.cpp
+++ b/plugins/clang/tests/files/classfunctions.cpp
@@ -80,3 +80,21 @@ public:
/// "isDefinition" : true
explicit operator bool() const noexcept final {return true;}
};
+
+class FinalDestructorBase
+{
+public:
+ /// "isAbstract" : true
+ virtual ~FinalDestructorBase() = 0;
+};
+
+class FinalDestructor final : public FinalDestructorBase
+{
+public:
+ /// "isNoexcept" : true,
+ /// "isAbstract" : false,
+ /// "isFinal" : true,
+ /// "isVirtual" : true,
+ /// "isDefinition" : true
+ ~FinalDestructor() final {}
+};
diff --git a/plugins/clang/tests/files/functions.cpp b/plugins/clang/tests/files/functions.cpp
index 9e31be8823..26da8523b1 100644
--- a/plugins/clang/tests/files/functions.cpp
+++ b/plugins/clang/tests/files/functions.cpp
@@ -42,6 +42,12 @@ public:
void nonConstMethod();
};
+class FinalDestructorBase
+{
+public:
+ virtual ~FinalDestructorBase() = default;
+};
+
class Derived : public Base
{
public:
@@ -53,6 +59,17 @@ public:
void bar3() final;
};
+class FinalDestructor final : public FinalDestructorBase
+{
+public:
+ /// "isNoexcept" : true,
+ /// "isStatic" : false,
+ /// "isVirtual" : true,
+ /// "isAbstract" : false,
+ /// "isFinal" : true
+ ~FinalDestructor() final = default;
+};
+
/// "isNoexcept" : false
void bar1() {}
/// "isNoexcept" : true
diff --git a/plugins/clang/tests/test_navigationcontext.cpp b/plugins/clang/tests/test_navigationcontext.cpp
index 36fd808b2c..397693a028 100644
--- a/plugins/clang/tests/test_navigationcontext.cpp
+++ b/plugins/clang/tests/test_navigationcontext.cpp
@@ -56,6 +56,15 @@ void TestNavigationContext::testDeclarationDetailsVirtualFinalAbstract()
virtual ~Derived();
virtual bool isFinal() final;
};
+
+ class DestructorBase {
+ public:
+ virtual ~DestructorBase() = default;
+ };
+
+ class FinalDestructor final : public DestructorBase {
+ ~FinalDestructor() final;
+ };
)"),
QStringLiteral("cpp"));
file.parse(TopDUContext::AllDeclarationsContextsAndUses);
@@ -78,6 +87,11 @@ void TestNavigationContext::testDeclarationDetailsVirtualFinalAbstract()
QCOMPARE(isFinalDecls.size(), 1);
const DeclarationPointer isFinalDecl(isFinalDecls.first());
+ const auto finalDestructorDecls =
+ top->findDeclarations(QualifiedIdentifier(u"FinalDestructor::~FinalDestructor"));
+ QCOMPARE(finalDestructorDecls.size(), 1);
+ const DeclarationPointer finalDestructorDecl(finalDestructorDecls.first());
+
const QStringList onlyVirtualDetails = TestDeclarationNavigationContext::declarationDetails(onlyVirtualDecl);
QVERIFY(onlyVirtualDetails.contains(QStringLiteral("virtual")));
QVERIFY(!onlyVirtualDetails.contains(QStringLiteral("abstract")));
@@ -92,6 +106,12 @@ void TestNavigationContext::testDeclarationDetailsVirtualFinalAbstract()
QVERIFY(isFinalDetails.contains(QStringLiteral("final")));
QVERIFY(!isFinalDetails.contains(QStringLiteral("virtual")));
QVERIFY(!isFinalDetails.contains(QStringLiteral("abstract")));
+
+ const QStringList finalDestructorDetails =
+ TestDeclarationNavigationContext::declarationDetails(finalDestructorDecl);
+ QVERIFY(finalDestructorDetails.contains(QStringLiteral("final")));
+ QVERIFY(!finalDestructorDetails.contains(QStringLiteral("virtual")));
+ QVERIFY(!finalDestructorDetails.contains(QStringLiteral("abstract")));
}
}
diff --git a/plugins/clang/util/clangutils.cpp b/plugins/clang/util/clangutils.cpp
index 93fa5b90d4..5f0fc71444 100644
--- a/plugins/clang/util/clangutils.cpp
+++ b/plugins/clang/util/clangutils.cpp
@@ -402,7 +402,8 @@ KDevelop::ClassFunctionFlags ClangUtils::specialAttributes(CXCursor cursor)
// check for our injected attributes to detect Qt signals and slots
// see also the contents of wrappedQtHeaders/QtCore/qobjectdefs.h
ClassFunctionFlags flags = {};
- if (cursor.kind == CXCursor_CXXMethod || cursor.kind == CXCursor_ConversionFunction) {
+ if (cursor.kind == CXCursor_CXXMethod || cursor.kind == CXCursor_ConversionFunction
+ || cursor.kind == CXCursor_Destructor) {
clang_visitChildren(cursor, [] (CXCursor cursor, CXCursor /*parent*/, CXClientData data) -> CXChildVisitResult {
auto& flags = *static_cast<ClassFunctionFlags*>(data);
switch (cursor.kind) {