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