ExprEngineCallAndReturn.cpp revision e90d3f847dcce76237078b67db8895eb7a24189e
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 3c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// The LLVM Compiler Infrastructure 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// This file is distributed under the University of Illinois Open Source 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// License. See LICENSE.TXT for details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt//===----------------------------------------------------------------------===// 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// This file defines ExprEngine's support for calls and returns. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt//===----------------------------------------------------------------------===// 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define DEBUG_TYPE "ExprEngine" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "clang/Analysis/Analyses/LiveVariables.h" 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "clang/StaticAnalyzer/Core/CheckerManager.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "clang/AST/DeclCXX.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "llvm/ADT/SmallSet.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "llvm/ADT/Statistic.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "llvm/Support/SaveAndRestore.h" 2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CXX_INLINING_ENABLED 1 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtusing namespace clang; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtusing namespace ento; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSTATISTIC(NumOfDynamicDispatchPathSplits, 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "The # of times we split the path due to imprecise dynamic dispatch info"); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Get the entry block in the CFG of the callee. 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *calleeCtx = CE.getCalleeContext(); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFG *CalleeCFG = calleeCtx->getCFG(); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFGBlock *Entry = &(CalleeCFG->getEntry()); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Validate the CFG. 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assert(Entry->empty()); 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt assert(Entry->succ_size() == 1); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Get the solitary sucessor. 4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const CFGBlock *Succ = *(Entry->succ_begin()); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Construct an edge representing the starting location in the callee. 4704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt BlockEdge Loc(Entry, Succ, calleeCtx); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef state = Pred->getState(); 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt // Construct a new node and add it to the worklist. 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isNew; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Node->addPredecessor(Pred, G); 55a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (isNew) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Engine.getWorkList()->enqueue(Node); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 59c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// Find the last statement on the path to the exploded node and the 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// corresponding Block. 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic std::pair<const Stmt*, 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFGBlock*> getLastStmt(const ExplodedNode *Node) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Stmt *S = 0; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *SF = 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Node->getLocation().getLocationContext()->getCurrentStackFrame(); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Back up through the ExplodedGraph until we reach a statement node. 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (Node) { 69c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const ProgramPoint &PP = Node->getLocation(); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 71c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) { 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt S = SP->getStmt(); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&PP)) { 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt S = CEE->getCalleeContext()->getCallSite(); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (S) 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If we have an implicit call, we'll probably end up with a 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // StmtPoint inside the callee, which is acceptable. 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // (It's possible a function ONLY contains implicit calls -- such as an 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // implicitly-generated destructor -- so we shouldn't just skip back to 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // the CallEnter node and keep going.) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (const CallEnter *CE = dyn_cast<CallEnter>(&PP)) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If we reached the CallEnter for this function, it has no statements. 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (CE->getCalleeContext() == SF) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Node = *Node->pred_begin(); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFGBlock *Blk = 0; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (S) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Now, get the enclosing basic block. 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (Node && Node->pred_size() >=1 ) { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const ProgramPoint &PP = Node->getLocation(); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (isa<BlockEdge>(PP) && 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (PP.getLocationContext()->getCurrentStackFrame() == SF)) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BlockEdge &EPP = cast<BlockEdge>(PP); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Blk = EPP.getDst(); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Node = *Node->pred_begin(); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return std::pair<const Stmt*, const CFGBlock*>(S, Blk); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// The call exit is simulated with a sequence of nodes, which occur between 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// CallExitBegin and CallExitEnd. The following operations occur between the 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// two program points: 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// 1. CallExitBegin (triggers the start of call exit sequence) 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// 2. Bind the return value 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// 3. Run Remove dead bindings to clean up the dead symbols from the callee. 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// 4. CallExitEnd (switch to the caller context) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// 5. PostStmt<CallExpr> 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::processCallExit(ExplodedNode *CEBNode) { 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Step 1 CEBNode was generated before the call. 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *calleeCtx = 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CEBNode->getLocationContext()->getCurrentStackFrame(); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // The parent context might not be a stack frame, so make sure we 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // look up the first enclosing stack frame. 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *callerCtx = 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt calleeCtx->getParent()->getCurrentStackFrame(); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Stmt *CE = calleeCtx->getCallSite(); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef state = CEBNode->getState(); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Find the last statement in the function and the corresponding basic block. 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Stmt *LastSt = 0; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFGBlock *Blk = 0; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt llvm::tie(LastSt, Blk) = getLastStmt(CEBNode); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Step 2: generate node with bound return value: CEBNode -> BindedRetNode. 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If the callee returns an expression, bind its value to CallExpr. 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (CE) { 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) { 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const LocationContext *LCtx = CEBNode->getLocationContext(); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SVal V = state->getSVal(RS, LCtx); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state = state->BindExpr(CE, callerCtx, V); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Bind the constructed object value to CXXConstructExpr. 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt loc::MemRegionVal This = 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SVal ThisV = state->getSVal(This); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Always bind the region to the CXXConstructExpr. 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state = state->BindExpr(CCE, callerCtx, ThisV); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Step 3: BindedRetNode -> CleanedNodes 15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // If we can find a statement and a block in the inlined function, run remove 15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // dead bindings before returning from the call. This is important to ensure 16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // that we report the issues such as leaks in the stack contexts in which 16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // they occurred. 16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ExplodedNodeSet CleanedNodes; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (LastSt && Blk) { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value"); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PostStmt Loc(LastSt, calleeCtx, &retValBind); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isNew; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BindedRetNode->addPredecessor(CEBNode, G); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!isNew) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt currentBuilderContext = &Ctx; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Here, we call the Symbol Reaper with 0 statement and caller location 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // context, telling it to clean up everything in the callee's context 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // (and it's children). We use LastStmt as a diagnostic statement, which 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // which the PreStmtPurge Dead point will be associated. 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramPoint::PostStmtPurgeDeadSymbolsKind); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt currentBuilderContext = 0; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CleanedNodes.Add(CEBNode); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ExplodedNodeSet::iterator I = CleanedNodes.begin(), 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt E = CleanedNodes.end(); I != E; ++I) { 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Step 4: Generate the CallExit and leave the callee's context. 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // CleanedNodes -> CEENode 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallExitEnd Loc(calleeCtx, callerCtx); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isNew; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState(); 193d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CEENode->addPredecessor(*I, G); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!isNew) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Step 5: Perform the post-condition check of the CallExpr and enqueue the 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // result onto the work list. 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // CEENode -> Dst -> WorkList 20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode); 20237d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext, 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &Ctx); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEventManager &CEMgr = getStateManager().getCallEventManager(); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEventRef<> Call = CEMgr.getCaller(calleeCtx, CEEState); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNodeSet DstPostCall; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode, *Call, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *this, true); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNodeSet Dst; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (isa<ObjCMethodCall>(Call)) { 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cast<ObjCMethodCall>(*Call), 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *this, true); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (CE) { 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *this, true); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Dst.insert(DstPostCall); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Enqueue the next element in the block. 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end(); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PSI != PSE; ++PSI) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(), 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt calleeCtx->getIndex()+1); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned getNumberStackFrames(const LocationContext *LCtx) { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned count = 0; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (LCtx) { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (isa<StackFrameContext>(LCtx)) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ++count; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LCtx = LCtx->getParent(); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return count; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Determine if we should inline the call. 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CFG *CalleeCFG = CalleeADC->getCFG(); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // It is possible that the CFG cannot be constructed. 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Be safe, and check if the CalleeCFG is valid. 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!CalleeCFG) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (getNumberStackFrames(Pred->getLocationContext()) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == AMgr.InlineMaxStackDepth) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D)) 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize) 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Do not inline variadic calls (for now). 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (BD->isVariadic()) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (FD->isVariadic()) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // It is possible that the live variables analysis cannot be 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // run. If so, bail out. 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!CalleeADC->getAnalysis<RelaxedLiveVariables>()) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// The GDM component containing the dynamic dispatch bifurcation info. When 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// the exact type of the receiver is not known, we want to explore both paths - 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// one on which we do inline it and the other one on which we don't. This is 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// done to ensure we do not drop coverage. 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// This is the map from the receiver region to a bool, specifying either we 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/// consider this region's information precise or not along the given path. 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnamespace clang { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnamespace ento { 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct DynamicDispatchBifurcationMap {}; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef llvm::ImmutableMap<const MemRegion*, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int> DynamicDispatchBifur; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttemplate<> struct ProgramStateTrait<DynamicDispatchBifurcationMap> 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt : public ProgramStatePartialTrait<DynamicDispatchBifur> { 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static void *GDMIndex() { static int index; return &index; } 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}} 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NodeBuilder &Bldr, ExplodedNode *Pred, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef State) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assert(D); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const LocationContext *CurLC = Pred->getLocationContext(); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame(); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const LocationContext *ParentOfCallee = 0; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // FIXME: Refactor this check into a hypothetical CallEvent::canInline. 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (Call.getKind()) { 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_Function: 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_CXXMember: 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_CXXMemberOperator: 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!CXX_INLINING_ENABLED) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_CXXConstructor: { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!CXX_INLINING_ENABLED) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Only inline constructors and destructors if we built the CFGs for them 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // properly. 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ADC->getCFGBuildOptions().AddImplicitDtors || 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !ADC->getCFGBuildOptions().AddInitializers) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // FIXME: We don't handle constructors or destructors for arrays properly. 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const MemRegion *Target = Ctor.getCXXThisVal().getAsRegion(); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (Target && isa<ElementRegion>(Target)) 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // FIXME: This is a hack. We don't handle temporary destructors 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // right now, so we shouldn't inline their constructors. 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr(); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!Target || !isa<DeclRegion>(Target)) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_CXXDestructor: { 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!CXX_INLINING_ENABLED) 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Only inline constructors and destructors if we built the CFGs for them 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // properly. 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ADC->getCFGBuildOptions().AddImplicitDtors || 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !ADC->getCFGBuildOptions().AddInitializers) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // FIXME: We don't handle constructors or destructors for arrays properly. 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion(); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (Target && isa<ElementRegion>(Target)) 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case CE_CXXAllocator: 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!CXX_INLINING_ENABLED) 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return false; 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // Do not inline allocators until we model deallocators. 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // This is unfortunate, but basically necessary for smart pointers and such. 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return false; 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case CE_Block: { 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion(); 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt assert(BR && "If we have the block definition we should have its region"); 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D); 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC, 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cast<BlockDecl>(D), 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BR); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CE_ObjCMessage: 38104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!(getAnalysisManager().IPAMode == DynamicDispatch || 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getAnalysisManager().IPAMode == DynamicDispatchBifurcate)) 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!shouldInlineDecl(D, Pred)) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ParentOfCallee) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ParentOfCallee = CallerSFC; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This may be NULL, but that's fine. 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Expr *CallE = Call.getOriginExpr(); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Construct a new stack frame for the callee. 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const StackFrameContext *CalleeSFC = 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CalleeADC->getStackFrame(ParentOfCallee, CallE, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt currentBuilderContext->getBlock(), 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt currentStmtIdx); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEnter Loc(CallE, CalleeSFC, CurLC); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Construct a new state which contains the mapping from actual to 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // formal arguments. 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State = State->enterStackFrame(Call, CalleeSFC); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isNew; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt N->addPredecessor(Pred, G); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (isNew) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Engine.getWorkList()->enqueue(N); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If we decided to inline the call, the successor has been manually 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // added onto the work list so remove it from the node builder. 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Bldr.takeNodes(Pred); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic ProgramStateRef getInlineFailedState(ProgramStateRef State, 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const Stmt *CallE) { 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt void *ReplayState = State->get<ReplayWithoutInlining>(); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ReplayState) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assert(ReplayState == (const void*)CallE && "Backtracked to the wrong call."); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void)CallE; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return State->remove<ReplayWithoutInlining>(); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNodeSet &dst) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Perform the previsit of the CallExpr. 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNodeSet dstPreVisit; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Get the call in its initial state. We use this as a template to perform 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // all the checks. 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEventManager &CEMgr = getStateManager().getCallEventManager(); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEventRef<SimpleCall> CallTemplate 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt = CEMgr.getSimpleCall(CE, Pred->getState(), Pred->getLocationContext()); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // Evaluate the function call. We try each of the checkers 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // to see if the can evaluate the function call. 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ExplodedNodeSet dstCallEvaluated; 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt I != E; ++I) { 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt evalCall(dstCallEvaluated, *I, *CallTemplate); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // Finally, perform the post-condition check of the CallExpr and store 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // the created nodes in 'Dst'. 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // Note that if the call was inlined, dstCallEvaluated will be empty. 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // The post-CallExpr check will occur in processCallExit. 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 46004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *this); 46104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 46204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 46304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, 464d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt const SimpleCall &Call) { 465d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt // WARNING: At this time, the state attached to 'Call' may be older than the 466d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt // state in 'Pred'. This is a minor optimization since CheckerManager will 467d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt // use an updated CallEvent instance when calling checkers, but if 'Call' is 468d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt // ever used directly in this function all callers should be updated to pass 46904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt // the most recent state. (It is probably not worth doing the work here since 47061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // for some callers this will not be necessary.) 47161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 47261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // Run any pre-call checks using the generic call interface. 47361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ExplodedNodeSet dstPreVisit; 47461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, Call, *this); 4759bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt 4769bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt // Actually evaluate the function call. We try each of the checkers 4779bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt // to see if the can evaluate the function call, and get a callback at 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // defaultEvalCall if all of them fail. 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNodeSet dstCallEvaluated; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit, 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Call, *this); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Finally, run any post-call checks. 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getCheckerManager().runCheckersForPostCall(Dst, dstCallEvaluated, 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Call, *this); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const LocationContext *LCtx, 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef State) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Expr *E = Call.getOriginExpr(); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!E) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return State; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Some method families have known return values. 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (Msg->getMethodFamily()) { 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case OMF_autorelease: 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case OMF_retain: 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case OMF_self: { 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // These methods return their receivers. 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return State->BindExpr(E, LCtx, Msg->getReceiverSVal()); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return State->BindExpr(E, LCtx, C->getCXXThisVal()); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Conjure a symbol if the return value is unknown. 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt QualType ResultTy = Call.getResultType(); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SValBuilder &SVB = getSValBuilder(); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned Count = currentBuilderContext->getCurrentBlockCount(); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SVal R = SVB.getConjuredSymbolVal(0, E, LCtx, ResultTy, Count); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return State->BindExpr(E, LCtx, R); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Conservatively evaluate call by invalidating regions and binding 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// a conjured return value. 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ExplodedNode *Pred, ProgramStateRef State) { 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned Count = currentBuilderContext->getCurrentBlockCount(); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State = Call.invalidateRegions(Count, State); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State = bindReturnValue(Call, Pred->getLocationContext(), State); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // And make the result node. 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Bldr.generateNode(Call.getProgramPoint(), State, Pred); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CallEvent &CallTemplate) { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Make sure we have the most recent state attached to the call. 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef State = Pred->getState(); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CallEventRef<> Call = CallTemplate.cloneWithState(State); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Try to inline the call. 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // The origin expression here is just used as a kind of checksum; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // this should still be safe even for CallEvents that don't come from exprs. 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Expr *E = Call->getOriginExpr(); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef InlinedFailedState = getInlineFailedState(State, E); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (InlinedFailedState) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If we already tried once and failed, make sure we don't retry later. 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State = InlinedFailedState; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (getAnalysisManager().shouldInlineCall()) { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RuntimeDefinition RD = Call->getRuntimeDefinition(); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const Decl *D = RD.Decl; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (D) { 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Explore with and without inlining the call. 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const MemRegion *BifurReg = RD.Reg; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (BifurReg && 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt getAnalysisManager().IPAMode == DynamicDispatchBifurcate) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BifurcateCall(BifurReg, *Call, D, Bldr, Pred); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // We are not bifurcating and we do have a Decl, so just inline. 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inlineCall(*Call, D, Bldr, Pred, State)) 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt // If we can't inline it, handle the return value and invalidate the regions. 5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conservativeEvalCall(*Call, Bldr, Pred, State); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ExprEngine::BifurcateCall(const MemRegion *BifurReg, 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const CallEvent &Call, const Decl *D, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NodeBuilder &Bldr, ExplodedNode *Pred) { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assert(BifurReg); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Check if we've performed the split already - note, we only want 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // to split the path once per memory region. 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef State = Pred->getState(); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DynamicDispatchBifur BM = State->get<DynamicDispatchBifurcationMap>(); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (DynamicDispatchBifur::iterator I = BM.begin(), 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt E = BM.end(); I != E; ++I) { 57961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (I->first == BifurReg) { 58061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // If we are on "inline path", keep inlining if possible. 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (I->second == true) 58261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (inlineCall(Call, D, Bldr, Pred, State)) 58361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 58461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // If inline failed, or we are on the path where we assume we 58561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // don't have enough info about the receiver to inline, conjure the 58661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // return value and invalidate the regions. 58761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt conservativeEvalCall(Call, Bldr, Pred, State); 58861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If we got here, this is the first time we process a message to this 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // region, so split the path. 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef IState = 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State->set<DynamicDispatchBifurcationMap>(BifurReg, true); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inlineCall(Call, D, Bldr, Pred, IState); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ProgramStateRef NoIState = 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt State->set<DynamicDispatchBifurcationMap>(BifurReg, false); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conservativeEvalCall(Call, Bldr, Pred, NoIState); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NumOfDynamicDispatchPathSplits++; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 60504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 60704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 60804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ExplodedNodeSet &Dst) { 60904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 61004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ExplodedNodeSet dstPreVisit; 61104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); 61204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 61304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext); 61404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 61504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (RS->getRetValue()) { 61604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), 61704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ei = dstPreVisit.end(); it != ei; ++it) { 61804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt B.generateNode(RS, *it, (*it)->getState()); 61904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 62004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 62104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 62204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt