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
173 /// Enqueue the given set of nodes onto the work list.
175
176 /// Enqueue nodes that were created as a result of processing
177 /// a statement onto the work list.
179 unsigned Idx);
180
181 /// enqueue the nodes corresponding to the end of function onto the
182 /// end of path / work list.
184
185 /// Enqueue a single node created as a result of statement processing.
186 void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
187
188 DataTag::Factory &getDataTags() { return DataTags; }
189};
190
192 const CoreEngine &Eng;
193 const CFGBlock *Block;
194 const LocationContext *LC;
195
196public:
198 const LocationContext *L)
199 : Eng(E), Block(B), LC(L) {
200 assert(B);
201 }
202
205
206 /// Return the CoreEngine associated with this builder.
207 const CoreEngine &getEngine() const { return Eng; }
208
209 /// Return the CFGBlock associated with this builder.
210 const CFGBlock *getBlock() const { return Block; }
211
212 /// Return the location context associated with this builder.
213 const LocationContext *getLocationContext() const { return LC; }
214
215 /// Returns the number of times the current basic block has been
216 /// visited on the exploded graph path.
217 unsigned blockCount() const {
218 return Eng.WList->getBlockCounter().getNumVisited(
219 LC->getStackFrame(),
220 Block->getBlockID());
221 }
222};
223
224/// \class NodeBuilder
225/// This is the simplest builder which generates nodes in the
226/// ExplodedGraph.
227///
228/// The main benefit of the builder is that it automatically tracks the
229/// frontier nodes (or destination set). This is the set of nodes which should
230/// be propagated to the next step / builder. They are the nodes which have been
231/// added to the builder (either as the input node set or as the newly
232/// constructed nodes) but did not have any outgoing transitions added.
233///
234/// TODO: This "main benefit" is often useless, in fact the only significant
235/// use is within `CheckerManager::ExpandGraphWithCheckers`. There this logic
236/// ensures that if a checker performs multiple transitions on the same path,
237/// then only the last of them is "built upon" by other checkers or the engine.
238///
239/// However, there are also many short-lived temporary `NodeBuilder` instances
240/// where the `generateNode` is called in a very predictable manner (once, or
241/// once for each source node) and the frontier management is overkill.
242/// These locations should be gradually simplified by using the method
243/// `CoreEngine::makeNode()` instead of the temporary `NodeBuilder`s.
245protected:
247
248 bool HasGeneratedNodes = false;
249
250 /// The frontier set - a set of nodes which need to be propagated after
251 /// the builder dies.
253
254public:
256 : C(Ctx), Frontier(DstSet) {}
257
259 const NodeBuilderContext &Ctx)
260 : NodeBuilder(DstSet, Ctx) {
261 Frontier.insert(SrcNode);
262 }
263
265 const NodeBuilderContext &Ctx)
266 : NodeBuilder(DstSet, Ctx) {
267 Frontier.insert(SrcSet);
268 }
269
270 /// Generates a node in the ExplodedGraph.
272 ExplodedNode *Pred, bool MarkAsSink = false);
273
274 /// Generates a sink in the ExplodedGraph.
275 ///
276 /// When a node is marked as sink, the exploration from the node is stopped -
277 /// the node becomes the last node on the path and certain kinds of bugs are
278 /// suppressed.
280 ProgramStateRef State,
281 ExplodedNode *Pred) {
282 return generateNode(PP, State, Pred, true);
283 }
284
286 ExplodedNode *Pred,
288 const ProgramPointTag *tag = nullptr,
291 Pred->getLocationContext(), tag);
292 return generateNode(L, St, Pred);
293 }
294
296 ExplodedNode *Pred,
298 const ProgramPointTag *tag = nullptr,
301 Pred->getLocationContext(), tag);
302 return generateSink(L, St, Pred);
303 }
304
305 const ExplodedNodeSet &getResults() const { return Frontier; }
306
307 bool hasGeneratedNodes() const { return HasGeneratedNodes; }
308
309 void takeNodes(const ExplodedNodeSet &S) {
310 for (const auto I : S)
311 Frontier.erase(I);
312 }
313
314 void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
315 void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
316 void addNodes(ExplodedNode *N) { Frontier.insert(N); }
317};
318
319/// BranchNodeBuilder is responsible for constructing the nodes
320/// corresponding to the two branches of the if statement - true and false.
322 const CFGBlock *DstT;
323 const CFGBlock *DstF;
324
325public:
327 const CFGBlock *DT, const CFGBlock *DF)
328 : NodeBuilder(DstSet, C), DstT(DT), DstF(DF) {}
329
330 ExplodedNode *generateNode(ProgramStateRef State, bool branch,
331 ExplodedNode *Pred);
332};
333
334} // namespace ento
335
336} // namespace clang
337
338#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
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
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: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...
ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)
BranchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &C, const CFGBlock *DT, const CFGBlock *DF)
Definition CoreEngine.h:326
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:188
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.
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
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 LocationContext * getLocationContext() const
const CoreEngine & getEngine() const
Return the CoreEngine associated with this builder.
Definition CoreEngine.h:207
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
Definition CoreEngine.h:210
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, const LocationContext *L)
Definition CoreEngine.h:197
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
Definition CoreEngine.h:203
const LocationContext * getLocationContext() const
Return the location context associated with this builder.
Definition CoreEngine.h:213
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path.
Definition CoreEngine.h:217
const NodeBuilderContext & C
Definition CoreEngine.h:246
void takeNodes(ExplodedNode *N)
Definition CoreEngine.h:314
NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:258
void takeNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:309
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:279
ExplodedNodeSet & Frontier
The frontier set - a set of nodes which need to be propagated after the builder dies.
Definition CoreEngine.h:252
void addNodes(ExplodedNode *N)
Definition CoreEngine.h:316
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:295
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition CoreEngine.h:285
void addNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:315
bool hasGeneratedNodes() const
Definition CoreEngine.h:307
const ExplodedNodeSet & getResults() const
Definition CoreEngine.h:305
NodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:255
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
Definition CoreEngine.h:264
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
Expr * Cond
};