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