blob: 4c996bb22ee53bf5f02ee1f46a57c9a91d08e177 [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
Zhongxing Xu03509ae2010-07-20 06:22:24 +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 Xu03509ae2010-07-20 06:22:24 +000080void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000081 ExplodedNodeSet &Dst) {
82 ExplodedNodeSet Tmp;
83 Visit(Ex, Pred, Tmp);
84 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
85 const GRState *state = GetState(*I);
86
87 // Bind the temporary object to the value of the expression. Then bind
88 // the expression to the location of the object.
89 SVal V = state->getSVal(Ex);
90
91 const MemRegion *R =
92 ValMgr.getRegionManager().getCXXObjectRegion(Ex,
93 Pred->getLocationContext());
94
95 state = state->bindLoc(loc::MemRegionVal(R), V);
96 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
97 }
98}
99
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000100void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
101 const MemRegion *Dest,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000102 ExplodedNode *Pred,
103 ExplodedNodeSet &Dst) {
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000104 if (!Dest)
105 Dest = ValMgr.getRegionManager().getCXXObjectRegion(E,
106 Pred->getLocationContext());
107
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000108 if (E->isElidable()) {
109 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
110 return;
111 }
112
113 const CXXConstructorDecl *CD = E->getConstructor();
114 assert(CD);
115
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000116 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000117 // FIXME: invalidate the object.
118 return;
119
120
121 // Evaluate other arguments.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000122 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000123 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000124 EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000125 // The callee stack frame context used to create the 'this' parameter region.
126 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
127 Pred->getLocationContext(),
128 E, Builder->getBlock(), Builder->getIndex());
129
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000130 const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
131 SFC);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000132
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000133 CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000134 for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
135 NE = ArgsEvaluated.end(); NI != NE; ++NI) {
136 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000137 // Setup 'this' region, so that the ctor is evaluated on the object pointed
138 // by 'Dest'.
Zhongxing Xu7ce351d2010-11-01 09:09:44 +0000139 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000140 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
141 if (N)
142 Dst.Add(N);
143 }
144}
145
146void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
147 ExplodedNode *Pred,
148 ExplodedNodeSet &Dst) {
149 // Get the method type.
150 const FunctionProtoType *FnType =
151 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
152 assert(FnType && "Method type not available");
153
154 // Evaluate explicit arguments with a worklist.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000155 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000156 EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000157
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000158 // Evaluate the implicit object argument.
159 ExplodedNodeSet AllArgsEvaluated;
160 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
161 if (!ME)
162 return;
163 Expr *ObjArgExpr = ME->getBase();
164 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
165 E = ArgsEvaluated.end(); I != E; ++I) {
166 if (ME->isArrow())
167 Visit(ObjArgExpr, *I, AllArgsEvaluated);
168 else
169 VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
170 }
171
Ted Kremeneka54e8242010-09-30 01:06:29 +0000172 // Allow checkers to pre-visit the member call.
173 ExplodedNodeSet PreVisitChecks;
174 CheckerVisit(MCE, PreVisitChecks, AllArgsEvaluated, PreVisitStmtCallback);
175
176 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000177 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
178 assert(MD && "not a CXXMethodDecl?");
179
Ted Kremeneka54e8242010-09-30 01:06:29 +0000180 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000181 // FIXME: conservative method call evaluation.
Ted Kremeneka54e8242010-09-30 01:06:29 +0000182 CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000183 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000184 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000185
Ted Kremeneka54e8242010-09-30 01:06:29 +0000186 ExplodedNodeSet SetupThis;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000187 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
188 Pred->getLocationContext(),
189 MCE,
190 Builder->getBlock(),
191 Builder->getIndex());
Zhongxing Xu9dc84c92010-11-16 07:52:17 +0000192 const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000193 CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000194 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
195 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000196 // Set up 'this' region.
197 const GRState *state = GetState(*I);
198 state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
Ted Kremeneka54e8242010-09-30 01:06:29 +0000199 SetupThis.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000200 }
201}
202
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000203void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000204 ExplodedNodeSet &Dst) {
205 if (CNE->isArray()) {
206 // FIXME: allocating an array has not been handled.
207 return;
208 }
209
210 unsigned Count = Builder->getCurrentBlockCount();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000211 DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000212 CNE->getType(), Count);
213 const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
214
215 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
216
217 const ElementRegion *EleReg =
218 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
219
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000220 // Evaluate constructor arguments.
221 const FunctionProtoType *FnType = NULL;
222 const CXXConstructorDecl *CD = CNE->getConstructor();
223 if (CD)
224 FnType = CD->getType()->getAs<FunctionProtoType>();
225 ExplodedNodeSet ArgsEvaluated;
226 EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
227 FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000228
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000229 // Initialize the object region and bind the 'new' expression.
230 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
231 E = ArgsEvaluated.end(); I != E; ++I) {
232 const GRState *state = GetState(*I);
233
234 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000235 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000236 } else {
237 if (CNE->hasInitializer()) {
238 SVal V = state->getSVal(*CNE->constructor_arg_begin());
239 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
240 } else {
241 // Explicitly set to undefined, because currently we retrieve symbolic
242 // value from symbolic region.
243 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
244 }
245 }
246 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000247 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000248 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000249}
250
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000251void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
252 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000253 // Should do more checking.
254 ExplodedNodeSet ArgEvaluated;
255 Visit(CDE->getArgument(), Pred, ArgEvaluated);
256 for (ExplodedNodeSet::iterator I = ArgEvaluated.begin(),
257 E = ArgEvaluated.end(); I != E; ++I) {
258 const GRState *state = GetState(*I);
259 MakeNode(Dst, CDE, *I, state);
260 }
261}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000262
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000263void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000264 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000265 // Get the this object region from StoreManager.
266 const MemRegion *R =
267 ValMgr.getRegionManager().getCXXThisRegion(
268 getContext().getCanonicalType(TE->getType()),
269 Pred->getLocationContext());
270
271 const GRState *state = GetState(Pred);
272 SVal V = state->getSVal(loc::MemRegionVal(R));
273 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
274}