1 //==- CoreEngine.cpp - 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 engine.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #define DEBUG_TYPE "CoreEngine"
16 
17 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20 #include "clang/Index/TranslationUnit.h"
21 #include "clang/AST/Expr.h"
22 #include "clang/AST/StmtCXX.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/Statistic.h"
26 
27 using namespace clang;
28 using namespace ento;
29 
30 STATISTIC(NumReachedMaxSteps,
31             "The # of times we reached the max number of steps.");
32 STATISTIC(NumPathsExplored,
33             "The # of paths explored by the analyzer.");
34 
35 //===----------------------------------------------------------------------===//
36 // Worklist classes for exploration of reachable states.
37 //===----------------------------------------------------------------------===//
38 
39 WorkList::Visitor::~Visitor() {}
40 
41 namespace {
42 class DFS : public WorkList {
43   SmallVector<WorkListUnit,20> Stack;
44 public:
45   virtual bool hasWork() const {
46     return !Stack.empty();
47   }
48 
49   virtual void enqueue(const WorkListUnit& U) {
50     Stack.push_back(U);
51   }
52 
53   virtual WorkListUnit dequeue() {
54     assert (!Stack.empty());
55     const WorkListUnit& U = Stack.back();
56     Stack.pop_back(); // This technically "invalidates" U, but we are fine.
57     return U;
58   }
59 
60   virtual bool visitItemsInWorkList(Visitor &V) {
61     for (SmallVectorImpl<WorkListUnit>::iterator
62          I = Stack.begin(), E = Stack.end(); I != E; ++I) {
63       if (V.visit(*I))
64         return true;
65     }
66     return false;
67   }
68 };
69 
70 class BFS : public WorkList {
71   std::deque<WorkListUnit> Queue;
72 public:
73   virtual bool hasWork() const {
74     return !Queue.empty();
75   }
76 
77   virtual void enqueue(const WorkListUnit& U) {
78     Queue.push_front(U);
79   }
80 
81   virtual WorkListUnit dequeue() {
82     WorkListUnit U = Queue.front();
83     Queue.pop_front();
84     return U;
85   }
86 
87   virtual bool visitItemsInWorkList(Visitor &V) {
88     for (std::deque<WorkListUnit>::iterator
89          I = Queue.begin(), E = Queue.end(); I != E; ++I) {
90       if (V.visit(*I))
91         return true;
92     }
93     return false;
94   }
95 };
96 
97 } // end anonymous namespace
98 
99 // Place the dstor for WorkList here because it contains virtual member
100 // functions, and we the code for the dstor generated in one compilation unit.
101 WorkList::~WorkList() {}
102 
103 WorkList *WorkList::makeDFS() { return new DFS(); }
104 WorkList *WorkList::makeBFS() { return new BFS(); }
105 
106 namespace {
107   class BFSBlockDFSContents : public WorkList {
108     std::deque<WorkListUnit> Queue;
109     SmallVector<WorkListUnit,20> Stack;
110   public:
111     virtual bool hasWork() const {
112       return !Queue.empty() || !Stack.empty();
113     }
114 
115     virtual void enqueue(const WorkListUnit& U) {
116       if (isa<BlockEntrance>(U.getNode()->getLocation()))
117         Queue.push_front(U);
118       else
119         Stack.push_back(U);
120     }
121 
122     virtual WorkListUnit dequeue() {
123       // Process all basic blocks to completion.
124       if (!Stack.empty()) {
125         const WorkListUnit& U = Stack.back();
126         Stack.pop_back(); // This technically "invalidates" U, but we are fine.
127         return U;
128       }
129 
130       assert(!Queue.empty());
131       // Don't use const reference.  The subsequent pop_back() might make it
132       // unsafe.
133       WorkListUnit U = Queue.front();
134       Queue.pop_front();
135       return U;
136     }
137     virtual bool visitItemsInWorkList(Visitor &V) {
138       for (SmallVectorImpl<WorkListUnit>::iterator
139            I = Stack.begin(), E = Stack.end(); I != E; ++I) {
140         if (V.visit(*I))
141           return true;
142       }
143       for (std::deque<WorkListUnit>::iterator
144            I = Queue.begin(), E = Queue.end(); I != E; ++I) {
145         if (V.visit(*I))
146           return true;
147       }
148       return false;
149     }
150 
151   };
152 } // end anonymous namespace
153 
154 WorkList* WorkList::makeBFSBlockDFSContents() {
155   return new BFSBlockDFSContents();
156 }
157 
158 //===----------------------------------------------------------------------===//
159 // Core analysis engine.
160 //===----------------------------------------------------------------------===//
161 
162 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
163 bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
164                                    ProgramStateRef InitState) {
165 
166   if (G->num_roots() == 0) { // Initialize the analysis by constructing
167     // the root if none exists.
168 
169     const CFGBlock *Entry = &(L->getCFG()->getEntry());
170 
171     assert (Entry->empty() &&
172             "Entry block must be empty.");
173 
174     assert (Entry->succ_size() == 1 &&
175             "Entry block must have 1 successor.");
176 
177     // Get the solitary successor.
178     const CFGBlock *Succ = *(Entry->succ_begin());
179 
180     // Construct an edge representing the
181     // starting location in the function.
182     BlockEdge StartLoc(Entry, Succ, L);
183 
184     // Set the current block counter to being empty.
185     WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
186 
187     if (!InitState)
188       // Generate the root.
189       generateNode(StartLoc, SubEng.getInitialState(L), 0);
190     else
191       generateNode(StartLoc, InitState, 0);
192   }
193 
194   // Check if we have a steps limit
195   bool UnlimitedSteps = Steps == 0;
196 
197   while (WList->hasWork()) {
198     if (!UnlimitedSteps) {
199       if (Steps == 0) {
200         NumReachedMaxSteps++;
201         break;
202       }
203       --Steps;
204     }
205 
206     const WorkListUnit& WU = WList->dequeue();
207 
208     // Set the current block counter.
209     WList->setBlockCounter(WU.getBlockCounter());
210 
211     // Retrieve the node.
212     ExplodedNode *Node = WU.getNode();
213 
214     dispatchWorkItem(Node, Node->getLocation(), WU);
215   }
216   SubEng.processEndWorklist(hasWorkRemaining());
217   return WList->hasWork();
218 }
219 
220 void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
221                                   const WorkListUnit& WU) {
222   // Dispatch on the location type.
223   switch (Loc.getKind()) {
224     case ProgramPoint::BlockEdgeKind:
225       HandleBlockEdge(cast<BlockEdge>(Loc), Pred);
226       break;
227 
228     case ProgramPoint::BlockEntranceKind:
229       HandleBlockEntrance(cast<BlockEntrance>(Loc), Pred);
230       break;
231 
232     case ProgramPoint::BlockExitKind:
233       assert (false && "BlockExit location never occur in forward analysis.");
234       break;
235 
236     case ProgramPoint::CallEnterKind: {
237       CallEnter CEnter = cast<CallEnter>(Loc);
238       if (AnalyzedCallees)
239         if (const CallExpr* CE =
240             dyn_cast_or_null<CallExpr>(CEnter.getCallExpr()))
241           if (const Decl *CD = CE->getCalleeDecl())
242             AnalyzedCallees->insert(CD);
243       SubEng.processCallEnter(CEnter, Pred);
244       break;
245     }
246 
247     case ProgramPoint::CallExitKind:
248       SubEng.processCallExit(Pred);
249       break;
250 
251     case ProgramPoint::EpsilonKind: {
252       assert(Pred->hasSinglePred() &&
253              "Assume epsilon has exactly one predecessor by construction");
254       ExplodedNode *PNode = Pred->getFirstPred();
255       dispatchWorkItem(Pred, PNode->getLocation(), WU);
256       break;
257     }
258     default:
259       assert(isa<PostStmt>(Loc) ||
260              isa<PostInitializer>(Loc));
261       HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
262       break;
263   }
264 }
265 
266 bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
267                                                  unsigned Steps,
268                                                  ProgramStateRef InitState,
269                                                  ExplodedNodeSet &Dst) {
270   bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
271   for (ExplodedGraph::eop_iterator I = G->eop_begin(),
272                                    E = G->eop_end(); I != E; ++I) {
273     Dst.Add(*I);
274   }
275   return DidNotFinish;
276 }
277 
278 void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
279 
280   const CFGBlock *Blk = L.getDst();
281   NodeBuilderContext BuilderCtx(*this, Blk, Pred);
282 
283   // Check if we are entering the EXIT block.
284   if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
285 
286     assert (L.getLocationContext()->getCFG()->getExit().size() == 0
287             && "EXIT block cannot contain Stmts.");
288 
289     // Process the final state transition.
290     SubEng.processEndOfFunction(BuilderCtx);
291 
292     // This path is done. Don't enqueue any more nodes.
293     return;
294   }
295 
296   // Call into the SubEngine to process entering the CFGBlock.
297   ExplodedNodeSet dstNodes;
298   BlockEntrance BE(Blk, Pred->getLocationContext());
299   NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
300   SubEng.processCFGBlockEntrance(L, nodeBuilder);
301 
302   // Auto-generate a node.
303   if (!nodeBuilder.hasGeneratedNodes()) {
304     nodeBuilder.generateNode(Pred->State, Pred);
305   }
306 
307   // Enqueue nodes onto the worklist.
308   enqueue(dstNodes);
309 }
310 
311 void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
312                                        ExplodedNode *Pred) {
313 
314   // Increment the block counter.
315   BlockCounter Counter = WList->getBlockCounter();
316   Counter = BCounterFactory.IncrementCount(Counter,
317                              Pred->getLocationContext()->getCurrentStackFrame(),
318                                            L.getBlock()->getBlockID());
319   WList->setBlockCounter(Counter);
320 
321   // Process the entrance of the block.
322   if (CFGElement E = L.getFirstElement()) {
323     NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
324     SubEng.processCFGElement(E, Pred, 0, &Ctx);
325   }
326   else
327     HandleBlockExit(L.getBlock(), Pred);
328 }
329 
330 void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
331 
332   if (const Stmt *Term = B->getTerminator()) {
333     switch (Term->getStmtClass()) {
334       default:
335         llvm_unreachable("Analysis for this terminator not implemented.");
336 
337       case Stmt::BinaryOperatorClass: // '&&' and '||'
338         HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
339         return;
340 
341       case Stmt::BinaryConditionalOperatorClass:
342       case Stmt::ConditionalOperatorClass:
343         HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
344                      Term, B, Pred);
345         return;
346 
347         // FIXME: Use constant-folding in CFG construction to simplify this
348         // case.
349 
350       case Stmt::ChooseExprClass:
351         HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
352         return;
353 
354       case Stmt::CXXTryStmtClass: {
355         // Generate a node for each of the successors.
356         // Our logic for EH analysis can certainly be improved.
357         for (CFGBlock::const_succ_iterator it = B->succ_begin(),
358              et = B->succ_end(); it != et; ++it) {
359           if (const CFGBlock *succ = *it) {
360             generateNode(BlockEdge(B, succ, Pred->getLocationContext()),
361                          Pred->State, Pred);
362           }
363         }
364         return;
365       }
366 
367       case Stmt::DoStmtClass:
368         HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
369         return;
370 
371       case Stmt::CXXForRangeStmtClass:
372         HandleBranch(cast<CXXForRangeStmt>(Term)->getCond(), Term, B, Pred);
373         return;
374 
375       case Stmt::ForStmtClass:
376         HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
377         return;
378 
379       case Stmt::ContinueStmtClass:
380       case Stmt::BreakStmtClass:
381       case Stmt::GotoStmtClass:
382         break;
383 
384       case Stmt::IfStmtClass:
385         HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
386         return;
387 
388       case Stmt::IndirectGotoStmtClass: {
389         // Only 1 successor: the indirect goto dispatch block.
390         assert (B->succ_size() == 1);
391 
392         IndirectGotoNodeBuilder
393            builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
394                    *(B->succ_begin()), this);
395 
396         SubEng.processIndirectGoto(builder);
397         return;
398       }
399 
400       case Stmt::ObjCForCollectionStmtClass: {
401         // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
402         //
403         //  (1) inside a basic block, which represents the binding of the
404         //      'element' variable to a value.
405         //  (2) in a terminator, which represents the branch.
406         //
407         // For (1), subengines will bind a value (i.e., 0 or 1) indicating
408         // whether or not collection contains any more elements.  We cannot
409         // just test to see if the element is nil because a container can
410         // contain nil elements.
411         HandleBranch(Term, Term, B, Pred);
412         return;
413       }
414 
415       case Stmt::SwitchStmtClass: {
416         SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
417                                     this);
418 
419         SubEng.processSwitch(builder);
420         return;
421       }
422 
423       case Stmt::WhileStmtClass:
424         HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
425         return;
426     }
427   }
428 
429   assert (B->succ_size() == 1 &&
430           "Blocks with no terminator should have at most 1 successor.");
431 
432   generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
433                Pred->State, Pred);
434 }
435 
436 void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
437                                 const CFGBlock * B, ExplodedNode *Pred) {
438   assert(B->succ_size() == 2);
439   NodeBuilderContext Ctx(*this, B, Pred);
440   ExplodedNodeSet Dst;
441   SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
442                        *(B->succ_begin()), *(B->succ_begin()+1));
443   // Enqueue the new frontier onto the worklist.
444   enqueue(Dst);
445 }
446 
447 void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
448                                   ExplodedNode *Pred) {
449   assert(B);
450   assert(!B->empty());
451 
452   if (StmtIdx == B->size())
453     HandleBlockExit(B, Pred);
454   else {
455     NodeBuilderContext Ctx(*this, B, Pred);
456     SubEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx);
457   }
458 }
459 
460 /// generateNode - Utility method to generate nodes, hook up successors,
461 ///  and add nodes to the worklist.
462 void CoreEngine::generateNode(const ProgramPoint &Loc,
463                               ProgramStateRef State,
464                               ExplodedNode *Pred) {
465 
466   bool IsNew;
467   ExplodedNode *Node = G->getNode(Loc, State, false, &IsNew);
468 
469   if (Pred)
470     Node->addPredecessor(Pred, *G);  // Link 'Node' with its predecessor.
471   else {
472     assert (IsNew);
473     G->addRoot(Node);  // 'Node' has no predecessor.  Make it a root.
474   }
475 
476   // Only add 'Node' to the worklist if it was freshly generated.
477   if (IsNew) WList->enqueue(Node);
478 }
479 
480 void CoreEngine::enqueueStmtNode(ExplodedNode *N,
481                                  const CFGBlock *Block, unsigned Idx) {
482   assert(Block);
483   assert (!N->isSink());
484 
485   // Check if this node entered a callee.
486   if (isa<CallEnter>(N->getLocation())) {
487     // Still use the index of the CallExpr. It's needed to create the callee
488     // StackFrameContext.
489     WList->enqueue(N, Block, Idx);
490     return;
491   }
492 
493   // Do not create extra nodes. Move to the next CFG element.
494   if (isa<PostInitializer>(N->getLocation())) {
495     WList->enqueue(N, Block, Idx+1);
496     return;
497   }
498 
499   if (isa<EpsilonPoint>(N->getLocation())) {
500     WList->enqueue(N, Block, Idx);
501     return;
502   }
503 
504   const CFGStmt *CS = (*Block)[Idx].getAs<CFGStmt>();
505   const Stmt *St = CS ? CS->getStmt() : 0;
506   PostStmt Loc(St, N->getLocationContext());
507 
508   if (Loc == N->getLocation()) {
509     // Note: 'N' should be a fresh node because otherwise it shouldn't be
510     // a member of Deferred.
511     WList->enqueue(N, Block, Idx+1);
512     return;
513   }
514 
515   bool IsNew;
516   ExplodedNode *Succ = G->getNode(Loc, N->getState(), false, &IsNew);
517   Succ->addPredecessor(N, *G);
518 
519   if (IsNew)
520     WList->enqueue(Succ, Block, Idx+1);
521 }
522 
523 ExplodedNode *CoreEngine::generateCallExitNode(ExplodedNode *N) {
524   // Create a CallExit node and enqueue it.
525   const StackFrameContext *LocCtx
526                          = cast<StackFrameContext>(N->getLocationContext());
527   const Stmt *CE = LocCtx->getCallSite();
528 
529   // Use the the callee location context.
530   CallExit Loc(CE, LocCtx);
531 
532   bool isNew;
533   ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
534   Node->addPredecessor(N, *G);
535   return isNew ? Node : 0;
536 }
537 
538 
539 void CoreEngine::enqueue(ExplodedNodeSet &Set) {
540   for (ExplodedNodeSet::iterator I = Set.begin(),
541                                  E = Set.end(); I != E; ++I) {
542     WList->enqueue(*I);
543   }
544 }
545 
546 void CoreEngine::enqueue(ExplodedNodeSet &Set,
547                          const CFGBlock *Block, unsigned Idx) {
548   for (ExplodedNodeSet::iterator I = Set.begin(),
549                                  E = Set.end(); I != E; ++I) {
550     enqueueStmtNode(*I, Block, Idx);
551   }
552 }
553 
554 void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
555   for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
556     ExplodedNode *N = *I;
557     // If we are in an inlined call, generate CallExit node.
558     if (N->getLocationContext()->getParent()) {
559       N = generateCallExitNode(N);
560       if (N)
561         WList->enqueue(N);
562     } else {
563       G->addEndOfPath(N);
564       NumPathsExplored++;
565     }
566   }
567 }
568 
569 
570 void NodeBuilder::anchor() { }
571 
572 ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
573                                             ProgramStateRef State,
574                                             ExplodedNode *FromN,
575                                             bool MarkAsSink) {
576   HasGeneratedNodes = true;
577   bool IsNew;
578   ExplodedNode *N = C.Eng.G->getNode(Loc, State, MarkAsSink, &IsNew);
579   N->addPredecessor(FromN, *C.Eng.G);
580   Frontier.erase(FromN);
581 
582   if (!IsNew)
583     return 0;
584 
585   if (!MarkAsSink)
586     Frontier.Add(N);
587 
588   return N;
589 }
590 
591 void NodeBuilderWithSinks::anchor() { }
592 
593 StmtNodeBuilder::~StmtNodeBuilder() {
594   if (EnclosingBldr)
595     for (ExplodedNodeSet::iterator I = Frontier.begin(),
596                                    E = Frontier.end(); I != E; ++I )
597       EnclosingBldr->addNodes(*I);
598 }
599 
600 void BranchNodeBuilder::anchor() { }
601 
602 ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
603                                               bool branch,
604                                               ExplodedNode *NodePred) {
605   // If the branch has been marked infeasible we should not generate a node.
606   if (!isFeasible(branch))
607     return NULL;
608 
609   ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
610                                NodePred->getLocationContext());
611   ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
612   return Succ;
613 }
614 
615 ExplodedNode*
616 IndirectGotoNodeBuilder::generateNode(const iterator &I,
617                                       ProgramStateRef St,
618                                       bool IsSink) {
619   bool IsNew;
620   ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
621                                       Pred->getLocationContext()), St,
622                                       IsSink, &IsNew);
623   Succ->addPredecessor(Pred, *Eng.G);
624 
625   if (!IsNew)
626     return 0;
627 
628   if (!IsSink)
629     Eng.WList->enqueue(Succ);
630 
631   return Succ;
632 }
633 
634 
635 ExplodedNode*
636 SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
637                                         ProgramStateRef St) {
638 
639   bool IsNew;
640   ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
641                                       Pred->getLocationContext()), St,
642                                       false, &IsNew);
643   Succ->addPredecessor(Pred, *Eng.G);
644   if (!IsNew)
645     return 0;
646 
647   Eng.WList->enqueue(Succ);
648   return Succ;
649 }
650 
651 
652 ExplodedNode*
653 SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
654                                            bool IsSink) {
655   // Get the block for the default case.
656   assert(Src->succ_rbegin() != Src->succ_rend());
657   CFGBlock *DefaultBlock = *Src->succ_rbegin();
658 
659   // Sanity check for default blocks that are unreachable and not caught
660   // by earlier stages.
661   if (!DefaultBlock)
662     return NULL;
663 
664   bool IsNew;
665   ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
666                                       Pred->getLocationContext()), St,
667                                       IsSink, &IsNew);
668   Succ->addPredecessor(Pred, *Eng.G);
669 
670   if (!IsNew)
671     return 0;
672 
673   if (!IsSink)
674     Eng.WList->enqueue(Succ);
675 
676   return Succ;
677 }
678