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