ExprEngineCallAndReturn.cpp revision 5eca482fe895ea57bc82410222e6426c09e63284
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    const LocationContext *LCtx = Pred->getLocationContext();
48    SVal RetVal = state->getSVal(ReturnedExpr, LCtx);
49    state = state->BindExpr(CE, LCtx, RetVal);
50    // Clear the return expr GDM.
51    state = state->remove<ReturnExpr>();
52  }
53
54  // Bind the constructed object value to CXXConstructExpr.
55  if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
56    const CXXThisRegion *ThisR =
57    getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
58
59    SVal ThisV = state->getSVal(ThisR);
60    // Always bind the region to the CXXConstructExpr.
61    state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
62  }
63
64  B.generateNode(state);
65}
66
67static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
68  QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType();
69  if (PointeeTy != QualType() && PointeeTy.isConstQualified() &&
70      !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) {
71    return true;
72  }
73  return false;
74}
75
76// Try to retrieve the function declaration and find the function parameter
77// types which are pointers/references to a non-pointer const.
78// We do not invalidate the corresponding argument regions.
79static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
80                       const CallOrObjCMessage &Call) {
81  const Decl *CallDecl = Call.getDecl();
82  if (!CallDecl)
83    return;
84
85  if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) {
86    for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) {
87      if (FDecl && Idx < FDecl->getNumParams()) {
88        if (isPointerToConst(FDecl->getParamDecl(Idx)))
89          PreserveArgs.insert(Idx);
90      }
91    }
92    return;
93  }
94
95  if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) {
96    assert(MDecl->param_size() <= Call.getNumArgs());
97    unsigned Idx = 0;
98    for (clang::ObjCMethodDecl::param_const_iterator
99         I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) {
100      if (isPointerToConst(*I))
101        PreserveArgs.insert(Idx);
102    }
103    return;
104  }
105}
106
107const ProgramState *
108ExprEngine::invalidateArguments(const ProgramState *State,
109                                const CallOrObjCMessage &Call,
110                                const LocationContext *LC) {
111  SmallVector<const MemRegion *, 8> RegionsToInvalidate;
112
113  if (Call.isObjCMessage()) {
114    // Invalidate all instance variables of the receiver of an ObjC message.
115    // FIXME: We should be able to do better with inter-procedural analysis.
116    if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion())
117      RegionsToInvalidate.push_back(MR);
118
119  } else if (Call.isCXXCall()) {
120    // Invalidate all instance variables for the callee of a C++ method call.
121    // FIXME: We should be able to do better with inter-procedural analysis.
122    // FIXME: We can probably do better for const versus non-const methods.
123    if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion())
124      RegionsToInvalidate.push_back(Callee);
125
126  } else if (Call.isFunctionCall()) {
127    // Block calls invalidate all captured-by-reference values.
128    SVal CalleeVal = Call.getFunctionCallee();
129    if (const MemRegion *Callee = CalleeVal.getAsRegion()) {
130      if (isa<BlockDataRegion>(Callee))
131        RegionsToInvalidate.push_back(Callee);
132    }
133  }
134
135  // Indexes of arguments whose values will be preserved by the call.
136  llvm::SmallSet<unsigned, 1> PreserveArgs;
137  findPtrToConstParams(PreserveArgs, Call);
138
139  for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) {
140    if (PreserveArgs.count(idx))
141      continue;
142
143    SVal V = Call.getArgSVal(idx);
144
145    // If we are passing a location wrapped as an integer, unwrap it and
146    // invalidate the values referred by the location.
147    if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
148      V = Wrapped->getLoc();
149    else if (!isa<Loc>(V))
150      continue;
151
152    if (const MemRegion *R = V.getAsRegion()) {
153      // Invalidate the value of the variable passed by reference.
154
155      // Are we dealing with an ElementRegion?  If the element type is
156      // a basic integer type (e.g., char, int) and the underlying region
157      // is a variable region then strip off the ElementRegion.
158      // FIXME: We really need to think about this for the general case
159      //   as sometimes we are reasoning about arrays and other times
160      //   about (char*), etc., is just a form of passing raw bytes.
161      //   e.g., void *p = alloca(); foo((char*)p);
162      if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
163        // Checking for 'integral type' is probably too promiscuous, but
164        // we'll leave it in for now until we have a systematic way of
165        // handling all of these cases.  Eventually we need to come up
166        // with an interface to StoreManager so that this logic can be
167        // appropriately delegated to the respective StoreManagers while
168        // still allowing us to do checker-specific logic (e.g.,
169        // invalidating reference counts), probably via callbacks.
170        if (ER->getElementType()->isIntegralOrEnumerationType()) {
171          const MemRegion *superReg = ER->getSuperRegion();
172          if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
173              isa<ObjCIvarRegion>(superReg))
174            R = cast<TypedRegion>(superReg);
175        }
176        // FIXME: What about layers of ElementRegions?
177      }
178
179      // Mark this region for invalidation.  We batch invalidate regions
180      // below for efficiency.
181      RegionsToInvalidate.push_back(R);
182    } else {
183      // Nuke all other arguments passed by reference.
184      // FIXME: is this necessary or correct? This handles the non-Region
185      //  cases.  Is it ever valid to store to these?
186      State = State->unbindLoc(cast<Loc>(V));
187    }
188  }
189
190  // Invalidate designated regions using the batch invalidation API.
191
192  // FIXME: We can have collisions on the conjured symbol if the
193  //  expression *I also creates conjured symbols.  We probably want
194  //  to identify conjured symbols by an expression pair: the enclosing
195  //  expression (the context) and the expression itself.  This should
196  //  disambiguate conjured symbols.
197  unsigned Count = currentBuilderContext->getCurrentBlockCount();
198  StoreManager::InvalidatedSymbols IS;
199
200  // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
201  //  global variables.
202  return State->invalidateRegions(RegionsToInvalidate,
203                                  Call.getOriginExpr(), Count,
204                                  &IS, &Call);
205
206}
207
208void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
209                               ExplodedNodeSet &dst) {
210  // Perform the previsit of the CallExpr.
211  ExplodedNodeSet dstPreVisit;
212  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
213
214  // Now evaluate the call itself.
215  class DefaultEval : public GraphExpander {
216    ExprEngine &Eng;
217    const CallExpr *CE;
218  public:
219
220    DefaultEval(ExprEngine &eng, const CallExpr *ce)
221    : Eng(eng), CE(ce) {}
222    virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
223      // Should we inline the call?
224      if (Eng.getAnalysisManager().shouldInlineCall() &&
225          Eng.InlineCall(Dst, CE, Pred)) {
226        return;
227      }
228
229      // First handle the return value.
230      StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext);
231
232      // Get the callee.
233      const Expr *Callee = CE->getCallee()->IgnoreParens();
234      const ProgramState *state = Pred->getState();
235      SVal L = state->getSVal(Callee, Pred->getLocationContext());
236
237      // Figure out the result type. We do this dance to handle references.
238      QualType ResultTy;
239      if (const FunctionDecl *FD = L.getAsFunctionDecl())
240        ResultTy = FD->getResultType();
241      else
242        ResultTy = CE->getType();
243
244      if (CE->isLValue())
245        ResultTy = Eng.getContext().getPointerType(ResultTy);
246
247      // Conjure a symbol value to use as the result.
248      SValBuilder &SVB = Eng.getSValBuilder();
249      unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount();
250      SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
251
252      // Generate a new state with the return value set.
253      const LocationContext *LCtx = Pred->getLocationContext();
254      state = state->BindExpr(CE, LCtx, RetVal);
255
256      // Invalidate the arguments.
257      state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx),
258                                      LCtx);
259
260      // And make the result node.
261      Bldr.generateNode(CE, Pred, state);
262    }
263  };
264
265  // Finally, evaluate the function call.  We try each of the checkers
266  // to see if the can evaluate the function call.
267  ExplodedNodeSet dstCallEvaluated;
268  DefaultEval defEval(*this, CE);
269  getCheckerManager().runCheckersForEvalCall(dstCallEvaluated,
270                                             dstPreVisit,
271                                             CE, *this, &defEval);
272
273  // Finally, perform the post-condition check of the CallExpr and store
274  // the created nodes in 'Dst'.
275  getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
276                                             *this);
277}
278
279void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
280                                 ExplodedNodeSet &Dst) {
281  ExplodedNodeSet Src;
282  {
283    StmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext);
284    if (const Expr *RetE = RS->getRetValue()) {
285      // Record the returned expression in the state. It will be used in
286      // processCallExit to bind the return value to the call expr.
287      {
288        static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
289        const ProgramState *state = Pred->getState();
290        state = state->set<ReturnExpr>(RetE);
291        Pred = Bldr.generateNode(RetE, Pred, state, false, &tag);
292      }
293      // We may get a NULL Pred because we generated a cached node.
294      if (Pred) {
295        Bldr.takeNodes(Pred);
296        ExplodedNodeSet Tmp;
297        Visit(RetE, Pred, Tmp);
298        Bldr.addNodes(Tmp);
299      }
300    }
301  }
302
303  getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
304}
305