ExprEngineCallAndReturn.cpp revision 2e9264a17bacc7dc228d5f93caaeb98dfb23d508
1//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines ExprEngine's support for calls and returns. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 16#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 17#include "clang/AST/DeclCXX.h" 18 19using namespace clang; 20using namespace ento; 21 22namespace { 23 // Trait class for recording returned expression in the state. 24 struct ReturnExpr { 25 static int TagInt; 26 typedef const Stmt *data_type; 27 }; 28 int ReturnExpr::TagInt; 29} 30 31void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) { 32 const ProgramState *state = 33 B.getState()->enterStackFrame(B.getCalleeContext()); 34 B.generateNode(state); 35} 36 37void ExprEngine::processCallExit(CallExitNodeBuilder &B) { 38 const ProgramState *state = B.getState(); 39 const ExplodedNode *Pred = B.getPredecessor(); 40 const StackFrameContext *calleeCtx = 41 cast<StackFrameContext>(Pred->getLocationContext()); 42 const Stmt *CE = calleeCtx->getCallSite(); 43 44 // If the callee returns an expression, bind its value to CallExpr. 45 const Stmt *ReturnedExpr = state->get<ReturnExpr>(); 46 if (ReturnedExpr) { 47 SVal RetVal = state->getSVal(ReturnedExpr); 48 state = state->BindExpr(CE, RetVal); 49 // Clear the return expr GDM. 50 state = state->remove<ReturnExpr>(); 51 } 52 53 // Bind the constructed object value to CXXConstructExpr. 54 if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { 55 const CXXThisRegion *ThisR = 56 getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); 57 58 SVal ThisV = state->getSVal(ThisR); 59 // Always bind the region to the CXXConstructExpr. 60 state = state->BindExpr(CCE, ThisV); 61 } 62 63 B.generateNode(state); 64} 65 66const ProgramState * 67ExprEngine::invalidateArguments(const ProgramState *State, 68 const CallOrObjCMessage &Call, 69 const LocationContext *LC) { 70 SmallVector<const MemRegion *, 8> RegionsToInvalidate; 71 72 if (Call.isObjCMessage()) { 73 // Invalidate all instance variables of the receiver of an ObjC message. 74 // FIXME: We should be able to do better with inter-procedural analysis. 75 if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion()) 76 RegionsToInvalidate.push_back(MR); 77 78 } else if (Call.isCXXCall()) { 79 // Invalidate all instance variables for the callee of a C++ method call. 80 // FIXME: We should be able to do better with inter-procedural analysis. 81 // FIXME: We can probably do better for const versus non-const methods. 82 if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion()) 83 RegionsToInvalidate.push_back(Callee); 84 85 } else if (Call.isFunctionCall()) { 86 // Block calls invalidate all captured-by-reference values. 87 if (const MemRegion *Callee = Call.getFunctionCallee().getAsRegion()) { 88 if (isa<BlockDataRegion>(Callee)) 89 RegionsToInvalidate.push_back(Callee); 90 } 91 } 92 93 for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) { 94 SVal V = Call.getArgSVal(idx); 95 96 // If we are passing a location wrapped as an integer, unwrap it and 97 // invalidate the values referred by the location. 98 if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 99 V = Wrapped->getLoc(); 100 else if (!isa<Loc>(V)) 101 continue; 102 103 if (const MemRegion *R = V.getAsRegion()) { 104 // Invalidate the value of the variable passed by reference. 105 106 // Are we dealing with an ElementRegion? If the element type is 107 // a basic integer type (e.g., char, int) and the underying region 108 // is a variable region then strip off the ElementRegion. 109 // FIXME: We really need to think about this for the general case 110 // as sometimes we are reasoning about arrays and other times 111 // about (char*), etc., is just a form of passing raw bytes. 112 // e.g., void *p = alloca(); foo((char*)p); 113 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 114 // Checking for 'integral type' is probably too promiscuous, but 115 // we'll leave it in for now until we have a systematic way of 116 // handling all of these cases. Eventually we need to come up 117 // with an interface to StoreManager so that this logic can be 118 // approriately delegated to the respective StoreManagers while 119 // still allowing us to do checker-specific logic (e.g., 120 // invalidating reference counts), probably via callbacks. 121 if (ER->getElementType()->isIntegralOrEnumerationType()) { 122 const MemRegion *superReg = ER->getSuperRegion(); 123 if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 124 isa<ObjCIvarRegion>(superReg)) 125 R = cast<TypedRegion>(superReg); 126 } 127 // FIXME: What about layers of ElementRegions? 128 } 129 130 // Mark this region for invalidation. We batch invalidate regions 131 // below for efficiency. 132 RegionsToInvalidate.push_back(R); 133 } else { 134 // Nuke all other arguments passed by reference. 135 // FIXME: is this necessary or correct? This handles the non-Region 136 // cases. Is it ever valid to store to these? 137 State = State->unbindLoc(cast<Loc>(V)); 138 } 139 } 140 141 // Invalidate designated regions using the batch invalidation API. 142 143 // FIXME: We can have collisions on the conjured symbol if the 144 // expression *I also creates conjured symbols. We probably want 145 // to identify conjured symbols by an expression pair: the enclosing 146 // expression (the context) and the expression itself. This should 147 // disambiguate conjured symbols. 148 unsigned Count = currentBuilderContext->getCurrentBlockCount(); 149 StoreManager::InvalidatedSymbols IS; 150 151 // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 152 // global variables. 153 return State->invalidateRegions(RegionsToInvalidate, 154 Call.getOriginExpr(), Count, 155 &IS, doesInvalidateGlobals(Call)); 156 157} 158 159void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 160 ExplodedNodeSet &dst) { 161 // Perform the previsit of the CallExpr. 162 ExplodedNodeSet dstPreVisit; 163 getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this); 164 165 // Now evaluate the call itself. 166 class DefaultEval : public GraphExpander { 167 ExprEngine &Eng; 168 const CallExpr *CE; 169 public: 170 171 DefaultEval(ExprEngine &eng, const CallExpr *ce) 172 : Eng(eng), CE(ce) {} 173 virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { 174 // Should we inline the call? 175 if (Eng.getAnalysisManager().shouldInlineCall() && 176 Eng.InlineCall(Dst, CE, Pred)) { 177 return; 178 } 179 180 // First handle the return value. 181 StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext); 182 183 // Get the callee. 184 const Expr *Callee = CE->getCallee()->IgnoreParens(); 185 const ProgramState *state = Pred->getState(); 186 SVal L = state->getSVal(Callee); 187 188 // Figure out the result type. We do this dance to handle references. 189 QualType ResultTy; 190 if (const FunctionDecl *FD = L.getAsFunctionDecl()) 191 ResultTy = FD->getResultType(); 192 else 193 ResultTy = CE->getType(); 194 195 if (CE->isLValue()) 196 ResultTy = Eng.getContext().getPointerType(ResultTy); 197 198 // Conjure a symbol value to use as the result. 199 SValBuilder &SVB = Eng.getSValBuilder(); 200 unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount(); 201 SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count); 202 203 // Generate a new state with the return value set. 204 state = state->BindExpr(CE, RetVal); 205 206 // Invalidate the arguments. 207 const LocationContext *LC = Pred->getLocationContext(); 208 state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC); 209 210 // And make the result node. 211 Bldr.generateNode(CE, Pred, state); 212 } 213 }; 214 215 // Finally, evaluate the function call. We try each of the checkers 216 // to see if the can evaluate the function call. 217 ExplodedNodeSet dstCallEvaluated; 218 DefaultEval defEval(*this, CE); 219 getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, 220 dstPreVisit, 221 CE, *this, &defEval); 222 223 // Finally, perform the post-condition check of the CallExpr and store 224 // the created nodes in 'Dst'. 225 getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, 226 *this); 227} 228 229void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, 230 ExplodedNodeSet &Dst) { 231 ExplodedNodeSet Src; 232 { 233 StmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext); 234 if (const Expr *RetE = RS->getRetValue()) { 235 // Record the returned expression in the state. It will be used in 236 // processCallExit to bind the return value to the call expr. 237 { 238 static SimpleProgramPointTag tag("ExprEngine: ReturnStmt"); 239 const ProgramState *state = Pred->getState(); 240 state = state->set<ReturnExpr>(RetE); 241 Pred = Bldr.generateNode(RetE, Pred, state, false, &tag); 242 } 243 // We may get a NULL Pred because we generated a cached node. 244 if (Pred) { 245 Bldr.takeNodes(Pred); 246 ExplodedNodeSet Tmp; 247 Visit(RetE, Pred, Tmp); 248 Bldr.addNodes(Tmp); 249 } 250 } 251 } 252 253 getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this); 254} 255