ExprEngineCallAndReturn.cpp revision 01561d1039bfdda61edd20eed939011a8632c7c7
12cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// 32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// The LLVM Compiler Infrastructure 42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// 52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// This file is distributed under the University of Illinois Open Source 62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// License. See LICENSE.TXT for details. 72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// 82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//===----------------------------------------------------------------------===// 92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// 102cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// This file defines ExprEngine's support for calls and returns. 112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// 122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//===----------------------------------------------------------------------===// 132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15e7785040107266d01ebdcc066365f70b7ace371fDouglas Gregor#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "clang/AST/DeclCXX.h" 182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "llvm/ADT/SmallSet.h" 192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "llvm/Support/SaveAndRestore.h" 200b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor 212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorusing namespace clang; 22a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallusing namespace ento; 237c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner 247c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnervoid ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { 2583d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff // Get the entry block in the CFG of the callee. 2614f79002e58556798e86168c63e48d533287eda5Douglas Gregor const StackFrameContext *calleeCtx = CE.getCalleeContext(); 273251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor const CFG *CalleeCFG = calleeCtx->getCFG(); 2814f79002e58556798e86168c63e48d533287eda5Douglas Gregor const CFGBlock *Entry = &(CalleeCFG->getEntry()); 29bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor 302bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor // Validate the CFG. 31ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor assert(Entry->empty()); 3217fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor assert(Entry->succ_size() == 1); 3317fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor 342596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar // Get the solitary sucessor. 352cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const CFGBlock *Succ = *(Entry->succ_begin()); 362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 3714f79002e58556798e86168c63e48d533287eda5Douglas Gregor // Construct an edge representing the starting location in the callee. 38b64c19365deab788753d29c9bc881253c3f16f37Douglas Gregor BlockEdge Loc(Entry, Succ, calleeCtx); 393c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner 402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Construct a new state which contains the mapping from actual to 412cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // formal arguments. 422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const LocationContext *callerCtx = Pred->getLocationContext(); 432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ProgramStateRef state = Pred->getState()->enterStackFrame(callerCtx, 442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor calleeCtx); 4512b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner 462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Construct a new node and add it to the worklist. 472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool isNew; 482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); 492cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Node->addPredecessor(Pred, G); 502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (isNew) 512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Engine.getWorkList()->enqueue(Node); 522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic const ReturnStmt *getReturnStmt(const ExplodedNode *Node) { 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump while (Node) { 564fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor const ProgramPoint &PP = Node->getLocation(); 572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Skip any BlockEdges. 582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) { 592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor assert(Node->pred_size() == 1); 602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Node = *Node->pred_begin(); 612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor continue; 622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) { 642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const Stmt *S = SP->getStmt(); 652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return dyn_cast<ReturnStmt>(S); 662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor break; 682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return 0; 702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid ExprEngine::processCallExit(ExplodedNode *Pred) { 732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ProgramStateRef state = Pred->getState(); 742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const StackFrameContext *calleeCtx = 752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Pred->getLocationContext()->getCurrentStackFrame(); 762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const LocationContext *callerCtx = calleeCtx->getParent(); 772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const Stmt *CE = calleeCtx->getCallSite(); 782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // If the callee returns an expression, bind its value to CallExpr. 802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (const ReturnStmt *RS = getReturnStmt(Pred)) { 812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const LocationContext *LCtx = Pred->getLocationContext(); 822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SVal V = state->getSVal(RS, LCtx); 832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor state = state->BindExpr(CE, callerCtx, V); 842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Bind the constructed object value to CXXConstructExpr. 872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const CXXThisRegion *ThisR = 892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); 901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SVal ThisV = state->getSVal(ThisR); 922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Always bind the region to the CXXConstructExpr. 932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV); 942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor static SimpleProgramPointTag returnTag("ExprEngine : Call Return"); 972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor PostStmt Loc(CE, callerCtx, &returnTag); 982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool isNew; 992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ExplodedNode *N = G.getNode(Loc, state, false, &isNew); 1002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor N->addPredecessor(Pred, G); 1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!isNew) 1022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return; 1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Perform the post-condition check of the CallExpr. 1051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNodeSet Dst; 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N); 1072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext, 1082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor &Ctx); 1092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); 1102cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this, 1122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor /* wasInlined */ true); 1130953e767ff7817f97b3ab20896b229891eeff45bJohn McCall 1142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Enqueue the next element in the block. 1152cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { 1162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Engine.getWorkList()->enqueue(*I, 1172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor calleeCtx->getCallSiteBlock(), 1182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor calleeCtx->getIndex()+1); 1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 1212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic unsigned getNumberStackFrames(const LocationContext *LCtx) { 1232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor unsigned count = 0; 1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor while (LCtx) { 1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (isa<StackFrameContext>(LCtx)) 1262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ++count; 1272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor LCtx = LCtx->getParent(); 1282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1297e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor return count; 1307e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor} 131c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor 1322cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Determine if we should inline the call. 1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorbool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) { 1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD); 1352cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const CFG *CalleeCFG = CalleeADC->getCFG(); 1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // It is possible that the CFG cannot be constructed. 1382cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Be safe, and check if the CalleeCFG is valid. 1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!CalleeCFG) 1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1412cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (getNumberStackFrames(Pred->getLocationContext()) 1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor == AMgr.InlineMaxStackDepth) 1442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (Engine.FunctionSummaries->hasReachedMaxBlockCount(FD)) 1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1492cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize) 1502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return true; 1532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 1542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// For now, skip inlining variadic functions. 1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// We also don't inline blocks. 1572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic bool shouldInlineCallExpr(const CallExpr *CE, ExprEngine *E) { 1582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!E->getAnalysisManager().shouldInlineCall()) 1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor QualType callee = CE->getCallee()->getType(); 1612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const FunctionProtoType *FT = 0; 162465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl if (const PointerType *PT = callee->getAs<PointerType>()) 163465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl FT = dyn_cast<FunctionProtoType>(PT->getPointeeType()); 164465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl else if (const BlockPointerType *BT = callee->getAs<BlockPointerType>()) { 165465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl // FIXME: inline blocks. 166465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl // FT = dyn_cast<FunctionProtoType>(BT->getPointeeType()); 1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor (void) BT; 1682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // If we have no prototype, assume the function is okay. 1712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!FT) 1722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return true; 1732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Skip inlining of variadic functions. 1752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return !FT->isVariadic(); 176c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor} 1772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorbool ExprEngine::InlineCall(ExplodedNodeSet &Dst, 1792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const CallExpr *CE, 1802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ExplodedNode *Pred) { 1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!shouldInlineCallExpr(CE, this)) 1822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ProgramStateRef state = Pred->getState(); 185395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson const Expr *Callee = CE->getCallee(); 186395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson const FunctionDecl *FD = 187395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl(); 188395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson if (!FD || !FD->hasBody(FD)) 189395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson return false; 1902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor switch (CE->getStmtClass()) { 1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump default: 1932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // FIXME: Handle C++. 1942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor break; 1952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor case Stmt::CallExprClass: { 1962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!shouldInlineDecl(FD, Pred)) 1972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 1982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Construct a new stack frame for the callee. 2002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD); 2012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const StackFrameContext *CallerSFC = 2022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor Pred->getLocationContext()->getCurrentStackFrame(); 2032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const StackFrameContext *CalleeSFC = 2042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor CalleeADC->getStackFrame(CallerSFC, CE, 2052cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor currentBuilderContext->getBlock(), 2067da2431c23ef1ee8acb114e39692246e1801afc2John McCall currentStmtIdx); 2077da2431c23ef1ee8acb114e39692246e1801afc2John McCall 2087da2431c23ef1ee8acb114e39692246e1801afc2John McCall CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext()); 2097da2431c23ef1ee8acb114e39692246e1801afc2John McCall bool isNew; 2107da2431c23ef1ee8acb114e39692246e1801afc2John McCall if (ExplodedNode *N = G.getNode(Loc, state, false, &isNew)) { 2117da2431c23ef1ee8acb114e39692246e1801afc2John McCall N->addPredecessor(Pred, G); 2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isNew) 21349a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall Engine.getWorkList()->enqueue(N); 21449a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall } 21549a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall return true; 21649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall } 21749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall } 21849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall return false; 21949a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall} 22049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall 2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic bool isPointerToConst(const ParmVarDecl *ParamDecl) { 2222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); 2236a2bfb2ead4489db37e80b696a6d7cc073c76fd7Douglas Gregor if (PointeeTy != QualType() && PointeeTy.isConstQualified() && 2242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { 2252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return true; 2262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 2286a2bfb2ead4489db37e80b696a6d7cc073c76fd7Douglas Gregor} 2292cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Try to retrieve the function declaration and find the function parameter 2312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// types which are pointers/references to a non-pointer const. 2322cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// We do not invalidate the corresponding argument regions. 2332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs, 2342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const CallOrObjCMessage &Call) { 235446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff const Decl *CallDecl = Call.getDecl(); 236446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff if (!CallDecl) 237446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff return; 238c15cb2af27514ecc879daba9aa01389c5203685dSteve Naroff 2392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) { 2402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const IdentifierInfo *II = FDecl->getIdentifier(); 241d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff 242d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff // List the cases, where the region should be invalidated even if the 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // argument is const. 2442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (II) { 245d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff StringRef FName = II->getName(); 246446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff // - 'int pthread_setspecific(ptheread_key k, const void *)' stores a 247446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff // value into thread local storage. The value can later be retrieved with 248d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff // 'void *ptheread_getspecific(pthread_key)'. So even thought the 2492cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // parameter is 'const void *', the region escapes through the call. 2502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // - funopen - sets a buffer for future IO calls. 251a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // - ObjC functions that end with "NoCopy" can free memory, of the passed 252a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // in buffer. 253a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // - Many CF containers allow objects to escape through custom 254a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // allocators/deallocators upon container construction. 255a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can 256a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // be deallocated by NSMapRemove. 257a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall if (FName == "pthread_setspecific" || 258a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall FName == "funopen" || 259a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall FName.endswith("NoCopy") || 260a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall (FName.startswith("NS") && 26151bd803fbdade51d674598ed45da3d54190a656cJohn McCall (FName.find("Insert") != StringRef::npos)) || 262a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall Call.isCFCGAllowingEscape(FName)) 26351bd803fbdade51d674598ed45da3d54190a656cJohn McCall return; 264a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall } 265a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall 26651bd803fbdade51d674598ed45da3d54190a656cJohn McCall for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) { 26751bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (FDecl && Idx < FDecl->getNumParams()) { 268a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall if (isPointerToConst(FDecl->getParamDecl(Idx))) 269a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall PreserveArgs.insert(Idx); 270a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall } 271a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall } 27251bd803fbdade51d674598ed45da3d54190a656cJohn McCall return; 27351bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 27451bd803fbdade51d674598ed45da3d54190a656cJohn McCall 27551bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) { 27651bd803fbdade51d674598ed45da3d54190a656cJohn McCall assert(MDecl->param_size() <= Call.getNumArgs()); 27751bd803fbdade51d674598ed45da3d54190a656cJohn McCall unsigned Idx = 0; 27851bd803fbdade51d674598ed45da3d54190a656cJohn McCall for (clang::ObjCMethodDecl::param_const_iterator 27951bd803fbdade51d674598ed45da3d54190a656cJohn McCall I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) { 28051bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (isPointerToConst(*I)) 28151bd803fbdade51d674598ed45da3d54190a656cJohn McCall PreserveArgs.insert(Idx); 28251bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 28351bd803fbdade51d674598ed45da3d54190a656cJohn McCall return; 28451bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 28551bd803fbdade51d674598ed45da3d54190a656cJohn McCall} 28651bd803fbdade51d674598ed45da3d54190a656cJohn McCall 28751bd803fbdade51d674598ed45da3d54190a656cJohn McCallProgramStateRef 28851bd803fbdade51d674598ed45da3d54190a656cJohn McCallExprEngine::invalidateArguments(ProgramStateRef State, 28951bd803fbdade51d674598ed45da3d54190a656cJohn McCall const CallOrObjCMessage &Call, 29051bd803fbdade51d674598ed45da3d54190a656cJohn McCall const LocationContext *LC) { 29151bd803fbdade51d674598ed45da3d54190a656cJohn McCall SmallVector<const MemRegion *, 8> RegionsToInvalidate; 29251bd803fbdade51d674598ed45da3d54190a656cJohn McCall 29351bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (Call.isObjCMessage()) { 29451bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Invalidate all instance variables of the receiver of an ObjC message. 29551bd803fbdade51d674598ed45da3d54190a656cJohn McCall // FIXME: We should be able to do better with inter-procedural analysis. 29651bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion()) 29751bd803fbdade51d674598ed45da3d54190a656cJohn McCall RegionsToInvalidate.push_back(MR); 29851bd803fbdade51d674598ed45da3d54190a656cJohn McCall 29951bd803fbdade51d674598ed45da3d54190a656cJohn McCall } else if (Call.isCXXCall()) { 30051bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Invalidate all instance variables for the callee of a C++ method call. 30151bd803fbdade51d674598ed45da3d54190a656cJohn McCall // FIXME: We should be able to do better with inter-procedural analysis. 30251bd803fbdade51d674598ed45da3d54190a656cJohn McCall // FIXME: We can probably do better for const versus non-const methods. 30351bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion()) 30451bd803fbdade51d674598ed45da3d54190a656cJohn McCall RegionsToInvalidate.push_back(Callee); 30551bd803fbdade51d674598ed45da3d54190a656cJohn McCall 30651bd803fbdade51d674598ed45da3d54190a656cJohn McCall } else if (Call.isFunctionCall()) { 30751bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Block calls invalidate all captured-by-reference values. 30851bd803fbdade51d674598ed45da3d54190a656cJohn McCall SVal CalleeVal = Call.getFunctionCallee(); 30951bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const MemRegion *Callee = CalleeVal.getAsRegion()) { 31051bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (isa<BlockDataRegion>(Callee)) 31151bd803fbdade51d674598ed45da3d54190a656cJohn McCall RegionsToInvalidate.push_back(Callee); 31251bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 31351bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 31451bd803fbdade51d674598ed45da3d54190a656cJohn McCall 31551bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Indexes of arguments whose values will be preserved by the call. 31651bd803fbdade51d674598ed45da3d54190a656cJohn McCall llvm::SmallSet<unsigned, 1> PreserveArgs; 31751bd803fbdade51d674598ed45da3d54190a656cJohn McCall findPtrToConstParams(PreserveArgs, Call); 31851bd803fbdade51d674598ed45da3d54190a656cJohn McCall 31951bd803fbdade51d674598ed45da3d54190a656cJohn McCall for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) { 32051bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (PreserveArgs.count(idx)) 32151bd803fbdade51d674598ed45da3d54190a656cJohn McCall continue; 32251bd803fbdade51d674598ed45da3d54190a656cJohn McCall 32351bd803fbdade51d674598ed45da3d54190a656cJohn McCall SVal V = Call.getArgSVal(idx); 32451bd803fbdade51d674598ed45da3d54190a656cJohn McCall 32551bd803fbdade51d674598ed45da3d54190a656cJohn McCall // If we are passing a location wrapped as an integer, unwrap it and 32651bd803fbdade51d674598ed45da3d54190a656cJohn McCall // invalidate the values referred by the location. 32751bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 32851bd803fbdade51d674598ed45da3d54190a656cJohn McCall V = Wrapped->getLoc(); 32951bd803fbdade51d674598ed45da3d54190a656cJohn McCall else if (!isa<Loc>(V)) 33051bd803fbdade51d674598ed45da3d54190a656cJohn McCall continue; 33151bd803fbdade51d674598ed45da3d54190a656cJohn McCall 33251bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const MemRegion *R = V.getAsRegion()) { 33351bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Invalidate the value of the variable passed by reference. 33451bd803fbdade51d674598ed45da3d54190a656cJohn McCall 33551bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Are we dealing with an ElementRegion? If the element type is 33651bd803fbdade51d674598ed45da3d54190a656cJohn McCall // a basic integer type (e.g., char, int) and the underlying region 33751bd803fbdade51d674598ed45da3d54190a656cJohn McCall // is a variable region then strip off the ElementRegion. 33851bd803fbdade51d674598ed45da3d54190a656cJohn McCall // FIXME: We really need to think about this for the general case 33951bd803fbdade51d674598ed45da3d54190a656cJohn McCall // as sometimes we are reasoning about arrays and other times 34051bd803fbdade51d674598ed45da3d54190a656cJohn McCall // about (char*), etc., is just a form of passing raw bytes. 34151bd803fbdade51d674598ed45da3d54190a656cJohn McCall // e.g., void *p = alloca(); foo((char*)p); 34251bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 34351bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Checking for 'integral type' is probably too promiscuous, but 34451bd803fbdade51d674598ed45da3d54190a656cJohn McCall // we'll leave it in for now until we have a systematic way of 34551bd803fbdade51d674598ed45da3d54190a656cJohn McCall // handling all of these cases. Eventually we need to come up 34651bd803fbdade51d674598ed45da3d54190a656cJohn McCall // with an interface to StoreManager so that this logic can be 34751bd803fbdade51d674598ed45da3d54190a656cJohn McCall // appropriately delegated to the respective StoreManagers while 34851bd803fbdade51d674598ed45da3d54190a656cJohn McCall // still allowing us to do checker-specific logic (e.g., 34951bd803fbdade51d674598ed45da3d54190a656cJohn McCall // invalidating reference counts), probably via callbacks. 35051bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (ER->getElementType()->isIntegralOrEnumerationType()) { 35151bd803fbdade51d674598ed45da3d54190a656cJohn McCall const MemRegion *superReg = ER->getSuperRegion(); 352a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 35351bd803fbdade51d674598ed45da3d54190a656cJohn McCall isa<ObjCIvarRegion>(superReg)) 35451bd803fbdade51d674598ed45da3d54190a656cJohn McCall R = cast<TypedRegion>(superReg); 355a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall } 35651bd803fbdade51d674598ed45da3d54190a656cJohn McCall // FIXME: What about layers of ElementRegions? 35751bd803fbdade51d674598ed45da3d54190a656cJohn McCall } 358a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall 35951bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Mark this region for invalidation. We batch invalidate regions 36051bd803fbdade51d674598ed45da3d54190a656cJohn McCall // below for efficiency. 361a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall RegionsToInvalidate.push_back(R); 36251bd803fbdade51d674598ed45da3d54190a656cJohn McCall } else { 36351bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Nuke all other arguments passed by reference. 364a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // FIXME: is this necessary or correct? This handles the non-Region 36549a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall // cases. Is it ever valid to store to these? 36649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall State = State->unbindLoc(cast<Loc>(V)); 36749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall } 36849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall } 36951bd803fbdade51d674598ed45da3d54190a656cJohn McCall 37051bd803fbdade51d674598ed45da3d54190a656cJohn McCall // Invalidate designated regions using the batch invalidation API. 371833ca991c1bfc967f0995974ca86f66ba1f666b5John McCall 372833ca991c1bfc967f0995974ca86f66ba1f666b5John McCall // FIXME: We can have collisions on the conjured symbol if the 373833ca991c1bfc967f0995974ca86f66ba1f666b5John McCall // expression *I also creates conjured symbols. We probably want 374833ca991c1bfc967f0995974ca86f66ba1f666b5John McCall // to identify conjured symbols by an expression pair: the enclosing 375833ca991c1bfc967f0995974ca86f66ba1f666b5John McCall // expression (the context) and the expression itself. This should 376a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall // disambiguate conjured symbols. 37751bd803fbdade51d674598ed45da3d54190a656cJohn McCall unsigned Count = currentBuilderContext->getCurrentBlockCount(); 37851bd803fbdade51d674598ed45da3d54190a656cJohn McCall StoreManager::InvalidatedSymbols IS; 379a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall 38051bd803fbdade51d674598ed45da3d54190a656cJohn McCall // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 38151bd803fbdade51d674598ed45da3d54190a656cJohn McCall // global variables. 382a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall return State->invalidateRegions(RegionsToInvalidate, 38351bd803fbdade51d674598ed45da3d54190a656cJohn McCall Call.getOriginExpr(), Count, LC, 38451bd803fbdade51d674598ed45da3d54190a656cJohn McCall &IS, &Call); 38554e14c4db764c0636160d26c5bbf491637c83a76John McCall 38654e14c4db764c0636160d26c5bbf491637c83a76John McCall} 38754e14c4db764c0636160d26c5bbf491637c83a76John McCall 38854e14c4db764c0636160d26c5bbf491637c83a76John McCallstatic ProgramStateRef getReplayWithoutInliningState(ExplodedNode *&N, 389a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall const CallExpr *CE) { 39051bd803fbdade51d674598ed45da3d54190a656cJohn McCall void *ReplayState = N->getState()->get<ReplayWithoutInlining>(); 39151bd803fbdade51d674598ed45da3d54190a656cJohn McCall if (!ReplayState) 39251bd803fbdade51d674598ed45da3d54190a656cJohn McCall return 0; 39351bd803fbdade51d674598ed45da3d54190a656cJohn McCall const CallExpr *ReplayCE = reinterpret_cast<const CallExpr*>(ReplayState); 39454e14c4db764c0636160d26c5bbf491637c83a76John McCall if (CE == ReplayCE) { 39554e14c4db764c0636160d26c5bbf491637c83a76John McCall return N->getState()->remove<ReplayWithoutInlining>(); 39654e14c4db764c0636160d26c5bbf491637c83a76John McCall } 39754e14c4db764c0636160d26c5bbf491637c83a76John McCall return 0; 39854e14c4db764c0636160d26c5bbf491637c83a76John McCall} 399a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall 400a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 4014dcf151a555ff51e4d643e8e6eeb80f121d11d1bChris Lattner ExplodedNodeSet &dst) { 4022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Perform the previsit of the CallExpr. 4032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ExplodedNodeSet dstPreVisit; 4042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 405b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 406b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner // Now evaluate the call itself. 407b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner class DefaultEval : public GraphExpander { 408b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner ExprEngine &Eng; 409b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner const CallExpr *CE; 410b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner public: 411b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 412b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner DefaultEval(ExprEngine &eng, const CallExpr *ce) 413b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner : Eng(eng), CE(ce) {} 414b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { 415b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 416b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner ProgramStateRef state = getReplayWithoutInliningState(Pred, CE); 417b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 418b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner // First, try to inline the call. 419b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner if (state == 0 && Eng.InlineCall(Dst, CE, Pred)) 420b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner return; 421b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 422b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner // First handle the return value. 423b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext); 424b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner 425b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner // Get the callee. 426b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner const Expr *Callee = CE->getCallee()->IgnoreParens(); 427b145b1e9de866e79fb386e4a074dc0b41853acf3Chris Lattner if (state == 0) 4280558df2da807646e65d4fa290f4e92114af1a746Chris Lattner state = Pred->getState(); 4290558df2da807646e65d4fa290f4e92114af1a746Chris Lattner SVal L = state->getSVal(Callee, Pred->getLocationContext()); 4300558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4310558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Figure out the result type. We do this dance to handle references. 4320558df2da807646e65d4fa290f4e92114af1a746Chris Lattner QualType ResultTy; 4330558df2da807646e65d4fa290f4e92114af1a746Chris Lattner if (const FunctionDecl *FD = L.getAsFunctionDecl()) 4340558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ResultTy = FD->getResultType(); 4350558df2da807646e65d4fa290f4e92114af1a746Chris Lattner else 4360558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ResultTy = CE->getType(); 4370558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4380558df2da807646e65d4fa290f4e92114af1a746Chris Lattner if (CE->isLValue()) 4390558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ResultTy = Eng.getContext().getPointerType(ResultTy); 4400558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4410558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Conjure a symbol value to use as the result. 4420558df2da807646e65d4fa290f4e92114af1a746Chris Lattner SValBuilder &SVB = Eng.getSValBuilder(); 4430558df2da807646e65d4fa290f4e92114af1a746Chris Lattner unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount(); 4440558df2da807646e65d4fa290f4e92114af1a746Chris Lattner const LocationContext *LCtx = Pred->getLocationContext(); 4450558df2da807646e65d4fa290f4e92114af1a746Chris Lattner SVal RetVal = SVB.getConjuredSymbolVal(0, CE, LCtx, ResultTy, Count); 4460558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4470558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Generate a new state with the return value set. 4480558df2da807646e65d4fa290f4e92114af1a746Chris Lattner state = state->BindExpr(CE, LCtx, RetVal); 4490558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4500558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Invalidate the arguments. 4510558df2da807646e65d4fa290f4e92114af1a746Chris Lattner state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx), 4520558df2da807646e65d4fa290f4e92114af1a746Chris Lattner LCtx); 4530558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4540558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // And make the result node. 4550558df2da807646e65d4fa290f4e92114af1a746Chris Lattner Bldr.generateNode(CE, Pred, state); 4560558df2da807646e65d4fa290f4e92114af1a746Chris Lattner } 4570558df2da807646e65d4fa290f4e92114af1a746Chris Lattner }; 4580558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4590558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Finally, evaluate the function call. We try each of the checkers 4600558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // to see if the can evaluate the function call. 4610558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ExplodedNodeSet dstCallEvaluated; 4620558df2da807646e65d4fa290f4e92114af1a746Chris Lattner DefaultEval defEval(*this, CE); 4630558df2da807646e65d4fa290f4e92114af1a746Chris Lattner getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, 4640558df2da807646e65d4fa290f4e92114af1a746Chris Lattner dstPreVisit, 4650558df2da807646e65d4fa290f4e92114af1a746Chris Lattner CE, *this, &defEval); 4660558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4670558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // Finally, perform the post-condition check of the CallExpr and store 4680558df2da807646e65d4fa290f4e92114af1a746Chris Lattner // the created nodes in 'Dst'. 4690558df2da807646e65d4fa290f4e92114af1a746Chris Lattner getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 4700558df2da807646e65d4fa290f4e92114af1a746Chris Lattner *this); 4710558df2da807646e65d4fa290f4e92114af1a746Chris Lattner} 4720558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4730558df2da807646e65d4fa290f4e92114af1a746Chris Lattnervoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 4740558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ExplodedNodeSet &Dst) { 4750558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4760558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ExplodedNodeSet dstPreVisit; 4770558df2da807646e65d4fa290f4e92114af1a746Chris Lattner getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); 4780558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4790558df2da807646e65d4fa290f4e92114af1a746Chris Lattner StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext); 4800558df2da807646e65d4fa290f4e92114af1a746Chris Lattner 4810558df2da807646e65d4fa290f4e92114af1a746Chris Lattner if (RS->getRetValue()) { 4820558df2da807646e65d4fa290f4e92114af1a746Chris Lattner for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), 4830558df2da807646e65d4fa290f4e92114af1a746Chris Lattner ei = dstPreVisit.end(); it != ei; ++it) { 4840558df2da807646e65d4fa290f4e92114af1a746Chris Lattner B.generateNode(RS, *it, (*it)->getState()); 4850558df2da807646e65d4fa290f4e92114af1a746Chris Lattner } 4860558df2da807646e65d4fa290f4e92114af1a746Chris Lattner } 4870558df2da807646e65d4fa290f4e92114af1a746Chris Lattner} 4880558df2da807646e65d4fa290f4e92114af1a746Chris Lattner