ExprEngineCXX.cpp revision 10f77ad7fc5e5cf3f37a9b14ff5843468b8b84d2
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
24void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
25                                          ExplodedNode *Pred,
26                                          ExplodedNodeSet &Dst) {
27  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
28  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
29  ProgramStateRef state = Pred->getState();
30  const LocationContext *LCtx = Pred->getLocationContext();
31
32  // Bind the temporary object to the value of the expression. Then bind
33  // the expression to the location of the object.
34  SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
35
36  const MemRegion *R =
37    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
38
39  state = state->bindLoc(loc::MemRegionVal(R), V);
40  Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
41}
42
43void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
44                                             ExplodedNode *Pred,
45                                             ExplodedNodeSet &Dst) {
46  VisitCXXConstructExpr(expr, 0, Pred, Dst);
47}
48
49void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
50                                       const MemRegion *Dest,
51                                       ExplodedNode *Pred,
52                                       ExplodedNodeSet &destNodes) {
53
54#if 0
55  const CXXConstructorDecl *CD = E->getConstructor();
56  assert(CD);
57#endif
58
59#if 0
60  if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
61    // FIXME: invalidate the object.
62    return;
63#endif
64
65#if 0
66  // Is the constructor elidable?
67  if (E->isElidable()) {
68    destNodes.Add(Pred);
69    return;
70  }
71#endif
72
73  // Perform the previsit of the constructor.
74  ExplodedNodeSet SrcNodes;
75  SrcNodes.Add(Pred);
76  ExplodedNodeSet TmpNodes;
77  getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this);
78
79  // Evaluate the constructor.  Currently we don't now allow checker-specific
80  // implementations of specific constructors (as we do with ordinary
81  // function calls.  We can re-evaluate this in the future.
82
83#if 0
84  // Inlining currently isn't fully implemented.
85
86  if (AMgr.shouldInlineCall()) {
87    if (!Dest)
88      Dest =
89        svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
90                                                  Pred->getLocationContext());
91
92    // The callee stack frame context used to create the 'this'
93    // parameter region.
94    const StackFrameContext *SFC =
95      AMgr.getStackFrame(CD, Pred->getLocationContext(),
96                         E, currentBuilderContext->getBlock(),
97                         currentStmtIdx);
98
99    // Create the 'this' region.
100    const CXXThisRegion *ThisR =
101      getCXXThisRegion(E->getConstructor()->getParent(), SFC);
102
103    CallEnter Loc(E, SFC, Pred->getLocationContext());
104
105    StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext);
106    for (ExplodedNodeSet::iterator NI = SrcNodes.begin(),
107                                   NE = SrcNodes.end(); NI != NE; ++NI) {
108      ProgramStateRef state = (*NI)->getState();
109      // Setup 'this' region, so that the ctor is evaluated on the object pointed
110      // by 'Dest'.
111      state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
112      Bldr.generateNode(Loc, *NI, state);
113    }
114  }
115#endif
116
117  // Default semantics: invalidate all regions passed as arguments.
118  ExplodedNodeSet destCall;
119  {
120    StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext);
121    for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end();
122         i != e; ++i)
123    {
124      ExplodedNode *Pred = *i;
125      const LocationContext *LC = Pred->getLocationContext();
126      ProgramStateRef state = Pred->getState();
127
128      state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
129      Bldr.generateNode(E, Pred, state);
130    }
131  }
132  // Do the post visit.
133  getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
134}
135
136void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
137                                      const MemRegion *Dest,
138                                      const Stmt *S,
139                                      ExplodedNode *Pred,
140                                      ExplodedNodeSet &Dst) {
141  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
142  if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
143    return;
144
145  // Create the context for 'this' region.
146  const StackFrameContext *SFC =
147    AnalysisDeclContexts.getContext(DD)->
148      getStackFrame(Pred->getLocationContext(), S,
149      currentBuilderContext->getBlock(), currentStmtIdx);
150
151  CallEnter PP(S, SFC, Pred->getLocationContext());
152  ProgramStateRef state = Pred->getState();
153  state = state->bindLoc(svalBuilder.getCXXThis(DD->getParent(), SFC),
154                         loc::MemRegionVal(Dest));
155  Bldr.generateNode(PP, Pred, state);
156}
157
158static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
159  // FIXME: Copied from ExprEngineCallAndReturn.cpp
160  QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType();
161  if (PointeeTy != QualType() && PointeeTy.isConstQualified() &&
162      !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) {
163    return true;
164  }
165  return false;
166}
167
168void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
169                                   ExplodedNodeSet &Dst) {
170  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
171
172  unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
173  const LocationContext *LCtx = Pred->getLocationContext();
174  DefinedOrUnknownSVal symVal =
175    svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
176  const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
177  QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
178  const ElementRegion *EleReg =
179    getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
180  ProgramStateRef State = Pred->getState();
181
182  if (CNE->isArray()) {
183    // FIXME: allocating an array requires simulating the constructors.
184    // For now, just return a symbolicated region.
185    State = State->BindExpr(CNE, Pred->getLocationContext(),
186                            loc::MemRegionVal(EleReg));
187    Bldr.generateNode(CNE, Pred, State);
188    return;
189  }
190
191  FunctionDecl *FD = CNE->getOperatorNew();
192  if (FD && FD->isReservedGlobalPlacementOperator()) {
193    // Non-array placement new should always return the placement location.
194    SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
195    State = State->BindExpr(CNE, LCtx, PlacementLoc);
196    // FIXME: Once we have proper support for CXXConstructExprs inside
197    // CXXNewExpr, we need to make sure that the constructed object is not
198    // immediately invalidated here. (The placement call should happen before
199    // the constructor call anyway.)
200  }
201
202  // Invalidate placement args.
203
204  // FIXME: This is largely copied from invalidateArguments, because
205  // CallOrObjCMessage is not general enough to handle new-expressions yet.
206  SmallVector<const MemRegion *, 4> RegionsToInvalidate;
207
208  unsigned Index = 0;
209  for (CXXNewExpr::const_arg_iterator I = CNE->placement_arg_begin(),
210                                      E = CNE->placement_arg_end();
211       I != E; ++I) {
212    // Pre-increment the argument index to skip over the implicit size arg.
213    ++Index;
214    if (FD && Index < FD->getNumParams())
215      if (isPointerToConst(FD->getParamDecl(Index)))
216        continue;
217
218    SVal V = State->getSVal(*I, LCtx);
219
220    // If we are passing a location wrapped as an integer, unwrap it and
221    // invalidate the values referred by the location.
222    if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
223      V = Wrapped->getLoc();
224    else if (!isa<Loc>(V))
225      continue;
226
227    if (const MemRegion *R = V.getAsRegion()) {
228      // Invalidate the value of the variable passed by reference.
229
230      // Are we dealing with an ElementRegion?  If the element type is
231      // a basic integer type (e.g., char, int) and the underlying region
232      // is a variable region then strip off the ElementRegion.
233      // FIXME: We really need to think about this for the general case
234      //   as sometimes we are reasoning about arrays and other times
235      //   about (char*), etc., is just a form of passing raw bytes.
236      //   e.g., void *p = alloca(); foo((char*)p);
237      if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
238        // Checking for 'integral type' is probably too promiscuous, but
239        // we'll leave it in for now until we have a systematic way of
240        // handling all of these cases.  Eventually we need to come up
241        // with an interface to StoreManager so that this logic can be
242        // appropriately delegated to the respective StoreManagers while
243        // still allowing us to do checker-specific logic (e.g.,
244        // invalidating reference counts), probably via callbacks.
245        if (ER->getElementType()->isIntegralOrEnumerationType()) {
246          const MemRegion *superReg = ER->getSuperRegion();
247          if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
248              isa<ObjCIvarRegion>(superReg))
249            R = cast<TypedRegion>(superReg);
250        }
251        // FIXME: What about layers of ElementRegions?
252      }
253
254      // Mark this region for invalidation.  We batch invalidate regions
255      // below for efficiency.
256      RegionsToInvalidate.push_back(R);
257    } else {
258      // Nuke all other arguments passed by reference.
259      // FIXME: is this necessary or correct? This handles the non-Region
260      //  cases.  Is it ever valid to store to these?
261      State = State->unbindLoc(cast<Loc>(V));
262    }
263  }
264
265  // Invalidate designated regions using the batch invalidation API.
266
267  // FIXME: We can have collisions on the conjured symbol if the
268  //  expression *I also creates conjured symbols.  We probably want
269  //  to identify conjured symbols by an expression pair: the enclosing
270  //  expression (the context) and the expression itself.  This should
271  //  disambiguate conjured symbols.
272  unsigned Count = currentBuilderContext->getCurrentBlockCount();
273
274  // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
275  //  global variables.
276  State = State->invalidateRegions(RegionsToInvalidate, CNE, Count, LCtx);
277  Bldr.generateNode(CNE, Pred, State);
278  return;
279
280  // FIXME: The below code is long-since dead. However, constructor handling
281  // in new-expressions is far from complete. See PR12014 for more details.
282#if 0
283  // Evaluate constructor arguments.
284  const FunctionProtoType *FnType = NULL;
285  const CXXConstructorDecl *CD = CNE->getConstructor();
286  if (CD)
287    FnType = CD->getType()->getAs<FunctionProtoType>();
288  ExplodedNodeSet argsEvaluated;
289  Bldr.takeNodes(Pred);
290  evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
291                FnType, Pred, argsEvaluated);
292  Bldr.addNodes(argsEvaluated);
293
294  // Initialize the object region and bind the 'new' expression.
295  for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
296                                 E = argsEvaluated.end(); I != E; ++I) {
297
298    ProgramStateRef state = (*I)->getState();
299
300    // Accumulate list of regions that are invalidated.
301    // FIXME: Eventually we should unify the logic for constructor
302    // processing in one place.
303    SmallVector<const MemRegion*, 10> regionsToInvalidate;
304    for (CXXNewExpr::const_arg_iterator
305          ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
306          ai != ae; ++ai)
307    {
308      SVal val = state->getSVal(*ai, (*I)->getLocationContext());
309      if (const MemRegion *region = val.getAsRegion())
310        regionsToInvalidate.push_back(region);
311    }
312
313    if (ObjTy->isRecordType()) {
314      regionsToInvalidate.push_back(EleReg);
315      // Invalidate the regions.
316      // TODO: Pass the call to new information as the last argument, to limit
317      // the globals which will get invalidated.
318      state = state->invalidateRegions(regionsToInvalidate,
319                                       CNE, blockCount, 0, 0);
320
321    } else {
322      // Invalidate the regions.
323      // TODO: Pass the call to new information as the last argument, to limit
324      // the globals which will get invalidated.
325      state = state->invalidateRegions(regionsToInvalidate,
326                                       CNE, blockCount, 0, 0);
327
328      if (CNE->hasInitializer()) {
329        SVal V = state->getSVal(*CNE->constructor_arg_begin(),
330                                (*I)->getLocationContext());
331        state = state->bindLoc(loc::MemRegionVal(EleReg), V);
332      } else {
333        // Explicitly set to undefined, because currently we retrieve symbolic
334        // value from symbolic region.
335        state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
336      }
337    }
338    state = state->BindExpr(CNE, (*I)->getLocationContext(),
339                            loc::MemRegionVal(EleReg));
340    Bldr.generateNode(CNE, *I, state);
341  }
342#endif
343}
344
345void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
346                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
347  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
348  ProgramStateRef state = Pred->getState();
349  Bldr.generateNode(CDE, Pred, state);
350}
351
352void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
353                                   ExplodedNode *Pred,
354                                   ExplodedNodeSet &Dst) {
355  const VarDecl *VD = CS->getExceptionDecl();
356  if (!VD) {
357    Dst.Add(Pred);
358    return;
359  }
360
361  const LocationContext *LCtx = Pred->getLocationContext();
362  SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
363                                 currentBuilderContext->getCurrentBlockCount());
364  ProgramStateRef state = Pred->getState();
365  state = state->bindLoc(state->getLValue(VD, LCtx), V);
366
367  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
368  Bldr.generateNode(CS, Pred, state);
369}
370
371void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
372                                    ExplodedNodeSet &Dst) {
373  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
374
375  // Get the this object region from StoreManager.
376  const LocationContext *LCtx = Pred->getLocationContext();
377  const MemRegion *R =
378    svalBuilder.getRegionManager().getCXXThisRegion(
379                                  getContext().getCanonicalType(TE->getType()),
380                                                    LCtx);
381
382  ProgramStateRef state = Pred->getState();
383  SVal V = state->getSVal(loc::MemRegionVal(R));
384  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
385}
386