]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
Update clang to trunk r290819 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / StaticAnalyzer / Core / PathSensitive / CoreEngine.h
1 //==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines a generic engine for intraprocedural, path-sensitive,
11 //  dataflow analysis via graph reachability.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
17
18 #include "clang/AST/Expr.h"
19 #include "clang/Analysis/AnalysisContext.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
22 #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
23 #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
24 #include <memory>
25
26 namespace clang {
27
28 class ProgramPointTag;
29   
30 namespace ento {
31
32 class NodeBuilder;
33
34 //===----------------------------------------------------------------------===//
35 /// CoreEngine - Implements the core logic of the graph-reachability
36 ///   analysis. It traverses the CFG and generates the ExplodedGraph.
37 ///   Program "states" are treated as opaque void pointers.
38 ///   The template class CoreEngine (which subclasses CoreEngine)
39 ///   provides the matching component to the engine that knows the actual types
40 ///   for states.  Note that this engine only dispatches to transfer functions
41 ///   at the statement and block-level.  The analyses themselves must implement
42 ///   any transfer function logic and the sub-expression level (if any).
43 class CoreEngine {
44   friend struct NodeBuilderContext;
45   friend class NodeBuilder;
46   friend class ExprEngine;
47   friend class CommonNodeBuilder;
48   friend class IndirectGotoNodeBuilder;
49   friend class SwitchNodeBuilder;
50   friend class EndOfFunctionNodeBuilder;
51 public:
52   typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
53             BlocksExhausted;
54   
55   typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
56             BlocksAborted;
57
58 private:
59
60   SubEngine& SubEng;
61
62   /// G - The simulation graph.  Each node is a (location,state) pair.
63   mutable ExplodedGraph G;
64
65   /// WList - A set of queued nodes that need to be processed by the
66   ///  worklist algorithm.  It is up to the implementation of WList to decide
67   ///  the order that nodes are processed.
68   std::unique_ptr<WorkList> WList;
69
70   /// BCounterFactory - A factory object for created BlockCounter objects.
71   ///   These are used to record for key nodes in the ExplodedGraph the
72   ///   number of times different CFGBlocks have been visited along a path.
73   BlockCounter::Factory BCounterFactory;
74
75   /// The locations where we stopped doing work because we visited a location
76   ///  too many times.
77   BlocksExhausted blocksExhausted;
78   
79   /// The locations where we stopped because the engine aborted analysis,
80   /// usually because it could not reason about something.
81   BlocksAborted blocksAborted;
82
83   /// The information about functions shared by the whole translation unit.
84   /// (This data is owned by AnalysisConsumer.)
85   FunctionSummariesTy *FunctionSummaries;
86
87   void generateNode(const ProgramPoint &Loc,
88                     ProgramStateRef State,
89                     ExplodedNode *Pred);
90
91   void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
92   void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred);
93   void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred);
94
95   void HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred);
96
97   void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred);
98
99   void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
100                     ExplodedNode *Pred);
101   void HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
102                                     const CFGBlock *B, ExplodedNode *Pred);
103
104   /// Handle conditional logic for running static initializers.
105   void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
106                         ExplodedNode *Pred);
107
108 private:
109   CoreEngine(const CoreEngine &) = delete;
110   void operator=(const CoreEngine &) = delete;
111
112   ExplodedNode *generateCallExitBeginNode(ExplodedNode *N,
113                                           const ReturnStmt *RS);
114
115 public:
116   /// Construct a CoreEngine object to analyze the provided CFG.
117   CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS)
118       : SubEng(subengine), WList(WorkList::makeDFS()),
119         BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
120
121   /// getGraph - Returns the exploded graph.
122   ExplodedGraph &getGraph() { return G; }
123
124   /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
125   ///  steps.  Returns true if there is still simulation state on the worklist.
126   bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
127                        ProgramStateRef InitState);
128   /// Returns true if there is still simulation state on the worklist.
129   bool ExecuteWorkListWithInitialState(const LocationContext *L,
130                                        unsigned Steps,
131                                        ProgramStateRef InitState, 
132                                        ExplodedNodeSet &Dst);
133
134   /// Dispatch the work list item based on the given location information.
135   /// Use Pred parameter as the predecessor state.
136   void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
137                         const WorkListUnit& WU);
138
139   // Functions for external checking of whether we have unfinished work
140   bool wasBlockAborted() const { return !blocksAborted.empty(); }
141   bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
142   bool hasWorkRemaining() const { return wasBlocksExhausted() || 
143                                          WList->hasWork() || 
144                                          wasBlockAborted(); }
145
146   /// Inform the CoreEngine that a basic block was aborted because
147   /// it could not be completely analyzed.
148   void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
149     blocksAborted.push_back(std::make_pair(block, node));
150   }
151   
152   WorkList *getWorkList() const { return WList.get(); }
153
154   BlocksExhausted::const_iterator blocks_exhausted_begin() const {
155     return blocksExhausted.begin();
156   }
157   BlocksExhausted::const_iterator blocks_exhausted_end() const {
158     return blocksExhausted.end();
159   }
160   BlocksAborted::const_iterator blocks_aborted_begin() const {
161     return blocksAborted.begin();
162   }
163   BlocksAborted::const_iterator blocks_aborted_end() const {
164     return blocksAborted.end();
165   }
166
167   /// \brief Enqueue the given set of nodes onto the work list.
168   void enqueue(ExplodedNodeSet &Set);
169
170   /// \brief Enqueue nodes that were created as a result of processing
171   /// a statement onto the work list.
172   void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx);
173
174   /// \brief enqueue the nodes corresponding to the end of function onto the
175   /// end of path / work list.
176   void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS);
177
178   /// \brief Enqueue a single node created as a result of statement processing.
179   void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
180 };
181
182 // TODO: Turn into a calss.
183 struct NodeBuilderContext {
184   const CoreEngine &Eng;
185   const CFGBlock *Block;
186   const LocationContext *LC;
187   NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
188     : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); }
189
190   /// \brief Return the CFGBlock associated with this builder.
191   const CFGBlock *getBlock() const { return Block; }
192
193   /// \brief Returns the number of times the current basic block has been
194   /// visited on the exploded graph path.
195   unsigned blockCount() const {
196     return Eng.WList->getBlockCounter().getNumVisited(
197                     LC->getCurrentStackFrame(),
198                     Block->getBlockID());
199   }
200 };
201
202 /// \class NodeBuilder
203 /// \brief This is the simplest builder which generates nodes in the
204 /// ExplodedGraph.
205 ///
206 /// The main benefit of the builder is that it automatically tracks the
207 /// frontier nodes (or destination set). This is the set of nodes which should
208 /// be propagated to the next step / builder. They are the nodes which have been
209 /// added to the builder (either as the input node set or as the newly
210 /// constructed nodes) but did not have any outgoing transitions added.
211 class NodeBuilder {
212   virtual void anchor();
213 protected:
214   const NodeBuilderContext &C;
215
216   /// Specifies if the builder results have been finalized. For example, if it
217   /// is set to false, autotransitions are yet to be generated.
218   bool Finalized;
219   bool HasGeneratedNodes;
220   /// \brief The frontier set - a set of nodes which need to be propagated after
221   /// the builder dies.
222   ExplodedNodeSet &Frontier;
223
224   /// Checkes if the results are ready.
225   virtual bool checkResults() {
226     if (!Finalized)
227       return false;
228     return true;
229   }
230
231   bool hasNoSinksInFrontier() {
232     for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) {
233       if ((*I)->isSink())
234         return false;
235     }
236     return true;
237   }
238
239   /// Allow subclasses to finalize results before result_begin() is executed.
240   virtual void finalizeResults() {}
241   
242   ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
243                                  ProgramStateRef State,
244                                  ExplodedNode *Pred,
245                                  bool MarkAsSink = false);
246
247 public:
248   NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
249               const NodeBuilderContext &Ctx, bool F = true)
250     : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
251     Frontier.Add(SrcNode);
252   }
253
254   NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
255               const NodeBuilderContext &Ctx, bool F = true)
256     : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
257     Frontier.insert(SrcSet);
258     assert(hasNoSinksInFrontier());
259   }
260
261   virtual ~NodeBuilder() {}
262
263   /// \brief Generates a node in the ExplodedGraph.
264   ExplodedNode *generateNode(const ProgramPoint &PP,
265                              ProgramStateRef State,
266                              ExplodedNode *Pred) {
267     return generateNodeImpl(PP, State, Pred, false);
268   }
269
270   /// \brief Generates a sink in the ExplodedGraph.
271   ///
272   /// When a node is marked as sink, the exploration from the node is stopped -
273   /// the node becomes the last node on the path and certain kinds of bugs are
274   /// suppressed.
275   ExplodedNode *generateSink(const ProgramPoint &PP,
276                              ProgramStateRef State,
277                              ExplodedNode *Pred) {
278     return generateNodeImpl(PP, State, Pred, true);
279   }
280
281   const ExplodedNodeSet &getResults() {
282     finalizeResults();
283     assert(checkResults());
284     return Frontier;
285   }
286
287   typedef ExplodedNodeSet::iterator iterator;
288   /// \brief Iterators through the results frontier.
289   inline iterator begin() {
290     finalizeResults();
291     assert(checkResults());
292     return Frontier.begin();
293   }
294   inline iterator end() {
295     finalizeResults();
296     return Frontier.end();
297   }
298
299   const NodeBuilderContext &getContext() { return C; }
300   bool hasGeneratedNodes() { return HasGeneratedNodes; }
301
302   void takeNodes(const ExplodedNodeSet &S) {
303     for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I )
304       Frontier.erase(*I);
305   }
306   void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
307   void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
308   void addNodes(ExplodedNode *N) { Frontier.Add(N); }
309 };
310
311 /// \class NodeBuilderWithSinks
312 /// \brief This node builder keeps track of the generated sink nodes.
313 class NodeBuilderWithSinks: public NodeBuilder {
314   void anchor() override;
315 protected:
316   SmallVector<ExplodedNode*, 2> sinksGenerated;
317   ProgramPoint &Location;
318
319 public:
320   NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
321                        const NodeBuilderContext &Ctx, ProgramPoint &L)
322     : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
323
324   ExplodedNode *generateNode(ProgramStateRef State,
325                              ExplodedNode *Pred,
326                              const ProgramPointTag *Tag = nullptr) {
327     const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
328     return NodeBuilder::generateNode(LocalLoc, State, Pred);
329   }
330
331   ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
332                              const ProgramPointTag *Tag = nullptr) {
333     const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
334     ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred);
335     if (N && N->isSink())
336       sinksGenerated.push_back(N);
337     return N;
338   }
339
340   const SmallVectorImpl<ExplodedNode*> &getSinks() const {
341     return sinksGenerated;
342   }
343 };
344
345 /// \class StmtNodeBuilder
346 /// \brief This builder class is useful for generating nodes that resulted from
347 /// visiting a statement. The main difference from its parent NodeBuilder is
348 /// that it creates a statement specific ProgramPoint.
349 class StmtNodeBuilder: public NodeBuilder {
350   NodeBuilder *EnclosingBldr;
351 public:
352
353   /// \brief Constructs a StmtNodeBuilder. If the builder is going to process
354   /// nodes currently owned by another builder(with larger scope), use
355   /// Enclosing builder to transfer ownership.
356   StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
357                   const NodeBuilderContext &Ctx,
358                   NodeBuilder *Enclosing = nullptr)
359     : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
360     if (EnclosingBldr)
361       EnclosingBldr->takeNodes(SrcNode);
362   }
363
364   StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
365                   const NodeBuilderContext &Ctx,
366                   NodeBuilder *Enclosing = nullptr)
367     : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
368     if (EnclosingBldr)
369       for (ExplodedNodeSet::iterator I = SrcSet.begin(),
370                                      E = SrcSet.end(); I != E; ++I )
371         EnclosingBldr->takeNodes(*I);
372   }
373
374   ~StmtNodeBuilder() override;
375
376   using NodeBuilder::generateNode;
377   using NodeBuilder::generateSink;
378
379   ExplodedNode *generateNode(const Stmt *S,
380                              ExplodedNode *Pred,
381                              ProgramStateRef St,
382                              const ProgramPointTag *tag = nullptr,
383                              ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
384     const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
385                                   Pred->getLocationContext(), tag);
386     return NodeBuilder::generateNode(L, St, Pred);
387   }
388
389   ExplodedNode *generateSink(const Stmt *S,
390                              ExplodedNode *Pred,
391                              ProgramStateRef St,
392                              const ProgramPointTag *tag = nullptr,
393                              ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
394     const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
395                                   Pred->getLocationContext(), tag);
396     return NodeBuilder::generateSink(L, St, Pred);
397   }
398 };
399
400 /// \brief BranchNodeBuilder is responsible for constructing the nodes
401 /// corresponding to the two branches of the if statement - true and false.
402 class BranchNodeBuilder: public NodeBuilder {
403   void anchor() override;
404   const CFGBlock *DstT;
405   const CFGBlock *DstF;
406
407   bool InFeasibleTrue;
408   bool InFeasibleFalse;
409
410 public:
411   BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
412                     const NodeBuilderContext &C,
413                     const CFGBlock *dstT, const CFGBlock *dstF)
414   : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
415     InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
416     // The branch node builder does not generate autotransitions.
417     // If there are no successors it means that both branches are infeasible.
418     takeNodes(SrcNode);
419   }
420
421   BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
422                     const NodeBuilderContext &C,
423                     const CFGBlock *dstT, const CFGBlock *dstF)
424   : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
425     InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
426     takeNodes(SrcSet);
427   }
428
429   ExplodedNode *generateNode(ProgramStateRef State, bool branch,
430                              ExplodedNode *Pred);
431
432   const CFGBlock *getTargetBlock(bool branch) const {
433     return branch ? DstT : DstF;
434   }
435
436   void markInfeasible(bool branch) {
437     if (branch)
438       InFeasibleTrue = true;
439     else
440       InFeasibleFalse = true;
441   }
442
443   bool isFeasible(bool branch) {
444     return branch ? !InFeasibleTrue : !InFeasibleFalse;
445   }
446 };
447
448 class IndirectGotoNodeBuilder {
449   CoreEngine& Eng;
450   const CFGBlock *Src;
451   const CFGBlock &DispatchBlock;
452   const Expr *E;
453   ExplodedNode *Pred;
454
455 public:
456   IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src, 
457                     const Expr *e, const CFGBlock *dispatch, CoreEngine* eng)
458     : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
459
460   class iterator {
461     CFGBlock::const_succ_iterator I;
462
463     friend class IndirectGotoNodeBuilder;
464     iterator(CFGBlock::const_succ_iterator i) : I(i) {}
465   public:
466
467     iterator &operator++() { ++I; return *this; }
468     bool operator!=(const iterator &X) const { return I != X.I; }
469
470     const LabelDecl *getLabel() const {
471       return cast<LabelStmt>((*I)->getLabel())->getDecl();
472     }
473
474     const CFGBlock *getBlock() const {
475       return *I;
476     }
477   };
478
479   iterator begin() { return iterator(DispatchBlock.succ_begin()); }
480   iterator end() { return iterator(DispatchBlock.succ_end()); }
481
482   ExplodedNode *generateNode(const iterator &I,
483                              ProgramStateRef State,
484                              bool isSink = false);
485
486   const Expr *getTarget() const { return E; }
487
488   ProgramStateRef getState() const { return Pred->State; }
489   
490   const LocationContext *getLocationContext() const {
491     return Pred->getLocationContext();
492   }
493 };
494
495 class SwitchNodeBuilder {
496   CoreEngine& Eng;
497   const CFGBlock *Src;
498   const Expr *Condition;
499   ExplodedNode *Pred;
500
501 public:
502   SwitchNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
503                     const Expr *condition, CoreEngine* eng)
504   : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
505
506   class iterator {
507     CFGBlock::const_succ_reverse_iterator I;
508
509     friend class SwitchNodeBuilder;
510     iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
511
512   public:
513     iterator &operator++() { ++I; return *this; }
514     bool operator!=(const iterator &X) const { return I != X.I; }
515     bool operator==(const iterator &X) const { return I == X.I; }
516
517     const CaseStmt *getCase() const {
518       return cast<CaseStmt>((*I)->getLabel());
519     }
520
521     const CFGBlock *getBlock() const {
522       return *I;
523     }
524   };
525
526   iterator begin() { return iterator(Src->succ_rbegin()+1); }
527   iterator end() { return iterator(Src->succ_rend()); }
528
529   const SwitchStmt *getSwitch() const {
530     return cast<SwitchStmt>(Src->getTerminator());
531   }
532
533   ExplodedNode *generateCaseStmtNode(const iterator &I,
534                                      ProgramStateRef State);
535
536   ExplodedNode *generateDefaultCaseNode(ProgramStateRef State,
537                                         bool isSink = false);
538
539   const Expr *getCondition() const { return Condition; }
540
541   ProgramStateRef getState() const { return Pred->State; }
542   
543   const LocationContext *getLocationContext() const {
544     return Pred->getLocationContext();
545   }
546 };
547
548 } // end ento namespace
549 } // end clang namespace
550
551 #endif