1 //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- 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/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"
19 #include "clang/AST/StmtCXX.h"
20
21 using namespace clang;
22 using namespace ento;
23
getCXXThisRegion(const CXXRecordDecl * D,const StackFrameContext * SFC)24 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
25 const StackFrameContext *SFC) {
26 const Type *T = D->getTypeForDecl();
27 QualType PT = getContext().getPointerType(QualType(T, 0));
28 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
29 }
30
getCXXThisRegion(const CXXMethodDecl * decl,const StackFrameContext * frameCtx)31 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
32 const StackFrameContext *frameCtx) {
33 return svalBuilder.getRegionManager().
34 getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
35 }
36
CreateCXXTemporaryObject(const MaterializeTemporaryExpr * ME,ExplodedNode * Pred,ExplodedNodeSet & Dst)37 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
38 ExplodedNode *Pred,
39 ExplodedNodeSet &Dst) {
40 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
41 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
42 ProgramStateRef state = Pred->getState();
43 const LocationContext *LCtx = Pred->getLocationContext();
44
45 // Bind the temporary object to the value of the expression. Then bind
46 // the expression to the location of the object.
47 SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
48
49 const MemRegion *R =
50 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
51
52 state = state->bindLoc(loc::MemRegionVal(R), V);
53 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
54 }
55
VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr * expr,ExplodedNode * Pred,ExplodedNodeSet & Dst)56 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
57 ExplodedNode *Pred,
58 ExplodedNodeSet &Dst) {
59 VisitCXXConstructExpr(expr, 0, Pred, Dst);
60 }
61
VisitCXXConstructExpr(const CXXConstructExpr * E,const MemRegion * Dest,ExplodedNode * Pred,ExplodedNodeSet & destNodes)62 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
63 const MemRegion *Dest,
64 ExplodedNode *Pred,
65 ExplodedNodeSet &destNodes) {
66
67 #if 0
68 const CXXConstructorDecl *CD = E->getConstructor();
69 assert(CD);
70 #endif
71
72 #if 0
73 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
74 // FIXME: invalidate the object.
75 return;
76 #endif
77
78 #if 0
79 // Is the constructor elidable?
80 if (E->isElidable()) {
81 destNodes.Add(Pred);
82 return;
83 }
84 #endif
85
86 // Perform the previsit of the constructor.
87 ExplodedNodeSet SrcNodes;
88 SrcNodes.Add(Pred);
89 ExplodedNodeSet TmpNodes;
90 getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this);
91
92 // Evaluate the constructor. Currently we don't now allow checker-specific
93 // implementations of specific constructors (as we do with ordinary
94 // function calls. We can re-evaluate this in the future.
95
96 #if 0
97 // Inlining currently isn't fully implemented.
98
99 if (AMgr.shouldInlineCall()) {
100 if (!Dest)
101 Dest =
102 svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
103 Pred->getLocationContext());
104
105 // The callee stack frame context used to create the 'this'
106 // parameter region.
107 const StackFrameContext *SFC =
108 AMgr.getStackFrame(CD, Pred->getLocationContext(),
109 E, currentBuilderContext->getBlock(),
110 currentStmtIdx);
111
112 // Create the 'this' region.
113 const CXXThisRegion *ThisR =
114 getCXXThisRegion(E->getConstructor()->getParent(), SFC);
115
116 CallEnter Loc(E, SFC, Pred->getLocationContext());
117
118 StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext);
119 for (ExplodedNodeSet::iterator NI = SrcNodes.begin(),
120 NE = SrcNodes.end(); NI != NE; ++NI) {
121 ProgramStateRef state = (*NI)->getState();
122 // Setup 'this' region, so that the ctor is evaluated on the object pointed
123 // by 'Dest'.
124 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
125 Bldr.generateNode(Loc, *NI, state);
126 }
127 }
128 #endif
129
130 // Default semantics: invalidate all regions passed as arguments.
131 ExplodedNodeSet destCall;
132 {
133 StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext);
134 for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end();
135 i != e; ++i)
136 {
137 ExplodedNode *Pred = *i;
138 const LocationContext *LC = Pred->getLocationContext();
139 ProgramStateRef state = Pred->getState();
140
141 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
142 Bldr.generateNode(E, Pred, state);
143 }
144 }
145 // Do the post visit.
146 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
147 }
148
VisitCXXDestructor(const CXXDestructorDecl * DD,const MemRegion * Dest,const Stmt * S,ExplodedNode * Pred,ExplodedNodeSet & Dst)149 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
150 const MemRegion *Dest,
151 const Stmt *S,
152 ExplodedNode *Pred,
153 ExplodedNodeSet &Dst) {
154 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
155 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
156 return;
157
158 // Create the context for 'this' region.
159 const StackFrameContext *SFC =
160 AnalysisDeclContexts.getContext(DD)->
161 getStackFrame(Pred->getLocationContext(), S,
162 currentBuilderContext->getBlock(), currentStmtIdx);
163
164 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
165
166 CallEnter PP(S, SFC, Pred->getLocationContext());
167
168 ProgramStateRef state = Pred->getState();
169 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
170 Bldr.generateNode(PP, Pred, state);
171 }
172
VisitCXXNewExpr(const CXXNewExpr * CNE,ExplodedNode * Pred,ExplodedNodeSet & Dst)173 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
174 ExplodedNodeSet &Dst) {
175 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
176
177 unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
178 const LocationContext *LCtx = Pred->getLocationContext();
179 DefinedOrUnknownSVal symVal =
180 svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
181 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
182 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
183 const ElementRegion *EleReg =
184 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
185
186 if (CNE->isArray()) {
187 // FIXME: allocating an array requires simulating the constructors.
188 // For now, just return a symbolicated region.
189 ProgramStateRef state = Pred->getState();
190 state = state->BindExpr(CNE, Pred->getLocationContext(),
191 loc::MemRegionVal(EleReg));
192 Bldr.generateNode(CNE, Pred, state);
193 return;
194 }
195
196 // FIXME: Update for AST changes.
197 #if 0
198 // Evaluate constructor arguments.
199 const FunctionProtoType *FnType = NULL;
200 const CXXConstructorDecl *CD = CNE->getConstructor();
201 if (CD)
202 FnType = CD->getType()->getAs<FunctionProtoType>();
203 ExplodedNodeSet argsEvaluated;
204 Bldr.takeNodes(Pred);
205 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
206 FnType, Pred, argsEvaluated);
207 Bldr.addNodes(argsEvaluated);
208
209 // Initialize the object region and bind the 'new' expression.
210 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
211 E = argsEvaluated.end(); I != E; ++I) {
212
213 ProgramStateRef state = (*I)->getState();
214
215 // Accumulate list of regions that are invalidated.
216 // FIXME: Eventually we should unify the logic for constructor
217 // processing in one place.
218 SmallVector<const MemRegion*, 10> regionsToInvalidate;
219 for (CXXNewExpr::const_arg_iterator
220 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
221 ai != ae; ++ai)
222 {
223 SVal val = state->getSVal(*ai, (*I)->getLocationContext());
224 if (const MemRegion *region = val.getAsRegion())
225 regionsToInvalidate.push_back(region);
226 }
227
228 if (ObjTy->isRecordType()) {
229 regionsToInvalidate.push_back(EleReg);
230 // Invalidate the regions.
231 // TODO: Pass the call to new information as the last argument, to limit
232 // the globals which will get invalidated.
233 state = state->invalidateRegions(regionsToInvalidate,
234 CNE, blockCount, 0, 0);
235
236 } else {
237 // Invalidate the regions.
238 // TODO: Pass the call to new information as the last argument, to limit
239 // the globals which will get invalidated.
240 state = state->invalidateRegions(regionsToInvalidate,
241 CNE, blockCount, 0, 0);
242
243 if (CNE->hasInitializer()) {
244 SVal V = state->getSVal(*CNE->constructor_arg_begin(),
245 (*I)->getLocationContext());
246 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
247 } else {
248 // Explicitly set to undefined, because currently we retrieve symbolic
249 // value from symbolic region.
250 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
251 }
252 }
253 state = state->BindExpr(CNE, (*I)->getLocationContext(),
254 loc::MemRegionVal(EleReg));
255 Bldr.generateNode(CNE, *I, state);
256 }
257 #endif
258 }
259
VisitCXXDeleteExpr(const CXXDeleteExpr * CDE,ExplodedNode * Pred,ExplodedNodeSet & Dst)260 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
261 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
262 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
263 ProgramStateRef state = Pred->getState();
264 Bldr.generateNode(CDE, Pred, state);
265 }
266
VisitCXXCatchStmt(const CXXCatchStmt * CS,ExplodedNode * Pred,ExplodedNodeSet & Dst)267 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
268 ExplodedNode *Pred,
269 ExplodedNodeSet &Dst) {
270 const VarDecl *VD = CS->getExceptionDecl();
271 if (!VD) {
272 Dst.Add(Pred);
273 return;
274 }
275
276 const LocationContext *LCtx = Pred->getLocationContext();
277 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
278 currentBuilderContext->getCurrentBlockCount());
279 ProgramStateRef state = Pred->getState();
280 state = state->bindLoc(state->getLValue(VD, LCtx), V);
281
282 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
283 Bldr.generateNode(CS, Pred, state);
284 }
285
VisitCXXThisExpr(const CXXThisExpr * TE,ExplodedNode * Pred,ExplodedNodeSet & Dst)286 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
287 ExplodedNodeSet &Dst) {
288 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
289
290 // Get the this object region from StoreManager.
291 const LocationContext *LCtx = Pred->getLocationContext();
292 const MemRegion *R =
293 svalBuilder.getRegionManager().getCXXThisRegion(
294 getContext().getCanonicalType(TE->getType()),
295 LCtx);
296
297 ProgramStateRef state = Pred->getState();
298 SVal V = state->getSVal(loc::MemRegionVal(R));
299 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
300 }
301