ExprEngineCallAndReturn.cpp revision 4a5f724538cbc275370c9504e8169ce92503256c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)//===----------------------------------------------------------------------===// 95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This file defines ExprEngine's support for calls and returns. 118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// 128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)//===----------------------------------------------------------------------===// 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclCXX.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallSet.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/SaveAndRestore.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the entry block in the CFG of the callee. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StackFrameContext *calleeCtx = CE.getCalleeContext(); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CFG *CalleeCFG = calleeCtx->getCFG(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CFGBlock *Entry = &(CalleeCFG->getEntry()); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the CFG. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Entry->empty()); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Entry->succ_size() == 1); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the solitary sucessor. 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const CFGBlock *Succ = *(Entry->succ_begin()); 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Construct an edge representing the starting location in the callee. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BlockEdge Loc(Entry, Succ, calleeCtx); 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct a new state which contains the mapping from actual to 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // formal arguments. 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const LocationContext *callerCtx = Pred->getLocationContext(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state = Pred->getState()->enterStackFrame(callerCtx, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calleeCtx); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Construct a new node and add it to the worklist. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool isNew; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Node->addPredecessor(Pred, G); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isNew) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Engine.getWorkList()->enqueue(Node); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ReturnStmt *getReturnStmt(const ExplodedNode *Node) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (Node) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProgramPoint &PP = Node->getLocation(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip any BlockEdges. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Node->pred_size() == 1); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Node = *Node->pred_begin(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *S = SP->getStmt(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dyn_cast<ReturnStmt>(S); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExprEngine::processCallExit(ExplodedNode *Pred) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state = Pred->getState(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StackFrameContext *calleeCtx = 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pred->getLocationContext()->getCurrentStackFrame(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *callerCtx = calleeCtx->getParent(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *CE = calleeCtx->getCallSite(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the callee returns an expression, bind its value to CallExpr. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const ReturnStmt *RS = getReturnStmt(Pred)) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *LCtx = Pred->getLocationContext(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = state->getSVal(RS, LCtx); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state = state->BindExpr(CE, callerCtx, V); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bind the constructed object value to CXXConstructExpr. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXThisRegion *ThisR = 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SVal ThisV = state->getSVal(ThisR); 928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Always bind the region to the CXXConstructExpr. 938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV); 948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) static SimpleProgramPointTag returnTag("ExprEngine : Call Return"); 978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) PostStmt Loc(CE, callerCtx, &returnTag); 988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool isNew; 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ExplodedNode *N = G.getNode(Loc, state, false, &isNew); 1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) N->addPredecessor(Pred, G); 1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!isNew) 1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Perform the post-condition check of the CallExpr. 1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ExplodedNodeSet Dst; 1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N); 1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext, 1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &Ctx); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* wasInlined */ true); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enqueue the next element in the block. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Engine.getWorkList()->enqueue(*I, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calleeCtx->getCallSiteBlock(), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calleeCtx->getIndex()+1); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned getNumberStackFrames(const LocationContext *LCtx) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned count = 0; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (LCtx) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isa<StackFrameContext>(LCtx)) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++count; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LCtx = LCtx->getParent(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return count; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determine if we should inline the call. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CFG *CalleeCFG = CalleeADC->getCFG(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getNumberStackFrames(Pred->getLocationContext()) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) == AMgr.InlineMaxStackDepth) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (FunctionSummaries->hasReachedMaxBlockCount(FD)) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For now, skip inlining variadic functions. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We also don't inline blocks. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool shouldInlineCallExpr(const CallExpr *CE, ExprEngine *E) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!E->getAnalysisManager().shouldInlineCall()) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType callee = CE->getCallee()->getType(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FunctionProtoType *FT = 0; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const PointerType *PT = callee->getAs<PointerType>()) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FT = dyn_cast<FunctionProtoType>(PT->getPointeeType()); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (const BlockPointerType *BT = callee->getAs<BlockPointerType>()) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: inline blocks. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FT = dyn_cast<FunctionProtoType>(BT->getPointeeType()); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) BT; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have no prototype, assume the function is okay. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FT) 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip inlining of variadic functions. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !FT->isVariadic(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallExpr *CE, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *Pred) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shouldInlineCallExpr(CE, this)) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state = Pred->getState(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *Callee = CE->getCallee(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FunctionDecl *FD = 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FD || !FD->hasBody(FD)) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (CE->getStmtClass()) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: Handle C++. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Stmt::CallExprClass: { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shouldInlineDecl(FD, Pred)) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct a new stack frame for the callee. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StackFrameContext *CallerSFC = 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pred->getLocationContext()->getCurrentStackFrame(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StackFrameContext *CalleeSFC = 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalleeADC->getStackFrame(CallerSFC, CE, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentBuilderContext->getBlock(), 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentStmtIdx); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext()); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isNew; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *N = G.getNode(Loc, state, false, &isNew); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) N->addPredecessor(Pred, G); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isNew) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Engine.getWorkList()->enqueue(N); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool isPointerToConst(const ParmVarDecl *ParamDecl) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PointeeTy != QualType() && PointeeTy.isConstQualified() && 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Try to retrieve the function declaration and find the function parameter 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// types which are pointers/references to a non-pointer const. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do not invalidate the corresponding argument regions. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallOrObjCMessage &Call) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Decl *CallDecl = Call.getDecl(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CallDecl) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IdentifierInfo *II = FDecl->getIdentifier(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // List the cases, where the region should be invalidated even if the 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // argument is const. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (II) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringRef FName = II->getName(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - 'int pthread_setspecific(ptheread_key k, const void *)' stores a 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // value into thread local storage. The value can later be retrieved with 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'void *ptheread_getspecific(pthread_key)'. So even thought the 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameter is 'const void *', the region escapes through the call. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - funopen - sets a buffer for future IO calls. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - ObjC functions that end with "NoCopy" can free memory, of the passed 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in buffer. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Many CF containers allow objects to escape through custom 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocators/deallocators upon container construction. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be deallocated by NSMapRemove. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FName == "pthread_setspecific" || 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FName == "funopen" || 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FName.endswith("NoCopy") || 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (FName.startswith("NS") && 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (FName.find("Insert") != StringRef::npos)) || 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Call.isCFCGAllowingEscape(FName)) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FDecl && Idx < FDecl->getNumParams()) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isPointerToConst(FDecl->getParamDecl(Idx))) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreserveArgs.insert(Idx); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(MDecl->param_size() <= Call.getNumArgs()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned Idx = 0; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (clang::ObjCMethodDecl::param_const_iterator 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isPointerToConst(*I)) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreserveArgs.insert(Idx); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProgramStateRef 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExprEngine::invalidateArguments(ProgramStateRef State, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallOrObjCMessage &Call, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *LC) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SmallVector<const MemRegion *, 8> RegionsToInvalidate; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Call.isObjCMessage()) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate all instance variables of the receiver of an ObjC message. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: We should be able to do better with inter-procedural analysis. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion()) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegionsToInvalidate.push_back(MR); 2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (Call.isCXXCall()) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate all instance variables for the callee of a C++ method call. 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // FIXME: We should be able to do better with inter-procedural analysis. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: We can probably do better for const versus non-const methods. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion()) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegionsToInvalidate.push_back(Callee); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (Call.isFunctionCall()) { 3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Block calls invalidate all captured-by-reference values. 3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SVal CalleeVal = Call.getFunctionCallee(); 3038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (const MemRegion *Callee = CalleeVal.getAsRegion()) { 3048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (isa<BlockDataRegion>(Callee)) 3058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) RegionsToInvalidate.push_back(Callee); 3068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 3078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 3088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Indexes of arguments whose values will be preserved by the call. 3108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) llvm::SmallSet<unsigned, 1> PreserveArgs; 3118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) findPtrToConstParams(PreserveArgs, Call); 3128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) { 3148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (PreserveArgs.count(idx)) 3158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 3168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = Call.getArgSVal(idx); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are passing a location wrapped as an integer, unwrap it and 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalidate the values referred by the location. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V = Wrapped->getLoc(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!isa<Loc>(V)) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const MemRegion *R = V.getAsRegion()) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate the value of the variable passed by reference. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are we dealing with an ElementRegion? If the element type is 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a basic integer type (e.g., char, int) and the underlying region 3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // is a variable region then strip off the ElementRegion. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: We really need to think about this for the general case 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as sometimes we are reasoning about arrays and other times 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about (char*), etc., is just a form of passing raw bytes. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // e.g., void *p = alloca(); foo((char*)p); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checking for 'integral type' is probably too promiscuous, but 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we'll leave it in for now until we have a systematic way of 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handling all of these cases. Eventually we need to come up 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with an interface to StoreManager so that this logic can be 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appropriately delegated to the respective StoreManagers while 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // still allowing us to do checker-specific logic (e.g., 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalidating reference counts), probably via callbacks. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ER->getElementType()->isIntegralOrEnumerationType()) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MemRegion *superReg = ER->getSuperRegion(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isa<ObjCIvarRegion>(superReg)) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R = cast<TypedRegion>(superReg); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // FIXME: What about layers of ElementRegions? 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark this region for invalidation. We batch invalidate regions 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // below for efficiency. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegionsToInvalidate.push_back(R); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nuke all other arguments passed by reference. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: is this necessary or correct? This handles the non-Region 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cases. Is it ever valid to store to these? 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State = State->unbindLoc(cast<Loc>(V)); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate designated regions using the batch invalidation API. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: We can have collisions on the conjured symbol if the 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expression *I also creates conjured symbols. We probably want 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to identify conjured symbols by an expression pair: the enclosing 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expression (the context) and the expression itself. This should 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // disambiguate conjured symbols. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned Count = currentBuilderContext->getCurrentBlockCount(); 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StoreManager::InvalidatedSymbols IS; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // global variables. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return State->invalidateRegions(RegionsToInvalidate, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Call.getOriginExpr(), Count, LC, 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &IS, &Call); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ProgramStateRef getReplayWithoutInliningState(ExplodedNode *&N, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallExpr *CE) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *ReplayState = N->getState()->get<ReplayWithoutInlining>(); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReplayState) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallExpr *ReplayCE = reinterpret_cast<const CallExpr*>(ReplayState); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CE == ReplayCE) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return N->getState()->remove<ReplayWithoutInlining>(); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &dst) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Perform the previsit of the CallExpr. 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExplodedNodeSet dstPreVisit; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now evaluate the call itself. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class DefaultEval : public GraphExpander { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallExpr *CE; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultEval(ExprEngine &eng, const CallExpr *ce) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Eng(eng), CE(ce) {} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state = getReplayWithoutInliningState(Pred, CE); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, try to inline the call. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == 0 && Eng.InlineCall(Dst, CE, Pred)) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First handle the return value. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the callee. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *Callee = CE->getCallee()->IgnoreParens(); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == 0) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state = Pred->getState(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal L = state->getSVal(Callee, Pred->getLocationContext()); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out the result type. We do this dance to handle references. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType ResultTy; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const FunctionDecl *FD = L.getAsFunctionDecl()) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultTy = FD->getResultType(); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultTy = CE->getType(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CE->isLValue()) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultTy = Eng.getContext().getPointerType(ResultTy); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Conjure a symbol value to use as the result. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SValBuilder &SVB = Eng.getSValBuilder(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *LCtx = Pred->getLocationContext(); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal RetVal = SVB.getConjuredSymbolVal(0, CE, LCtx, ResultTy, Count); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate a new state with the return value set. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state = state->BindExpr(CE, LCtx, RetVal); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate the arguments. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx), 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LCtx); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And make the result node. 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bldr.generateNode(CE, Pred, state); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, evaluate the function call. We try each of the checkers 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to see if the can evaluate the function call. 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet dstCallEvaluated; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultEval defEval(*this, CE); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dstPreVisit, 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CE, *this, &defEval); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, perform the post-condition check of the CallExpr and store 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the created nodes in 'Dst'. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *this); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet dstPreVisit; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RS->getRetValue()) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ei = dstPreVisit.end(); it != ei; ++it) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) B.generateNode(RS, *it, (*it)->getState()); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 482