clang 23.0.0git
NoDeleteChecker.cpp
Go to the documentation of this file.
1//=======- NoDeleteChecker.cpp -----------------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DiagOutputUtils.h"
10#include "PtrTypesSemantics.h"
12#include "clang/AST/Decl.h"
13#include "clang/AST/DeclCXX.h"
21
22using namespace clang;
23using namespace ento;
24
25namespace {
26
27class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
28 BugType Bug;
29 mutable BugReporter *BR = nullptr;
30 mutable TrivialFunctionAnalysis TFA;
31
32public:
33 NoDeleteChecker()
34 : Bug(this,
35 "Incorrect [[clang::annotate_type(\"webkit.nodelete\")]] "
36 "annotation",
37 "WebKit coding guidelines") {}
38
39 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
40 BugReporter &BRArg) const {
41 BR = &BRArg;
42
43 // The calls to checkAST* from AnalysisConsumer don't
44 // visit template instantiations or lambda classes. We
45 // want to visit those, so we make our own visitor.
46 struct LocalVisitor final : public ConstDynamicRecursiveASTVisitor {
47 const NoDeleteChecker *Checker;
48 Decl *DeclWithIssue{nullptr};
49
50 explicit LocalVisitor(const NoDeleteChecker *Checker) : Checker(Checker) {
51 assert(Checker);
52 ShouldVisitTemplateInstantiations = true;
53 ShouldWalkTypesOfTypeLocs = true;
54 ShouldVisitImplicitCode = false;
55 ShouldVisitLambdaBody = true;
56 }
57
58 bool VisitFunctionDecl(const FunctionDecl *FD) override {
59 Checker->visitFunctionDecl(FD);
60 return true;
61 }
62 };
63
64 LocalVisitor visitor(this);
65 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
66 }
67
68 void visitFunctionDecl(const FunctionDecl *FD) const {
70 return;
71
72 bool HasNoDeleteAnnotation = isNoDeleteFunction(FD);
73 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
74 if (auto *Cls = MD->getParent(); Cls && MD->isVirtual()) {
75 CXXBasePaths Paths;
76 Paths.setOrigin(Cls);
77
78 Cls->lookupInBases(
79 [&](const CXXBaseSpecifier *Base, CXXBasePath &) {
80 const Type *T = Base->getType().getTypePtrOrNull();
81 if (!T)
82 return false;
83
84 const CXXRecordDecl *R = T->getAsCXXRecordDecl();
85 if (!R)
86 return false;
87
88 for (const CXXMethodDecl *BaseMD : R->methods()) {
89 if (BaseMD->getCorrespondingMethodInClass(Cls) == MD) {
90 if (isNoDeleteFunction(FD)) {
91 HasNoDeleteAnnotation = true;
92 return false;
93 }
94 }
95 }
96 return true;
97 },
98 Paths, /*LookupInDependent =*/true);
99 }
100 }
101
102 auto Body = FD->getBody();
103 if (!Body || TFA.isTrivial(Body))
104 return;
105
106 SmallString<100> Buf;
107 llvm::raw_svector_ostream Os(Buf);
108
109 Os << "A function ";
110 printQuotedName(Os, FD);
111 Os << " has [[clang::annotate_type(\"webkit.nodelete\")]] but it contains "
112 "code that could destruct an object";
113
114 const SourceLocation SrcLocToReport = FD->getBeginLoc();
115 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
116 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
117 Report->addRange(FD->getSourceRange());
118 Report->setDeclWithIssue(FD);
119 BR->emitReport(std::move(Report));
120 }
121};
122
123} // namespace
124
125void ento::registerNoDeleteChecker(CheckerManager &Mgr) {
126 Mgr.registerChecker<NoDeleteChecker>();
127}
128
129bool ento::shouldRegisterNoDeleteChecker(const CheckerManager &) {
130 return true;
131}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::SourceLocation class and associated facilities.
void setOrigin(const CXXRecordDecl *Rec)
method_range methods() const
Definition DeclCXX.h:650
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3279
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2326
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4549
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
Definition Checker.h:553
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
void printQuotedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
DynamicRecursiveASTVisitorBase< true > ConstDynamicRecursiveASTVisitor
const FunctionProtoType * T
@ Type
The name was classified as a type.
Definition Sema.h:564
bool isNoDeleteFunction(const FunctionDecl *F)