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 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 18 #include "clang/Index/TranslationUnit.h" 19 #include "clang/AST/Expr.h" 20 #include "llvm/Support/Casting.h" 21 #include "llvm/ADT/DenseMap.h" 22 23 using llvm::cast; 24 using llvm::isa; 25 using namespace clang; 26 using namespace ento; 27 28 // This should be removed in the future. 29 namespace clang { 30 namespace ento { 31 TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, 32 const LangOptions& lopts); 33 } 34 } 35 36 //===----------------------------------------------------------------------===// 37 // Worklist classes for exploration of reachable states. 38 //===----------------------------------------------------------------------===// 39 40 WorkList::Visitor::~Visitor() {} 41 42 namespace { 43 class DFS : public WorkList { 44 llvm::SmallVector<WorkListUnit,20> Stack; 45 public: 46 virtual bool hasWork() const { 47 return !Stack.empty(); 48 } 49 50 virtual void enqueue(const WorkListUnit& U) { 51 Stack.push_back(U); 52 } 53 54 virtual WorkListUnit dequeue() { 55 assert (!Stack.empty()); 56 const WorkListUnit& U = Stack.back(); 57 Stack.pop_back(); // This technically "invalidates" U, but we are fine. 58 return U; 59 } 60 61 virtual bool visitItemsInWorkList(Visitor &V) { 62 for (llvm::SmallVectorImpl<WorkListUnit>::iterator 63 I = Stack.begin(), E = Stack.end(); I != E; ++I) { 64 if (V.visit(*I)) 65 return true; 66 } 67 return false; 68 } 69 }; 70 71 class BFS : public WorkList { 72 std::deque<WorkListUnit> Queue; 73 public: 74 virtual bool hasWork() const { 75 return !Queue.empty(); 76 } 77 78 virtual void enqueue(const WorkListUnit& U) { 79 Queue.push_front(U); 80 } 81 82 virtual WorkListUnit dequeue() { 83 WorkListUnit U = Queue.front(); 84 Queue.pop_front(); 85 return U; 86 } 87 88 virtual bool visitItemsInWorkList(Visitor &V) { 89 for (std::deque<WorkListUnit>::iterator 90 I = Queue.begin(), E = Queue.end(); I != E; ++I) { 91 if (V.visit(*I)) 92 return true; 93 } 94 return false; 95 } 96 }; 97 98 } // end anonymous namespace 99 100 // Place the dstor for WorkList here because it contains virtual member 101 // functions, and we the code for the dstor generated in one compilation unit. 102 WorkList::~WorkList() {} 103 104 WorkList *WorkList::makeDFS() { return new DFS(); } 105 WorkList *WorkList::makeBFS() { return new BFS(); } 106 107 namespace { 108 class BFSBlockDFSContents : public WorkList { 109 std::deque<WorkListUnit> Queue; 110 llvm::SmallVector<WorkListUnit,20> Stack; 111 public: 112 virtual bool hasWork() const { 113 return !Queue.empty() || !Stack.empty(); 114 } 115 116 virtual void enqueue(const WorkListUnit& U) { 117 if (isa<BlockEntrance>(U.getNode()->getLocation())) 118 Queue.push_front(U); 119 else 120 Stack.push_back(U); 121 } 122 123 virtual WorkListUnit dequeue() { 124 // Process all basic blocks to completion. 125 if (!Stack.empty()) { 126 const WorkListUnit& U = Stack.back(); 127 Stack.pop_back(); // This technically "invalidates" U, but we are fine. 128 return U; 129 } 130 131 assert(!Queue.empty()); 132 // Don't use const reference. The subsequent pop_back() might make it 133 // unsafe. 134 WorkListUnit U = Queue.front(); 135 Queue.pop_front(); 136 return U; 137 } 138 virtual bool visitItemsInWorkList(Visitor &V) { 139 for (llvm::SmallVectorImpl<WorkListUnit>::iterator 140 I = Stack.begin(), E = Stack.end(); I != E; ++I) { 141 if (V.visit(*I)) 142 return true; 143 } 144 for (std::deque<WorkListUnit>::iterator 145 I = Queue.begin(), E = Queue.end(); I != E; ++I) { 146 if (V.visit(*I)) 147 return true; 148 } 149 return false; 150 } 151 152 }; 153 } // end anonymous namespace 154 155 WorkList* WorkList::makeBFSBlockDFSContents() { 156 return new BFSBlockDFSContents(); 157 } 158 159 //===----------------------------------------------------------------------===// 160 // Core analysis engine. 161 //===----------------------------------------------------------------------===// 162 163 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps. 164 bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps, 165 const GRState *InitState) { 166 167 if (G->num_roots() == 0) { // Initialize the analysis by constructing 168 // the root if none exists. 169 170 const CFGBlock* Entry = &(L->getCFG()->getEntry()); 171 172 assert (Entry->empty() && 173 "Entry block must be empty."); 174 175 assert (Entry->succ_size() == 1 && 176 "Entry block must have 1 successor."); 177 178 // Get the solitary successor. 179 const CFGBlock* Succ = *(Entry->succ_begin()); 180 181 // Construct an edge representing the 182 // starting location in the function. 183 BlockEdge StartLoc(Entry, Succ, L); 184 185 // Set the current block counter to being empty. 186 WList->setBlockCounter(BCounterFactory.GetEmptyCounter()); 187 188 if (!InitState) 189 // Generate the root. 190 generateNode(StartLoc, SubEng.getInitialState(L), 0); 191 else 192 generateNode(StartLoc, InitState, 0); 193 } 194 195 // Check if we have a steps limit 196 bool UnlimitedSteps = Steps == 0; 197 198 while (WList->hasWork()) { 199 if (!UnlimitedSteps) { 200 if (Steps == 0) 201 break; 202 --Steps; 203 } 204 205 const WorkListUnit& WU = WList->dequeue(); 206 207 // Set the current block counter. 208 WList->setBlockCounter(WU.getBlockCounter()); 209 210 // Retrieve the node. 211 ExplodedNode* Node = WU.getNode(); 212 213 // Dispatch on the location type. 214 switch (Node->getLocation().getKind()) { 215 case ProgramPoint::BlockEdgeKind: 216 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node); 217 break; 218 219 case ProgramPoint::BlockEntranceKind: 220 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node); 221 break; 222 223 case ProgramPoint::BlockExitKind: 224 assert (false && "BlockExit location never occur in forward analysis."); 225 break; 226 227 case ProgramPoint::CallEnterKind: 228 HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(), 229 WU.getIndex(), Node); 230 break; 231 232 case ProgramPoint::CallExitKind: 233 HandleCallExit(cast<CallExit>(Node->getLocation()), Node); 234 break; 235 236 default: 237 assert(isa<PostStmt>(Node->getLocation()) || 238 isa<PostInitializer>(Node->getLocation())); 239 HandlePostStmt(WU.getBlock(), WU.getIndex(), Node); 240 break; 241 } 242 } 243 244 SubEng.processEndWorklist(hasWorkRemaining()); 245 return WList->hasWork(); 246 } 247 248 void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, 249 unsigned Steps, 250 const GRState *InitState, 251 ExplodedNodeSet &Dst) { 252 ExecuteWorkList(L, Steps, InitState); 253 for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(), 254 E = G->EndNodes.end(); I != E; ++I) { 255 Dst.Add(*I); 256 } 257 } 258 259 void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block, 260 unsigned Index, ExplodedNode *Pred) { 261 CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), 262 L.getCalleeContext(), Block, Index); 263 SubEng.processCallEnter(Builder); 264 } 265 266 void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) { 267 CallExitNodeBuilder Builder(*this, Pred); 268 SubEng.processCallExit(Builder); 269 } 270 271 void CoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) { 272 273 const CFGBlock* Blk = L.getDst(); 274 275 // Check if we are entering the EXIT block. 276 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) { 277 278 assert (L.getLocationContext()->getCFG()->getExit().size() == 0 279 && "EXIT block cannot contain Stmts."); 280 281 // Process the final state transition. 282 EndOfFunctionNodeBuilder Builder(Blk, Pred, this); 283 SubEng.processEndOfFunction(Builder); 284 285 // This path is done. Don't enqueue any more nodes. 286 return; 287 } 288 289 // Call into the subengine to process entering the CFGBlock. 290 ExplodedNodeSet dstNodes; 291 BlockEntrance BE(Blk, Pred->getLocationContext()); 292 GenericNodeBuilder<BlockEntrance> nodeBuilder(*this, Pred, BE); 293 SubEng.processCFGBlockEntrance(dstNodes, nodeBuilder); 294 295 if (dstNodes.empty()) { 296 if (!nodeBuilder.hasGeneratedNode) { 297 // Auto-generate a node and enqueue it to the worklist. 298 generateNode(BE, Pred->State, Pred); 299 } 300 } 301 else { 302 for (ExplodedNodeSet::iterator I = dstNodes.begin(), E = dstNodes.end(); 303 I != E; ++I) { 304 WList->enqueue(*I); 305 } 306 } 307 308 for (llvm::SmallVectorImpl<ExplodedNode*>::const_iterator 309 I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end(); 310 I != E; ++I) { 311 blocksExhausted.push_back(std::make_pair(L, *I)); 312 } 313 } 314 315 void CoreEngine::HandleBlockEntrance(const BlockEntrance& L, 316 ExplodedNode* Pred) { 317 318 // Increment the block counter. 319 BlockCounter Counter = WList->getBlockCounter(); 320 Counter = BCounterFactory.IncrementCount(Counter, 321 Pred->getLocationContext()->getCurrentStackFrame(), 322 L.getBlock()->getBlockID()); 323 WList->setBlockCounter(Counter); 324 325 // Process the entrance of the block. 326 if (CFGElement E = L.getFirstElement()) { 327 StmtNodeBuilder Builder(L.getBlock(), 0, Pred, this, 328 SubEng.getStateManager()); 329 SubEng.processCFGElement(E, Builder); 330 } 331 else 332 HandleBlockExit(L.getBlock(), Pred); 333 } 334 335 void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) { 336 337 if (const Stmt* Term = B->getTerminator()) { 338 switch (Term->getStmtClass()) { 339 default: 340 assert(false && "Analysis for this terminator not implemented."); 341 break; 342 343 case Stmt::BinaryOperatorClass: // '&&' and '||' 344 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred); 345 return; 346 347 case Stmt::BinaryConditionalOperatorClass: 348 case Stmt::ConditionalOperatorClass: 349 HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(), 350 Term, B, Pred); 351 return; 352 353 // FIXME: Use constant-folding in CFG construction to simplify this 354 // case. 355 356 case Stmt::ChooseExprClass: 357 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred); 358 return; 359 360 case Stmt::DoStmtClass: 361 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred); 362 return; 363 364 case Stmt::ForStmtClass: 365 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred); 366 return; 367 368 case Stmt::ContinueStmtClass: 369 case Stmt::BreakStmtClass: 370 case Stmt::GotoStmtClass: 371 break; 372 373 case Stmt::IfStmtClass: 374 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred); 375 return; 376 377 case Stmt::IndirectGotoStmtClass: { 378 // Only 1 successor: the indirect goto dispatch block. 379 assert (B->succ_size() == 1); 380 381 IndirectGotoNodeBuilder 382 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(), 383 *(B->succ_begin()), this); 384 385 SubEng.processIndirectGoto(builder); 386 return; 387 } 388 389 case Stmt::ObjCForCollectionStmtClass: { 390 // In the case of ObjCForCollectionStmt, it appears twice in a CFG: 391 // 392 // (1) inside a basic block, which represents the binding of the 393 // 'element' variable to a value. 394 // (2) in a terminator, which represents the branch. 395 // 396 // For (1), subengines will bind a value (i.e., 0 or 1) indicating 397 // whether or not collection contains any more elements. We cannot 398 // just test to see if the element is nil because a container can 399 // contain nil elements. 400 HandleBranch(Term, Term, B, Pred); 401 return; 402 } 403 404 case Stmt::SwitchStmtClass: { 405 SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(), 406 this); 407 408 SubEng.processSwitch(builder); 409 return; 410 } 411 412 case Stmt::WhileStmtClass: 413 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred); 414 return; 415 } 416 } 417 418 assert (B->succ_size() == 1 && 419 "Blocks with no terminator should have at most 1 successor."); 420 421 generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()), 422 Pred->State, Pred); 423 } 424 425 void CoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term, 426 const CFGBlock * B, ExplodedNode* Pred) { 427 assert(B->succ_size() == 2); 428 BranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1), 429 Pred, this); 430 SubEng.processBranch(Cond, Term, Builder); 431 } 432 433 void CoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, 434 ExplodedNode* Pred) { 435 assert (!B->empty()); 436 437 if (StmtIdx == B->size()) 438 HandleBlockExit(B, Pred); 439 else { 440 StmtNodeBuilder Builder(B, StmtIdx, Pred, this, 441 SubEng.getStateManager()); 442 SubEng.processCFGElement((*B)[StmtIdx], Builder); 443 } 444 } 445 446 /// generateNode - Utility method to generate nodes, hook up successors, 447 /// and add nodes to the worklist. 448 void CoreEngine::generateNode(const ProgramPoint& Loc, 449 const GRState* State, ExplodedNode* Pred) { 450 451 bool IsNew; 452 ExplodedNode* Node = G->getNode(Loc, State, &IsNew); 453 454 if (Pred) 455 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor. 456 else { 457 assert (IsNew); 458 G->addRoot(Node); // 'Node' has no predecessor. Make it a root. 459 } 460 461 // Only add 'Node' to the worklist if it was freshly generated. 462 if (IsNew) WList->enqueue(Node); 463 } 464 465 ExplodedNode * 466 GenericNodeBuilderImpl::generateNodeImpl(const GRState *state, 467 ExplodedNode *pred, 468 ProgramPoint programPoint, 469 bool asSink) { 470 471 hasGeneratedNode = true; 472 bool isNew; 473 ExplodedNode *node = engine.getGraph().getNode(programPoint, state, &isNew); 474 if (pred) 475 node->addPredecessor(pred, engine.getGraph()); 476 if (isNew) { 477 if (asSink) { 478 node->markAsSink(); 479 sinksGenerated.push_back(node); 480 } 481 return node; 482 } 483 return 0; 484 } 485 486 StmtNodeBuilder::StmtNodeBuilder(const CFGBlock* b, unsigned idx, 487 ExplodedNode* N, CoreEngine* e, 488 GRStateManager &mgr) 489 : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr), 490 PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false), 491 PointKind(ProgramPoint::PostStmtKind), Tag(0) { 492 Deferred.insert(N); 493 CleanedState = Pred->getState(); 494 } 495 496 StmtNodeBuilder::~StmtNodeBuilder() { 497 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I) 498 if (!(*I)->isSink()) 499 GenerateAutoTransition(*I); 500 } 501 502 void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) { 503 assert (!N->isSink()); 504 505 // Check if this node entered a callee. 506 if (isa<CallEnter>(N->getLocation())) { 507 // Still use the index of the CallExpr. It's needed to create the callee 508 // StackFrameContext. 509 Eng.WList->enqueue(N, &B, Idx); 510 return; 511 } 512 513 // Do not create extra nodes. Move to the next CFG element. 514 if (isa<PostInitializer>(N->getLocation())) { 515 Eng.WList->enqueue(N, &B, Idx+1); 516 return; 517 } 518 519 PostStmt Loc(getStmt(), N->getLocationContext()); 520 521 if (Loc == N->getLocation()) { 522 // Note: 'N' should be a fresh node because otherwise it shouldn't be 523 // a member of Deferred. 524 Eng.WList->enqueue(N, &B, Idx+1); 525 return; 526 } 527 528 bool IsNew; 529 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew); 530 Succ->addPredecessor(N, *Eng.G); 531 532 if (IsNew) 533 Eng.WList->enqueue(Succ, &B, Idx+1); 534 } 535 536 ExplodedNode* StmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S, 537 ExplodedNode* Pred, const GRState* St, 538 ProgramPoint::Kind K) { 539 540 ExplodedNode* N = generateNode(S, St, Pred, K); 541 542 if (N) { 543 if (BuildSinks) 544 N->markAsSink(); 545 else 546 Dst.Add(N); 547 } 548 549 return N; 550 } 551 552 static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K, 553 const LocationContext *LC, const void *tag){ 554 switch (K) { 555 default: 556 assert(false && "Unhandled ProgramPoint kind"); 557 case ProgramPoint::PreStmtKind: 558 return PreStmt(S, LC, tag); 559 case ProgramPoint::PostStmtKind: 560 return PostStmt(S, LC, tag); 561 case ProgramPoint::PreLoadKind: 562 return PreLoad(S, LC, tag); 563 case ProgramPoint::PostLoadKind: 564 return PostLoad(S, LC, tag); 565 case ProgramPoint::PreStoreKind: 566 return PreStore(S, LC, tag); 567 case ProgramPoint::PostStoreKind: 568 return PostStore(S, LC, tag); 569 case ProgramPoint::PostLValueKind: 570 return PostLValue(S, LC, tag); 571 case ProgramPoint::PostPurgeDeadSymbolsKind: 572 return PostPurgeDeadSymbols(S, LC, tag); 573 } 574 } 575 576 ExplodedNode* 577 StmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state, 578 ExplodedNode* Pred, 579 ProgramPoint::Kind K, 580 const void *tag) { 581 582 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag); 583 return generateNodeInternal(L, state, Pred); 584 } 585 586 ExplodedNode* 587 StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc, 588 const GRState* State, 589 ExplodedNode* Pred) { 590 bool IsNew; 591 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew); 592 N->addPredecessor(Pred, *Eng.G); 593 Deferred.erase(Pred); 594 595 if (IsNew) { 596 Deferred.insert(N); 597 return N; 598 } 599 600 return NULL; 601 } 602 603 // This function generate a new ExplodedNode but not a new branch(block edge). 604 ExplodedNode* BranchNodeBuilder::generateNode(const Stmt* Condition, 605 const GRState* State) { 606 bool IsNew; 607 608 ExplodedNode* Succ 609 = Eng.G->getNode(PostCondition(Condition, Pred->getLocationContext()), State, 610 &IsNew); 611 612 Succ->addPredecessor(Pred, *Eng.G); 613 614 Pred = Succ; 615 616 if (IsNew) 617 return Succ; 618 619 return NULL; 620 } 621 622 ExplodedNode* BranchNodeBuilder::generateNode(const GRState* State, 623 bool branch) { 624 625 // If the branch has been marked infeasible we should not generate a node. 626 if (!isFeasible(branch)) 627 return NULL; 628 629 bool IsNew; 630 631 ExplodedNode* Succ = 632 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()), 633 State, &IsNew); 634 635 Succ->addPredecessor(Pred, *Eng.G); 636 637 if (branch) 638 GeneratedTrue = true; 639 else 640 GeneratedFalse = true; 641 642 if (IsNew) { 643 Deferred.push_back(Succ); 644 return Succ; 645 } 646 647 return NULL; 648 } 649 650 BranchNodeBuilder::~BranchNodeBuilder() { 651 if (!GeneratedTrue) generateNode(Pred->State, true); 652 if (!GeneratedFalse) generateNode(Pred->State, false); 653 654 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I) 655 if (!(*I)->isSink()) Eng.WList->enqueue(*I); 656 } 657 658 659 ExplodedNode* 660 IndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St, 661 bool isSink) { 662 bool IsNew; 663 664 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), 665 Pred->getLocationContext()), St, &IsNew); 666 667 Succ->addPredecessor(Pred, *Eng.G); 668 669 if (IsNew) { 670 671 if (isSink) 672 Succ->markAsSink(); 673 else 674 Eng.WList->enqueue(Succ); 675 676 return Succ; 677 } 678 679 return NULL; 680 } 681 682 683 ExplodedNode* 684 SwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){ 685 686 bool IsNew; 687 688 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), 689 Pred->getLocationContext()), St, &IsNew); 690 Succ->addPredecessor(Pred, *Eng.G); 691 692 if (IsNew) { 693 Eng.WList->enqueue(Succ); 694 return Succ; 695 } 696 697 return NULL; 698 } 699 700 701 ExplodedNode* 702 SwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) { 703 704 // Get the block for the default case. 705 assert (Src->succ_rbegin() != Src->succ_rend()); 706 CFGBlock* DefaultBlock = *Src->succ_rbegin(); 707 708 bool IsNew; 709 710 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock, 711 Pred->getLocationContext()), St, &IsNew); 712 Succ->addPredecessor(Pred, *Eng.G); 713 714 if (IsNew) { 715 if (isSink) 716 Succ->markAsSink(); 717 else 718 Eng.WList->enqueue(Succ); 719 720 return Succ; 721 } 722 723 return NULL; 724 } 725 726 EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() { 727 // Auto-generate an EOP node if one has not been generated. 728 if (!hasGeneratedNode) { 729 // If we are in an inlined call, generate CallExit node. 730 if (Pred->getLocationContext()->getParent()) 731 GenerateCallExitNode(Pred->State); 732 else 733 generateNode(Pred->State); 734 } 735 } 736 737 ExplodedNode* 738 EndOfFunctionNodeBuilder::generateNode(const GRState* State, 739 ExplodedNode* P, const void *tag) { 740 hasGeneratedNode = true; 741 bool IsNew; 742 743 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B, 744 Pred->getLocationContext(), tag ? tag : Tag), 745 State, &IsNew); 746 747 Node->addPredecessor(P ? P : Pred, *Eng.G); 748 749 if (IsNew) { 750 Eng.G->addEndOfPath(Node); 751 return Node; 752 } 753 754 return NULL; 755 } 756 757 void EndOfFunctionNodeBuilder::GenerateCallExitNode(const GRState *state) { 758 hasGeneratedNode = true; 759 // Create a CallExit node and enqueue it. 760 const StackFrameContext *LocCtx 761 = cast<StackFrameContext>(Pred->getLocationContext()); 762 const Stmt *CE = LocCtx->getCallSite(); 763 764 // Use the the callee location context. 765 CallExit Loc(CE, LocCtx); 766 767 bool isNew; 768 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); 769 Node->addPredecessor(Pred, *Eng.G); 770 771 if (isNew) 772 Eng.WList->enqueue(Node); 773 } 774 775 776 void CallEnterNodeBuilder::generateNode(const GRState *state) { 777 // Check if the callee is in the same translation unit. 778 if (CalleeCtx->getTranslationUnit() != 779 Pred->getLocationContext()->getTranslationUnit()) { 780 // Create a new engine. We must be careful that the new engine should not 781 // reference data structures owned by the old engine. 782 783 AnalysisManager &OldMgr = Eng.SubEng.getAnalysisManager(); 784 785 // Get the callee's translation unit. 786 idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit(); 787 788 // Create a new AnalysisManager with components of the callee's 789 // TranslationUnit. 790 // The Diagnostic is actually shared when we create ASTUnits from AST files. 791 AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), 792 OldMgr.getLangOptions(), 793 OldMgr.getPathDiagnosticClient(), 794 OldMgr.getStoreManagerCreator(), 795 OldMgr.getConstraintManagerCreator(), 796 OldMgr.getCheckerManager(), 797 OldMgr.getIndexer(), 798 OldMgr.getMaxNodes(), OldMgr.getMaxVisit(), 799 OldMgr.shouldVisualizeGraphviz(), 800 OldMgr.shouldVisualizeUbigraph(), 801 OldMgr.shouldPurgeDead(), 802 OldMgr.shouldEagerlyAssume(), 803 OldMgr.shouldTrimGraph(), 804 OldMgr.shouldInlineCall(), 805 OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(), 806 OldMgr.getAnalysisContextManager().getAddImplicitDtors(), 807 OldMgr.getAnalysisContextManager().getAddInitializers(), 808 OldMgr.shouldEagerlyTrimExplodedGraph()); 809 llvm::OwningPtr<TransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(), 810 /* GCEnabled */ false, 811 AMgr.getLangOptions())); 812 // Create the new engine. 813 ExprEngine NewEng(AMgr, TF.take()); 814 815 // Create the new LocationContext. 816 AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(), 817 CalleeCtx->getTranslationUnit()); 818 const StackFrameContext *OldLocCtx = CalleeCtx; 819 const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, 820 OldLocCtx->getParent(), 821 OldLocCtx->getCallSite(), 822 OldLocCtx->getCallSiteBlock(), 823 OldLocCtx->getIndex()); 824 825 // Now create an initial state for the new engine. 826 const GRState *NewState = NewEng.getStateManager().MarshalState(state, 827 NewLocCtx); 828 ExplodedNodeSet ReturnNodes; 829 NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(), 830 NewState, ReturnNodes); 831 return; 832 } 833 834 // Get the callee entry block. 835 const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry()); 836 assert(Entry->empty()); 837 assert(Entry->succ_size() == 1); 838 839 // Get the solitary successor. 840 const CFGBlock *SuccB = *(Entry->succ_begin()); 841 842 // Construct an edge representing the starting location in the callee. 843 BlockEdge Loc(Entry, SuccB, CalleeCtx); 844 845 bool isNew; 846 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); 847 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G); 848 849 if (isNew) 850 Eng.WList->enqueue(Node); 851 } 852 853 void CallExitNodeBuilder::generateNode(const GRState *state) { 854 // Get the callee's location context. 855 const StackFrameContext *LocCtx 856 = cast<StackFrameContext>(Pred->getLocationContext()); 857 // When exiting an implicit automatic obj dtor call, the callsite is the Stmt 858 // that triggers the dtor. 859 PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent()); 860 bool isNew; 861 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); 862 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G); 863 if (isNew) 864 Eng.WList->enqueue(Node, LocCtx->getCallSiteBlock(), 865 LocCtx->getIndex() + 1); 866 } 867