[clang] [alpha.webkit.NoDeleteChecker] Don't emit a warning for a function without annotation. (PR #178824)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 30 12:51:26 PST 2026
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/178824
>From 1ae2ec2568ecd5884b0fd3662b75d2a142c065d9 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Thu, 29 Jan 2026 19:31:35 -0800
Subject: [PATCH 1/3] [alpha.webkit.NoDeleteChecker] Don't emit a warning for a
function without annotation.
This PR fixes the bug in alpha.webkit.NoDeleteChecker that it emits a warning for any
function without [[clang::annotate_type("webkit.nodelete")]] annotation if it contains
non-trivial code. It also fixes a bug hat we weren't checking the presence of the
annotation on superclass' corresponding member functions.
---
.../Checkers/WebKit/NoDeleteChecker.cpp | 15 ++++++++++++---
.../Checkers/WebKit/nodelete-annotation.cpp | 4 ++++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
index 397fda8cd67ed..482cdb3f96ec2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
@@ -70,6 +70,12 @@ class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
return;
bool HasNoDeleteAnnotation = isNoDeleteFunction(FD);
+ for (auto* D = FD->getPreviousDecl(); D; D = D->getPreviousDecl()) {
+ if (isNoDeleteFunction(D)) {
+ HasNoDeleteAnnotation = true;
+ break;
+ }
+ }
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (auto *Cls = MD->getParent(); Cls && MD->isVirtual()) {
CXXBasePaths Paths;
@@ -84,18 +90,21 @@ class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
const CXXRecordDecl *R = T->getAsCXXRecordDecl();
for (const CXXMethodDecl *BaseMD : R->methods()) {
if (BaseMD->getCorrespondingMethodInClass(Cls) == MD) {
- if (isNoDeleteFunction(FD)) {
+ if (isNoDeleteFunction(BaseMD)) {
HasNoDeleteAnnotation = true;
- return false;
+ return true;
}
}
}
- return true;
+ return false;
},
Paths, /*LookupInDependent =*/true);
}
}
+ if (!HasNoDeleteAnnotation)
+ return;
+
auto Body = FD->getBody();
if (!Body || TFA.isTrivial(Body))
return;
diff --git a/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp b/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp
index b23fd007ff789..121719400d08b 100644
--- a/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp
@@ -3,6 +3,10 @@
void someFunction();
void [[clang::annotate_type("webkit.nodelete")]] safeFunction();
+void functionWithoutNoDeleteAnnotation() {
+ someFunction();
+}
+
void [[clang::annotate_type("webkit.nodelete")]] callsUnsafe() {
// expected-warning at -1{{A function 'callsUnsafe' has [[clang::annotate_type("webkit.nodelete")]] but it contains code that could destruct an object}}
someFunction();
>From 8448d4ec62179d1cbf823459a6fd8ec23a904001 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Fri, 30 Jan 2026 12:22:35 -0800
Subject: [PATCH 2/3] Address the review comments by simplyfing the check for
webkit.nodelete annotation.
---
.../Checkers/WebKit/NoDeleteChecker.cpp | 54 +++++++------------
1 file changed, 20 insertions(+), 34 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
index 482cdb3f96ec2..23d6d38cf1bc3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
@@ -65,44 +65,30 @@ class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
}
- void visitFunctionDecl(const FunctionDecl *FD) const {
- if (!FD->doesThisDeclarationHaveABody())
- return;
+ static bool hasNoDeleteAnnotation(const FunctionDecl *FD) {
+ if (llvm::any_of(FD->redecls(), isNoDeleteFunction))
+ return true;
- bool HasNoDeleteAnnotation = isNoDeleteFunction(FD);
- for (auto* D = FD->getPreviousDecl(); D; D = D->getPreviousDecl()) {
- if (isNoDeleteFunction(D)) {
- HasNoDeleteAnnotation = true;
- break;
- }
- }
- if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (auto *Cls = MD->getParent(); Cls && MD->isVirtual()) {
- CXXBasePaths Paths;
- Paths.setOrigin(Cls);
-
- Cls->lookupInBases(
- [&](const CXXBaseSpecifier *Base, CXXBasePath &) {
- const Type *T = Base->getType().getTypePtrOrNull();
- if (!T)
- return false;
-
- const CXXRecordDecl *R = T->getAsCXXRecordDecl();
- for (const CXXMethodDecl *BaseMD : R->methods()) {
- if (BaseMD->getCorrespondingMethodInClass(Cls) == MD) {
- if (isNoDeleteFunction(BaseMD)) {
- HasNoDeleteAnnotation = true;
- return true;
- }
- }
- }
- return false;
- },
- Paths, /*LookupInDependent =*/true);
+ const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (!MD || !MD->isVirtual())
+ return false;
+
+ auto Overriders = llvm::to_vector(MD->overridden_methods());
+ while (!Overriders.empty()) {
+ const auto *Fn = Overriders.pop_back_val();
+ llvm::append_range(Overriders, Fn->overridden_methods());
+ if (isNoDeleteFunction(Fn))
+ return true;
}
+
+ return false;
}
- if (!HasNoDeleteAnnotation)
+ void visitFunctionDecl(const FunctionDecl *FD) const {
+ if (!FD->doesThisDeclarationHaveABody())
+ return;
+
+ if (!hasNoDeleteAnnotation(FD))
return;
auto Body = FD->getBody();
>From 07ecc8e3c281b6c40bfebef17e323a1329bc9794 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Fri, 30 Jan 2026 12:51:09 -0800
Subject: [PATCH 3/3] Fix formatting.
---
.../Checkers/WebKit/NoDeleteChecker.cpp | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
index 23d6d38cf1bc3..2740890704767 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp
@@ -66,24 +66,24 @@ class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
}
static bool hasNoDeleteAnnotation(const FunctionDecl *FD) {
- if (llvm::any_of(FD->redecls(), isNoDeleteFunction))
- return true;
-
- const auto *MD = dyn_cast<CXXMethodDecl>(FD);
- if (!MD || !MD->isVirtual())
- return false;
-
- auto Overriders = llvm::to_vector(MD->overridden_methods());
- while (!Overriders.empty()) {
- const auto *Fn = Overriders.pop_back_val();
- llvm::append_range(Overriders, Fn->overridden_methods());
- if (isNoDeleteFunction(Fn))
- return true;
- }
+ if (llvm::any_of(FD->redecls(), isNoDeleteFunction))
+ return true;
+ const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (!MD || !MD->isVirtual())
return false;
+
+ auto Overriders = llvm::to_vector(MD->overridden_methods());
+ while (!Overriders.empty()) {
+ const auto *Fn = Overriders.pop_back_val();
+ llvm::append_range(Overriders, Fn->overridden_methods());
+ if (isNoDeleteFunction(Fn))
+ return true;
}
+ return false;
+ }
+
void visitFunctionDecl(const FunctionDecl *FD) const {
if (!FD->doesThisDeclarationHaveABody())
return;
More information about the cfe-commits
mailing list