blob: d0a0e32f74d120f0e18800c37cc54f36ab2e1213 [file] [log] [blame]
Ted Kremenek5f764312011-08-20 05:59:58 +00001//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
Zhongxing Xucb7464a2010-04-19 12:51:02 +00002//
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
Argyrios Kyrtzidiseb48bd12011-03-01 01:16:03 +000014#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000015#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
Jordan Rosef540c542012-07-26 21:39:41 +000017#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000018#include "clang/AST/DeclCXX.h"
Ted Kremenek337e4db2012-03-10 01:34:17 +000019#include "clang/AST/StmtCXX.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000020
21using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000022using namespace ento;
Zhongxing Xucb7464a2010-04-19 12:51:02 +000023
Ted Kremenekeea72a92011-07-28 23:07:36 +000024void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
25 ExplodedNode *Pred,
26 ExplodedNodeSet &Dst) {
Anna Zaksaa0aeb12011-10-24 21:19:59 +000027 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Ted Kremenek6a835dd2011-10-02 00:54:48 +000028 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
Ted Kremenek8bef8232012-01-26 21:29:00 +000029 ProgramStateRef state = Pred->getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +000030 const LocationContext *LCtx = Pred->getLocationContext();
Zhongxing Xucb7464a2010-04-19 12:51:02 +000031
Ted Kremenek6a835dd2011-10-02 00:54:48 +000032 // Bind the temporary object to the value of the expression. Then bind
33 // the expression to the location of the object.
Ted Kremenek5eca4822012-01-06 22:09:28 +000034 SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +000035
Ted Kremenek6a835dd2011-10-02 00:54:48 +000036 const MemRegion *R =
Ted Kremenek5eca4822012-01-06 22:09:28 +000037 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000038
Ted Kremenek6a835dd2011-10-02 00:54:48 +000039 state = state->bindLoc(loc::MemRegionVal(R), V);
Ted Kremenek5eca4822012-01-06 22:09:28 +000040 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
Zhongxing Xucb7464a2010-04-19 12:51:02 +000041}
42
Jordan Rose362a31c2012-07-02 19:28:12 +000043void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
Ted Kremenek5fe98722011-04-08 22:42:35 +000044 ExplodedNode *Pred,
45 ExplodedNodeSet &destNodes) {
Jordan Rose888c90a2012-07-26 20:04:13 +000046 const LocationContext *LCtx = Pred->getLocationContext();
Jordan Rose075f6fb2012-07-26 20:04:16 +000047 ProgramStateRef State = Pred->getState();
48
Jordan Rose888c90a2012-07-26 20:04:13 +000049 const MemRegion *Target = 0;
50
51 switch (CE->getConstructionKind()) {
52 case CXXConstructExpr::CK_Complete: {
Jordan Rose075f6fb2012-07-26 20:04:16 +000053 // 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?
Jordan Rosee460c462012-07-26 20:04:25 +000060 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()->IgnoreImplicit() == CE) {
64 QualType Ty = Var->getType();
65 if (const ArrayType *AT = getContext().getAsArrayType(Ty)) {
66 // FIXME: Handle arrays, which run the same constructor for
67 // every element. This workaround will just run the first
68 // constructor (which should still invalidate the entire array).
69 SVal Base = State->getLValue(Var, LCtx);
70 Target = State->getLValue(AT->getElementType(),
71 getSValBuilder().makeZeroArrayIndex(),
72 Base).getAsRegion();
73 } else {
74 Target = State->getLValue(Var, LCtx).getAsRegion();
75 }
76 }
77 }
78 }
79 }
80
Jordan Rose3a0a9e32012-07-26 20:04:21 +000081 // Is this a constructor for a member?
82 if (const CFGInitializer *InitElem = dyn_cast<CFGInitializer>(&Next)) {
83 const CXXCtorInitializer *Init = InitElem->getInitializer();
84 assert(Init->isAnyMemberInitializer());
85
86 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
87 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
88 LCtx->getCurrentStackFrame());
89 SVal ThisVal = State->getSVal(ThisPtr);
90
91 if (Init->isIndirectMemberInitializer()) {
92 SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal);
Jordan Rosee460c462012-07-26 20:04:25 +000093 Target = Field.getAsRegion();
Jordan Rose3a0a9e32012-07-26 20:04:21 +000094 } else {
95 SVal Field = State->getLValue(Init->getMember(), ThisVal);
Jordan Rosee460c462012-07-26 20:04:25 +000096 Target = Field.getAsRegion();
Jordan Rose3a0a9e32012-07-26 20:04:21 +000097 }
98 }
99
Jordan Rose075f6fb2012-07-26 20:04:16 +0000100 // FIXME: This will eventually need to handle new-expressions as well.
101 }
102
103 // If we couldn't find an existing region to construct into, we'll just
Jordan Rose888c90a2012-07-26 20:04:13 +0000104 // generate a symbolic region, which is fine.
Jordan Rose075f6fb2012-07-26 20:04:16 +0000105
Jordan Rose888c90a2012-07-26 20:04:13 +0000106 break;
107 }
108 case CXXConstructExpr::CK_NonVirtualBase:
109 case CXXConstructExpr::CK_VirtualBase:
110 case CXXConstructExpr::CK_Delegating: {
111 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
112 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
113 LCtx->getCurrentStackFrame());
Jordan Rose075f6fb2012-07-26 20:04:16 +0000114 SVal ThisVal = State->getSVal(ThisPtr);
Jordan Rose888c90a2012-07-26 20:04:13 +0000115
116 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
117 Target = ThisVal.getAsRegion();
118 } else {
119 // Cast to the base type.
120 QualType BaseTy = CE->getType();
121 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
Jordan Rosee460c462012-07-26 20:04:25 +0000122 Target = BaseVal.getAsRegion();
Jordan Rose888c90a2012-07-26 20:04:13 +0000123 }
124 break;
125 }
126 }
127
Jordan Rosed563d3f2012-07-30 20:22:09 +0000128 CallEventManager &CEMgr = getStateManager().getCallEventManager();
129 CallEventRef<CXXConstructorCall> Call =
130 CEMgr.getCXXConstructorCall(CE, Target, State, LCtx);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000131
Jordan Rose362a31c2012-07-02 19:28:12 +0000132 ExplodedNodeSet DstPreVisit;
133 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
Jordan Rose96479da2012-07-02 19:28:16 +0000134 ExplodedNodeSet DstPreCall;
135 getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
Jordan Rosed563d3f2012-07-30 20:22:09 +0000136 *Call, *this);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000137
Jordan Rose362a31c2012-07-02 19:28:12 +0000138 ExplodedNodeSet DstInvalidated;
Anna Zakse81ce252012-07-19 23:38:13 +0000139 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
Jordan Rose96479da2012-07-02 19:28:16 +0000140 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
Jordan Rose362a31c2012-07-02 19:28:12 +0000141 I != E; ++I)
Jordan Rosed563d3f2012-07-30 20:22:09 +0000142 defaultEvalCall(Bldr, *I, *Call);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000143
Jordan Rose96479da2012-07-02 19:28:16 +0000144 ExplodedNodeSet DstPostCall;
145 getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
Jordan Rosed563d3f2012-07-30 20:22:09 +0000146 *Call, *this);
Jordan Rose96479da2012-07-02 19:28:16 +0000147 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000148}
149
Jordan Rose888c90a2012-07-26 20:04:13 +0000150void ExprEngine::VisitCXXDestructor(QualType ObjectType,
151 const MemRegion *Dest,
152 const Stmt *S,
153 ExplodedNode *Pred,
154 ExplodedNodeSet &Dst) {
Jordan Rosed563d3f2012-07-30 20:22:09 +0000155 const LocationContext *LCtx = Pred->getLocationContext();
156 ProgramStateRef State = Pred->getState();
157
Jordan Rosee460c462012-07-26 20:04:25 +0000158 // FIXME: We need to run the same destructor on every element of the array.
159 // This workaround will just run the first destructor (which will still
160 // invalidate the entire array).
161 if (const ArrayType *AT = getContext().getAsArrayType(ObjectType)) {
162 ObjectType = AT->getElementType();
Jordan Rosed563d3f2012-07-30 20:22:09 +0000163 Dest = State->getLValue(ObjectType, getSValBuilder().makeZeroArrayIndex(),
164 loc::MemRegionVal(Dest)).getAsRegion();
Jordan Rosee460c462012-07-26 20:04:25 +0000165 }
166
Jordan Rose888c90a2012-07-26 20:04:13 +0000167 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
168 assert(RecordDecl && "Only CXXRecordDecls should have destructors");
169 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
170
Jordan Rosed563d3f2012-07-30 20:22:09 +0000171 CallEventManager &CEMgr = getStateManager().getCallEventManager();
172 CallEventRef<CXXDestructorCall> Call =
173 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, State, LCtx);
Ted Kremenekb1b5daf2011-10-23 02:31:52 +0000174
Jordan Rose8d276d32012-07-10 22:07:47 +0000175 ExplodedNodeSet DstPreCall;
176 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
Jordan Rosed563d3f2012-07-30 20:22:09 +0000177 *Call, *this);
Zhongxing Xub13453b2010-11-20 06:53:12 +0000178
Jordan Rose8d276d32012-07-10 22:07:47 +0000179 ExplodedNodeSet DstInvalidated;
Anna Zakse81ce252012-07-19 23:38:13 +0000180 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
Jordan Rose8d276d32012-07-10 22:07:47 +0000181 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
182 I != E; ++I)
Jordan Rosed563d3f2012-07-30 20:22:09 +0000183 defaultEvalCall(Bldr, *I, *Call);
Jordan Rose8d276d32012-07-10 22:07:47 +0000184
185 ExplodedNodeSet DstPostCall;
186 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
Jordan Rosed563d3f2012-07-30 20:22:09 +0000187 *Call, *this);
Zhongxing Xub13453b2010-11-20 06:53:12 +0000188}
189
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000190void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000191 ExplodedNodeSet &Dst) {
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000192 // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
193 // Also, we need to decide how allocators actually work -- they're not
194 // really part of the CXXNewExpr because they happen BEFORE the
195 // CXXConstructExpr subexpression. See PR12014 for some discussion.
Anna Zaksaa0aeb12011-10-24 21:19:59 +0000196 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Ted Kremenek41c5f492011-03-31 04:04:48 +0000197
Anna Zaksebae6d02011-10-24 18:26:19 +0000198 unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
Ted Kremenek3133f792012-02-17 23:13:45 +0000199 const LocationContext *LCtx = Pred->getLocationContext();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000200 DefinedOrUnknownSVal symVal =
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000201 svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000202 ProgramStateRef State = Pred->getState();
Ted Kremenek41c5f492011-03-31 04:04:48 +0000203
Jordan Rosed563d3f2012-07-30 20:22:09 +0000204 CallEventManager &CEMgr = getStateManager().getCallEventManager();
205 CallEventRef<CXXAllocatorCall> Call =
206 CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
207
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000208 // Invalidate placement args.
Jordan Rosed563d3f2012-07-30 20:22:09 +0000209 // FIXME: Once we figure out how we want allocators to work,
210 // we should be using the usual pre-/(default-)eval-/post-call checks here.
211 State = Call->invalidateRegions(blockCount);
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000212
Ted Kremenek41c5f492011-03-31 04:04:48 +0000213 if (CNE->isArray()) {
214 // FIXME: allocating an array requires simulating the constructors.
215 // For now, just return a symbolicated region.
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000216 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
217 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
218 const ElementRegion *EleReg =
219 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000220 State = State->BindExpr(CNE, Pred->getLocationContext(),
Ted Kremenek5eca4822012-01-06 22:09:28 +0000221 loc::MemRegionVal(EleReg));
Jordan Rosee38c1c22012-06-20 01:32:01 +0000222 Bldr.generateNode(CNE, Pred, State);
Ted Kremenek41c5f492011-03-31 04:04:48 +0000223 return;
224 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000225
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000226 // FIXME: Once we have proper support for CXXConstructExprs inside
227 // CXXNewExpr, we need to make sure that the constructed object is not
228 // immediately invalidated here. (The placement call should happen before
229 // the constructor call anyway.)
Jordan Rosee38c1c22012-06-20 01:32:01 +0000230 FunctionDecl *FD = CNE->getOperatorNew();
231 if (FD && FD->isReservedGlobalPlacementOperator()) {
232 // Non-array placement new should always return the placement location.
233 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
234 State = State->BindExpr(CNE, LCtx, PlacementLoc);
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000235 } else {
236 State = State->BindExpr(CNE, LCtx, symVal);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000237 }
238
Jordan Rose89e5aaf2012-07-16 23:38:09 +0000239 // If the type is not a record, we won't have a CXXConstructExpr as an
240 // initializer. Copy the value over.
241 if (const Expr *Init = CNE->getInitializer()) {
242 if (!isa<CXXConstructExpr>(Init)) {
243 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
244 (void)ObjTy;
245 assert(!ObjTy->isRecordType());
246 SVal Location = State->getSVal(CNE, LCtx);
247 if (isa<Loc>(Location))
248 State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
249 }
250 }
251
Jordan Rosee38c1c22012-06-20 01:32:01 +0000252 Bldr.generateNode(CNE, Pred, State);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000253}
254
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000255void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Anna Zaksebae6d02011-10-24 18:26:19 +0000256 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
Erik Verbruggen4fafeb62012-02-29 08:42:57 +0000257 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
258 ProgramStateRef state = Pred->getState();
259 Bldr.generateNode(CDE, Pred, state);
Zhongxing Xu6b851382010-04-21 02:17:31 +0000260}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000261
Ted Kremenek337e4db2012-03-10 01:34:17 +0000262void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
263 ExplodedNode *Pred,
264 ExplodedNodeSet &Dst) {
265 const VarDecl *VD = CS->getExceptionDecl();
Ted Kremenekce612f52012-03-16 05:58:15 +0000266 if (!VD) {
267 Dst.Add(Pred);
268 return;
269 }
270
Ted Kremenek337e4db2012-03-10 01:34:17 +0000271 const LocationContext *LCtx = Pred->getLocationContext();
272 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
273 currentBuilderContext->getCurrentBlockCount());
274 ProgramStateRef state = Pred->getState();
275 state = state->bindLoc(state->getLValue(VD, LCtx), V);
276
277 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
278 Bldr.generateNode(CS, Pred, state);
279}
280
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000281void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000282 ExplodedNodeSet &Dst) {
Anna Zaksaa0aeb12011-10-24 21:19:59 +0000283 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Anna Zaksebae6d02011-10-24 18:26:19 +0000284
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000285 // Get the this object region from StoreManager.
Ted Kremenek5eca4822012-01-06 22:09:28 +0000286 const LocationContext *LCtx = Pred->getLocationContext();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000287 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000288 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000289 getContext().getCanonicalType(TE->getType()),
Ted Kremenek5eca4822012-01-06 22:09:28 +0000290 LCtx);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000291
Ted Kremenek8bef8232012-01-26 21:29:00 +0000292 ProgramStateRef state = Pred->getState();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000293 SVal V = state->getSVal(loc::MemRegionVal(R));
Ted Kremenek5eca4822012-01-06 22:09:28 +0000294 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000295}