blob: 7d8a22bf2b8f3b8e4b3d65022b5f85105f0f703f [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
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"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000017#include "clang/AST/DeclCXX.h"
18
19using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000020using namespace ento;
Zhongxing Xucb7464a2010-04-19 12:51:02 +000021
Ted Kremenekc69c4382010-09-23 05:14:51 +000022namespace {
23class CallExprWLItem {
24public:
25 CallExpr::const_arg_iterator I;
26 ExplodedNode *N;
27
28 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
29 : I(i), N(n) {}
30};
31}
32
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000033void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
Zhongxing Xub17b1b32010-04-20 03:37:34 +000034 const FunctionProtoType *FnType,
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000035 ExplodedNode *Pred, ExplodedNodeSet &Dst,
36 bool FstArgAsLValue) {
Ted Kremenekc69c4382010-09-23 05:14:51 +000037
38
Zhongxing Xub17b1b32010-04-20 03:37:34 +000039 llvm::SmallVector<CallExprWLItem, 20> WorkList;
40 WorkList.reserve(AE - AI);
41 WorkList.push_back(CallExprWLItem(AI, Pred));
42
43 while (!WorkList.empty()) {
44 CallExprWLItem Item = WorkList.back();
45 WorkList.pop_back();
46
47 if (Item.I == AE) {
48 Dst.insert(Item.N);
49 continue;
50 }
51
Ted Kremenekc69c4382010-09-23 05:14:51 +000052 // Evaluate the argument.
Zhongxing Xub17b1b32010-04-20 03:37:34 +000053 ExplodedNodeSet Tmp;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000054 if (FstArgAsLValue) {
55 FstArgAsLValue = false;
Marcin Swiderski82c63bf2010-11-17 21:27:36 +000056 }
Ted Kremenekc69c4382010-09-23 05:14:51 +000057
Ted Kremenek892697d2010-12-16 07:46:53 +000058 Visit(*Item.I, Item.N, Tmp);
Zhongxing Xub17b1b32010-04-20 03:37:34 +000059 ++(Item.I);
60 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
61 WorkList.push_back(CallExprWLItem(Item.I, *NI));
62 }
63}
64
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000065const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000066 const StackFrameContext *SFC) {
John McCallf4c73712011-01-19 06:33:43 +000067 const Type *T = D->getTypeForDecl();
John McCallb168cbf2010-11-16 09:18:38 +000068 QualType PT = getContext().getPointerType(QualType(T, 0));
Ted Kremenekc8413fd2010-12-02 07:49:45 +000069 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000070}
71
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000072const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
Zhongxing Xu32303022010-11-24 13:48:50 +000073 const StackFrameContext *frameCtx) {
Ted Kremenekc8413fd2010-12-02 07:49:45 +000074 return svalBuilder.getRegionManager().
Zhongxing Xu32303022010-11-24 13:48:50 +000075 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
76}
77
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000078void ExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000079 ExplodedNodeSet &Dst) {
80 ExplodedNodeSet Tmp;
81 Visit(Ex, Pred, Tmp);
82 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
83 const GRState *state = GetState(*I);
84
85 // Bind the temporary object to the value of the expression. Then bind
86 // the expression to the location of the object.
87 SVal V = state->getSVal(Ex);
88
89 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +000090 svalBuilder.getRegionManager().getCXXTempObjectRegion(Ex,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000091 Pred->getLocationContext());
92
93 state = state->bindLoc(loc::MemRegionVal(R), V);
94 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
95 }
96}
97
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000098void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +000099 const MemRegion *Dest,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000100 ExplodedNode *Pred,
Ted Kremenek892697d2010-12-16 07:46:53 +0000101 ExplodedNodeSet &Dst) {
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000102 if (!Dest)
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000103 Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000104 Pred->getLocationContext());
105
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000106 if (E->isElidable()) {
107 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
108 return;
109 }
110
111 const CXXConstructorDecl *CD = E->getConstructor();
112 assert(CD);
113
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000114 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000115 // FIXME: invalidate the object.
116 return;
117
118
119 // Evaluate other arguments.
Ted Kremenek9c149532010-12-01 21:57:22 +0000120 ExplodedNodeSet argsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000121 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000122 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000123 // The callee stack frame context used to create the 'this' parameter region.
124 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
125 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000126 E, Builder->getBlock(),
127 Builder->getIndex());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000128
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000129 const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
130 SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000131
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000132 CallEnter Loc(E, SFC, Pred->getLocationContext());
Ted Kremenek9c149532010-12-01 21:57:22 +0000133 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
134 NE = argsEvaluated.end(); NI != NE; ++NI) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000135 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000136 // Setup 'this' region, so that the ctor is evaluated on the object pointed
137 // by 'Dest'.
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000138 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000139 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
140 if (N)
141 Dst.Add(N);
142 }
143}
144
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000145void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
Zhongxing Xub13453b2010-11-20 06:53:12 +0000146 const MemRegion *Dest,
147 const Stmt *S,
148 ExplodedNode *Pred,
149 ExplodedNodeSet &Dst) {
150 if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
151 return;
152 // Create the context for 'this' region.
153 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
154 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000155 S, Builder->getBlock(),
Zhongxing Xub13453b2010-11-20 06:53:12 +0000156 Builder->getIndex());
157
158 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
159
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000160 CallEnter PP(S, SFC, Pred->getLocationContext());
Zhongxing Xub13453b2010-11-20 06:53:12 +0000161
162 const GRState *state = Pred->getState();
163 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
164 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
165 if (N)
166 Dst.Add(N);
167}
168
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000169void ExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000170 ExplodedNode *Pred,
171 ExplodedNodeSet &Dst) {
172 // Get the method type.
173 const FunctionProtoType *FnType =
174 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
175 assert(FnType && "Method type not available");
176
177 // Evaluate explicit arguments with a worklist.
Ted Kremenek9c149532010-12-01 21:57:22 +0000178 ExplodedNodeSet argsEvaluated;
179 evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000180
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000181 // Evaluate the implicit object argument.
Ted Kremenek9c149532010-12-01 21:57:22 +0000182 ExplodedNodeSet AllargsEvaluated;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000183 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
184 if (!ME)
185 return;
186 Expr *ObjArgExpr = ME->getBase();
Ted Kremenek9c149532010-12-01 21:57:22 +0000187 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
188 E = argsEvaluated.end(); I != E; ++I) {
Ted Kremenek9c149532010-12-01 21:57:22 +0000189 Visit(ObjArgExpr, *I, AllargsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000190 }
191
Ted Kremeneka54e8242010-09-30 01:06:29 +0000192 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000193 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
194 assert(MD && "not a CXXMethodDecl?");
Ted Kremenek9c149532010-12-01 21:57:22 +0000195 evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000196}
197
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000198void ExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000199 ExplodedNode *Pred,
200 ExplodedNodeSet &Dst) {
201 const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
202 if (!MD) {
203 // If the operator doesn't represent a method call treat as regural call.
Ted Kremenek892697d2010-12-16 07:46:53 +0000204 VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000205 return;
206 }
207
208 // Determine the type of function we're calling (if available).
209 const FunctionProtoType *Proto = NULL;
210 QualType FnType = C->getCallee()->IgnoreParens()->getType();
211 if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
212 Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
213
214 // Evaluate arguments treating the first one (object method is called on)
215 // as alvalue.
Ted Kremenek9c149532010-12-01 21:57:22 +0000216 ExplodedNodeSet argsEvaluated;
217 evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000218
219 // Now evaluate the call itself.
Ted Kremenek9c149532010-12-01 21:57:22 +0000220 evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000221}
222
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000223void ExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000224 const Expr *ThisExpr, ExplodedNode *Pred,
225 ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
226 // Allow checkers to pre-visit the member call.
227 ExplodedNodeSet PreVisitChecks;
Argyrios Kyrtzidiseb48bd12011-03-01 01:16:03 +0000228 getCheckerManager().runCheckersForPreStmt(PreVisitChecks, Src, MCE, *this);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000229
Ted Kremeneka54e8242010-09-30 01:06:29 +0000230 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000231 // FIXME: conservative method call evaluation.
Argyrios Kyrtzidiseb48bd12011-03-01 01:16:03 +0000232 getCheckerManager().runCheckersForPostStmt(Dst, PreVisitChecks, MCE, *this);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000233 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000234 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000235
236 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
237 Pred->getLocationContext(),
Ted Kremenek892697d2010-12-16 07:46:53 +0000238 MCE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000239 Builder->getBlock(),
240 Builder->getIndex());
Zhongxing Xu32303022010-11-24 13:48:50 +0000241 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xu19b78d92010-11-24 08:53:20 +0000242 CallEnter Loc(MCE, SFC, Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000243 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
244 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000245 // Set up 'this' region.
246 const GRState *state = GetState(*I);
Marcin Swiderski6a02b602010-11-18 06:29:23 +0000247 state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
248 Dst.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000249 }
250}
251
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000252void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000253 ExplodedNodeSet &Dst) {
254 if (CNE->isArray()) {
255 // FIXME: allocating an array has not been handled.
256 return;
257 }
258
259 unsigned Count = Builder->getCurrentBlockCount();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000260 DefinedOrUnknownSVal symVal =
261 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count);
262 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000263
264 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
265
266 const ElementRegion *EleReg =
267 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
268
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000269 // Evaluate constructor arguments.
270 const FunctionProtoType *FnType = NULL;
271 const CXXConstructorDecl *CD = CNE->getConstructor();
272 if (CD)
273 FnType = CD->getType()->getAs<FunctionProtoType>();
Ted Kremenek9c149532010-12-01 21:57:22 +0000274 ExplodedNodeSet argsEvaluated;
275 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
276 FnType, Pred, argsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000277
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000278 // Initialize the object region and bind the 'new' expression.
Ted Kremenek9c149532010-12-01 21:57:22 +0000279 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
280 E = argsEvaluated.end(); I != E; ++I) {
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000281 const GRState *state = GetState(*I);
282
283 if (ObjTy->isRecordType()) {
Ted Kremenek25345282011-02-11 19:48:15 +0000284 state = state->invalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000285 } else {
286 if (CNE->hasInitializer()) {
287 SVal V = state->getSVal(*CNE->constructor_arg_begin());
288 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
289 } else {
290 // Explicitly set to undefined, because currently we retrieve symbolic
291 // value from symbolic region.
292 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
293 }
294 }
295 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000296 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000297 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000298}
299
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000300void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000301 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000302 // Should do more checking.
Ted Kremenek9c149532010-12-01 21:57:22 +0000303 ExplodedNodeSet Argevaluated;
304 Visit(CDE->getArgument(), Pred, Argevaluated);
305 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
306 E = Argevaluated.end(); I != E; ++I) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000307 const GRState *state = GetState(*I);
308 MakeNode(Dst, CDE, *I, state);
309 }
310}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000311
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000312void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000313 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000314 // Get the this object region from StoreManager.
315 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000316 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000317 getContext().getCanonicalType(TE->getType()),
318 Pred->getLocationContext());
319
320 const GRState *state = GetState(Pred);
321 SVal V = state->getSVal(loc::MemRegionVal(R));
322 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
323}