blob: 47b3a0bd06905f01f6c94b201cd24f4b7e9ee7cb [file] [log] [blame]
Zhongxing Xucb7464a2010-04-19 12:51:02 +00001//===- GRCXXExprEngine.cpp - C++ expr evaluation engine ---------*- 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
Ted Kremenek21142582010-12-23 19:38:26 +000014#include "clang/StaticAnalyzer/PathSensitive/AnalysisManager.h"
15#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000016#include "clang/AST/DeclCXX.h"
17
18using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000019using namespace ento;
Zhongxing Xucb7464a2010-04-19 12:51:02 +000020
Ted Kremenekc69c4382010-09-23 05:14:51 +000021namespace {
22class CallExprWLItem {
23public:
24 CallExpr::const_arg_iterator I;
25 ExplodedNode *N;
26
27 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
28 : I(i), N(n) {}
29};
30}
31
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000032void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
Zhongxing Xub17b1b32010-04-20 03:37:34 +000033 const FunctionProtoType *FnType,
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000034 ExplodedNode *Pred, ExplodedNodeSet &Dst,
35 bool FstArgAsLValue) {
Ted Kremenekc69c4382010-09-23 05:14:51 +000036
37
Zhongxing Xub17b1b32010-04-20 03:37:34 +000038 llvm::SmallVector<CallExprWLItem, 20> WorkList;
39 WorkList.reserve(AE - AI);
40 WorkList.push_back(CallExprWLItem(AI, Pred));
41
42 while (!WorkList.empty()) {
43 CallExprWLItem Item = WorkList.back();
44 WorkList.pop_back();
45
46 if (Item.I == AE) {
47 Dst.insert(Item.N);
48 continue;
49 }
50
Ted Kremenekc69c4382010-09-23 05:14:51 +000051 // Evaluate the argument.
Zhongxing Xub17b1b32010-04-20 03:37:34 +000052 ExplodedNodeSet Tmp;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000053 bool VisitAsLvalue = FstArgAsLValue;
54 if (FstArgAsLValue) {
55 FstArgAsLValue = false;
56 } else {
57 const unsigned ParamIdx = Item.I - AI;
58 VisitAsLvalue = FnType && ParamIdx < FnType->getNumArgs()
59 ? FnType->getArgType(ParamIdx)->isReferenceType()
60 : false;
61 }
Ted Kremenekc69c4382010-09-23 05:14:51 +000062
Ted Kremenek892697d2010-12-16 07:46:53 +000063 Visit(*Item.I, Item.N, Tmp);
Zhongxing Xub17b1b32010-04-20 03:37:34 +000064 ++(Item.I);
65 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
66 WorkList.push_back(CallExprWLItem(Item.I, *NI));
67 }
68}
69
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000070const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000071 const StackFrameContext *SFC) {
John McCallb168cbf2010-11-16 09:18:38 +000072 Type *T = D->getTypeForDecl();
73 QualType PT = getContext().getPointerType(QualType(T, 0));
Ted Kremenekc8413fd2010-12-02 07:49:45 +000074 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000075}
76
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000077const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
Zhongxing Xu32303022010-11-24 13:48:50 +000078 const StackFrameContext *frameCtx) {
Ted Kremenekc8413fd2010-12-02 07:49:45 +000079 return svalBuilder.getRegionManager().
Zhongxing Xu32303022010-11-24 13:48:50 +000080 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
81}
82
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000083void ExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000084 ExplodedNodeSet &Dst) {
85 ExplodedNodeSet Tmp;
86 Visit(Ex, Pred, Tmp);
87 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
88 const GRState *state = GetState(*I);
89
90 // Bind the temporary object to the value of the expression. Then bind
91 // the expression to the location of the object.
92 SVal V = state->getSVal(Ex);
93
94 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +000095 svalBuilder.getRegionManager().getCXXTempObjectRegion(Ex,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000096 Pred->getLocationContext());
97
98 state = state->bindLoc(loc::MemRegionVal(R), V);
99 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
100 }
101}
102
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000103void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000104 const MemRegion *Dest,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000105 ExplodedNode *Pred,
Ted Kremenek892697d2010-12-16 07:46:53 +0000106 ExplodedNodeSet &Dst) {
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000107 if (!Dest)
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000108 Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000109 Pred->getLocationContext());
110
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000111 if (E->isElidable()) {
112 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
113 return;
114 }
115
116 const CXXConstructorDecl *CD = E->getConstructor();
117 assert(CD);
118
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000119 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000120 // FIXME: invalidate the object.
121 return;
122
123
124 // Evaluate other arguments.
Ted Kremenek9c149532010-12-01 21:57:22 +0000125 ExplodedNodeSet argsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000126 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000127 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000128 // The callee stack frame context used to create the 'this' parameter region.
129 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
130 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000131 E, Builder->getBlock(),
132 Builder->getIndex());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000133
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000134 const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
135 SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000136
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000137 CallEnter Loc(E, SFC, Pred->getLocationContext());
Ted Kremenek9c149532010-12-01 21:57:22 +0000138 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
139 NE = argsEvaluated.end(); NI != NE; ++NI) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000140 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000141 // Setup 'this' region, so that the ctor is evaluated on the object pointed
142 // by 'Dest'.
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000143 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000144 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
145 if (N)
146 Dst.Add(N);
147 }
148}
149
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000150void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
Zhongxing Xub13453b2010-11-20 06:53:12 +0000151 const MemRegion *Dest,
152 const Stmt *S,
153 ExplodedNode *Pred,
154 ExplodedNodeSet &Dst) {
155 if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
156 return;
157 // Create the context for 'this' region.
158 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
159 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000160 S, Builder->getBlock(),
Zhongxing Xub13453b2010-11-20 06:53:12 +0000161 Builder->getIndex());
162
163 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
164
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000165 CallEnter PP(S, SFC, Pred->getLocationContext());
Zhongxing Xub13453b2010-11-20 06:53:12 +0000166
167 const GRState *state = Pred->getState();
168 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
169 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
170 if (N)
171 Dst.Add(N);
172}
173
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000174void ExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000175 ExplodedNode *Pred,
176 ExplodedNodeSet &Dst) {
177 // Get the method type.
178 const FunctionProtoType *FnType =
179 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
180 assert(FnType && "Method type not available");
181
182 // Evaluate explicit arguments with a worklist.
Ted Kremenek9c149532010-12-01 21:57:22 +0000183 ExplodedNodeSet argsEvaluated;
184 evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000185
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000186 // Evaluate the implicit object argument.
Ted Kremenek9c149532010-12-01 21:57:22 +0000187 ExplodedNodeSet AllargsEvaluated;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000188 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
189 if (!ME)
190 return;
191 Expr *ObjArgExpr = ME->getBase();
Ted Kremenek9c149532010-12-01 21:57:22 +0000192 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
193 E = argsEvaluated.end(); I != E; ++I) {
Ted Kremenek9c149532010-12-01 21:57:22 +0000194 Visit(ObjArgExpr, *I, AllargsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000195 }
196
Ted Kremeneka54e8242010-09-30 01:06:29 +0000197 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000198 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
199 assert(MD && "not a CXXMethodDecl?");
Ted Kremenek9c149532010-12-01 21:57:22 +0000200 evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000201}
202
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000203void ExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000204 ExplodedNode *Pred,
205 ExplodedNodeSet &Dst) {
206 const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
207 if (!MD) {
208 // If the operator doesn't represent a method call treat as regural call.
Ted Kremenek892697d2010-12-16 07:46:53 +0000209 VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000210 return;
211 }
212
213 // Determine the type of function we're calling (if available).
214 const FunctionProtoType *Proto = NULL;
215 QualType FnType = C->getCallee()->IgnoreParens()->getType();
216 if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
217 Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
218
219 // Evaluate arguments treating the first one (object method is called on)
220 // as alvalue.
Ted Kremenek9c149532010-12-01 21:57:22 +0000221 ExplodedNodeSet argsEvaluated;
222 evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000223
224 // Now evaluate the call itself.
Ted Kremenek9c149532010-12-01 21:57:22 +0000225 evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000226}
227
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000228void ExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000229 const Expr *ThisExpr, ExplodedNode *Pred,
230 ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
231 // Allow checkers to pre-visit the member call.
232 ExplodedNodeSet PreVisitChecks;
233 CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000234
Ted Kremeneka54e8242010-09-30 01:06:29 +0000235 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000236 // FIXME: conservative method call evaluation.
Ted Kremeneka54e8242010-09-30 01:06:29 +0000237 CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000238 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000239 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000240
241 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
242 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000243 MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000244 Builder->getBlock(),
245 Builder->getIndex());
Zhongxing Xu32303022010-11-24 13:48:50 +0000246 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000247 CallEnter Loc(MCE, SFC, Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000248 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
249 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000250 // Set up 'this' region.
251 const GRState *state = GetState(*I);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000252 state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
253 Dst.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000254 }
255}
256
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000257void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000258 ExplodedNodeSet &Dst) {
259 if (CNE->isArray()) {
260 // FIXME: allocating an array has not been handled.
261 return;
262 }
263
264 unsigned Count = Builder->getCurrentBlockCount();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000265 DefinedOrUnknownSVal symVal =
266 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count);
267 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000268
269 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
270
271 const ElementRegion *EleReg =
272 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
273
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000274 // Evaluate constructor arguments.
275 const FunctionProtoType *FnType = NULL;
276 const CXXConstructorDecl *CD = CNE->getConstructor();
277 if (CD)
278 FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000279 ExplodedNodeSet argsEvaluated;
280 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
281 FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000282
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000283 // Initialize the object region and bind the 'new' expression.
Ted Kremenek9c149532010-12-01 21:57:22 +0000284 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
285 E = argsEvaluated.end(); I != E; ++I) {
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000286 const GRState *state = GetState(*I);
287
288 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000289 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000290 } else {
291 if (CNE->hasInitializer()) {
292 SVal V = state->getSVal(*CNE->constructor_arg_begin());
293 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
294 } else {
295 // Explicitly set to undefined, because currently we retrieve symbolic
296 // value from symbolic region.
297 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
298 }
299 }
300 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000301 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000302 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000303}
304
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000305void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000306 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000307 // Should do more checking.
Ted Kremenek9c149532010-12-01 21:57:22 +0000308 ExplodedNodeSet Argevaluated;
309 Visit(CDE->getArgument(), Pred, Argevaluated);
310 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
311 E = Argevaluated.end(); I != E; ++I) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000312 const GRState *state = GetState(*I);
313 MakeNode(Dst, CDE, *I, state);
314 }
315}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000316
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000317void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000318 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000319 // Get the this object region from StoreManager.
320 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000321 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000322 getContext().getCanonicalType(TE->getType()),
323 Pred->getLocationContext());
324
325 const GRState *state = GetState(Pred);
326 SVal V = state->getSVal(loc::MemRegionVal(R));
327 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
328}