ExprEngineCXX.cpp revision 337e4dbc6859589b8878146a88bebf754e916702
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- 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 the C++ expression evaluation engine.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Core/CheckerManager.h"
15#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/StmtCXX.h"
20
21using namespace clang;
22using namespace ento;
23
24namespace {
25class CallExprWLItem {
26public:
27  CallExpr::const_arg_iterator I;
28  ExplodedNode *N;
29
30  CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
31    : I(i), N(n) {}
32};
33}
34
35void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
36                                 const FunctionProtoType *FnType,
37                                 ExplodedNode *Pred, ExplodedNodeSet &Dst,
38                                 bool FstArgAsLValue) {
39
40
41  SmallVector<CallExprWLItem, 20> WorkList;
42  WorkList.reserve(AE - AI);
43  WorkList.push_back(CallExprWLItem(AI, Pred));
44
45  while (!WorkList.empty()) {
46    CallExprWLItem Item = WorkList.back();
47    WorkList.pop_back();
48
49    if (Item.I == AE) {
50      Dst.insert(Item.N);
51      continue;
52    }
53
54    // Evaluate the argument.
55    ExplodedNodeSet Tmp;
56    if (FstArgAsLValue) {
57      FstArgAsLValue = false;
58    }
59
60    Visit(*Item.I, Item.N, Tmp);
61    ++(Item.I);
62    for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
63      WorkList.push_back(CallExprWLItem(Item.I, *NI));
64  }
65}
66
67void ExprEngine::evalCallee(const CallExpr *callExpr,
68                            const ExplodedNodeSet &src,
69                            ExplodedNodeSet &dest) {
70
71  const Expr *callee = 0;
72
73  switch (callExpr->getStmtClass()) {
74    case Stmt::CXXMemberCallExprClass: {
75      // Evaluate the implicit object argument that is the recipient of the
76      // call.
77      callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
78
79      // FIXME: handle member pointers.
80      if (!callee)
81        return;
82
83      break;
84    }
85    default: {
86      callee = callExpr->getCallee()->IgnoreParens();
87      break;
88    }
89  }
90
91  for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
92    Visit(callee, *i, dest);
93}
94
95const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
96                                                 const StackFrameContext *SFC) {
97  const Type *T = D->getTypeForDecl();
98  QualType PT = getContext().getPointerType(QualType(T, 0));
99  return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
100}
101
102const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
103                                            const StackFrameContext *frameCtx) {
104  return svalBuilder.getRegionManager().
105                    getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
106}
107
108void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
109                                          ExplodedNode *Pred,
110                                          ExplodedNodeSet &Dst) {
111  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
112  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
113  ProgramStateRef state = Pred->getState();
114  const LocationContext *LCtx = Pred->getLocationContext();
115
116  // Bind the temporary object to the value of the expression. Then bind
117  // the expression to the location of the object.
118  SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
119
120  const MemRegion *R =
121    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
122
123  state = state->bindLoc(loc::MemRegionVal(R), V);
124  Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
125}
126
127void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
128                                             ExplodedNode *Pred,
129                                             ExplodedNodeSet &Dst) {
130  VisitCXXConstructExpr(expr, 0, Pred, Dst);
131}
132
133void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
134                                       const MemRegion *Dest,
135                                       ExplodedNode *Pred,
136                                       ExplodedNodeSet &destNodes) {
137
138  const CXXConstructorDecl *CD = E->getConstructor();
139  assert(CD);
140
141#if 0
142  if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
143    // FIXME: invalidate the object.
144    return;
145#endif
146
147  // Evaluate other arguments.
148  ExplodedNodeSet argsEvaluated;
149  const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
150  evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
151
152#if 0
153  // Is the constructor elidable?
154  if (E->isElidable()) {
155    VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
156    // FIXME: this is here to force propagation if VisitAggExpr doesn't
157    if (destNodes.empty())
158      destNodes.Add(Pred);
159    return;
160  }
161#endif
162
163  // Perform the previsit of the constructor.
164  ExplodedNodeSet destPreVisit;
165  getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
166                                            *this);
167
168  // Evaluate the constructor.  Currently we don't now allow checker-specific
169  // implementations of specific constructors (as we do with ordinary
170  // function calls.  We can re-evaluate this in the future.
171
172#if 0
173  // Inlining currently isn't fully implemented.
174
175  if (AMgr.shouldInlineCall()) {
176    if (!Dest)
177      Dest =
178        svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
179                                                  Pred->getLocationContext());
180
181    // The callee stack frame context used to create the 'this'
182    // parameter region.
183    const StackFrameContext *SFC =
184      AMgr.getStackFrame(CD, Pred->getLocationContext(),
185                         E, currentBuilderContext->getBlock(),
186                         currentStmtIdx);
187
188    // Create the 'this' region.
189    const CXXThisRegion *ThisR =
190      getCXXThisRegion(E->getConstructor()->getParent(), SFC);
191
192    CallEnter Loc(E, SFC, Pred->getLocationContext());
193
194    StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
195    for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
196                                  NE = argsEvaluated.end(); NI != NE; ++NI) {
197      ProgramStateRef state = (*NI)->getState();
198      // Setup 'this' region, so that the ctor is evaluated on the object pointed
199      // by 'Dest'.
200      state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
201      Bldr.generateNode(Loc, *NI, state);
202    }
203  }
204#endif
205
206  // Default semantics: invalidate all regions passed as arguments.
207  ExplodedNodeSet destCall;
208  {
209    StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext);
210    for (ExplodedNodeSet::iterator
211        i = destPreVisit.begin(), e = destPreVisit.end();
212        i != e; ++i)
213    {
214      ExplodedNode *Pred = *i;
215      const LocationContext *LC = Pred->getLocationContext();
216      ProgramStateRef state = Pred->getState();
217
218      state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
219      Bldr.generateNode(E, Pred, state);
220    }
221  }
222  // Do the post visit.
223  getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
224}
225
226void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
227                                      const MemRegion *Dest,
228                                      const Stmt *S,
229                                      ExplodedNode *Pred,
230                                      ExplodedNodeSet &Dst) {
231  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
232  if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
233    return;
234
235  // Create the context for 'this' region.
236  const StackFrameContext *SFC =
237    AnalysisDeclContexts.getContext(DD)->
238      getStackFrame(Pred->getLocationContext(), S,
239      currentBuilderContext->getBlock(), currentStmtIdx);
240
241  const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
242
243  CallEnter PP(S, SFC, Pred->getLocationContext());
244
245  ProgramStateRef state = Pred->getState();
246  state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
247  Bldr.generateNode(PP, Pred, state);
248}
249
250void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
251                                   ExplodedNodeSet &Dst) {
252  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
253
254  unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
255  const LocationContext *LCtx = Pred->getLocationContext();
256  DefinedOrUnknownSVal symVal =
257    svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
258  const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
259  QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
260  const ElementRegion *EleReg =
261    getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
262
263  if (CNE->isArray()) {
264    // FIXME: allocating an array requires simulating the constructors.
265    // For now, just return a symbolicated region.
266    ProgramStateRef state = Pred->getState();
267    state = state->BindExpr(CNE, Pred->getLocationContext(),
268                            loc::MemRegionVal(EleReg));
269    Bldr.generateNode(CNE, Pred, state);
270    return;
271  }
272
273  // FIXME: Update for AST changes.
274#if 0
275  // Evaluate constructor arguments.
276  const FunctionProtoType *FnType = NULL;
277  const CXXConstructorDecl *CD = CNE->getConstructor();
278  if (CD)
279    FnType = CD->getType()->getAs<FunctionProtoType>();
280  ExplodedNodeSet argsEvaluated;
281  Bldr.takeNodes(Pred);
282  evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
283                FnType, Pred, argsEvaluated);
284  Bldr.addNodes(argsEvaluated);
285
286  // Initialize the object region and bind the 'new' expression.
287  for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
288                                 E = argsEvaluated.end(); I != E; ++I) {
289
290    ProgramStateRef state = (*I)->getState();
291
292    // Accumulate list of regions that are invalidated.
293    // FIXME: Eventually we should unify the logic for constructor
294    // processing in one place.
295    SmallVector<const MemRegion*, 10> regionsToInvalidate;
296    for (CXXNewExpr::const_arg_iterator
297          ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
298          ai != ae; ++ai)
299    {
300      SVal val = state->getSVal(*ai, (*I)->getLocationContext());
301      if (const MemRegion *region = val.getAsRegion())
302        regionsToInvalidate.push_back(region);
303    }
304
305    if (ObjTy->isRecordType()) {
306      regionsToInvalidate.push_back(EleReg);
307      // Invalidate the regions.
308      // TODO: Pass the call to new information as the last argument, to limit
309      // the globals which will get invalidated.
310      state = state->invalidateRegions(regionsToInvalidate,
311                                       CNE, blockCount, 0, 0);
312
313    } else {
314      // Invalidate the regions.
315      // TODO: Pass the call to new information as the last argument, to limit
316      // the globals which will get invalidated.
317      state = state->invalidateRegions(regionsToInvalidate,
318                                       CNE, blockCount, 0, 0);
319
320      if (CNE->hasInitializer()) {
321        SVal V = state->getSVal(*CNE->constructor_arg_begin(),
322                                (*I)->getLocationContext());
323        state = state->bindLoc(loc::MemRegionVal(EleReg), V);
324      } else {
325        // Explicitly set to undefined, because currently we retrieve symbolic
326        // value from symbolic region.
327        state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
328      }
329    }
330    state = state->BindExpr(CNE, (*I)->getLocationContext(),
331                            loc::MemRegionVal(EleReg));
332    Bldr.generateNode(CNE, *I, state);
333  }
334#endif
335}
336
337void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
338                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
339  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
340  ProgramStateRef state = Pred->getState();
341  Bldr.generateNode(CDE, Pred, state);
342}
343
344void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
345                                   ExplodedNode *Pred,
346                                   ExplodedNodeSet &Dst) {
347  const VarDecl *VD = CS->getExceptionDecl();
348  const LocationContext *LCtx = Pred->getLocationContext();
349  SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
350                                 currentBuilderContext->getCurrentBlockCount());
351  ProgramStateRef state = Pred->getState();
352  state = state->bindLoc(state->getLValue(VD, LCtx), V);
353
354  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
355  Bldr.generateNode(CS, Pred, state);
356}
357
358void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
359                                    ExplodedNodeSet &Dst) {
360  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
361
362  // Get the this object region from StoreManager.
363  const LocationContext *LCtx = Pred->getLocationContext();
364  const MemRegion *R =
365    svalBuilder.getRegionManager().getCXXThisRegion(
366                                  getContext().getCanonicalType(TE->getType()),
367                                                    LCtx);
368
369  ProgramStateRef state = Pred->getState();
370  SVal V = state->getSVal(loc::MemRegionVal(R));
371  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
372}
373