blob: 7622eab9310f0239a65f55102041ca3f519ad4f2 [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"
Jordy Rosed1e5a892011-09-02 08:02:59 +000017#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000018#include "clang/AST/DeclCXX.h"
19
20using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000021using namespace ento;
Zhongxing Xucb7464a2010-04-19 12:51:02 +000022
Ted Kremenekc69c4382010-09-23 05:14:51 +000023namespace {
24class CallExprWLItem {
25public:
26 CallExpr::const_arg_iterator I;
27 ExplodedNode *N;
28
29 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
30 : I(i), N(n) {}
31};
32}
33
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000034void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
Zhongxing Xub17b1b32010-04-20 03:37:34 +000035 const FunctionProtoType *FnType,
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000036 ExplodedNode *Pred, ExplodedNodeSet &Dst,
37 bool FstArgAsLValue) {
Ted Kremenekc69c4382010-09-23 05:14:51 +000038
39
Chris Lattner5f9e2722011-07-23 10:55:15 +000040 SmallVector<CallExprWLItem, 20> WorkList;
Zhongxing Xub17b1b32010-04-20 03:37:34 +000041 WorkList.reserve(AE - AI);
42 WorkList.push_back(CallExprWLItem(AI, Pred));
43
44 while (!WorkList.empty()) {
45 CallExprWLItem Item = WorkList.back();
46 WorkList.pop_back();
47
48 if (Item.I == AE) {
49 Dst.insert(Item.N);
50 continue;
51 }
52
Ted Kremenekc69c4382010-09-23 05:14:51 +000053 // Evaluate the argument.
Zhongxing Xub17b1b32010-04-20 03:37:34 +000054 ExplodedNodeSet Tmp;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000055 if (FstArgAsLValue) {
56 FstArgAsLValue = false;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000057 }
Ted Kremenekc69c4382010-09-23 05:14:51 +000058
Ted Kremenek892697d2010-12-16 07:46:53 +000059 Visit(*Item.I, Item.N, Tmp);
Zhongxing Xub17b1b32010-04-20 03:37:34 +000060 ++(Item.I);
61 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
62 WorkList.push_back(CallExprWLItem(Item.I, *NI));
63 }
64}
65
Ted Kremenekb2771592011-03-30 17:41:19 +000066void ExprEngine::evalCallee(const CallExpr *callExpr,
67 const ExplodedNodeSet &src,
68 ExplodedNodeSet &dest) {
69
70 const Expr *callee = 0;
71
72 switch (callExpr->getStmtClass()) {
73 case Stmt::CXXMemberCallExprClass: {
74 // Evaluate the implicit object argument that is the recipient of the
75 // call.
76 callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
77
78 // FIXME: handle member pointers.
79 if (!callee)
80 return;
81
82 break;
83 }
84 default: {
85 callee = callExpr->getCallee()->IgnoreParens();
86 break;
87 }
88 }
89
90 for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
91 Visit(callee, *i, dest);
92}
93
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000094const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000095 const StackFrameContext *SFC) {
John McCallf4c73712011-01-19 06:33:43 +000096 const Type *T = D->getTypeForDecl();
John McCallb168cbf2010-11-16 09:18:38 +000097 QualType PT = getContext().getPointerType(QualType(T, 0));
Ted Kremenekc8413fd2010-12-02 07:49:45 +000098 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000099}
100
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000101const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
Zhongxing Xu32303022010-11-24 13:48:50 +0000102 const StackFrameContext *frameCtx) {
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000103 return svalBuilder.getRegionManager().
Zhongxing Xu32303022010-11-24 13:48:50 +0000104 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
105}
106
Ted Kremenekeea72a92011-07-28 23:07:36 +0000107void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
108 ExplodedNode *Pred,
109 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000110 ExplodedNodeSet Tmp;
Ted Kremenekeea72a92011-07-28 23:07:36 +0000111 Visit(ME->GetTemporaryExpr(), Pred, Tmp);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000112 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000113 const ProgramState *state = (*I)->getState();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000114
115 // Bind the temporary object to the value of the expression. Then bind
116 // the expression to the location of the object.
Ted Kremenekeea72a92011-07-28 23:07:36 +0000117 SVal V = state->getSVal(ME->GetTemporaryExpr());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000118
119 const MemRegion *R =
Ted Kremenekeea72a92011-07-28 23:07:36 +0000120 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000121 Pred->getLocationContext());
122
123 state = state->bindLoc(loc::MemRegionVal(R), V);
Ted Kremenekeea72a92011-07-28 23:07:36 +0000124 MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000125 }
126}
127
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000128void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
Ted Kremenek5fe98722011-04-08 22:42:35 +0000129 const MemRegion *Dest,
130 ExplodedNode *Pred,
131 ExplodedNodeSet &destNodes) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000132
133 const CXXConstructorDecl *CD = E->getConstructor();
134 assert(CD);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000135
136#if 0
Sean Hunt10620eb2011-05-06 20:44:56 +0000137 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000138 // FIXME: invalidate the object.
139 return;
Ted Kremenek5fe98722011-04-08 22:42:35 +0000140#endif
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000141
142 // Evaluate other arguments.
Ted Kremenek9c149532010-12-01 21:57:22 +0000143 ExplodedNodeSet argsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000144 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000145 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000146
Ted Kremenek5fe98722011-04-08 22:42:35 +0000147#if 0
148 // Is the constructor elidable?
149 if (E->isElidable()) {
150 VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
Chris Lattnerfc8f0e12011-04-15 05:22:18 +0000151 // FIXME: this is here to force propagation if VisitAggExpr doesn't
Ted Kremenek5fe98722011-04-08 22:42:35 +0000152 if (destNodes.empty())
153 destNodes.Add(Pred);
154 return;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000155 }
Ted Kremenek5fe98722011-04-08 22:42:35 +0000156#endif
157
158 // Perform the previsit of the constructor.
159 ExplodedNodeSet destPreVisit;
160 getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
161 *this);
162
163 // Evaluate the constructor. Currently we don't now allow checker-specific
164 // implementations of specific constructors (as we do with ordinary
165 // function calls. We can re-evaluate this in the future.
166
167#if 0
168 // Inlining currently isn't fully implemented.
169
170 if (AMgr.shouldInlineCall()) {
171 if (!Dest)
172 Dest =
173 svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
174 Pred->getLocationContext());
175
176 // The callee stack frame context used to create the 'this'
177 // parameter region.
178 const StackFrameContext *SFC =
179 AMgr.getStackFrame(CD, Pred->getLocationContext(),
180 E, Builder->getBlock(), Builder->getIndex());
181
182 // Create the 'this' region.
183 const CXXThisRegion *ThisR =
184 getCXXThisRegion(E->getConstructor()->getParent(), SFC);
185
186 CallEnter Loc(E, SFC, Pred->getLocationContext());
187
188
189 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
190 NE = argsEvaluated.end(); NI != NE; ++NI) {
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000191 const ProgramState *state = (*NI)->getState();
Ted Kremenek5fe98722011-04-08 22:42:35 +0000192 // Setup 'this' region, so that the ctor is evaluated on the object pointed
193 // by 'Dest'.
194 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
195 if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
196 destNodes.Add(N);
197 }
198 }
199#endif
200
201 // Default semantics: invalidate all regions passed as arguments.
Ted Kremenek5fe98722011-04-08 22:42:35 +0000202 ExplodedNodeSet destCall;
203
204 for (ExplodedNodeSet::iterator
205 i = destPreVisit.begin(), e = destPreVisit.end();
206 i != e; ++i)
207 {
208 ExplodedNode *Pred = *i;
Jordy Rosee38dd952011-08-28 05:16:28 +0000209 const LocationContext *LC = Pred->getLocationContext();
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000210 const ProgramState *state = Pred->getState();
Ted Kremenek5fe98722011-04-08 22:42:35 +0000211
Jordy Rosee38dd952011-08-28 05:16:28 +0000212 state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000213 Builder->MakeNode(destCall, E, Pred, state);
214 }
215
216 // Do the post visit.
217 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000218}
219
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000220void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
Zhongxing Xub13453b2010-11-20 06:53:12 +0000221 const MemRegion *Dest,
222 const Stmt *S,
223 ExplodedNode *Pred,
224 ExplodedNodeSet &Dst) {
Sean Hunt10620eb2011-05-06 20:44:56 +0000225 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
Zhongxing Xub13453b2010-11-20 06:53:12 +0000226 return;
227 // Create the context for 'this' region.
228 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
229 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000230 S, Builder->getBlock(),
Zhongxing Xub13453b2010-11-20 06:53:12 +0000231 Builder->getIndex());
232
233 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
234
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000235 CallEnter PP(S, SFC, Pred->getLocationContext());
Zhongxing Xub13453b2010-11-20 06:53:12 +0000236
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000237 const ProgramState *state = Pred->getState();
Zhongxing Xub13453b2010-11-20 06:53:12 +0000238 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
239 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
240 if (N)
241 Dst.Add(N);
242}
243
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000244void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000245 ExplodedNodeSet &Dst) {
Ted Kremenek41c5f492011-03-31 04:04:48 +0000246
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000247 unsigned blockCount = Builder->getCurrentBlockCount();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000248 DefinedOrUnknownSVal symVal =
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000249 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
Ted Kremenek41c5f492011-03-31 04:04:48 +0000250 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000251 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000252 const ElementRegion *EleReg =
Ted Kremenek41c5f492011-03-31 04:04:48 +0000253 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
254
255 if (CNE->isArray()) {
256 // FIXME: allocating an array requires simulating the constructors.
257 // For now, just return a symbolicated region.
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000258 const ProgramState *state = Pred->getState();
Ted Kremenek41c5f492011-03-31 04:04:48 +0000259 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
260 MakeNode(Dst, CNE, Pred, state);
261 return;
262 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000263
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000264 // Evaluate constructor arguments.
265 const FunctionProtoType *FnType = NULL;
266 const CXXConstructorDecl *CD = CNE->getConstructor();
267 if (CD)
268 FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000269 ExplodedNodeSet argsEvaluated;
270 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
271 FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000272
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000273 // Initialize the object region and bind the 'new' expression.
Ted Kremenek9c149532010-12-01 21:57:22 +0000274 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
275 E = argsEvaluated.end(); I != E; ++I) {
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000276
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000277 const ProgramState *state = (*I)->getState();
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000278
279 // Accumulate list of regions that are invalidated.
280 // FIXME: Eventually we should unify the logic for constructor
281 // processing in one place.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000282 SmallVector<const MemRegion*, 10> regionsToInvalidate;
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000283 for (CXXNewExpr::const_arg_iterator
284 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
285 ai != ae; ++ai)
286 {
287 SVal val = state->getSVal(*ai);
288 if (const MemRegion *region = val.getAsRegion())
289 regionsToInvalidate.push_back(region);
290 }
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000291
292 if (ObjTy->isRecordType()) {
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000293 regionsToInvalidate.push_back(EleReg);
294 // Invalidate the regions.
Jordy Rose537716a2011-08-27 22:51:26 +0000295 state = state->invalidateRegions(regionsToInvalidate,
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000296 CNE, blockCount, 0,
297 /* invalidateGlobals = */ true);
298
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000299 } else {
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000300 // Invalidate the regions.
Jordy Rose537716a2011-08-27 22:51:26 +0000301 state = state->invalidateRegions(regionsToInvalidate,
Ted Kremenek9d5d3082011-04-12 05:12:39 +0000302 CNE, blockCount, 0,
303 /* invalidateGlobals = */ true);
304
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000305 if (CNE->hasInitializer()) {
306 SVal V = state->getSVal(*CNE->constructor_arg_begin());
307 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
308 } else {
309 // Explicitly set to undefined, because currently we retrieve symbolic
310 // value from symbolic region.
311 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
312 }
313 }
314 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000315 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000316 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000317}
318
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000319void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000320 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000321 // Should do more checking.
Ted Kremenek9c149532010-12-01 21:57:22 +0000322 ExplodedNodeSet Argevaluated;
323 Visit(CDE->getArgument(), Pred, Argevaluated);
324 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
325 E = Argevaluated.end(); I != E; ++I) {
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000326 const ProgramState *state = (*I)->getState();
Zhongxing Xu6b851382010-04-21 02:17:31 +0000327 MakeNode(Dst, CDE, *I, state);
328 }
329}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000330
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000331void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000332 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000333 // Get the this object region from StoreManager.
334 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000335 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000336 getContext().getCanonicalType(TE->getType()),
337 Pred->getLocationContext());
338
Ted Kremenek18c66fd2011-08-15 22:09:50 +0000339 const ProgramState *state = Pred->getState();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000340 SVal V = state->getSVal(loc::MemRegionVal(R));
341 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
342}