ExprEngineCXX.cpp revision 075f6fbcb4d858c09e9b138f8dc10d8d3d43d935
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/Calls.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::VisitCXXConstructExpr(const CXXConstructExpr *CE,
44                                       ExplodedNode *Pred,
45                                       ExplodedNodeSet &destNodes) {
46  const LocationContext *LCtx = Pred->getLocationContext();
47  ProgramStateRef State = Pred->getState();
48
49  const MemRegion *Target = 0;
50
51  switch (CE->getConstructionKind()) {
52  case CXXConstructExpr::CK_Complete: {
53    // See if we're constructing an existing region by looking at the next
54    // element in the CFG.
55    const CFGBlock *B = currentBuilderContext->getBlock();
56    if (currentStmtIdx + 1 < B->size()) {
57      CFGElement Next = (*B)[currentStmtIdx+1];
58
59      // Is this a constructor for a local variable?
60      if (const CFGStmt *StmtElem = dyn_cast<CFGStmt>(&Next))
61        if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt()))
62          if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl()))
63            if (Var->getInit() == CE)
64              Target = State->getLValue(Var, LCtx).getAsRegion();
65
66      // FIXME: This will eventually need to handle new-expressions as well.
67    }
68
69    // If we couldn't find an existing region to construct into, we'll just
70    // generate a symbolic region, which is fine.
71
72    break;
73  }
74  case CXXConstructExpr::CK_NonVirtualBase:
75  case CXXConstructExpr::CK_VirtualBase:
76  case CXXConstructExpr::CK_Delegating: {
77    const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
78    Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
79                                              LCtx->getCurrentStackFrame());
80    SVal ThisVal = State->getSVal(ThisPtr);
81
82    if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
83      Target = ThisVal.getAsRegion();
84    } else {
85      // Cast to the base type.
86      QualType BaseTy = CE->getType();
87      SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
88      Target = cast<loc::MemRegionVal>(BaseVal).getRegion();
89    }
90    break;
91  }
92  }
93
94  CXXConstructorCall Call(CE, Target, State, LCtx);
95
96  ExplodedNodeSet DstPreVisit;
97  getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
98  ExplodedNodeSet DstPreCall;
99  getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
100                                            Call, *this);
101
102  ExplodedNodeSet DstInvalidated;
103  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
104  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
105       I != E; ++I)
106    defaultEvalCall(Bldr, *I, Call);
107
108  ExplodedNodeSet DstPostCall;
109  getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
110                                             Call, *this);
111  getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
112}
113
114void ExprEngine::VisitCXXDestructor(QualType ObjectType,
115                                    const MemRegion *Dest,
116                                    const Stmt *S,
117                                    ExplodedNode *Pred,
118                                    ExplodedNodeSet &Dst) {
119  const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
120  assert(RecordDecl && "Only CXXRecordDecls should have destructors");
121  const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
122
123  CXXDestructorCall Call(DtorDecl, S, Dest, Pred->getState(),
124                         Pred->getLocationContext());
125
126  ExplodedNodeSet DstPreCall;
127  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
128                                            Call, *this);
129
130  ExplodedNodeSet DstInvalidated;
131  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
132  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
133       I != E; ++I)
134    defaultEvalCall(Bldr, *I, Call);
135
136  ExplodedNodeSet DstPostCall;
137  getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
138                                             Call, *this);
139}
140
141void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
142                                   ExplodedNodeSet &Dst) {
143  // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
144  // Also, we need to decide how allocators actually work -- they're not
145  // really part of the CXXNewExpr because they happen BEFORE the
146  // CXXConstructExpr subexpression. See PR12014 for some discussion.
147  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
148
149  unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
150  const LocationContext *LCtx = Pred->getLocationContext();
151  DefinedOrUnknownSVal symVal =
152    svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
153  ProgramStateRef State = Pred->getState();
154
155  // Invalidate placement args.
156  CXXAllocatorCall Call(CNE, State, LCtx);
157  State = Call.invalidateRegions(blockCount);
158
159  if (CNE->isArray()) {
160    // FIXME: allocating an array requires simulating the constructors.
161    // For now, just return a symbolicated region.
162    const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
163    QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
164    const ElementRegion *EleReg =
165      getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
166    State = State->BindExpr(CNE, Pred->getLocationContext(),
167                            loc::MemRegionVal(EleReg));
168    Bldr.generateNode(CNE, Pred, State);
169    return;
170  }
171
172  // FIXME: Once we have proper support for CXXConstructExprs inside
173  // CXXNewExpr, we need to make sure that the constructed object is not
174  // immediately invalidated here. (The placement call should happen before
175  // the constructor call anyway.)
176  FunctionDecl *FD = CNE->getOperatorNew();
177  if (FD && FD->isReservedGlobalPlacementOperator()) {
178    // Non-array placement new should always return the placement location.
179    SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
180    State = State->BindExpr(CNE, LCtx, PlacementLoc);
181  } else {
182    State = State->BindExpr(CNE, LCtx, symVal);
183  }
184
185  // If the type is not a record, we won't have a CXXConstructExpr as an
186  // initializer. Copy the value over.
187  if (const Expr *Init = CNE->getInitializer()) {
188    if (!isa<CXXConstructExpr>(Init)) {
189      QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
190      (void)ObjTy;
191      assert(!ObjTy->isRecordType());
192      SVal Location = State->getSVal(CNE, LCtx);
193      if (isa<Loc>(Location))
194        State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
195    }
196  }
197
198  Bldr.generateNode(CNE, Pred, State);
199}
200
201void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
202                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
203  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
204  ProgramStateRef state = Pred->getState();
205  Bldr.generateNode(CDE, Pred, state);
206}
207
208void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
209                                   ExplodedNode *Pred,
210                                   ExplodedNodeSet &Dst) {
211  const VarDecl *VD = CS->getExceptionDecl();
212  if (!VD) {
213    Dst.Add(Pred);
214    return;
215  }
216
217  const LocationContext *LCtx = Pred->getLocationContext();
218  SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
219                                 currentBuilderContext->getCurrentBlockCount());
220  ProgramStateRef state = Pred->getState();
221  state = state->bindLoc(state->getLValue(VD, LCtx), V);
222
223  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
224  Bldr.generateNode(CS, Pred, state);
225}
226
227void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
228                                    ExplodedNodeSet &Dst) {
229  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
230
231  // Get the this object region from StoreManager.
232  const LocationContext *LCtx = Pred->getLocationContext();
233  const MemRegion *R =
234    svalBuilder.getRegionManager().getCXXThisRegion(
235                                  getContext().getCanonicalType(TE->getType()),
236                                                    LCtx);
237
238  ProgramStateRef state = Pred->getState();
239  SVal V = state->getSVal(loc::MemRegionVal(R));
240  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
241}
242