1 //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the C++ expression evaluation engine.
12 //===----------------------------------------------------------------------===//
14 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
18 #include "clang/AST/DeclCXX.h"
20 using namespace clang;
24 class CallExprWLItem {
26 CallExpr::const_arg_iterator I;
29 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
34 void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
35 const FunctionProtoType *FnType,
36 ExplodedNode *Pred, ExplodedNodeSet &Dst,
37 bool FstArgAsLValue) {
40 SmallVector<CallExprWLItem, 20> WorkList;
41 WorkList.reserve(AE - AI);
42 WorkList.push_back(CallExprWLItem(AI, Pred));
44 while (!WorkList.empty()) {
45 CallExprWLItem Item = WorkList.back();
53 // Evaluate the argument.
56 FstArgAsLValue = false;
59 Visit(*Item.I, Item.N, Tmp);
61 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
62 WorkList.push_back(CallExprWLItem(Item.I, *NI));
66 void ExprEngine::evalCallee(const CallExpr *callExpr,
67 const ExplodedNodeSet &src,
68 ExplodedNodeSet &dest) {
70 const Expr *callee = 0;
72 switch (callExpr->getStmtClass()) {
73 case Stmt::CXXMemberCallExprClass: {
74 // Evaluate the implicit object argument that is the recipient of the
76 callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
78 // FIXME: handle member pointers.
85 callee = callExpr->getCallee()->IgnoreParens();
90 for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
91 Visit(callee, *i, dest);
94 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
95 const StackFrameContext *SFC) {
96 const Type *T = D->getTypeForDecl();
97 QualType PT = getContext().getPointerType(QualType(T, 0));
98 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
101 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
102 const StackFrameContext *frameCtx) {
103 return svalBuilder.getRegionManager().
104 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
107 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
109 ExplodedNodeSet &Dst) {
110 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
111 const ProgramState *state = Pred->getState();
113 // Bind the temporary object to the value of the expression. Then bind
114 // the expression to the location of the object.
115 SVal V = state->getSVal(tempExpr);
118 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
119 Pred->getLocationContext());
121 state = state->bindLoc(loc::MemRegionVal(R), V);
122 MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
125 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
126 const MemRegion *Dest,
128 ExplodedNodeSet &destNodes) {
130 const CXXConstructorDecl *CD = E->getConstructor();
134 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
135 // FIXME: invalidate the object.
139 // Evaluate other arguments.
140 ExplodedNodeSet argsEvaluated;
141 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
142 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
145 // Is the constructor elidable?
146 if (E->isElidable()) {
147 VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
148 // FIXME: this is here to force propagation if VisitAggExpr doesn't
149 if (destNodes.empty())
155 // Perform the previsit of the constructor.
156 ExplodedNodeSet destPreVisit;
157 getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
160 // Evaluate the constructor. Currently we don't now allow checker-specific
161 // implementations of specific constructors (as we do with ordinary
162 // function calls. We can re-evaluate this in the future.
165 // Inlining currently isn't fully implemented.
167 if (AMgr.shouldInlineCall()) {
170 svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
171 Pred->getLocationContext());
173 // The callee stack frame context used to create the 'this'
175 const StackFrameContext *SFC =
176 AMgr.getStackFrame(CD, Pred->getLocationContext(),
177 E, Builder->getBlock(), Builder->getIndex());
179 // Create the 'this' region.
180 const CXXThisRegion *ThisR =
181 getCXXThisRegion(E->getConstructor()->getParent(), SFC);
183 CallEnter Loc(E, SFC, Pred->getLocationContext());
186 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
187 NE = argsEvaluated.end(); NI != NE; ++NI) {
188 const ProgramState *state = (*NI)->getState();
189 // Setup 'this' region, so that the ctor is evaluated on the object pointed
191 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
192 if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
198 // Default semantics: invalidate all regions passed as arguments.
199 ExplodedNodeSet destCall;
201 for (ExplodedNodeSet::iterator
202 i = destPreVisit.begin(), e = destPreVisit.end();
205 ExplodedNode *Pred = *i;
206 const LocationContext *LC = Pred->getLocationContext();
207 const ProgramState *state = Pred->getState();
209 state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
210 Builder->MakeNode(destCall, E, Pred, state);
213 // Do the post visit.
214 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
217 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
218 const MemRegion *Dest,
221 ExplodedNodeSet &Dst) {
222 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
224 // Create the context for 'this' region.
225 const StackFrameContext *SFC = AMgr.getStackFrame(DD,
226 Pred->getLocationContext(),
227 S, Builder->getBlock(),
228 Builder->getIndex());
230 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
232 CallEnter PP(S, SFC, Pred->getLocationContext());
234 const ProgramState *state = Pred->getState();
235 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
236 ExplodedNode *N = Builder->generateNode(PP, state, Pred);
241 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
242 ExplodedNodeSet &Dst) {
244 unsigned blockCount = Builder->getCurrentBlockCount();
245 DefinedOrUnknownSVal symVal =
246 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
247 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
248 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
249 const ElementRegion *EleReg =
250 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
252 if (CNE->isArray()) {
253 // FIXME: allocating an array requires simulating the constructors.
254 // For now, just return a symbolicated region.
255 const ProgramState *state = Pred->getState();
256 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
257 MakeNode(Dst, CNE, Pred, state);
261 // Evaluate constructor arguments.
262 const FunctionProtoType *FnType = NULL;
263 const CXXConstructorDecl *CD = CNE->getConstructor();
265 FnType = CD->getType()->getAs<FunctionProtoType>();
266 ExplodedNodeSet argsEvaluated;
267 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
268 FnType, Pred, argsEvaluated);
270 // Initialize the object region and bind the 'new' expression.
271 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
272 E = argsEvaluated.end(); I != E; ++I) {
274 const ProgramState *state = (*I)->getState();
276 // Accumulate list of regions that are invalidated.
277 // FIXME: Eventually we should unify the logic for constructor
278 // processing in one place.
279 SmallVector<const MemRegion*, 10> regionsToInvalidate;
280 for (CXXNewExpr::const_arg_iterator
281 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
284 SVal val = state->getSVal(*ai);
285 if (const MemRegion *region = val.getAsRegion())
286 regionsToInvalidate.push_back(region);
289 if (ObjTy->isRecordType()) {
290 regionsToInvalidate.push_back(EleReg);
291 // Invalidate the regions.
292 state = state->invalidateRegions(regionsToInvalidate,
294 /* invalidateGlobals = */ true);
297 // Invalidate the regions.
298 state = state->invalidateRegions(regionsToInvalidate,
300 /* invalidateGlobals = */ true);
302 if (CNE->hasInitializer()) {
303 SVal V = state->getSVal(*CNE->constructor_arg_begin());
304 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
306 // Explicitly set to undefined, because currently we retrieve symbolic
307 // value from symbolic region.
308 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
311 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
312 MakeNode(Dst, CNE, *I, state);
316 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
317 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
318 // Should do more checking.
319 ExplodedNodeSet Argevaluated;
320 Visit(CDE->getArgument(), Pred, Argevaluated);
321 for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
322 E = Argevaluated.end(); I != E; ++I) {
323 const ProgramState *state = (*I)->getState();
324 MakeNode(Dst, CDE, *I, state);
328 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
329 ExplodedNodeSet &Dst) {
330 // Get the this object region from StoreManager.
332 svalBuilder.getRegionManager().getCXXThisRegion(
333 getContext().getCanonicalType(TE->getType()),
334 Pred->getLocationContext());
336 const ProgramState *state = Pred->getState();
337 SVal V = state->getSVal(loc::MemRegionVal(R));
338 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));