blob: 20d2fa7790ff73913e743a49026cdcf294b43881 [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
14#include "clang/Checker/PathSensitive/AnalysisManager.h"
15#include "clang/Checker/PathSensitive/GRExprEngine.h"
16#include "clang/AST/DeclCXX.h"
17
18using namespace clang;
19
Ted Kremenekc69c4382010-09-23 05:14:51 +000020namespace {
21class CallExprWLItem {
22public:
23 CallExpr::const_arg_iterator I;
24 ExplodedNode *N;
25
26 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
27 : I(i), N(n) {}
28};
29}
30
Ted Kremenek9c149532010-12-01 21:57:22 +000031void GRExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
Zhongxing Xub17b1b32010-04-20 03:37:34 +000032 const FunctionProtoType *FnType,
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000033 ExplodedNode *Pred, ExplodedNodeSet &Dst,
34 bool FstArgAsLValue) {
Ted Kremenekc69c4382010-09-23 05:14:51 +000035
36
Zhongxing Xub17b1b32010-04-20 03:37:34 +000037 llvm::SmallVector<CallExprWLItem, 20> WorkList;
38 WorkList.reserve(AE - AI);
39 WorkList.push_back(CallExprWLItem(AI, Pred));
40
41 while (!WorkList.empty()) {
42 CallExprWLItem Item = WorkList.back();
43 WorkList.pop_back();
44
45 if (Item.I == AE) {
46 Dst.insert(Item.N);
47 continue;
48 }
49
Ted Kremenekc69c4382010-09-23 05:14:51 +000050 // Evaluate the argument.
Zhongxing Xub17b1b32010-04-20 03:37:34 +000051 ExplodedNodeSet Tmp;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000052 bool VisitAsLvalue = FstArgAsLValue;
53 if (FstArgAsLValue) {
54 FstArgAsLValue = false;
55 } else {
56 const unsigned ParamIdx = Item.I - AI;
57 VisitAsLvalue = FnType && ParamIdx < FnType->getNumArgs()
58 ? FnType->getArgType(ParamIdx)->isReferenceType()
59 : false;
60 }
Ted Kremenekc69c4382010-09-23 05:14:51 +000061
Zhongxing Xub17b1b32010-04-20 03:37:34 +000062 if (VisitAsLvalue)
63 VisitLValue(*Item.I, Item.N, Tmp);
64 else
65 Visit(*Item.I, Item.N, Tmp);
66
67 ++(Item.I);
68 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
69 WorkList.push_back(CallExprWLItem(Item.I, *NI));
70 }
71}
72
Zhongxing Xu9dc84c92010-11-16 07:52:17 +000073const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000074 const StackFrameContext *SFC) {
John McCallb168cbf2010-11-16 09:18:38 +000075 Type *T = D->getTypeForDecl();
76 QualType PT = getContext().getPointerType(QualType(T, 0));
Zhongxing Xucb7464a2010-04-19 12:51:02 +000077 return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
78}
79
Zhongxing Xu32303022010-11-24 13:48:50 +000080const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
81 const StackFrameContext *frameCtx) {
82 return ValMgr.getRegionManager().
83 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
84}
85
Zhongxing Xu03509ae2010-07-20 06:22:24 +000086void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000087 ExplodedNodeSet &Dst) {
88 ExplodedNodeSet Tmp;
89 Visit(Ex, Pred, Tmp);
90 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
91 const GRState *state = GetState(*I);
92
93 // Bind the temporary object to the value of the expression. Then bind
94 // the expression to the location of the object.
95 SVal V = state->getSVal(Ex);
96
97 const MemRegion *R =
Zhongxing Xu02fe28c2010-11-26 08:52:48 +000098 ValMgr.getRegionManager().getCXXTempObjectRegion(Ex,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000099 Pred->getLocationContext());
100
101 state = state->bindLoc(loc::MemRegionVal(R), V);
102 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
103 }
104}
105
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000106void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
107 const MemRegion *Dest,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000108 ExplodedNode *Pred,
Zhongxing Xud7064342010-11-24 13:08:51 +0000109 ExplodedNodeSet &Dst, bool asLValue) {
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000110 if (!Dest)
Zhongxing Xu02fe28c2010-11-26 08:52:48 +0000111 Dest = ValMgr.getRegionManager().getCXXTempObjectRegion(E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000112 Pred->getLocationContext());
113
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000114 if (E->isElidable()) {
115 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
116 return;
117 }
118
119 const CXXConstructorDecl *CD = E->getConstructor();
120 assert(CD);
121
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000122 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000123 // FIXME: invalidate the object.
124 return;
125
126
127 // Evaluate other arguments.
Ted Kremenek9c149532010-12-01 21:57:22 +0000128 ExplodedNodeSet argsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000129 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000130 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000131 // The callee stack frame context used to create the 'this' parameter region.
132 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
133 Pred->getLocationContext(),
Zhongxing Xud7064342010-11-24 13:08:51 +0000134 E, asLValue, Builder->getBlock(), Builder->getIndex());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000135
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000136 const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
137 SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000138
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000139 CallEnter Loc(E, SFC, Pred->getLocationContext());
Ted Kremenek9c149532010-12-01 21:57:22 +0000140 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
141 NE = argsEvaluated.end(); NI != NE; ++NI) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000142 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000143 // Setup 'this' region, so that the ctor is evaluated on the object pointed
144 // by 'Dest'.
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000145 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000146 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
147 if (N)
148 Dst.Add(N);
149 }
150}
151
Zhongxing Xub13453b2010-11-20 06:53:12 +0000152void GRExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
153 const MemRegion *Dest,
154 const Stmt *S,
155 ExplodedNode *Pred,
156 ExplodedNodeSet &Dst) {
157 if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
158 return;
159 // Create the context for 'this' region.
160 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
161 Pred->getLocationContext(),
Zhongxing Xud7064342010-11-24 13:08:51 +0000162 S, false, Builder->getBlock(),
Zhongxing Xub13453b2010-11-20 06:53:12 +0000163 Builder->getIndex());
164
165 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
166
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000167 CallEnter PP(S, SFC, Pred->getLocationContext());
Zhongxing Xub13453b2010-11-20 06:53:12 +0000168
169 const GRState *state = Pred->getState();
170 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
171 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
172 if (N)
173 Dst.Add(N);
174}
175
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000176void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
177 ExplodedNode *Pred,
178 ExplodedNodeSet &Dst) {
179 // Get the method type.
180 const FunctionProtoType *FnType =
181 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
182 assert(FnType && "Method type not available");
183
184 // Evaluate explicit arguments with a worklist.
Ted Kremenek9c149532010-12-01 21:57:22 +0000185 ExplodedNodeSet argsEvaluated;
186 evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000187
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000188 // Evaluate the implicit object argument.
Ted Kremenek9c149532010-12-01 21:57:22 +0000189 ExplodedNodeSet AllargsEvaluated;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000190 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
191 if (!ME)
192 return;
193 Expr *ObjArgExpr = ME->getBase();
Ted Kremenek9c149532010-12-01 21:57:22 +0000194 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
195 E = argsEvaluated.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000196 if (ME->isArrow())
Ted Kremenek9c149532010-12-01 21:57:22 +0000197 Visit(ObjArgExpr, *I, AllargsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000198 else
Ted Kremenek9c149532010-12-01 21:57:22 +0000199 VisitLValue(ObjArgExpr, *I, AllargsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000200 }
201
Ted Kremeneka54e8242010-09-30 01:06:29 +0000202 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000203 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
204 assert(MD && "not a CXXMethodDecl?");
Ted Kremenek9c149532010-12-01 21:57:22 +0000205 evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000206}
207
208void GRExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
209 ExplodedNode *Pred,
210 ExplodedNodeSet &Dst) {
211 const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
212 if (!MD) {
213 // If the operator doesn't represent a method call treat as regural call.
214 VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
215 return;
216 }
217
218 // Determine the type of function we're calling (if available).
219 const FunctionProtoType *Proto = NULL;
220 QualType FnType = C->getCallee()->IgnoreParens()->getType();
221 if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
222 Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
223
224 // Evaluate arguments treating the first one (object method is called on)
225 // as alvalue.
Ted Kremenek9c149532010-12-01 21:57:22 +0000226 ExplodedNodeSet argsEvaluated;
227 evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000228
229 // Now evaluate the call itself.
Ted Kremenek9c149532010-12-01 21:57:22 +0000230 evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000231}
232
Ted Kremenek9c149532010-12-01 21:57:22 +0000233void GRExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000234 const Expr *ThisExpr, ExplodedNode *Pred,
235 ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
236 // Allow checkers to pre-visit the member call.
237 ExplodedNodeSet PreVisitChecks;
238 CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000239
Ted Kremeneka54e8242010-09-30 01:06:29 +0000240 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000241 // FIXME: conservative method call evaluation.
Ted Kremeneka54e8242010-09-30 01:06:29 +0000242 CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000243 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000244 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000245
246 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
247 Pred->getLocationContext(),
Zhongxing Xud7064342010-11-24 13:08:51 +0000248 MCE, false,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000249 Builder->getBlock(),
250 Builder->getIndex());
Zhongxing Xu32303022010-11-24 13:48:50 +0000251 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000252 CallEnter Loc(MCE, SFC, Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000253 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
254 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000255 // Set up 'this' region.
256 const GRState *state = GetState(*I);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000257 state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
258 Dst.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000259 }
260}
261
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000262void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000263 ExplodedNodeSet &Dst) {
264 if (CNE->isArray()) {
265 // FIXME: allocating an array has not been handled.
266 return;
267 }
268
269 unsigned Count = Builder->getCurrentBlockCount();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000270 DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000271 CNE->getType(), Count);
272 const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
273
274 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
275
276 const ElementRegion *EleReg =
277 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
278
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000279 // Evaluate constructor arguments.
280 const FunctionProtoType *FnType = NULL;
281 const CXXConstructorDecl *CD = CNE->getConstructor();
282 if (CD)
283 FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000284 ExplodedNodeSet argsEvaluated;
285 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
286 FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000287
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000288 // Initialize the object region and bind the 'new' expression.
Ted Kremenek9c149532010-12-01 21:57:22 +0000289 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
290 E = argsEvaluated.end(); I != E; ++I) {
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000291 const GRState *state = GetState(*I);
292
293 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000294 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000295 } else {
296 if (CNE->hasInitializer()) {
297 SVal V = state->getSVal(*CNE->constructor_arg_begin());
298 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
299 } else {
300 // Explicitly set to undefined, because currently we retrieve symbolic
301 // value from symbolic region.
302 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
303 }
304 }
305 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000306 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000307 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000308}
309
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000310void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
311 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000312 // Should do more checking.
Ted Kremenek9c149532010-12-01 21:57:22 +0000313 ExplodedNodeSet Argevaluated;
314 Visit(CDE->getArgument(), Pred, Argevaluated);
315 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
316 E = Argevaluated.end(); I != E; ++I) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000317 const GRState *state = GetState(*I);
318 MakeNode(Dst, CDE, *I, state);
319 }
320}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000321
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000322void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000323 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000324 // Get the this object region from StoreManager.
325 const MemRegion *R =
326 ValMgr.getRegionManager().getCXXThisRegion(
327 getContext().getCanonicalType(TE->getType()),
328 Pred->getLocationContext());
329
330 const GRState *state = GetState(Pred);
331 SVal V = state->getSVal(loc::MemRegionVal(R));
332 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
333}