ExprEngineCallAndReturn.cpp revision 256ef642f8feef22fd53be7efa868e8e34752eed
1294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 2294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 3294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// The LLVM Compiler Infrastructure 4294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 5294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// This file is distributed under the University of Illinois Open Source 6294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// License. See LICENSE.TXT for details. 7294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 8294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//===----------------------------------------------------------------------===// 9294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 10294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// This file defines ExprEngine's support for calls and returns. 11294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 12294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//===----------------------------------------------------------------------===// 13294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 14294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 16e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 17256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek#include "clang/Analysis/Support/SaveAndRestore.h" 18294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/AST/DeclCXX.h" 19294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 20294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace clang; 21294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace ento; 22294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 233070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenekvoid ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { 243070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Get the entry block in the CFG of the callee. 253070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek const StackFrameContext *SFC = CE.getCalleeContext(); 263070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek const CFG *CalleeCFG = SFC->getCFG(); 273070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek const CFGBlock *Entry = &(CalleeCFG->getEntry()); 283070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek 293070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Validate the CFG. 303070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek assert(Entry->empty()); 313070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek assert(Entry->succ_size() == 1); 323070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek 333070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Get the solitary sucessor. 343070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek const CFGBlock *Succ = *(Entry->succ_begin()); 353070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek 363070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Construct an edge representing the starting location in the callee. 373070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek BlockEdge Loc(Entry, Succ, SFC); 383070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek 393070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Construct a new state which contains the mapping from actual to 403070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // formal arguments. 413070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek const ProgramState *state = Pred->getState()->enterStackFrame(SFC); 423070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek 433070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Construct a new node and add it to the worklist. 443070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek bool isNew; 453070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); 463070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek Node->addPredecessor(Pred, G); 473070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek if (isNew) 483070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek Engine.getWorkList()->enqueue(Node); 49294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 50294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 51256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenekstatic const ReturnStmt *getReturnStmt(const ExplodedNode *Node) { 52256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek while (Node) { 53256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const ProgramPoint &PP = Node->getLocation(); 54256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek // Skip any BlockEdges. 55256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) { 56256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek assert(Node->pred_size() == 1); 57256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek Node = *Node->pred_begin(); 58256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek continue; 59256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 60256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) { 61256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const Stmt *S = SP->getStmt(); 62256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek return dyn_cast<ReturnStmt>(S); 63256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 64256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek break; 65256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 66256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek return 0; 67256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek} 68256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 69894212e9510299abb203801e014fec76b7926a05Ted Kremenekvoid ExprEngine::processCallExit(ExplodedNode *Pred) { 70894212e9510299abb203801e014fec76b7926a05Ted Kremenek const ProgramState *state = Pred->getState(); 71294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const StackFrameContext *calleeCtx = 72894212e9510299abb203801e014fec76b7926a05Ted Kremenek Pred->getLocationContext()->getCurrentStackFrame(); 73256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const LocationContext *callerCtx = calleeCtx->getParent(); 74294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Stmt *CE = calleeCtx->getCallSite(); 75294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 76294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // If the callee returns an expression, bind its value to CallExpr. 77256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (const ReturnStmt *RS = getReturnStmt(Pred)) { 785eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 79256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek SVal V = state->getSVal(RS, LCtx); 80256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek state = state->BindExpr(CE, callerCtx, V); 81294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 82294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 83294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bind the constructed object value to CXXConstructExpr. 84294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 85294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const CXXThisRegion *ThisR = 86294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); 87294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 88294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal ThisV = state->getSVal(ThisR); 89294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Always bind the region to the CXXConstructExpr. 905eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV); 91294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 92294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 93256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek static SimpleProgramPointTag returnTag("ExprEngine : Call Return"); 94256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek PostStmt Loc(CE, callerCtx, &returnTag); 95894212e9510299abb203801e014fec76b7926a05Ted Kremenek bool isNew; 96894212e9510299abb203801e014fec76b7926a05Ted Kremenek ExplodedNode *N = G.getNode(Loc, state, false, &isNew); 97894212e9510299abb203801e014fec76b7926a05Ted Kremenek N->addPredecessor(Pred, G); 98894212e9510299abb203801e014fec76b7926a05Ted Kremenek if (!isNew) 99894212e9510299abb203801e014fec76b7926a05Ted Kremenek return; 100894212e9510299abb203801e014fec76b7926a05Ted Kremenek 101894212e9510299abb203801e014fec76b7926a05Ted Kremenek // Perform the post-condition check of the CallExpr. 102894212e9510299abb203801e014fec76b7926a05Ted Kremenek ExplodedNodeSet Dst; 103256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N); 104256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext, 105256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek &Ctx); 106256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); 107256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 108894212e9510299abb203801e014fec76b7926a05Ted Kremenek getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this); 109894212e9510299abb203801e014fec76b7926a05Ted Kremenek 110242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek // Enqueue the next element in the block. 111242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { 112242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek Engine.getWorkList()->enqueue(*I, 113242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek calleeCtx->getCallSiteBlock(), 114242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek calleeCtx->getIndex()+1); 115242384ddb0e0b65dd7e9e0ac0cf3c31cf98b06a6Ted Kremenek } 116294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 117294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 118256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenekbool ExprEngine::InlineCall(ExplodedNodeSet &Dst, 119256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const CallExpr *CE, 120256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek ExplodedNode *Pred) { 121256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const ProgramState *state = Pred->getState(); 122256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const Expr *Callee = CE->getCallee(); 123256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const FunctionDecl *FD = 124256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl(); 125256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (!FD || !FD->hasBody(FD)) 126256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek return false; 127256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 128256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek switch (CE->getStmtClass()) { 129256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek default: 130256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek // FIXME: Handle C++. 131256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek break; 132256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek case Stmt::CallExprClass: { 133256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek // Construct a new stack frame for the callee. 134256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD); 135256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const StackFrameContext *CallerSFC = 136256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek Pred->getLocationContext()->getCurrentStackFrame(); 137256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek const StackFrameContext *CalleeSFC = 138256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek CalleeADC->getStackFrame(CallerSFC, CE, 139256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek currentBuilderContext->getBlock(), 140256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek currentStmtIdx); 141256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 142256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext()); 143256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek bool isNew; 144256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek ExplodedNode *N = G.getNode(Loc, state, false, &isNew); 145256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek N->addPredecessor(Pred, G); 146256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (isNew) 147256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek Engine.getWorkList()->enqueue(N); 148256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek return true; 149256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 150256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 151256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek return false; 152256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek} 153256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 1542cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaksstatic bool isPointerToConst(const ParmVarDecl *ParamDecl) { 1552cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); 1562cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (PointeeTy != QualType() && PointeeTy.isConstQualified() && 1572cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { 1582cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks return true; 1592cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1602cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks return false; 1612cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks} 1622cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 1632cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks// Try to retrieve the function declaration and find the function parameter 1642cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks// types which are pointers/references to a non-pointer const. 1652cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks// We do not invalidate the corresponding argument regions. 1662cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaksstatic void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs, 1672cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks const CallOrObjCMessage &Call) { 1682cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks const Decl *CallDecl = Call.getDecl(); 1692cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (!CallDecl) 1702cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks return; 1712cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 1722cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) { 1732cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) { 1742cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (FDecl && Idx < FDecl->getNumParams()) { 1752cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (isPointerToConst(FDecl->getParamDecl(Idx))) 1762cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks PreserveArgs.insert(Idx); 1772cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1782cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1792cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks return; 1802cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1812cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 1822cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) { 1832cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks assert(MDecl->param_size() <= Call.getNumArgs()); 1842cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks unsigned Idx = 0; 1852cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks for (clang::ObjCMethodDecl::param_const_iterator 1862cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) { 1872cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (isPointerToConst(*I)) 1882cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks PreserveArgs.insert(Idx); 1892cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1902cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks return; 1912cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks } 1922cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks} 1932cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 194e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Roseconst ProgramState * 195e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy RoseExprEngine::invalidateArguments(const ProgramState *State, 196e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose const CallOrObjCMessage &Call, 197e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose const LocationContext *LC) { 198e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose SmallVector<const MemRegion *, 8> RegionsToInvalidate; 199e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 200e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (Call.isObjCMessage()) { 201e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate all instance variables of the receiver of an ObjC message. 202e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: We should be able to do better with inter-procedural analysis. 203e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion()) 204e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose RegionsToInvalidate.push_back(MR); 205e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 206e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } else if (Call.isCXXCall()) { 207e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate all instance variables for the callee of a C++ method call. 208e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: We should be able to do better with inter-procedural analysis. 209e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: We can probably do better for const versus non-const methods. 210e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion()) 211e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose RegionsToInvalidate.push_back(Callee); 212e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 213e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } else if (Call.isFunctionCall()) { 214e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Block calls invalidate all captured-by-reference values. 2152cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks SVal CalleeVal = Call.getFunctionCallee(); 2162cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (const MemRegion *Callee = CalleeVal.getAsRegion()) { 217e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (isa<BlockDataRegion>(Callee)) 218e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose RegionsToInvalidate.push_back(Callee); 219e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 220e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 221e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 2222cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks // Indexes of arguments whose values will be preserved by the call. 2232cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks llvm::SmallSet<unsigned, 1> PreserveArgs; 2242cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks findPtrToConstParams(PreserveArgs, Call); 2252cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 226e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) { 2272cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks if (PreserveArgs.count(idx)) 2282cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks continue; 2292cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks 230e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose SVal V = Call.getArgSVal(idx); 231e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 232e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // If we are passing a location wrapped as an integer, unwrap it and 233e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // invalidate the values referred by the location. 234e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 235e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose V = Wrapped->getLoc(); 236e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose else if (!isa<Loc>(V)) 237e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose continue; 238e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 239e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (const MemRegion *R = V.getAsRegion()) { 240e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate the value of the variable passed by reference. 241e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 242e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Are we dealing with an ElementRegion? If the element type is 2432cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks // a basic integer type (e.g., char, int) and the underlying region 244e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // is a variable region then strip off the ElementRegion. 245e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: We really need to think about this for the general case 246e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // as sometimes we are reasoning about arrays and other times 247e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // about (char*), etc., is just a form of passing raw bytes. 248e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // e.g., void *p = alloca(); foo((char*)p); 249e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 250e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Checking for 'integral type' is probably too promiscuous, but 251e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // we'll leave it in for now until we have a systematic way of 252e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // handling all of these cases. Eventually we need to come up 253e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // with an interface to StoreManager so that this logic can be 2542cbe791d3e9b26f30196c4852da75d9ad67b4ad9Anna Zaks // appropriately delegated to the respective StoreManagers while 255e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // still allowing us to do checker-specific logic (e.g., 256e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // invalidating reference counts), probably via callbacks. 257e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (ER->getElementType()->isIntegralOrEnumerationType()) { 258e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose const MemRegion *superReg = ER->getSuperRegion(); 259e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 260e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose isa<ObjCIvarRegion>(superReg)) 261e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose R = cast<TypedRegion>(superReg); 262e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 263e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: What about layers of ElementRegions? 264e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 265e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 266e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Mark this region for invalidation. We batch invalidate regions 267e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // below for efficiency. 268e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose RegionsToInvalidate.push_back(R); 269e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } else { 270e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Nuke all other arguments passed by reference. 271e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: is this necessary or correct? This handles the non-Region 272e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // cases. Is it ever valid to store to these? 273e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose State = State->unbindLoc(cast<Loc>(V)); 274e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 275e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose } 276e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 277e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate designated regions using the batch invalidation API. 278e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 279e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // FIXME: We can have collisions on the conjured symbol if the 280e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // expression *I also creates conjured symbols. We probably want 281e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // to identify conjured symbols by an expression pair: the enclosing 282e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // expression (the context) and the expression itself. This should 283e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // disambiguate conjured symbols. 284ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks unsigned Count = currentBuilderContext->getCurrentBlockCount(); 285e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose StoreManager::InvalidatedSymbols IS; 286e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 287e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 288e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // global variables. 289e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose return State->invalidateRegions(RegionsToInvalidate, 290e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose Call.getOriginExpr(), Count, 291eb31a76d1cdaaf8874c549dc6bd964ff270d3822Anna Zaks &IS, &Call); 292e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 293e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose} 294e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 295294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 296294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &dst) { 297294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Perform the previsit of the CallExpr. 298294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstPreVisit; 299294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 300294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 301294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Now evaluate the call itself. 302294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek class DefaultEval : public GraphExpander { 303294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExprEngine &Eng; 304294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const CallExpr *CE; 305294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek public: 306294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 307294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefaultEval(ExprEngine &eng, const CallExpr *ce) 308294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek : Eng(eng), CE(ce) {} 309294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { 310294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Should we inline the call? 311294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (Eng.getAnalysisManager().shouldInlineCall() && 312294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Eng.InlineCall(Dst, CE, Pred)) { 313294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek return; 314294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 315500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 316500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // First handle the return value. 317aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext); 318500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 319500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Get the callee. 320294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Expr *Callee = CE->getCallee()->IgnoreParens(); 321294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ProgramState *state = Pred->getState(); 3225eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal L = state->getSVal(Callee, Pred->getLocationContext()); 323500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 324500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Figure out the result type. We do this dance to handle references. 325500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose QualType ResultTy; 326500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose if (const FunctionDecl *FD = L.getAsFunctionDecl()) 327500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = FD->getResultType(); 328500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose else 329500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = CE->getType(); 330500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 331500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose if (CE->isLValue()) 332500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = Eng.getContext().getPointerType(ResultTy); 333500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 334500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Conjure a symbol value to use as the result. 335500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SValBuilder &SVB = Eng.getSValBuilder(); 336ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount(); 337500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count); 338500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 339e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Generate a new state with the return value set. 3405eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 3415eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, RetVal); 342e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 343e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate the arguments. 3445eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx), 3455eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek LCtx); 346500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 347fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose // And make the result node. 348ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks Bldr.generateNode(CE, Pred, state); 349294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 350294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek }; 351294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 352294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, evaluate the function call. We try each of the checkers 353294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // to see if the can evaluate the function call. 354294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstCallEvaluated; 355294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefaultEval defEval(*this, CE); 356294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, 357294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek dstPreVisit, 358294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek CE, *this, &defEval); 359294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 360294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, perform the post-condition check of the CallExpr and store 361294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 362294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 363294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek *this); 364294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 365294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 366294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 367294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 368256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 369256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek ExplodedNodeSet dstPreVisit; 370256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); 371256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 372256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext); 373256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek 374256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek if (RS->getRetValue()) { 375256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), 376256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek ei = dstPreVisit.end(); it != ei; ++it) { 377256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek B.generateNode(RS, *it, (*it)->getState()); 378294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 379294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 380256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek else { 381256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek B.takeNodes(dstPreVisit); 382256ef642f8feef22fd53be7efa868e8e34752eedTed Kremenek } 383294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 384