blob: 67c478b86fd707d55a541b9175156be129c29816 [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
Zhongxing Xub17b1b32010-04-20 03:37:34 +000020void GRExprEngine::EvalArguments(ExprIterator AI, ExprIterator AE,
21 const FunctionProtoType *FnType,
22 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
23 llvm::SmallVector<CallExprWLItem, 20> WorkList;
24 WorkList.reserve(AE - AI);
25 WorkList.push_back(CallExprWLItem(AI, Pred));
26
27 while (!WorkList.empty()) {
28 CallExprWLItem Item = WorkList.back();
29 WorkList.pop_back();
30
31 if (Item.I == AE) {
32 Dst.insert(Item.N);
33 continue;
34 }
35
36 ExplodedNodeSet Tmp;
37 const unsigned ParamIdx = Item.I - AI;
38 bool VisitAsLvalue = FnType? FnType->getArgType(ParamIdx)->isReferenceType()
39 : false;
40 if (VisitAsLvalue)
41 VisitLValue(*Item.I, Item.N, Tmp);
42 else
43 Visit(*Item.I, Item.N, Tmp);
44
45 ++(Item.I);
46 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
47 WorkList.push_back(CallExprWLItem(Item.I, *NI));
48 }
49}
50
Zhongxing Xucb7464a2010-04-19 12:51:02 +000051const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
52 const StackFrameContext *SFC) {
53 Type *T = D->getParent()->getTypeForDecl();
54 QualType PT = getContext().getPointerType(QualType(T,0));
55 return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
56}
57
58void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
59 ExplodedNodeSet &Dst) {
60 ExplodedNodeSet Tmp;
61 Visit(Ex, Pred, Tmp);
62 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
63 const GRState *state = GetState(*I);
64
65 // Bind the temporary object to the value of the expression. Then bind
66 // the expression to the location of the object.
67 SVal V = state->getSVal(Ex);
68
69 const MemRegion *R =
70 ValMgr.getRegionManager().getCXXObjectRegion(Ex,
71 Pred->getLocationContext());
72
73 state = state->bindLoc(loc::MemRegionVal(R), V);
74 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
75 }
76}
77
78void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
79 ExplodedNode *Pred,
80 ExplodedNodeSet &Dst) {
81 if (E->isElidable()) {
82 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
83 return;
84 }
85
86 const CXXConstructorDecl *CD = E->getConstructor();
87 assert(CD);
88
89 if (!CD->isThisDeclarationADefinition())
90 // FIXME: invalidate the object.
91 return;
92
93
94 // Evaluate other arguments.
95 CXXConstructExpr::arg_iterator AB
96 = const_cast<CXXConstructExpr*>(E)->arg_begin();
97 CXXConstructExpr::arg_iterator AE
98 = const_cast<CXXConstructExpr*>(E)->arg_end();
99 llvm::SmallVector<CallExprWLItem, 20> WorkList;
100 WorkList.reserve(AE - AB);
101 WorkList.push_back(CallExprWLItem(AB, Pred));
102 ExplodedNodeSet ArgsEvaluated;
103 const FunctionProtoType *Proto = CD->getType()->getAs<FunctionProtoType>();
104
105 while (!WorkList.empty()) {
106 CallExprWLItem Item = WorkList.back();
107 WorkList.pop_back();
108
109 if (Item.I == AE) {
110 ArgsEvaluated.insert(Item.N);
111 continue;
112 }
113
114 // Evaluate the argument.
115 ExplodedNodeSet Tmp;
116 const unsigned ParamIdx = Item.I - AB;
117
118 bool VisitAsLvalue = false;
119
120 if (ParamIdx < Proto->getNumArgs())
121 VisitAsLvalue = Proto->getArgType(ParamIdx)->isReferenceType();
122
123 if (VisitAsLvalue)
124 VisitLValue(*Item.I, Item.N, Tmp);
125 else
126 Visit(*Item.I, Item.N, Tmp);
127
128 ++(Item.I);
129
130 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
131 WorkList.push_back(CallExprWLItem(Item.I, *NI));
132 }
133 // The callee stack frame context used to create the 'this' parameter region.
134 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
135 Pred->getLocationContext(),
136 E, Builder->getBlock(), Builder->getIndex());
137
138 const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
139
140 CallEnter Loc(E, CD, Pred->getLocationContext());
141 for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
142 NE = ArgsEvaluated.end(); NI != NE; ++NI) {
143 const GRState *state = GetState(*NI);
144 // Setup 'this' region.
145 state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
146 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
147 if (N)
148 Dst.Add(N);
149 }
150}
151
152void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
153 ExplodedNode *Pred,
154 ExplodedNodeSet &Dst) {
155 // Get the method type.
156 const FunctionProtoType *FnType =
157 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
158 assert(FnType && "Method type not available");
159
160 // Evaluate explicit arguments with a worklist.
161 CallExpr::arg_iterator AB = const_cast<CXXMemberCallExpr*>(MCE)->arg_begin(),
162 AE = const_cast<CXXMemberCallExpr*>(MCE)->arg_end();
163 llvm::SmallVector<CallExprWLItem, 20> WorkList;
164 WorkList.reserve(AE - AB);
165 WorkList.push_back(CallExprWLItem(AB, Pred));
166 ExplodedNodeSet ArgsEvaluated;
167
168 while (!WorkList.empty()) {
169 CallExprWLItem Item = WorkList.back();
170 WorkList.pop_back();
171
172 if (Item.I == AE) {
173 ArgsEvaluated.insert(Item.N);
174 continue;
175 }
176
177 ExplodedNodeSet Tmp;
178 const unsigned ParamIdx = Item.I - AB;
179 bool VisitAsLvalue = FnType->getArgType(ParamIdx)->isReferenceType();
180
181 if (VisitAsLvalue)
182 VisitLValue(*Item.I, Item.N, Tmp);
183 else
184 Visit(*Item.I, Item.N, Tmp);
185
186 ++(Item.I);
187 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
188 WorkList.push_back(CallExprWLItem(Item.I, *NI));
189 }
190 // Evaluate the implicit object argument.
191 ExplodedNodeSet AllArgsEvaluated;
192 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
193 if (!ME)
194 return;
195 Expr *ObjArgExpr = ME->getBase();
196 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
197 E = ArgsEvaluated.end(); I != E; ++I) {
198 if (ME->isArrow())
199 Visit(ObjArgExpr, *I, AllArgsEvaluated);
200 else
201 VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
202 }
203
204 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
205 assert(MD && "not a CXXMethodDecl?");
206
207 if (!MD->isThisDeclarationADefinition())
208 // FIXME: conservative method call evaluation.
209 return;
210
211 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
212 Pred->getLocationContext(),
213 MCE,
214 Builder->getBlock(),
215 Builder->getIndex());
216 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
217 CallEnter Loc(MCE, MD, Pred->getLocationContext());
218 for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
219 E = AllArgsEvaluated.end(); I != E; ++I) {
220 // Set up 'this' region.
221 const GRState *state = GetState(*I);
222 state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
223 ExplodedNode *N = Builder->generateNode(Loc, state, *I);
224 if (N)
225 Dst.Add(N);
226 }
227}
228
229void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
230 ExplodedNodeSet &Dst) {
231 if (CNE->isArray()) {
232 // FIXME: allocating an array has not been handled.
233 return;
234 }
235
236 unsigned Count = Builder->getCurrentBlockCount();
237 DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
238 CNE->getType(), Count);
239 const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
240
241 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
242
243 const ElementRegion *EleReg =
244 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
245
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000246 // Evaluate constructor arguments.
247 const FunctionProtoType *FnType = NULL;
248 const CXXConstructorDecl *CD = CNE->getConstructor();
249 if (CD)
250 FnType = CD->getType()->getAs<FunctionProtoType>();
251 ExplodedNodeSet ArgsEvaluated;
252 EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
253 FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000254
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000255 // Initialize the object region and bind the 'new' expression.
256 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
257 E = ArgsEvaluated.end(); I != E; ++I) {
258 const GRState *state = GetState(*I);
259
260 if (ObjTy->isRecordType()) {
261 Store store = state->getStore();
262 StoreManager::InvalidatedSymbols IS;
263 store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS);
264 state = state->makeWithStore(store);
265 } else {
266 if (CNE->hasInitializer()) {
267 SVal V = state->getSVal(*CNE->constructor_arg_begin());
268 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
269 } else {
270 // Explicitly set to undefined, because currently we retrieve symbolic
271 // value from symbolic region.
272 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
273 }
274 }
275 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
276 MakeNode(Dst, CNE, Pred, state);
277 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000278}
279
280
281void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
282 ExplodedNodeSet & Dst) {
283 // Get the this object region from StoreManager.
284 const MemRegion *R =
285 ValMgr.getRegionManager().getCXXThisRegion(
286 getContext().getCanonicalType(TE->getType()),
287 Pred->getLocationContext());
288
289 const GRState *state = GetState(Pred);
290 SVal V = state->getSVal(loc::MemRegionVal(R));
291 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
292}