ExprEngineCallAndReturn.cpp revision 580cd17f256259f39a382e967173f34d68e73859
1659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The LLVM Compiler Infrastructure 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file is distributed under the University of Illinois Open Source 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// License. See LICENSE.TXT for details. 743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file defines ExprEngine's support for calls and returns. 1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define DEBUG_TYPE "ExprEngine" 1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/Analysis/Analyses/LiveVariables.h" 1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/CheckerManager.h" 1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/AST/DeclCXX.h" 2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/AST/ParentMap.h" 2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/ADT/SmallSet.h" 2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/ADT/Statistic.h" 2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/Support/SaveAndRestore.h" 2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenusing namespace clang; 2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenusing namespace ento; 2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenSTATISTIC(NumOfDynamicDispatchPathSplits, 3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen "The # of times we split the path due to imprecise dynamic dispatch info"); 311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comSTATISTIC(NumInlinedCalls, 33ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org "The # of times we inlined a call"); 349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 3571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgvoid ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { 3671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org // Get the entry block in the CFG of the callee. 3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const StackFrameContext *calleeCtx = CE.getCalleeContext(); 38659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org const CFG *CalleeCFG = calleeCtx->getCFG(); 39659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org const CFGBlock *Entry = &(CalleeCFG->getEntry()); 40a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 41659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org // Validate the CFG. 42659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org assert(Entry->empty()); 43ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com assert(Entry->succ_size() == 1); 44a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Get the solitary sucessor. 4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const CFGBlock *Succ = *(Entry->succ_begin()); 4768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org 4868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org // Construct an edge representing the starting location in the callee. 49c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org BlockEdge Loc(Entry, Succ, calleeCtx); 5068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org 51c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org ProgramStateRef state = Pred->getState(); 52c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org 53bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // Construct a new node and add it to the worklist. 54bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org bool isNew; 5568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); 5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Node->addPredecessor(Pred, G); 5743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (isNew) 582ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org Engine.getWorkList()->enqueue(Node); 592ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org} 602ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org 612ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org// Find the last statement on the path to the exploded node and the 6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// corresponding Block. 6343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic std::pair<const Stmt*, 6443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const CFGBlock*> getLastStmt(const ExplodedNode *Node) { 6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const Stmt *S = 0; 6643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const StackFrameContext *SF = 6743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Node->getLocation().getLocationContext()->getCurrentStackFrame(); 688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org 698bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org // Back up through the ExplodedGraph until we reach a statement node in this 708bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org // stack frame. 717be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org while (Node) { 7241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org const ProgramPoint &PP = Node->getLocation(); 7341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org 741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (PP.getLocationContext()->getCurrentStackFrame() == SF) { 7543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) { 7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen S = SP->getStmt(); 7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 7841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&PP)) { 7941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org S = CEE->getCalleeContext()->getCallSite(); 807be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org if (S) 815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org break; 8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 838bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org // If there is no statement, this is an implicitly-generated call. 84cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org // We'll walk backwards over it and then continue the loop to find 85cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org // an actual statement. 86cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org const CallEnter *CE; 87cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org do { 88a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org Node = Node->getFirstPred(); 89a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org CE = Node->getLocationAs<CallEnter>(); 907be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org } while (!CE || CE->getCalleeContext() != CEE->getCalleeContext()); 917be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org 927be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // Continue searching the graph. 937be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org } 947be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org } else if (const CallEnter *CE = dyn_cast<CallEnter>(&PP)) { 95355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // If we reached the CallEnter for this function, it has no statements. 96355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (CE->getCalleeContext() == SF) 97355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org break; 98355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 99355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 100355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org Node = *Node->pred_begin(); 101355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 102355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 10341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org const CFGBlock *Blk = 0; 10441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org if (S) { 1057be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // Now, get the enclosing basic block. 1067be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org while (Node && Node->pred_size() >=1 ) { 10741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org const ProgramPoint &PP = Node->getLocation(); 108cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org if (isa<BlockEdge>(PP) && 109cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org (PP.getLocationContext()->getCurrentStackFrame() == SF)) { 110cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org BlockEdge &EPP = cast<BlockEdge>(PP); 111cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org Blk = EPP.getDst(); 112cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org break; 113cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org } 114cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org Node = *Node->pred_begin(); 115355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 116cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org } 117cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org 1185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org return std::pair<const Stmt*, const CFGBlock*>(S, Blk); 119cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org} 12015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org 12115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// The call exit is simulated with a sequence of nodes, which occur between 12215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// CallExitBegin and CallExitEnd. The following operations occur between the 12315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// two program points: 124cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// 1. CallExitBegin (triggers the start of call exit sequence) 125cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// 2. Bind the return value 12615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 3. Run Remove dead bindings to clean up the dead symbols from the callee. 12715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 4. CallExitEnd (switch to the caller context) 12815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 5. PostStmt<CallExpr> 129355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.orgvoid ExprEngine::processCallExit(ExplodedNode *CEBNode) { 130355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Step 1 CEBNode was generated before the call. 131cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org 132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const StackFrameContext *calleeCtx = 13341826e77311db718135ef6517b846933dfd275f3ager@chromium.org CEBNode->getLocationContext()->getCurrentStackFrame(); 134355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 13541826e77311db718135ef6517b846933dfd275f3ager@chromium.org // The parent context might not be a stack frame, so make sure we 136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // look up the first enclosing stack frame. 137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const StackFrameContext *callerCtx = 1387be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org calleeCtx->getParent()->getCurrentStackFrame(); 1395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const Stmt *CE = calleeCtx->getCallSite(); 141355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org ProgramStateRef state = CEBNode->getState(); 142355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Find the last statement in the function and the corresponding basic block. 143355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org const Stmt *LastSt = 0; 144355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org const CFGBlock *Blk = 0; 145355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org llvm::tie(LastSt, Blk) = getLastStmt(CEBNode); 146355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 147355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Step 2: generate node with bound return value: CEBNode -> BindedRetNode. 148355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 149355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // If the callee returns an expression, bind its value to CallExpr. 150355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (CE) { 151355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) { 152355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org const LocationContext *LCtx = CEBNode->getLocationContext(); 153355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org SVal V = state->getSVal(RS, LCtx); 154355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org state = state->BindExpr(CE, callerCtx, V); 1552f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org } 156355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 157355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Bind the constructed object value to CXXConstructExpr. 158355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 159355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org loc::MemRegionVal This = 160355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); 1612f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org SVal ThisV = state->getSVal(This); 162355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 1632f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org // If the constructed object is a prvalue, get its bindings. 164355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Note that we have to be careful here because constructors embedded 1652f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org // in DeclStmts are not marked as lvalues. 166355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (!CCE->isGLValue()) 167355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (const MemRegion *MR = ThisV.getAsRegion()) 168355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (isa<CXXTempObjectRegion>(MR)) 169355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org ThisV = state->getSVal(cast<Loc>(ThisV)); 170355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 171355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org state = state->BindExpr(CCE, callerCtx, ThisV); 172355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 173355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 174355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 175355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // Generate a CallEvent /before/ cleaning the state, so that we can get the 176355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org // correct value for 'this' (if necessary). 177355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org CallEventManager &CEMgr = getStateManager().getCallEventManager(); 178355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org CallEventRef<> Call = CEMgr.getCaller(calleeCtx, state); 179355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 1800c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org // Step 3: BindedRetNode -> CleanedNodes 1817be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // If we can find a statement and a block in the inlined function, run remove 1827be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // dead bindings before returning from the call. This is important to ensure 1837be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // that we report the issues such as leaks in the stack contexts in which 184bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // they occurred. 1857be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org ExplodedNodeSet CleanedNodes; 1867be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) { 1870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value"); 1880c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org PostStmt Loc(LastSt, calleeCtx, &retValBind); 1890c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org bool isNew; 1900c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew); 1910c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org BindedRetNode->addPredecessor(CEBNode, G); 1920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org if (!isNew) 1930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org return; 1940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org 1950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode); 1960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org currBldrCtx = &Ctx; 197bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // Here, we call the Symbol Reaper with 0 statement and caller location 1987be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // context, telling it to clean up everything in the callee's context 1997be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // (and it's children). We use LastStmt as a diagnostic statement, which 2007be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // which the PreStmtPurge Dead point will be associated. 2017be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt, 2027be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org ProgramPoint::PostStmtPurgeDeadSymbolsKind); 2037be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org currBldrCtx = 0; 2047be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org } else { 2057be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org CleanedNodes.Add(CEBNode); 2067be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org } 207bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 2087be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org for (ExplodedNodeSet::iterator I = CleanedNodes.begin(), 2097be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org E = CleanedNodes.end(); I != E; ++I) { 2107be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org 211bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // Step 4: Generate the CallExit and leave the callee's context. 2127be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // CleanedNodes -> CEENode 2137be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org CallExitEnd Loc(calleeCtx, callerCtx); 2147be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org bool isNew; 2157be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState(); 2167be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew); 217a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org CEENode->addPredecessor(*I, G); 218bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org if (!isNew) 219bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org return; 220bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 2217be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // Step 5: Perform the post-condition check of the CallExpr and enqueue the 222bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // result onto the work list. 2237be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org // CEENode -> Dst -> WorkList 2247be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode); 2257be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org SaveAndRestore<const NodeBuilderContext*> NBCSave(currBldrCtx, 2267be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org &Ctx); 2277be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org SaveAndRestore<unsigned> CBISave(currStmtIdx, calleeCtx->getIndex()); 2287be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org 22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen CallEventRef<> UpdatedCall = Call.cloneWithState(CEEState); 23083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 23183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org ExplodedNodeSet DstPostCall; 23283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode, 23383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org *UpdatedCall, *this, 23483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org /*WasInlined=*/true); 23583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 23683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org ExplodedNodeSet Dst; 23783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) { 238bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg, 2397d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org *this, 2405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org /*WasInlined=*/true); 2417d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org } else if (CE) { 2425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE, 24343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen *this, /*WasInlined=*/true); 24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } else { 24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Dst.insert(DstPostCall); 2460c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org } 2470c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org 2480c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org // Enqueue the next element in the block. 2490c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end(); 2500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org PSI != PSE; ++PSI) { 2510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(), 2520c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org calleeCtx->getIndex()+1); 2530c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org } 2540c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org } 2550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org} 2561044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org 2571044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.orgvoid ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx, 258a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org bool &IsRecursive, unsigned &StackDepth) { 259a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org IsRecursive = false; 260a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org StackDepth = 0; 261a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 262a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org while (LCtx) { 263a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LCtx)) { 2647028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org const Decl *DI = SFC->getDecl(); 2657028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 266ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // Mark recursive (and mutually recursive) functions and always count 267a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // them when measuring the stack depth. 268a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (DI == D) { 269a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org IsRecursive = true; 270a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org ++StackDepth; 271a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org LCtx = LCtx->getParent(); 272a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org continue; 273a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 274a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 275a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Do not count the small functions when determining the stack depth. 276a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI); 277a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const CFG *CalleeCFG = CalleeADC->getCFG(); 278a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize()) 279a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org ++StackDepth; 280a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 281a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org LCtx = LCtx->getParent(); 282a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 2838bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org 284a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} 2857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 2867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.orgstatic bool IsInStdNamespace(const FunctionDecl *FD) { 287a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const DeclContext *DC = FD->getEnclosingNamespaceContext(); 288ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); 289a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!ND) 2907028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org return false; 2917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 2920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org while (const DeclContext *Parent = ND->getParent()) { 2930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org if (!isa<NamespaceDecl>(Parent)) 2940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org break; 2950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org ND = cast<NamespaceDecl>(Parent); 2960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org } 2970c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org 2980c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org return ND->getName() == "std"; 2990c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org} 3000c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org 3010c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// Determine if we should inline the call. 3027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.orgbool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { 3037028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); 304a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const CFG *CalleeCFG = CalleeADC->getCFG(); 305a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 306a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // It is possible that the CFG cannot be constructed. 307a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Be safe, and check if the CalleeCFG is valid. 308a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!CalleeCFG) 309a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 310a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 311a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org bool IsRecursive = false; 312a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org unsigned StackDepth = 0; 313a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth); 314a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if ((StackDepth >= AMgr.options.InlineMaxStackDepth) && 315a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org ((CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize()) 316a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org || IsRecursive)) 317a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 3187028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 319a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D)) 320a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 321a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 322a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (CalleeCFG->getNumBlockIDs() > AMgr.options.InlineMaxFunctionSize) 323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 324a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 325a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Do not inline variadic calls (for now). 3267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 327a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (BD->isVariadic()) 328a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 329a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 3317028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org if (FD->isVariadic()) 332a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 333a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 334a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 335a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (getContext().getLangOpts().CPlusPlus) { 336a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 337a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Conditionally allow the inlining of template functions. 3383291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org if (!getAnalysisManager().options.mayInlineTemplateFunctions()) 339a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) 340a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 341a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 342a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Conditionally allow the inlining of C++ standard library functions. 343a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!getAnalysisManager().options.mayInlineCXXStandardLibrary()) 344a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (getContext().getSourceManager().isInSystemHeader(FD->getLocation())) 345a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (IsInStdNamespace(FD)) 3467028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org return false; 3477028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org } 348a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 349a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 350a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // It is possible that the live variables analysis cannot be 351a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // run. If so, bail out. 352a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!CalleeADC->getAnalysis<RelaxedLiveVariables>()) 353a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 354a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 355a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return true; 3567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org} 3577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 3587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org/// The GDM component containing the dynamic dispatch bifurcation info. When 359a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// the exact type of the receiver is not known, we want to explore both paths - 360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// one on which we do inline it and the other one on which we don't. This is 361a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// done to ensure we do not drop coverage. 362a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// This is the map from the receiver region to a bool, specifying either we 363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// consider this region's information precise or not along the given path. 364a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgnamespace clang { 365a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgnamespace ento { 366a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgenum DynamicDispatchMode { DynamicDispatchModeInlined = 1, 367a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org DynamicDispatchModeConservative }; 368a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 369a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstruct DynamicDispatchBifurcationMap {}; 370a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgtypedef llvm::ImmutableMap<const MemRegion*, 371a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org unsigned int> DynamicDispatchBifur; 372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgtemplate<> struct ProgramStateTrait<DynamicDispatchBifurcationMap> 373a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org : public ProgramStatePartialTrait<DynamicDispatchBifur> { 374a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org static void *GDMIndex() { static int index; return &index; } 375a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}; 376a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}} 378a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, 380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org NodeBuilder &Bldr, ExplodedNode *Pred, 381a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org ProgramStateRef State) { 3827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org assert(D); 383a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 384a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const LocationContext *CurLC = Pred->getLocationContext(); 385a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame(); 386a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const LocationContext *ParentOfCallee = 0; 3877028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 3887028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org const AnalyzerOptions &Opts = getAnalysisManager().options; 3897028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 39083e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org // FIXME: Refactor this check into a hypothetical CallEvent::canInline. 391a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org switch (Call.getKind()) { 392a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org case CE_Function: 393a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org break; 394a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org case CE_CXXMember: 395a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org case CE_CXXMemberOperator: 396a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!Opts.mayInlineCXXMemberFunction(CIMK_MemberFunctions)) 397a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 398a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org break; 399a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org case CE_CXXConstructor: { 400a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!Opts.mayInlineCXXMemberFunction(CIMK_Constructors)) 401a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 402a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 403a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call); 404a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 405a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // FIXME: We don't handle constructors or destructors for arrays properly. 406ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org const MemRegion *Target = Ctor.getCXXThisVal().getAsRegion(); 407a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (Target && isa<ElementRegion>(Target)) 408a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 409a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 410a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // FIXME: This is a hack. We don't use the correct region for a new 411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // expression, so if we inline the constructor its result will just be 412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // thrown away. This short-term hack is tracked in <rdar://problem/12180598> 413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // and the longer-term possible fix is discussed in PR12014. 414a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr(); 415a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (const Stmt *Parent = CurLC->getParentMap().getParent(CtorExpr)) 416a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (isa<CXXNewExpr>(Parent)) 417a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 418a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 419a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Inlining constructors requires including initializers in the CFG. 420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); 421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers"); 422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org (void)ADC; 423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 424a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // If the destructor is trivial, it's always safe to inline the constructor. 425a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (Ctor.getDecl()->getParent()->hasTrivialDestructor()) 426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org break; 427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // For other types, only inline constructors if destructor inlining is 4299259716434187c932704601f700375e53d865de8rossberg@chromium.org // also enabled. 430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors)) 4319259716434187c932704601f700375e53d865de8rossberg@chromium.org return false; 4329259716434187c932704601f700375e53d865de8rossberg@chromium.org 4339259716434187c932704601f700375e53d865de8rossberg@chromium.org // FIXME: This is a hack. We don't handle temporary destructors 4349259716434187c932704601f700375e53d865de8rossberg@chromium.org // right now, so we shouldn't inline their constructors. 4359259716434187c932704601f700375e53d865de8rossberg@chromium.org if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) 436a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!Target || !isa<DeclRegion>(Target)) 437a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 4389259716434187c932704601f700375e53d865de8rossberg@chromium.org 4399259716434187c932704601f700375e53d865de8rossberg@chromium.org break; 4409259716434187c932704601f700375e53d865de8rossberg@chromium.org } 4419259716434187c932704601f700375e53d865de8rossberg@chromium.org case CE_CXXDestructor: { 4429259716434187c932704601f700375e53d865de8rossberg@chromium.org if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors)) 4439259716434187c932704601f700375e53d865de8rossberg@chromium.org return false; 4449259716434187c932704601f700375e53d865de8rossberg@chromium.org 4459259716434187c932704601f700375e53d865de8rossberg@chromium.org // Inlining destructors requires building the CFG correctly. 4469259716434187c932704601f700375e53d865de8rossberg@chromium.org const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); 4479259716434187c932704601f700375e53d865de8rossberg@chromium.org assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors"); 4489259716434187c932704601f700375e53d865de8rossberg@chromium.org (void)ADC; 4499259716434187c932704601f700375e53d865de8rossberg@chromium.org 4509259716434187c932704601f700375e53d865de8rossberg@chromium.org const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call); 4519259716434187c932704601f700375e53d865de8rossberg@chromium.org 4529259716434187c932704601f700375e53d865de8rossberg@chromium.org // FIXME: We don't handle constructors or destructors for arrays properly. 4539259716434187c932704601f700375e53d865de8rossberg@chromium.org const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion(); 4549259716434187c932704601f700375e53d865de8rossberg@chromium.org if (Target && isa<ElementRegion>(Target)) 4559259716434187c932704601f700375e53d865de8rossberg@chromium.org return false; 4569259716434187c932704601f700375e53d865de8rossberg@chromium.org 4579259716434187c932704601f700375e53d865de8rossberg@chromium.org break; 4589259716434187c932704601f700375e53d865de8rossberg@chromium.org } 4599259716434187c932704601f700375e53d865de8rossberg@chromium.org case CE_CXXAllocator: 4609259716434187c932704601f700375e53d865de8rossberg@chromium.org // Do not inline allocators until we model deallocators. 4619259716434187c932704601f700375e53d865de8rossberg@chromium.org // This is unfortunate, but basically necessary for smart pointers and such. 4629259716434187c932704601f700375e53d865de8rossberg@chromium.org return false; 4639259716434187c932704601f700375e53d865de8rossberg@chromium.org case CE_Block: { 464a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion(); 465a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org assert(BR && "If we have the block definition we should have its region"); 466a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D); 4673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC, 4688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org cast<BlockDecl>(D), 4698bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org BR); 470a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org break; 471a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org case CE_ObjCMessage: 473a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!Opts.mayInlineObjCMethod()) 474a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 475a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!(getAnalysisManager().options.IPAMode == DynamicDispatch || 476a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate)) 477a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 4781044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org break; 4791044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org } 480a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 481a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!shouldInlineDecl(D, Pred)) 482a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return false; 483a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 484a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!ParentOfCallee) 485a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org ParentOfCallee = CallerSFC; 486a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 48737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // This may be NULL, but that's fine. 488a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const Expr *CallE = Call.getOriginExpr(); 489a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 490a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Construct a new stack frame for the callee. 491a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); 492a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const StackFrameContext *CalleeSFC = 493a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org CalleeADC->getStackFrame(ParentOfCallee, CallE, 494a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org currBldrCtx->getBlock(), 495a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org currStmtIdx); 496a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 497a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org CallEnter Loc(CallE, CalleeSFC, CurLC); 498a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 4998bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org // Construct a new state which contains the mapping from actual to 5008bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org // formal arguments. 5018bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org State = State->enterStackFrame(Call, CalleeSFC); 5028bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org 5038bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org bool isNew; 5048bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) { 505a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org N->addPredecessor(Pred, G); 506a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (isNew) 507a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org Engine.getWorkList()->enqueue(N); 508a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 509a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 510a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // If we decided to inline the call, the successor has been manually 511a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // added onto the work list so remove it from the node builder. 512a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org Bldr.takeNodes(Pred); 513a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 514a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org NumInlinedCalls++; 515a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 516a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Mark the decl as visited. 517a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (VisitedCallees) 518a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org VisitedCallees->insert(D); 519a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 520a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return true; 521a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} 522a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 523a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic ProgramStateRef getInlineFailedState(ProgramStateRef State, 524a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const Stmt *CallE) { 525a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org void *ReplayState = State->get<ReplayWithoutInlining>(); 526a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!ReplayState) 527a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return 0; 528a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 5291044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org assert(ReplayState == (const void*)CallE && "Backtracked to the wrong call."); 530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org (void)CallE; 531a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return State->remove<ReplayWithoutInlining>(); 53337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com} 53437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 53537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 53637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com ExplodedNodeSet &dst) { 53737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Perform the previsit of the CallExpr. 53837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com ExplodedNodeSet dstPreVisit; 53937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 540245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org 541245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org // Get the call in its initial state. We use this as a template to perform 54237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // all the checks. 54337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com CallEventManager &CEMgr = getStateManager().getCallEventManager(); 54437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com CallEventRef<> CallTemplate 545245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org = CEMgr.getSimpleCall(CE, Pred->getState(), Pred->getLocationContext()); 546245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org 54737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Evaluate the function call. We try each of the checkers 54837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // to see if the can evaluate the function call. 54937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com ExplodedNodeSet dstCallEvaluated; 55037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); 55137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com I != E; ++I) { 55237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com evalCall(dstCallEvaluated, *I, *CallTemplate); 553245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org } 554245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org 55537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Finally, perform the post-condition check of the CallExpr and store 55637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // the created nodes in 'Dst'. 55737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Note that if the call was inlined, dstCallEvaluated will be empty. 55837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // The post-CallExpr check will occur in processCallExit. 55937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 56037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com *this); 56137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com} 56237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 56337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, 56437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com const CallEvent &Call) { 56537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // WARNING: At this time, the state attached to 'Call' may be older than the 56637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // state in 'Pred'. This is a minor optimization since CheckerManager will 56737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // use an updated CallEvent instance when calling checkers, but if 'Call' is 56837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // ever used directly in this function all callers should be updated to pass 56937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // the most recent state. (It is probably not worth doing the work here since 57037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // for some callers this will not be necessary.) 57137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 57237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Run any pre-call checks using the generic call interface. 57337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com ExplodedNodeSet dstPreVisit; 57437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, Call, *this); 57537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 57637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Actually evaluate the function call. We try each of the checkers 57737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // to see if the can evaluate the function call, and get a callback at 57837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // defaultEvalCall if all of them fail. 579245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org ExplodedNodeSet dstCallEvaluated; 580245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit, 581245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org Call, *this); 58237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 58337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Finally, run any post-call checks. 58437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com getCheckerManager().runCheckersForPostCall(Dst, dstCallEvaluated, 5851044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org Call, *this); 5861044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org} 5871044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org 588a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, 589a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org const LocationContext *LCtx, 590400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org ProgramStateRef State) { 591400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org const Expr *E = Call.getOriginExpr(); 592ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com if (!E) 593ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com return State; 59437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 595a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // Some method families have known return values. 596a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { 597ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org switch (Msg->getMethodFamily()) { 59837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com default: 599ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org break; 600ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org case OMF_autorelease: 601a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org case OMF_retain: 602a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org case OMF_self: { 603a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // These methods return their receivers. 604a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return State->BindExpr(E, LCtx, Msg->getReceiverSVal()); 6054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org } 60637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com } 60737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){ 60837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com return State->BindExpr(E, LCtx, C->getCXXThisVal()); 60937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com } 6103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 61137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com // Conjure a symbol if the return value is unknown. 61237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com QualType ResultTy = Call.getResultType(); 61337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com SValBuilder &SVB = getSValBuilder(); 61437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com unsigned Count = currBldrCtx->blockCount(); 61537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com SVal R = SVB.conjureSymbolVal(0, E, LCtx, ResultTy, Count); 61637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com return State->BindExpr(E, LCtx, R); 61737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com} 61837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com 61937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Conservatively evaluate call by invalidating regions and binding 62037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// a conjured return value. 621245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgvoid ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, 622245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org ExplodedNode *Pred, ProgramStateRef State) { 6238bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org State = Call.invalidateRegions(currBldrCtx->blockCount(), State); 6248bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org State = bindReturnValue(Call, Pred->getLocationContext(), State); 6257d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org 6267d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org // And make the result node. 6277d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org Bldr.generateNode(Call.getProgramPoint(), State, Pred); 6287d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org} 6297d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org 6307d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgvoid ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, 6317d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org const CallEvent &CallTemplate) { 6327d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org // Make sure we have the most recent state attached to the call. 6337d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org ProgramStateRef State = Pred->getState(); 6347d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org CallEventRef<> Call = CallTemplate.cloneWithState(State); 635400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org 636400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org if (!getAnalysisManager().shouldInlineCall()) { 6374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org conservativeEvalCall(*Call, Bldr, Pred, State); 63837141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org return; 639400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org } 64037141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org // Try to inline the call. 64137141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org // The origin expression here is just used as a kind of checksum; 6427d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org // this should still be safe even for CallEvents that don't come from exprs. 6437d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org const Expr *E = Call->getOriginExpr(); 6441044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org ProgramStateRef InlinedFailedState = getInlineFailedState(State, E); 6451044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org 6461044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org if (InlinedFailedState) { 6471044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org // If we already tried once and failed, make sure we don't retry later. 64859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org State = InlinedFailedState; 6491044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org } else { 6501044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org RuntimeDefinition RD = Call->getRuntimeDefinition(); 6511044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org const Decl *D = RD.getDecl(); 6521044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org if (D) { 6531044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org if (RD.mayHaveOtherDefinitions()) { 6541044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org // Explore with and without inlining the call. 6551044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org if (getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate) { 6561044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred); 6571044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org return; 6581044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org } 6591044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org 660ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // Don't inline if we're not in any dynamic dispatch mode. 661ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com if (getAnalysisManager().options.IPAMode != DynamicDispatch) { 662ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com conservativeEvalCall(*Call, Bldr, Pred, State); 663ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com return; 664ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com } 665ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com } 666ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com 6677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org // We are not bifurcating and we do have a Decl, so just inline. 6688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org if (inlineCall(*Call, D, Bldr, Pred, State)) 6692efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org return; 6703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org } 6713291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org } 6723291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 6733291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org // If we can't inline it, handle the return value and invalidate the regions. 6743291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org conservativeEvalCall(*Call, Bldr, Pred, State); 675a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} 676a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 677a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid ExprEngine::BifurcateCall(const MemRegion *BifurReg, 678ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com const CallEvent &Call, const Decl *D, 679ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com NodeBuilder &Bldr, ExplodedNode *Pred) { 680ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com assert(BifurReg); 6810c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org BifurReg = BifurReg->StripCasts(); 6827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 683400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org // Check if we've performed the split already - note, we only want 684a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // to split the path once per memory region. 685ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org ProgramStateRef State = Pred->getState(); 6861044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org const unsigned int *BState = 6870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org State->get<DynamicDispatchBifurcationMap>(BifurReg); 6883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org if (BState) { 689a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // If we are on "inline path", keep inlining if possible. 690ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com if (*BState == DynamicDispatchModeInlined) 691ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com if (inlineCall(Call, D, Bldr, Pred, State)) 692ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com return; 693ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // If inline failed, or we are on the path where we assume we 694a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org // don't have enough info about the receiver to inline, conjure the 6950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org // return value and invalidate the regions. 696a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org conservativeEvalCall(Call, Bldr, Pred, State); 697a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org return; 6983291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org } 6993291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org // If we got here, this is the first time we process a message to this 7013291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org // region, so split the path. 7023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org ProgramStateRef IState = 7033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org State->set<DynamicDispatchBifurcationMap>(BifurReg, 704ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com DynamicDispatchModeInlined); 705400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org inlineCall(Call, D, Bldr, Pred, IState); 706400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org 7073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org ProgramStateRef NoIState = 7083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org State->set<DynamicDispatchBifurcationMap>(BifurReg, 7093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org DynamicDispatchModeConservative); 7103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org conservativeEvalCall(Call, Bldr, Pred, NoIState); 7113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org NumOfDynamicDispatchPathSplits++; 7133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org return; 7143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org} 7153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 7183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org ExplodedNodeSet &Dst) { 7193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org ExplodedNodeSet dstPreVisit; 7213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); 7223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7233291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx); 7243291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org 7253291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org if (RS->getRetValue()) { 7263291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), 727ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com ei = dstPreVisit.end(); it != ei; ++it) { 728ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com B.generateNode(RS, *it, (*it)->getState()); 7293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org } 7303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org } 7313291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org} 7323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org