blob: c6be6b681da5198981aa8135fcb66534ce95e0c6 [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,
33 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
Ted Kremenekc69c4382010-09-23 05:14:51 +000034
35
Zhongxing Xub17b1b32010-04-20 03:37:34 +000036 llvm::SmallVector<CallExprWLItem, 20> WorkList;
37 WorkList.reserve(AE - AI);
38 WorkList.push_back(CallExprWLItem(AI, Pred));
39
40 while (!WorkList.empty()) {
41 CallExprWLItem Item = WorkList.back();
42 WorkList.pop_back();
43
44 if (Item.I == AE) {
45 Dst.insert(Item.N);
46 continue;
47 }
48
Ted Kremenekc69c4382010-09-23 05:14:51 +000049 // Evaluate the argument.
Zhongxing Xub17b1b32010-04-20 03:37:34 +000050 ExplodedNodeSet Tmp;
51 const unsigned ParamIdx = Item.I - AI;
Ted Kremenekc69c4382010-09-23 05:14:51 +000052 const bool VisitAsLvalue = FnType && ParamIdx < FnType->getNumArgs()
53 ? FnType->getArgType(ParamIdx)->isReferenceType()
54 : false;
55
Zhongxing Xub17b1b32010-04-20 03:37:34 +000056 if (VisitAsLvalue)
57 VisitLValue(*Item.I, Item.N, Tmp);
58 else
59 Visit(*Item.I, Item.N, Tmp);
60
61 ++(Item.I);
62 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
63 WorkList.push_back(CallExprWLItem(Item.I, *NI));
64 }
65}
66
Zhongxing Xucb7464a2010-04-19 12:51:02 +000067const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
68 const StackFrameContext *SFC) {
69 Type *T = D->getParent()->getTypeForDecl();
70 QualType PT = getContext().getPointerType(QualType(T,0));
71 return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
72}
73
Zhongxing Xu03509ae2010-07-20 06:22:24 +000074void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000075 ExplodedNodeSet &Dst) {
76 ExplodedNodeSet Tmp;
77 Visit(Ex, Pred, Tmp);
78 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
79 const GRState *state = GetState(*I);
80
81 // Bind the temporary object to the value of the expression. Then bind
82 // the expression to the location of the object.
83 SVal V = state->getSVal(Ex);
84
85 const MemRegion *R =
86 ValMgr.getRegionManager().getCXXObjectRegion(Ex,
87 Pred->getLocationContext());
88
89 state = state->bindLoc(loc::MemRegionVal(R), V);
90 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
91 }
92}
93
94void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
95 ExplodedNode *Pred,
96 ExplodedNodeSet &Dst) {
97 if (E->isElidable()) {
98 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
99 return;
100 }
101
102 const CXXConstructorDecl *CD = E->getConstructor();
103 assert(CD);
104
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000105 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000106 // FIXME: invalidate the object.
107 return;
108
109
110 // Evaluate other arguments.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000111 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000112 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000113 EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000114 // The callee stack frame context used to create the 'this' parameter region.
115 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
116 Pred->getLocationContext(),
117 E, Builder->getBlock(), Builder->getIndex());
118
119 const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
120
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000121 CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000122 for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
123 NE = ArgsEvaluated.end(); NI != NE; ++NI) {
124 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000125 // Setup 'this' region, so that the ctor is evaluated on the object pointed
126 // by 'Dest'.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000127 state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
128 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
129 if (N)
130 Dst.Add(N);
131 }
132}
133
134void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
135 ExplodedNode *Pred,
136 ExplodedNodeSet &Dst) {
137 // Get the method type.
138 const FunctionProtoType *FnType =
139 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
140 assert(FnType && "Method type not available");
141
142 // Evaluate explicit arguments with a worklist.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000143 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000144 EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000145
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000146 // Evaluate the implicit object argument.
147 ExplodedNodeSet AllArgsEvaluated;
148 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
149 if (!ME)
150 return;
151 Expr *ObjArgExpr = ME->getBase();
152 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
153 E = ArgsEvaluated.end(); I != E; ++I) {
154 if (ME->isArrow())
155 Visit(ObjArgExpr, *I, AllArgsEvaluated);
156 else
157 VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
158 }
159
Ted Kremeneka54e8242010-09-30 01:06:29 +0000160 // Allow checkers to pre-visit the member call.
161 ExplodedNodeSet PreVisitChecks;
162 CheckerVisit(MCE, PreVisitChecks, AllArgsEvaluated, PreVisitStmtCallback);
163
164 // Now evaluate the call itself.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000165 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
166 assert(MD && "not a CXXMethodDecl?");
167
Ted Kremeneka54e8242010-09-30 01:06:29 +0000168 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000169 // FIXME: conservative method call evaluation.
Ted Kremeneka54e8242010-09-30 01:06:29 +0000170 CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000171 return;
Ted Kremeneka54e8242010-09-30 01:06:29 +0000172 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000173
Ted Kremeneka54e8242010-09-30 01:06:29 +0000174 ExplodedNodeSet SetupThis;
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000175 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
176 Pred->getLocationContext(),
177 MCE,
178 Builder->getBlock(),
179 Builder->getIndex());
180 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000181 CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
Ted Kremeneka54e8242010-09-30 01:06:29 +0000182 for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
183 E = PreVisitChecks.end(); I != E; ++I) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000184 // Set up 'this' region.
185 const GRState *state = GetState(*I);
186 state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
Ted Kremeneka54e8242010-09-30 01:06:29 +0000187 SetupThis.Add(Builder->generateNode(Loc, state, *I));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000188 }
Ted Kremeneka54e8242010-09-30 01:06:29 +0000189
190 // FIXME: Perform the actual method call. Right now all we do is evaluate
191 // the arguments.
192
193 // Perform post-visit.
194 CheckerVisit(MCE, Dst, /* FIXME: don't forget to update later */ SetupThis,
195 PostVisitStmtCallback);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000196}
197
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000198void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000199 ExplodedNodeSet &Dst) {
200 if (CNE->isArray()) {
201 // FIXME: allocating an array has not been handled.
202 return;
203 }
204
205 unsigned Count = Builder->getCurrentBlockCount();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000206 DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000207 CNE->getType(), Count);
208 const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
209
210 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
211
212 const ElementRegion *EleReg =
213 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
214
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000215 // Evaluate constructor arguments.
216 const FunctionProtoType *FnType = NULL;
217 const CXXConstructorDecl *CD = CNE->getConstructor();
218 if (CD)
219 FnType = CD->getType()->getAs<FunctionProtoType>();
220 ExplodedNodeSet ArgsEvaluated;
221 EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
222 FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000223
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000224 // Initialize the object region and bind the 'new' expression.
225 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
226 E = ArgsEvaluated.end(); I != E; ++I) {
227 const GRState *state = GetState(*I);
228
229 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000230 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000231 } else {
232 if (CNE->hasInitializer()) {
233 SVal V = state->getSVal(*CNE->constructor_arg_begin());
234 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
235 } else {
236 // Explicitly set to undefined, because currently we retrieve symbolic
237 // value from symbolic region.
238 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
239 }
240 }
241 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000242 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000243 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000244}
245
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000246void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
247 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000248 // Should do more checking.
249 ExplodedNodeSet ArgEvaluated;
250 Visit(CDE->getArgument(), Pred, ArgEvaluated);
251 for (ExplodedNodeSet::iterator I = ArgEvaluated.begin(),
252 E = ArgEvaluated.end(); I != E; ++I) {
253 const GRState *state = GetState(*I);
254 MakeNode(Dst, CDE, *I, state);
255 }
256}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000257
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000258void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000259 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000260 // Get the this object region from StoreManager.
261 const MemRegion *R =
262 ValMgr.getRegionManager().getCXXThisRegion(
263 getContext().getCanonicalType(TE->getType()),
264 Pred->getLocationContext());
265
266 const GRState *state = GetState(Pred);
267 SVal V = state->getSVal(loc::MemRegionVal(R));
268 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
269}