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