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