blob: 149d4bd9abe82d9dbc4648605ef4f894591f94d8 [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 if (FstArgAsLValue) {
54 FstArgAsLValue = false;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000055 }
Ted Kremenekc69c4382010-09-23 05:14:51 +000056
Ted Kremenek892697d2010-12-16 07:46:53 +000057 Visit(*Item.I, Item.N, Tmp);
Zhongxing Xub17b1b32010-04-20 03:37:34 +000058 ++(Item.I);
59 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
60 WorkList.push_back(CallExprWLItem(Item.I, *NI));
61 }
62}
63
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000064const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000065 const StackFrameContext *SFC) {
John McCallb168cbf2010-11-16 09:18:38 +000066 Type *T = D->getTypeForDecl();
67 QualType PT = getContext().getPointerType(QualType(T, 0));
Ted Kremenekc8413fd2010-12-02 07:49:45 +000068 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000069}
70
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000071const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
Zhongxing Xu32303022010-11-24 13:48:50 +000072 const StackFrameContext *frameCtx) {
Ted Kremenekc8413fd2010-12-02 07:49:45 +000073 return svalBuilder.getRegionManager().
Zhongxing Xu32303022010-11-24 13:48:50 +000074 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
75}
76
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000077void ExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000078 ExplodedNodeSet &Dst) {
79 ExplodedNodeSet Tmp;
80 Visit(Ex, Pred, Tmp);
81 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
82 const GRState *state = GetState(*I);
83
84 // Bind the temporary object to the value of the expression. Then bind
85 // the expression to the location of the object.
86 SVal V = state->getSVal(Ex);
87
88 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +000089 svalBuilder.getRegionManager().getCXXTempObjectRegion(Ex,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000090 Pred->getLocationContext());
91
92 state = state->bindLoc(loc::MemRegionVal(R), V);
93 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
94 }
95}
96
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000097void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +000098 const MemRegion *Dest,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000099 ExplodedNode *Pred,
Ted Kremenek892697d2010-12-16 07:46:53 +0000100 ExplodedNodeSet &Dst) {
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000101 if (!Dest)
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000102 Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000103 Pred->getLocationContext());
104
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000105 if (E->isElidable()) {
106 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
107 return;
108 }
109
110 const CXXConstructorDecl *CD = E->getConstructor();
111 assert(CD);
112
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000113 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000114 // FIXME: invalidate the object.
115 return;
116
117
118 // Evaluate other arguments.
Ted Kremenek9c149532010-12-01 21:57:22 +0000119 ExplodedNodeSet argsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000120 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000121 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000122 // The callee stack frame context used to create the 'this' parameter region.
123 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
124 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000125 E, Builder->getBlock(),
126 Builder->getIndex());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000127
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000128 const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
129 SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000130
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000131 CallEnter Loc(E, SFC, Pred->getLocationContext());
Ted Kremenek9c149532010-12-01 21:57:22 +0000132 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
133 NE = argsEvaluated.end(); NI != NE; ++NI) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000134 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000135 // Setup 'this' region, so that the ctor is evaluated on the object pointed
136 // by 'Dest'.
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000137 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000138 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
139 if (N)
140 Dst.Add(N);
141 }
142}
143
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000144void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
Zhongxing Xub13453b2010-11-20 06:53:12 +0000145 const MemRegion *Dest,
146 const Stmt *S,
147 ExplodedNode *Pred,
148 ExplodedNodeSet &Dst) {
149 if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
150 return;
151 // Create the context for 'this' region.
152 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
153 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000154 S, Builder->getBlock(),
Zhongxing Xub13453b2010-11-20 06:53:12 +0000155 Builder->getIndex());
156
157 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
158
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000159 CallEnter PP(S, SFC, Pred->getLocationContext());
Zhongxing Xub13453b2010-11-20 06:53:12 +0000160
161 const GRState *state = Pred->getState();
162 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
163 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
164 if (N)
165 Dst.Add(N);
166}
167
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000168void ExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000169 ExplodedNode *Pred,
170 ExplodedNodeSet &Dst) {
171 // Get the method type.
172 const FunctionProtoType *FnType =
173 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
174 assert(FnType && "Method type not available");
175
176 // Evaluate explicit arguments with a worklist.
Ted Kremenek9c149532010-12-01 21:57:22 +0000177 ExplodedNodeSet argsEvaluated;
178 evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000179
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000180 // Evaluate the implicit object argument.
Ted Kremenek9c149532010-12-01 21:57:22 +0000181 ExplodedNodeSet AllargsEvaluated;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000182 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
183 if (!ME)
184 return;
185 Expr *ObjArgExpr = ME->getBase();
Ted Kremenek9c149532010-12-01 21:57:22 +0000186 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
187 E = argsEvaluated.end(); I != E; ++I) {
Ted Kremenek9c149532010-12-01 21:57:22 +0000188 Visit(ObjArgExpr, *I, AllargsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000189 }
190
Ted Kremeneka54e8242010-09-30 01:06:29 +0000191 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000192 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
193 assert(MD && "not a CXXMethodDecl?");
Ted Kremenek9c149532010-12-01 21:57:22 +0000194 evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000195}
196
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000197void ExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000198 ExplodedNode *Pred,
199 ExplodedNodeSet &Dst) {
200 const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
201 if (!MD) {
202 // If the operator doesn't represent a method call treat as regural call.
Ted Kremenek892697d2010-12-16 07:46:53 +0000203 VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000204 return;
205 }
206
207 // Determine the type of function we're calling (if available).
208 const FunctionProtoType *Proto = NULL;
209 QualType FnType = C->getCallee()->IgnoreParens()->getType();
210 if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
211 Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
212
213 // Evaluate arguments treating the first one (object method is called on)
214 // as alvalue.
Ted Kremenek9c149532010-12-01 21:57:22 +0000215 ExplodedNodeSet argsEvaluated;
216 evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000217
218 // Now evaluate the call itself.
Ted Kremenek9c149532010-12-01 21:57:22 +0000219 evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000220}
221
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000222void ExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000223 const Expr *ThisExpr, ExplodedNode *Pred,
224 ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
225 // Allow checkers to pre-visit the member call.
226 ExplodedNodeSet PreVisitChecks;
227 CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000228
Ted Kremeneka54e8242010-09-30 01:06:29 +0000229 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000230 // FIXME: conservative method call evaluation.
Ted Kremeneka54e8242010-09-30 01:06:29 +0000231 CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000232 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000233 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000234
235 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
236 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000237 MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000238 Builder->getBlock(),
239 Builder->getIndex());
Zhongxing Xu32303022010-11-24 13:48:50 +0000240 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000241 CallEnter Loc(MCE, SFC, Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000242 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
243 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000244 // Set up 'this' region.
245 const GRState *state = GetState(*I);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000246 state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
247 Dst.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000248 }
249}
250
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000251void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000252 ExplodedNodeSet &Dst) {
253 if (CNE->isArray()) {
254 // FIXME: allocating an array has not been handled.
255 return;
256 }
257
258 unsigned Count = Builder->getCurrentBlockCount();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000259 DefinedOrUnknownSVal symVal =
260 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count);
261 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000262
263 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
264
265 const ElementRegion *EleReg =
266 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
267
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000268 // Evaluate constructor arguments.
269 const FunctionProtoType *FnType = NULL;
270 const CXXConstructorDecl *CD = CNE->getConstructor();
271 if (CD)
272 FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000273 ExplodedNodeSet argsEvaluated;
274 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
275 FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000276
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000277 // Initialize the object region and bind the 'new' expression.
Ted Kremenek9c149532010-12-01 21:57:22 +0000278 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
279 E = argsEvaluated.end(); I != E; ++I) {
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000280 const GRState *state = GetState(*I);
281
282 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000283 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000284 } else {
285 if (CNE->hasInitializer()) {
286 SVal V = state->getSVal(*CNE->constructor_arg_begin());
287 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
288 } else {
289 // Explicitly set to undefined, because currently we retrieve symbolic
290 // value from symbolic region.
291 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
292 }
293 }
294 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000295 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000296 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000297}
298
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000299void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000300 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000301 // Should do more checking.
Ted Kremenek9c149532010-12-01 21:57:22 +0000302 ExplodedNodeSet Argevaluated;
303 Visit(CDE->getArgument(), Pred, Argevaluated);
304 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
305 E = Argevaluated.end(); I != E; ++I) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000306 const GRState *state = GetState(*I);
307 MakeNode(Dst, CDE, *I, state);
308 }
309}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000310
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000311void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000312 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000313 // Get the this object region from StoreManager.
314 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000315 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000316 getContext().getCanonicalType(TE->getType()),
317 Pred->getLocationContext());
318
319 const GRState *state = GetState(Pred);
320 SVal V = state->getSVal(loc::MemRegionVal(R));
321 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
322}