ExprEngineCallAndReturn.cpp revision 500abad7edfcc2409b18dd616cdbc28a094926f5
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" 16294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/AST/DeclCXX.h" 17294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/Analysis/Support/SaveAndRestore.h" 18294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 19294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace clang; 20294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace ento; 21294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 22294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremeneknamespace { 23294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Trait class for recording returned expression in the state. 24294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek struct ReturnExpr { 25294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek static int TagInt; 26294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek typedef const Stmt *data_type; 27294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek }; 28294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek int ReturnExpr::TagInt; 29294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 30294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 31294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::processCallEnter(CallEnterNodeBuilder &B) { 32294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ProgramState *state = 33294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek B.getState()->enterStackFrame(B.getCalleeContext()); 34294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek B.generateNode(state); 35294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 36294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 37294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::processCallExit(CallExitNodeBuilder &B) { 38294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ProgramState *state = B.getState(); 39294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ExplodedNode *Pred = B.getPredecessor(); 40294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const StackFrameContext *calleeCtx = 41294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek cast<StackFrameContext>(Pred->getLocationContext()); 42294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Stmt *CE = calleeCtx->getCallSite(); 43294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 44294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // If the callee returns an expression, bind its value to CallExpr. 45294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Stmt *ReturnedExpr = state->get<ReturnExpr>(); 46294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (ReturnedExpr) { 47294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal RetVal = state->getSVal(ReturnedExpr); 48294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek state = state->BindExpr(CE, RetVal); 49294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Clear the return expr GDM. 50294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek state = state->remove<ReturnExpr>(); 51294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 52294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 53294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bind the constructed object value to CXXConstructExpr. 54294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 55294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const CXXThisRegion *ThisR = 56294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); 57294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 58294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal ThisV = state->getSVal(ThisR); 59294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Always bind the region to the CXXConstructExpr. 60294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek state = state->BindExpr(CCE, ThisV); 61294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 62294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 63294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek B.generateNode(state); 64294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 65294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 66294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 67294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &dst) { 68294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Perform the previsit of the CallExpr. 69294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstPreVisit; 70294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 71294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 72294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Now evaluate the call itself. 73294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek class DefaultEval : public GraphExpander { 74294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExprEngine &Eng; 75294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const CallExpr *CE; 76294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek public: 77294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 78294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefaultEval(ExprEngine &eng, const CallExpr *ce) 79294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek : Eng(eng), CE(ce) {} 80294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { 81294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Should we inline the call? 82294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (Eng.getAnalysisManager().shouldInlineCall() && 83294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Eng.InlineCall(Dst, CE, Pred)) { 84294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek return; 85294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 86500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 87500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // First handle the return value. 88294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek StmtNodeBuilder &Builder = Eng.getBuilder(); 89294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(&Builder && "StmtNodeBuilder must be defined."); 90500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 91500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Get the callee. 92294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Expr *Callee = CE->getCallee()->IgnoreParens(); 93294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ProgramState *state = Pred->getState(); 94294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal L = state->getSVal(Callee); 95500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 96500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Figure out the result type. We do this dance to handle references. 97500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose QualType ResultTy; 98500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose if (const FunctionDecl *FD = L.getAsFunctionDecl()) 99500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = FD->getResultType(); 100500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose else 101500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = CE->getType(); 102500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 103500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose if (CE->isLValue()) 104500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ResultTy = Eng.getContext().getPointerType(ResultTy); 105500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 106500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Conjure a symbol value to use as the result. 107500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SValBuilder &SVB = Eng.getSValBuilder(); 108500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose unsigned Count = Builder.getCurrentBlockCount(); 109500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count); 110500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 111500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Generate a new ExplodedNode with the return value set. 112500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose state = state->BindExpr(CE, RetVal); 113500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose Pred = Builder.generateNode(CE, state, Pred); 114500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 115500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Then handle everything else. 116500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose unsigned oldSize = Dst.size(); 117500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SaveOr OldHasGen(Builder.hasGeneratedNode); 118500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 119500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Dispatch to transfer function logic to handle the rest of the call. 120294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred); 121294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 122294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where no nodes where generated. Auto-generate that 123294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // contains the updated state if we aren't generating sinks. 124294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (!Builder.BuildSinks && Dst.size() == oldSize && 125294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek !Builder.hasGeneratedNode) 126294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Eng.MakeNode(Dst, CE, Pred, state); 127294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 128294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek }; 129294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 130294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, evaluate the function call. We try each of the checkers 131294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // to see if the can evaluate the function call. 132294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstCallEvaluated; 133294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefaultEval defEval(*this, CE); 134294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, 135294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek dstPreVisit, 136294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek CE, *this, &defEval); 137294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 138294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, perform the post-condition check of the CallExpr and store 139294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 140294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 141294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek *this); 142294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 143294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 144294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 145294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 146294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet Src; 147294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const Expr *RetE = RS->getRetValue()) { 148294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Record the returned expression in the state. It will be used in 149294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // processCallExit to bind the return value to the call expr. 150294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek { 151294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek static SimpleProgramPointTag tag("ExprEngine: ReturnStmt"); 152294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const ProgramState *state = Pred->getState(); 153294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek state = state->set<ReturnExpr>(RetE); 154294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Pred = Builder->generateNode(RetE, state, Pred, &tag); 155294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 156294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // We may get a NULL Pred because we generated a cached node. 157294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (Pred) 158294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Visit(RetE, Pred, Src); 159294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 160294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek else { 161294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Src.Add(Pred); 162294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 163294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 164294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet CheckedSet; 165294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this); 166294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 167294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); 168294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek I != E; ++I) { 169294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 170294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(Builder && "StmtNodeBuilder must be defined."); 171294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 172294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Pred = *I; 173294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek unsigned size = Dst.size(); 174294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 175294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SaveAndRestore<bool> OldSink(Builder->BuildSinks); 176294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SaveOr OldHasGen(Builder->hasGeneratedNode); 177294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 178294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getTF().evalReturn(Dst, *this, *Builder, RS, Pred); 179294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 180294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where no nodes where generated. 181294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (!Builder->BuildSinks && Dst.size() == size && 182294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek !Builder->hasGeneratedNode) 183294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek MakeNode(Dst, RS, Pred, Pred->getState()); 184294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 185294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 186