clang 23.0.0git
CoreEngine.h
Go to the documentation of this file.
1//===- CoreEngine.h - Path-Sensitive Dataflow Engine ------------*- 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 file defines a generic engine for intraprocedural, path-sensitive,
10// dataflow analysis via graph reachability.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
15#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
16
17#include "clang/AST/Stmt.h"
19#include "clang/Analysis/CFG.h"
21#include "clang/Basic/LLVM.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/ADT/iterator_range.h"
29#include "llvm/Support/Casting.h"
30#include <cassert>
31#include <memory>
32#include <utility>
33#include <vector>
34
35namespace clang {
36
37class AnalyzerOptions;
39class Expr;
40class LabelDecl;
41
42namespace ento {
43
45class ExprEngine;
46
47//===----------------------------------------------------------------------===//
48/// CoreEngine - Implements the core logic of the graph-reachability analysis.
49/// It traverses the CFG and generates the ExplodedGraph.
51 friend class ExprEngine;
52 friend class NodeBuilder;
53 friend class NodeBuilderContext;
54
55public:
57 std::vector<std::pair<BlockEdge, const ExplodedNode *>>;
58
60 std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>;
61
62private:
63 ExprEngine &ExprEng;
64
65 /// G - The simulation graph. Each node is a (location,state) pair.
66 mutable ExplodedGraph G;
67
68 /// WList - A set of queued nodes that need to be processed by the
69 /// worklist algorithm. It is up to the implementation of WList to decide
70 /// the order that nodes are processed.
71 std::unique_ptr<WorkList> WList;
72 std::unique_ptr<WorkList> CTUWList;
73
74 /// BCounterFactory - A factory object for created BlockCounter objects.
75 /// These are used to record for key nodes in the ExplodedGraph the
76 /// number of times different CFGBlocks have been visited along a path.
77 BlockCounter::Factory BCounterFactory;
78
79 /// The locations where we stopped doing work because we visited a location
80 /// too many times.
81 BlocksExhausted blocksExhausted;
82
83 /// The locations where we stopped because the engine aborted analysis,
84 /// usually because it could not reason about something.
85 BlocksAborted blocksAborted;
86
87 /// The information about functions shared by the whole translation unit.
88 /// (This data is owned by AnalysisConsumer.)
89 FunctionSummariesTy *FunctionSummaries;
90
91 /// Add path tags with some useful data along the path when we see that
92 /// something interesting is happening. This field is the allocator for such
93 /// tags.
94 DataTag::Factory DataTags;
95
96 void setBlockCounter(BlockCounter C);
97
98 void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
99 void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred);
100 void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred);
101
102 void HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred);
103
104 void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred);
105
106 void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
107 ExplodedNode *Pred);
108 void HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
109 const CFGBlock *B, ExplodedNode *Pred);
110
111 /// Handle conditional logic for running static initializers.
112 void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
113 ExplodedNode *Pred);
114
115 void HandleVirtualBaseBranch(const CFGBlock *B, ExplodedNode *Pred);
116
117private:
118 /// Helper function called by `HandleBranch()`. If the currently handled
119 /// branch corresponds to a loop, this returns the number of already
120 /// completed iterations in that loop, otherwise the return value is
121 /// `std::nullopt`. Note that this counts _all_ earlier iterations, including
122 /// ones that were performed within an earlier iteration of an outer loop.
123 std::optional<unsigned> getCompletedIterationCount(const CFGBlock *B,
124 ExplodedNode *Pred) const;
125
126public:
127 /// Construct a CoreEngine object to analyze the provided CFG.
128 CoreEngine(ExprEngine &exprengine,
130 AnalyzerOptions &Opts);
131
132 CoreEngine(const CoreEngine &) = delete;
133 CoreEngine &operator=(const CoreEngine &) = delete;
134
135 /// getGraph - Returns the exploded graph.
136 ExplodedGraph &getGraph() { return G; }
137
138 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
139 /// steps. Returns true if there is still simulation state on the worklist.
140 bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
141 ProgramStateRef InitState);
142
143 /// Dispatch the work list item based on the given location information.
144 /// Use Pred parameter as the predecessor state.
146 const WorkListUnit& WU);
147
148 // Functions for external checking of whether we have unfinished work.
149 bool wasBlockAborted() const { return !blocksAborted.empty(); }
150 bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
151 bool hasWorkRemaining() const { return wasBlocksExhausted() ||
152 WList->hasWork() ||
153 wasBlockAborted(); }
154
155 /// Inform the CoreEngine that a basic block was aborted because
156 /// it could not be completely analyzed.
157 void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
158 blocksAborted.push_back(std::make_pair(block, node));
159 }
160
161 WorkList *getWorkList() const { return WList.get(); }
162 WorkList *getCTUWorkList() const { return CTUWList.get(); }
163
164 auto exhausted_blocks() const {
165 return llvm::iterator_range(blocksExhausted);
166 }
167
168 auto aborted_blocks() const { return llvm::iterator_range(blocksAborted); }
169
171 ExplodedNode *Pred, bool MarkAsSink = false) const;
172
174 ExplodedNode *Pred,
175 bool MarkAsSink = false) const {
176 PostStmt Loc(S, Pred->getLocationContext(), /*tag=*/nullptr);
177 return makeNode(Loc, State, Pred, MarkAsSink);
178 }
179
182 ProgramStateRef State,
184 const LocationContext *LC = Pred->getLocationContext();
185 State = State->BindExpr(E, LC, V);
186 const auto &L = ProgramPoint::getProgramPoint(E, K, LC, /*tag=*/nullptr);
187 return makeNode(L, State, Pred);
188 }
189
193 return makeNodeWithBinding(Pred, E, V, Pred->getState(), K);
194 }
195
196 /// Enqueue the given set of nodes onto the work list.
198
199 /// Enqueue nodes that were created as a result of processing
200 /// a statement onto the work list.
202 unsigned Idx);
203
204 /// enqueue the nodes corresponding to the end of function onto the
205 /// end of path / work list.
207
208 /// Enqueue a single node created as a result of statement processing.
209 void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
210
211 DataTag::Factory &getDataTags() { return DataTags; }
212};
213
215 const CoreEngine &Eng;
216 const CFGBlock *Block;
217 const LocationContext *LC;
218
219public:
221 const LocationContext *L)
222 : Eng(E), Block(B), LC(L) {
223 assert(B);
224 }
225
228
229 /// Return the CoreEngine associated with this builder.
230 const CoreEngine &getEngine() const { return Eng; }
231
232 /// Return the CFGBlock associated with this builder.
233 const CFGBlock *getBlock() const { return Block; }
234
235 /// Return the location context associated with this builder.
236 const LocationContext *getLocationContext() const { return LC; }
237
238 /// Returns the number of times the current basic block has been
239 /// visited on the exploded graph path.
240 unsigned blockCount() const {
241 return Eng.WList->getBlockCounter().getNumVisited(
242 LC->getStackFrame(),
243 Block->getBlockID());
244 }
245};
246
247/// \class NodeBuilder
248/// This is the simplest builder which generates nodes in the
249/// ExplodedGraph.
250///
251/// The main benefit of the builder is that it automatically tracks the
252/// frontier nodes (or destination set). This is the set of nodes which should
253/// be propagated to the next step / builder. They are the nodes which have been
254/// added to the builder (either as the input node set or as the newly
255/// constructed nodes) but did not have any outgoing transitions added.
256///
257/// TODO: This "main benefit" is often useless, in fact the only significant
258/// use is within `CheckerManager::ExpandGraphWithCheckers`. There this logic
259/// ensures that if a checker performs multiple transitions on the same path,
260/// then only the last of them is "built upon" by other checkers or the engine.
261///
262/// However, there are also many short-lived temporary `NodeBuilder` instances
263/// where the `generateNode` is called in a very predictable manner (once, or
264/// once for each source node) and the frontier management is overkill.
265/// These locations should be gradually simplified by using the method
266/// `CoreEngine::makeNode()` instead of the temporary `NodeBuilder`s.
268protected:
270
271 bool HasGeneratedNodes = false;
272
273 /// The frontier set - a set of nodes which need to be propagated after
274 /// the builder dies.
276
277public:
279 : C(Ctx), Frontier(DstSet) {}
280
282 const NodeBuilderContext &Ctx)
283 : NodeBuilder(DstSet, Ctx) {
284 Frontier.insert(SrcNode);
285 }
286
288 const NodeBuilderContext &Ctx)
289 : NodeBuilder(DstSet, Ctx) {
290 Frontier.insert(SrcSet);
291 }
292
293 /// Generates a node in the ExplodedGraph.
295 ExplodedNode *Pred, bool MarkAsSink = false);
296
297 /// Generates a sink in the ExplodedGraph.
298 ///
299 /// When a node is marked as sink, the exploration from the node is stopped -
300 /// the node becomes the last node on the path and certain kinds of bugs are
301 /// suppressed.
303 ProgramStateRef State,
304 ExplodedNode *Pred) {
305 return generateNode(PP, State, Pred, true);
306 }
307
309 ExplodedNode *Pred,
311 const ProgramPointTag *tag = nullptr,
314 Pred->getLocationContext(), tag);
315 return generateNode(L, St, Pred);
316 }
317
319 ExplodedNode *Pred,
321 const ProgramPointTag *tag = nullptr,
324 Pred->getLocationContext(), tag);
325 return generateSink(L, St, Pred);
326 }
327
328 const ExplodedNodeSet &getResults() const { return Frontier; }
329
330 bool hasGeneratedNodes() const { return HasGeneratedNodes; }
331
332 void takeNodes(const ExplodedNodeSet &S) {
333 for (const auto I : S)
334 Frontier.erase(I);
335 }
336
337 void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
338 void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
339 void addNodes(ExplodedNode *N) { Frontier.insert(N); }
340};
341
342} // namespace ento
343
344} // namespace clang
345
346#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
#define V(N, I)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Stores options for the analyzer from the command line.
Represents a single basic block in a source-level CFG.
Definition CFG.h:632
Represents binding an expression to a temporary.
Definition ExprCXX.h:1497
Represents a point when we begin processing an inlined call.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1637
This represents one expression.
Definition Expr.h:112
Represents the declaration of a label.
Definition Decl.h:524
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag)
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3166
Stmt - This represents one statement.
Definition Stmt.h:86
An abstract data type used to count the number of times a given block has been visited along a path a...
CoreEngine - Implements the core logic of the graph-reachability analysis.
Definition CoreEngine.h:50
void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)
Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.
Definition CoreEngine.h:157
CoreEngine(ExprEngine &exprengine, FunctionSummariesTy *FS, AnalyzerOptions &Opts)
Construct a CoreEngine object to analyze the provided CFG.
DataTag::Factory & getDataTags()
Definition CoreEngine.h:211
friend class ExprEngine
Definition CoreEngine.h:51
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
bool wasBlockAborted() const
Definition CoreEngine.h:149
CoreEngine & operator=(const CoreEngine &)=delete
void dispatchWorkItem(ExplodedNode *Pred, ProgramPoint Loc, const WorkListUnit &WU)
Dispatch the work list item based on the given location information.
friend class NodeBuilder
Definition CoreEngine.h:52
std::vector< std::pair< const CFGBlock *, const ExplodedNode * > > BlocksAborted
Definition CoreEngine.h:59
WorkList * getCTUWorkList() const
Definition CoreEngine.h:162
bool wasBlocksExhausted() const
Definition CoreEngine.h:150
WorkList * getWorkList() const
Definition CoreEngine.h:161
void enqueueStmtNodes(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx)
Enqueue nodes that were created as a result of processing a statement onto the work list.
CoreEngine(const CoreEngine &)=delete
std::vector< std::pair< BlockEdge, const ExplodedNode * > > BlocksExhausted
Definition CoreEngine.h:56
friend class NodeBuilderContext
Definition CoreEngine.h:53
bool ExecuteWorkList(const LocationContext *L, unsigned Steps, ProgramStateRef InitState)
ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
ExplodedNode * makePostStmtNode(const Stmt *S, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false) const
Definition CoreEngine.h:173
auto exhausted_blocks() const
Definition CoreEngine.h:164
bool hasWorkRemaining() const
Definition CoreEngine.h:151
ExplodedGraph & getGraph()
getGraph - Returns the exploded graph.
Definition CoreEngine.h:136
ExplodedNode * makeNodeWithBinding(ExplodedNode *Pred, const Expr *E, SVal V, ProgramPoint::Kind K=ProgramPoint::PostStmtKind) const
Definition CoreEngine.h:191
ExplodedNode * makeNodeWithBinding(ExplodedNode *Pred, const Expr *E, SVal V, ProgramStateRef State, ProgramPoint::Kind K=ProgramPoint::PostStmtKind) const
Definition CoreEngine.h:181
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)
enqueue the nodes corresponding to the end of function onto the end of path / work list.
auto aborted_blocks() const
Definition CoreEngine.h:168
ExplodedNode * makeNode(const ProgramPoint &Loc, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false) const
void enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
const ProgramStateRef & getState() const
const LocationContext * getLocationContext() const
const CoreEngine & getEngine() const
Return the CoreEngine associated with this builder.
Definition CoreEngine.h:230
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
Definition CoreEngine.h:233
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, const LocationContext *L)
Definition CoreEngine.h:220
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
Definition CoreEngine.h:226
const LocationContext * getLocationContext() const
Return the location context associated with this builder.
Definition CoreEngine.h:236
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path.
Definition CoreEngine.h:240
const NodeBuilderContext & C
Definition CoreEngine.h:269
void takeNodes(ExplodedNode *N)
Definition CoreEngine.h:337
NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:281
void takeNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:332
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false)
Generates a node in the ExplodedGraph.
ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a sink in the ExplodedGraph.
Definition CoreEngine.h:302
ExplodedNodeSet & Frontier
The frontier set - a set of nodes which need to be propagated after the builder dies.
Definition CoreEngine.h:275
void addNodes(ExplodedNode *N)
Definition CoreEngine.h:339
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:318
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:308
void addNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:338
bool hasGeneratedNodes() const
Definition CoreEngine.h:330
const ExplodedNodeSet & getResults() const
Definition CoreEngine.h:328
NodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:278
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:287
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:56
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
Expr * Cond
};