[clang] Add nodelete annotation for WebKit checkers with a new checker for validation (PR #177839)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 27 09:18:30 PST 2026
================
@@ -0,0 +1,130 @@
+//=======- NoDeleteChecker.cpp -----------------------------------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTUtils.h"
+#include "DiagOutputUtils.h"
+#include "PtrTypesSemantics.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
+ BugType Bug;
+ mutable BugReporter *BR = nullptr;
+ mutable TrivialFunctionAnalysis TFA;
+
+public:
+ NoDeleteChecker()
+ : Bug(this,
+ "Incorrect [[clang::annotate_type(\"webkit.nodelete\")]] "
+ "annotation",
+ "WebKit coding guidelines") {}
+
+ void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
+ BugReporter &BRArg) const {
+ BR = &BRArg;
+
+ // The calls to checkAST* from AnalysisConsumer don't
+ // visit template instantiations or lambda classes. We
+ // want to visit those, so we make our own RecursiveASTVisitor.
+ struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+ const NoDeleteChecker *Checker;
+ Decl *DeclWithIssue{nullptr};
+
+ explicit LocalVisitor(const NoDeleteChecker *Checker) : Checker(Checker) {
+ assert(Checker);
+ }
+
+ bool shouldVisitTemplateInstantiations() const { return true; }
+ bool shouldVisitImplicitCode() const { return false; }
+
+ bool VisitFunctionDecl(FunctionDecl *FD) {
+ Checker->visitFunctionDecl(FD);
+ return true;
+ }
+ };
+
+ LocalVisitor visitor(this);
+ visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
+ }
+
+ void visitFunctionDecl(const FunctionDecl *FD) const {
+ if (!FD->doesThisDeclarationHaveABody())
+ return;
+
+ bool HasNoDeleteAnnotation = isNoDeleteFunction(FD);
+ 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(FD)) {
+ HasNoDeleteAnnotation = true;
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ Paths, /*LookupInDependent =*/true);
+ }
+ }
+
+ auto Body = FD->getBody();
+ if (!Body || TFA.isTrivial(Body))
+ return;
----------------
rniwa wrote:
Yeah, I think that might be a nice follow up. I often need to investigate why a given code isn't a trivial so that'll aid me in that too.
https://github.com/llvm/llvm-project/pull/177839
More information about the cfe-commits
mailing list