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