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"
22
23using namespace clang;
24using namespace ento;
25
26namespace {
27
28class NoDeleteChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
29 BugType Bug;
30 mutable BugReporter *BR = nullptr;
31 mutable TrivialFunctionAnalysis TFA;
32
33public:
34 NoDeleteChecker()
35 : Bug(this,
36 "Incorrect [[clang::annotate_type(\"webkit.nodelete\")]] "
37 "annotation",
38 "WebKit coding guidelines") {}
39
40 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
41 BugReporter &BRArg) const {
42 BR = &BRArg;
43
44 // The calls to checkAST* from AnalysisConsumer don't
45 // visit template instantiations or lambda classes. We
46 // want to visit those, so we make our own visitor.
47 struct LocalVisitor final : public ConstDynamicRecursiveASTVisitor {
48 const NoDeleteChecker *Checker;
49 Decl *DeclWithIssue{nullptr};
50
51 explicit LocalVisitor(const NoDeleteChecker *Checker) : Checker(Checker) {
52 assert(Checker);
53 ShouldVisitTemplateInstantiations = true;
54 ShouldWalkTypesOfTypeLocs = true;
55 ShouldVisitImplicitCode = false;
56 ShouldVisitLambdaBody = true;
57 }
58
59 bool VisitFunctionDecl(const FunctionDecl *FD) override {
60 Checker->visitFunctionDecl(FD);
61 return true;
62 }
63 };
64
65 LocalVisitor visitor(this);
66 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
67 }
68
69 void visitFunctionDecl(const FunctionDecl *FD) const {
71 return;
72
73 if (!isNoDeleteFunction(FD))
74 return;
75
76 auto Body = FD->getBody();
77 if (!Body)
78 return;
79
80 NamedDecl *ParamDecl = nullptr;
81 for (auto *D : FD->parameters()) {
82 if (!TFA.hasTrivialDtor(D)) {
83 ParamDecl = D;
84 break;
85 }
86 }
87 const Stmt *OffendingStmt = nullptr;
88 if (!ParamDecl && TFA.isTrivial(Body, &OffendingStmt))
89 return;
90
91 SmallString<100> Buf;
92 llvm::raw_svector_ostream Os(Buf);
93
94 Os << "A function ";
95 printQuotedName(Os, FD);
96 Os << " has [[clang::annotate_type(\"webkit.nodelete\")]] but it contains ";
97 SourceLocation SrcLocToReport;
98 SourceRange Range;
99 if (ParamDecl) {
100 Os << "a parameter ";
101 printQuotedName(Os, ParamDecl);
102 Os << " which could destruct an object.";
103 SrcLocToReport = FD->getBeginLoc();
104 Range = ParamDecl->getSourceRange();
105 } else {
106 Os << "code that could destruct an object.";
107 SrcLocToReport = OffendingStmt->getBeginLoc();
108 Range = OffendingStmt->getSourceRange();
109 }
110
111 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
112 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
113 Report->addRange(Range);
114 Report->setDeclWithIssue(FD);
115 BR->emitReport(std::move(Report));
116 }
117};
118
119} // namespace
120
121void ento::registerNoDeleteChecker(CheckerManager &Mgr) {
122 Mgr.registerChecker<NoDeleteChecker>();
123}
124
125bool ento::shouldRegisterNoDeleteChecker(const CheckerManager &) {
126 return true;
127}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::SourceLocation class and associated facilities.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
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:3280
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2326
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
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
bool isNoDeleteFunction(const FunctionDecl *F)