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;
53 friend class NodeBuilder;
54 friend class NodeBuilderContext;
55 friend class SwitchNodeBuilder;
56
57public:
59 std::vector<std::pair<BlockEdge, const ExplodedNode *>>;
60
62 std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>;
63
64private:
65 ExprEngine &ExprEng;
66
67 /// G - The simulation graph. Each node is a (location,state) pair.
68 mutable ExplodedGraph G;
69
70 /// WList - A set of queued nodes that need to be processed by the
71 /// worklist algorithm. It is up to the implementation of WList to decide
72 /// the order that nodes are processed.
73 std::unique_ptr<WorkList> WList;
74 std::unique_ptr<WorkList> CTUWList;
75
76 /// BCounterFactory - A factory object for created BlockCounter objects.
77 /// These are used to record for key nodes in the ExplodedGraph the
78 /// number of times different CFGBlocks have been visited along a path.
79 BlockCounter::Factory BCounterFactory;
80
81 /// The locations where we stopped doing work because we visited a location
82 /// too many times.
83 BlocksExhausted blocksExhausted;
84
85 /// The locations where we stopped because the engine aborted analysis,
86 /// usually because it could not reason about something.
87 BlocksAborted blocksAborted;
88
89 /// The information about functions shared by the whole translation unit.
90 /// (This data is owned by AnalysisConsumer.)
91 FunctionSummariesTy *FunctionSummaries;
92
93 /// Add path tags with some useful data along the path when we see that
94 /// something interesting is happening. This field is the allocator for such
95 /// tags.
96 DataTag::Factory DataTags;
97
98 void setBlockCounter(BlockCounter C);
99
100 void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
101 void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred);
102 void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred);
103
104 void HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred);
105
106 void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred);
107
108 void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
109 ExplodedNode *Pred);
110 void HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
111 const CFGBlock *B, ExplodedNode *Pred);
112
113 /// Handle conditional logic for running static initializers.
114 void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
115 ExplodedNode *Pred);
116
117 void HandleVirtualBaseBranch(const CFGBlock *B, ExplodedNode *Pred);
118
119private:
120 /// Helper function called by `HandleBranch()`. If the currently handled
121 /// branch corresponds to a loop, this returns the number of already
122 /// completed iterations in that loop, otherwise the return value is
123 /// `std::nullopt`. Note that this counts _all_ earlier iterations, including
124 /// ones that were performed within an earlier iteration of an outer loop.
125 std::optional<unsigned> getCompletedIterationCount(const CFGBlock *B,
126 ExplodedNode *Pred) const;
127
128public:
129 /// Construct a CoreEngine object to analyze the provided CFG.
130 CoreEngine(ExprEngine &exprengine,
132 AnalyzerOptions &Opts);
133
134 CoreEngine(const CoreEngine &) = delete;
135 CoreEngine &operator=(const CoreEngine &) = delete;
136
137 /// getGraph - Returns the exploded graph.
138 ExplodedGraph &getGraph() { return G; }
139
140 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
141 /// steps. Returns true if there is still simulation state on the worklist.
142 bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
143 ProgramStateRef InitState);
144
145 /// Dispatch the work list item based on the given location information.
146 /// Use Pred parameter as the predecessor state.
148 const WorkListUnit& WU);
149
150 // Functions for external checking of whether we have unfinished work.
151 bool wasBlockAborted() const { return !blocksAborted.empty(); }
152 bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
153 bool hasWorkRemaining() const { return wasBlocksExhausted() ||
154 WList->hasWork() ||
155 wasBlockAborted(); }
156
157 /// Inform the CoreEngine that a basic block was aborted because
158 /// it could not be completely analyzed.
159 void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
160 blocksAborted.push_back(std::make_pair(block, node));
161 }
162
163 WorkList *getWorkList() const { return WList.get(); }
164 WorkList *getCTUWorkList() const { return CTUWList.get(); }
165
166 auto exhausted_blocks() const {
167 return llvm::iterator_range(blocksExhausted);
168 }
169
170 auto aborted_blocks() const { return llvm::iterator_range(blocksAborted); }
171
173 ExplodedNode *Pred, bool MarkAsSink = false) const;
174
175 /// Enqueue the given set of nodes onto the work list.
177
178 /// Enqueue nodes that were created as a result of processing
179 /// a statement onto the work list.
181 unsigned Idx);
182
183 /// enqueue the nodes corresponding to the end of function onto the
184 /// end of path / work list.
186
187 /// Enqueue a single node created as a result of statement processing.
188 void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
189
190 DataTag::Factory &getDataTags() { return DataTags; }
191};
192
194 const CoreEngine &Eng;
195 const CFGBlock *Block;
196 const LocationContext *LC;
197
198public:
200 const LocationContext *L)
201 : Eng(E), Block(B), LC(L) {
202 assert(B);
203 }
204
207
208 /// Return the CoreEngine associated with this builder.
209 const CoreEngine &getEngine() const { return Eng; }
210
211 /// Return the CFGBlock associated with this builder.
212 const CFGBlock *getBlock() const { return Block; }
213
214 /// Return the location context associated with this builder.
215 const LocationContext *getLocationContext() const { return LC; }
216
217 /// Returns the number of times the current basic block has been
218 /// visited on the exploded graph path.
219 unsigned blockCount() const {
220 return Eng.WList->getBlockCounter().getNumVisited(
221 LC->getStackFrame(),
222 Block->getBlockID());
223 }
224};
225
226/// \class NodeBuilder
227/// This is the simplest builder which generates nodes in the
228/// ExplodedGraph.
229///
230/// The main benefit of the builder is that it automatically tracks the
231/// frontier nodes (or destination set). This is the set of nodes which should
232/// be propagated to the next step / builder. They are the nodes which have been
233/// added to the builder (either as the input node set or as the newly
234/// constructed nodes) but did not have any outgoing transitions added.
235///
236/// TODO: This "main benefit" is often useless, in fact the only significant
237/// use is within `CheckerManager::ExpandGraphWithCheckers`. There this logic
238/// ensures that if a checker performs multiple transitions on the same path,
239/// then only the last of them is "built upon" by other checkers or the engine.
240///
241/// However, there are also many short-lived temporary `NodeBuilder` instances
242/// where the `generateNode` is called in a very predictable manner (once, or
243/// once for each source node) and the frontier management is overkill.
244/// These locations should be gradually simplified by using the method
245/// `CoreEngine::makeNode()` instead of the temporary `NodeBuilder`s.
247protected:
249
250 bool HasGeneratedNodes = false;
251
252 /// The frontier set - a set of nodes which need to be propagated after
253 /// the builder dies.
255
256public:
258 : C(Ctx), Frontier(DstSet) {}
259
261 const NodeBuilderContext &Ctx)
262 : NodeBuilder(DstSet, Ctx) {
263 Frontier.Add(SrcNode);
264 }
265
267 const NodeBuilderContext &Ctx)
268 : NodeBuilder(DstSet, Ctx) {
269 Frontier.insert(SrcSet);
270 }
271
272 /// Generates a node in the ExplodedGraph.
274 ExplodedNode *Pred, bool MarkAsSink = false);
275
276 /// Generates a sink in the ExplodedGraph.
277 ///
278 /// When a node is marked as sink, the exploration from the node is stopped -
279 /// the node becomes the last node on the path and certain kinds of bugs are
280 /// suppressed.
282 ProgramStateRef State,
283 ExplodedNode *Pred) {
284 return generateNode(PP, State, Pred, true);
285 }
286
288 ExplodedNode *Pred,
290 const ProgramPointTag *tag = nullptr,
293 Pred->getLocationContext(), tag);
294 return generateNode(L, St, Pred);
295 }
296
298 ExplodedNode *Pred,
300 const ProgramPointTag *tag = nullptr,
303 Pred->getLocationContext(), tag);
304 return generateSink(L, St, Pred);
305 }
306
307 const ExplodedNodeSet &getResults() const { return Frontier; }
308
309 const NodeBuilderContext &getContext() const { return C; }
310 bool hasGeneratedNodes() const { return HasGeneratedNodes; }
311
312 void takeNodes(const ExplodedNodeSet &S) {
313 for (const auto I : S)
314 Frontier.erase(I);
315 }
316
317 void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
318 void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
319 void addNodes(ExplodedNode *N) { Frontier.Add(N); }
320};
321
322/// BranchNodeBuilder is responsible for constructing the nodes
323/// corresponding to the two branches of the if statement - true and false.
325 const CFGBlock *DstT;
326 const CFGBlock *DstF;
327
328public:
330 const CFGBlock *DT, const CFGBlock *DF)
331 : NodeBuilder(DstSet, C), DstT(DT), DstF(DF) {}
332
333 ExplodedNode *generateNode(ProgramStateRef State, bool branch,
334 ExplodedNode *Pred);
335};
336
338 const CFGBlock &DispatchBlock;
339 const Expr *Target;
340
341public:
343 const Expr *Tgt, const CFGBlock *Dispatch)
344 : NodeBuilder(DstSet, Ctx), DispatchBlock(*Dispatch), Target(Tgt) {}
345
347
348 iterator begin() { return DispatchBlock.succ_begin(); }
349 iterator end() { return DispatchBlock.succ_end(); }
350
352
354 ExplodedNode *Pred);
355
356 const Expr *getTarget() const { return Target; }
357
359 return C.getLocationContext();
360 }
361};
362
364public:
366 : NodeBuilder(DstSet, Ctx) {}
367
369
370 iterator begin() { return C.getBlock()->succ_rbegin() + 1; }
371 iterator end() { return C.getBlock()->succ_rend(); }
372
374 ProgramStateRef State, ExplodedNode *Pred);
375
377 ExplodedNode *Pred);
378};
379
380} // namespace ento
381
382} // namespace clang
383
384#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
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
AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator
Definition CFG.h:995
AdjacentBlocks::const_iterator const_succ_iterator
Definition CFG.h:993
Represents binding an expression to a temporary.
Definition ExprCXX.h:1494
Represents a point when we begin processing an inlined call.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1623
This represents one expression.
Definition Expr.h:112
Represents the declaration of a label.
Definition Decl.h:524
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
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:3152
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...
ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)
BranchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &C, const CFGBlock *DT, const CFGBlock *DF)
Definition CoreEngine.h:329
CoreEngine - Implements the core logic of the graph-reachability analysis.
Definition CoreEngine.h:50
friend class SwitchNodeBuilder
Definition CoreEngine.h:55
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:159
CoreEngine(ExprEngine &exprengine, FunctionSummariesTy *FS, AnalyzerOptions &Opts)
Construct a CoreEngine object to analyze the provided CFG.
DataTag::Factory & getDataTags()
Definition CoreEngine.h:190
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:151
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:53
std::vector< std::pair< const CFGBlock *, const ExplodedNode * > > BlocksAborted
Definition CoreEngine.h:61
WorkList * getCTUWorkList() const
Definition CoreEngine.h:164
bool wasBlocksExhausted() const
Definition CoreEngine.h:152
friend class IndirectGotoNodeBuilder
Definition CoreEngine.h:52
WorkList * getWorkList() const
Definition CoreEngine.h:163
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:58
friend class NodeBuilderContext
Definition CoreEngine.h:54
bool ExecuteWorkList(const LocationContext *L, unsigned Steps, ProgramStateRef InitState)
ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
auto exhausted_blocks() const
Definition CoreEngine.h:166
bool hasWorkRemaining() const
Definition CoreEngine.h:153
ExplodedGraph & getGraph()
getGraph - Returns the exploded graph.
Definition CoreEngine.h:138
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:170
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.
const LocationContext * getLocationContext() const
IndirectGotoNodeBuilder(ExplodedNodeSet &DstSet, NodeBuilderContext &Ctx, const Expr *Tgt, const CFGBlock *Dispatch)
Definition CoreEngine.h:342
CFGBlock::const_succ_iterator iterator
Definition CoreEngine.h:346
const LocationContext * getLocationContext() const
Definition CoreEngine.h:358
ExplodedNode * generateNode(const CFGBlock *Block, ProgramStateRef State, ExplodedNode *Pred)
const CoreEngine & getEngine() const
Return the CoreEngine associated with this builder.
Definition CoreEngine.h:209
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
Definition CoreEngine.h:212
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, const LocationContext *L)
Definition CoreEngine.h:199
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
Definition CoreEngine.h:205
const LocationContext * getLocationContext() const
Return the location context associated with this builder.
Definition CoreEngine.h:215
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path.
Definition CoreEngine.h:219
const NodeBuilderContext & C
Definition CoreEngine.h:248
void takeNodes(ExplodedNode *N)
Definition CoreEngine.h:317
const NodeBuilderContext & getContext() const
Definition CoreEngine.h:309
NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:260
void takeNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:312
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:281
ExplodedNodeSet & Frontier
The frontier set - a set of nodes which need to be propagated after the builder dies.
Definition CoreEngine.h:254
void addNodes(ExplodedNode *N)
Definition CoreEngine.h:319
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:297
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:287
void addNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:318
bool hasGeneratedNodes() const
Definition CoreEngine.h:310
const ExplodedNodeSet & getResults() const
Definition CoreEngine.h:307
NodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:257
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:266
SwitchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:365
CFGBlock::const_succ_reverse_iterator iterator
Definition CoreEngine.h:368
ExplodedNode * generateCaseStmtNode(const CFGBlock *Block, ProgramStateRef State, ExplodedNode *Pred)
ExplodedNode * generateDefaultCaseNode(ProgramStateRef State, ExplodedNode *Pred)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
Expr * Cond
};