Author: Ryosuke Niwa Date: 2026-03-01T22:38:42-08:00 New Revision: b8d0bb2ddc77c6f9a856ae90fd1329778c070823
URL: https://github.com/llvm/llvm-project/commit/b8d0bb2ddc77c6f9a856ae90fd1329778c070823 DIFF: https://github.com/llvm/llvm-project/commit/b8d0bb2ddc77c6f9a856ae90fd1329778c070823.diff LOG: [WebKit checkers] Trivial function analysis ignores some nodelete annotation (#183970) This PR fixes the bug that TrivialFunctionAnalysis can ignore nodelete annotation set on some but not all function declarations because it does not check the annotation on prior declarations unlike alpha.webkit.NoDeleteChecker which checks it on any declaration by replacing isNoDeleteFunction with NoDeleteChecker's hasNoDeleteAnnotation. Added: Modified: clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp index 075c46c79f139..b3b43361a25ef 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoDeleteChecker.cpp @@ -66,30 +66,11 @@ class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> { visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD)); } - 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; - } - - return false; - } - void visitFunctionDecl(const FunctionDecl *FD) const { if (!FD->doesThisDeclarationHaveABody() || FD->isDependentContext()) return; - if (!hasNoDeleteAnnotation(FD)) + if (!isNoDeleteFunction(FD)) return; auto Body = FD->getBody(); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 7a7e22ead74a8..0b1f30923d49c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -454,10 +454,29 @@ bool isPtrConversion(const FunctionDecl *F) { return false; } -bool isNoDeleteFunction(const FunctionDecl *F) { +static bool isNoDeleteFunctionDecl(const FunctionDecl *F) { return typeAnnotationForReturnType(F) == WebKitAnnotation::NoDelete; } +bool isNoDeleteFunction(const FunctionDecl *F) { + if (llvm::any_of(F->redecls(), isNoDeleteFunctionDecl)) + return true; + + const auto *MD = dyn_cast<CXXMethodDecl>(F); + 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 (isNoDeleteFunctionDecl(Fn)) + return true; + } + + return false; +} + bool isTrivialBuiltinFunction(const FunctionDecl *F) { if (!F || !F->getDeclName().isIdentifier()) return false; diff --git a/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp b/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp index c030402166258..203edc050e618 100644 --- a/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp +++ b/clang/test/Analysis/Checkers/WebKit/nodelete-annotation.cpp @@ -70,6 +70,16 @@ void [[clang::annotate_type("webkit.nodelete")]] callsUnsafe() { someFunction(); // expected-warning{{A function 'callsUnsafe' has [[clang::annotate_type("webkit.nodelete")]] but it contains code that could destruct an object}} } +void [[clang::annotate_type("webkit.nodelete")]] callsUnsafeWithSuppress(); + +[[clang::suppress]] void callsUnsafeWithSuppress() { + someFunction(); +} + +void [[clang::annotate_type("webkit.nodelete")]] callsNoDeleteFunction() { + callsUnsafeWithSuppress(); +} + #define EXPORT_IMPORT __attribute__((visibility("default"))) EXPORT_IMPORT unsigned [[clang::annotate_type("webkit.nodelete")]] safeFunctionWithAttr(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
