clang 10.0.0git

AnalysisOrderChecker.cpp
Go to the documentation of this file.
1 //===- AnalysisOrderChecker - Print callbacks called ------------*- 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 // This checker prints callbacks that are called during analysis.
10 // This is required to ensure that callbacks are fired in order
11 // and do not duplicate or get lost.
12 // Feel free to extend this checker with any callback you need to check.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
17 #include "clang/AST/ExprCXX.h"
18 #include "clang/Analysis/CFGStmtMap.h"
19 #include "clang/StaticAnalyzer/Core/Checker.h"
20 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
22 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23
24 using namespace clang;
25 using namespace ento;
26
27 namespace {
28
29 class AnalysisOrderChecker
30 : public Checker<check::PreStmt<CastExpr>,
31 check::PostStmt<CastExpr>,
32 check::PreStmt<ArraySubscriptExpr>,
33 check::PostStmt<ArraySubscriptExpr>,
34 check::PreStmt<CXXNewExpr>,
35 check::PostStmt<CXXNewExpr>,
36 check::PreStmt<OffsetOfExpr>,
37 check::PostStmt<OffsetOfExpr>,
38 check::PreCall,
39 check::PostCall,
40 check::EndFunction,
41 check::NewAllocator,
42 check::Bind,
43 check::PointerEscape,
44 check::RegionChanges,
45 check::LiveSymbols> {
46
47 bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
48 return Opts.getCheckerBooleanOption(this, "*") ||
49 Opts.getCheckerBooleanOption(this, CallbackName);
50 }
51
52 bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const {
53 AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions();
54 return isCallbackEnabled(Opts, CallbackName);
55 }
56
57 bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const {
58 AnalyzerOptions &Opts = State->getStateManager().getOwningEngine()
59 .getAnalysisManager().getAnalyzerOptions();
60 return isCallbackEnabled(Opts, CallbackName);
61 }
62
63 public:
64 void checkPreStmt(const CastExpr *CE, CheckerContext &C) const {
65 if (isCallbackEnabled(C, "PreStmtCastExpr"))
66 llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName()
67 << ")\n";
68 }
69
70 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const {
71 if (isCallbackEnabled(C, "PostStmtCastExpr"))
72 llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName()
73 << ")\n";
74 }
75
76 void checkPreStmt(const ArraySubscriptExpr *SubExpr,
77 CheckerContext &C) const {
78 if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr"))
79 llvm::errs() << "PreStmt<ArraySubscriptExpr>\n";
80 }
81
82 void checkPostStmt(const ArraySubscriptExpr *SubExpr,
83 CheckerContext &C) const {
84 if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr"))
85 llvm::errs() << "PostStmt<ArraySubscriptExpr>\n";
86 }
87
88 void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const {
89 if (isCallbackEnabled(C, "PreStmtCXXNewExpr"))
90 llvm::errs() << "PreStmt<CXXNewExpr>\n";
91 }
92
93 void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const {
94 if (isCallbackEnabled(C, "PostStmtCXXNewExpr"))
95 llvm::errs() << "PostStmt<CXXNewExpr>\n";
96 }
97
98 void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
99 if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
100 llvm::errs() << "PreStmt<OffsetOfExpr>\n";
101 }
102
103 void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
104 if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
105 llvm::errs() << "PostStmt<OffsetOfExpr>\n";
106 }
107
108 void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
109 if (isCallbackEnabled(C, "PreCall")) {
110 llvm::errs() << "PreCall";
111 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
112 llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
113 llvm::errs() << '\n';
114 }
115 }
116
117 void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
118 if (isCallbackEnabled(C, "PostCall")) {
119 llvm::errs() << "PostCall";
120 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
121 llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
122 llvm::errs() << '\n';
123 }
124 }
125
126 void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const {
127 if (isCallbackEnabled(C, "EndFunction")) {
128 llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n";
129 if (!S)
130 return;
131
132 llvm::errs() << "CFGElement: ";
133 CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap();
134 CFGElement LastElement = Map->getBlock(S)->back();
135
136 if (LastElement.getAs<CFGStmt>())
137 llvm::errs() << "CFGStmt\n";
138 else if (LastElement.getAs<CFGAutomaticObjDtor>())
139 llvm::errs() << "CFGAutomaticObjDtor\n";
140 }
141 }
142
143 void checkNewAllocator(const CXXNewExpr *CNE, SVal Target,
144 CheckerContext &C) const {
145 if (isCallbackEnabled(C, "NewAllocator"))
146 llvm::errs() << "NewAllocator\n";
147 }
148
149 void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const {
150 if (isCallbackEnabled(C, "Bind"))
151 llvm::errs() << "Bind\n";
152 }
153
154 void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const {
155 if (isCallbackEnabled(State, "LiveSymbols"))
156 llvm::errs() << "LiveSymbols\n";
157 }
158
159 ProgramStateRef
160 checkRegionChanges(ProgramStateRef State,
161 const InvalidatedSymbols *Invalidated,
162 ArrayRef<const MemRegion *> ExplicitRegions,
163 ArrayRef<const MemRegion *> Regions,
164 const LocationContext *LCtx, const CallEvent *Call) const {
165 if (isCallbackEnabled(State, "RegionChanges"))
166 llvm::errs() << "RegionChanges\n";
167 return State;
168 }
169
170 ProgramStateRef checkPointerEscape(ProgramStateRef State,
171 const InvalidatedSymbols &Escaped,
172 const CallEvent *Call,
173 PointerEscapeKind Kind) const {
174 if (isCallbackEnabled(State, "PointerEscape"))
175 llvm::errs() << "PointerEscape\n";
176 return State;
177 }
178 };
179 } // end anonymous namespace
180
181 //===----------------------------------------------------------------------===//
182 // Registration.
183 //===----------------------------------------------------------------------===//
184
185 void ento::registerAnalysisOrderChecker(CheckerManager &mgr) {
186 mgr.registerChecker<AnalysisOrderChecker>();
187 }
188
189 bool ento::shouldRegisterAnalysisOrderChecker(const LangOptions &LO) {
190 return true;
191 }
ento
clang::ento::InvalidatedSymbols
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:51
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:66
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
clang::LocationContext
Definition: AnalysisDeclContext.h:216
CFGStmtMap.h
ExprCXX.h
Defines the clang::Expr interface and subclasses for C++ expressions.
State
LineState State
Definition: UnwrappedLineFormatter.cpp:932
clang::CFGAutomaticObjDtor
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition: CFG.h:389
Checker.h
CheckerManager.h
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:53
clang::CFGStmt
Definition: CFG.h:132
clang::CastExpr
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3150
llvm::ArrayRef
Definition: LLVM.h:31
clang::CFGStmtMap::getBlock
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
Definition: CFGStmtMap.cpp:26
clang::CFGStmtMap
Definition: CFGStmtMap.h:24
clang::ReturnStmt
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2636
clang::CFGBlock::back
CFGElement back() const
Definition: CFG.h:874
BuiltinCheckerRegistration.h
Kind
Kind
Definition: ChrootChecker.cpp:29
clang::CXXNewExpr
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Definition: ExprCXX.h:2100
clang::CFGElement::getAs
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Definition: CFG.h:109
clang::AnalyzerOptions::getCheckerBooleanOption
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option&#39;s string value as a boolean.
Definition: AnalyzerOptions.cpp:151
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:21
clang::interp::NE
bool NE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:223
clang::ento::PointerEscapeKind
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Definition: CheckerManager.h:75
clang::ArraySubscriptExpr
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2462
clang::CastExpr::getCastKindName
static const char * getCastKindName(CastKind CK)
Definition: Expr.cpp:1894
clang::AnalyzerOptions
Stores options for the analyzer from the command line.
Definition: AnalyzerOptions.h:162
clang::CFGElement
Represents a top-level expression in a basic block.
Definition: CFG.h:55
clang::NamedDecl
This represents a decl that may have a name.
Definition: Decl.h:223
clang::OffsetOfExpr
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type, member-designator).
Definition: Expr.h:2267
CallEvent.h
CallEvent
CheckerContext.h