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 
20 using namespace clang;
21 using namespace ento;
22 
23 namespace {
24 class CallExprWLItem {
25 public:
26   CallExpr::const_arg_iterator I;
27   ExplodedNode *N;
28 
29   CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
30     : I(i), N(n) {}
31 };
32 }
33 
34 void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
35                                  const FunctionProtoType *FnType,
36                                  ExplodedNode *Pred, ExplodedNodeSet &Dst,
37                                  bool FstArgAsLValue) {
38 
39 
40   SmallVector<CallExprWLItem, 20> WorkList;
41   WorkList.reserve(AE - AI);
42   WorkList.push_back(CallExprWLItem(AI, Pred));
43 
44   while (!WorkList.empty()) {
45     CallExprWLItem Item = WorkList.back();
46     WorkList.pop_back();
47 
48     if (Item.I == AE) {
49       Dst.insert(Item.N);
50       continue;
51     }
52 
53     // Evaluate the argument.
54     ExplodedNodeSet Tmp;
55     if (FstArgAsLValue) {
56       FstArgAsLValue = false;
57     }
58 
59     Visit(*Item.I, Item.N, Tmp);
60     ++(Item.I);
61     for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
62       WorkList.push_back(CallExprWLItem(Item.I, *NI));
63   }
64 }
65 
66 void ExprEngine::evalCallee(const CallExpr *callExpr,
67                             const ExplodedNodeSet &src,
68                             ExplodedNodeSet &dest) {
69 
70   const Expr *callee = 0;
71 
72   switch (callExpr->getStmtClass()) {
73     case Stmt::CXXMemberCallExprClass: {
74       // Evaluate the implicit object argument that is the recipient of the
75       // call.
76       callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
77 
78       // FIXME: handle member pointers.
79       if (!callee)
80         return;
81 
82       break;
83     }
84     default: {
85       callee = callExpr->getCallee()->IgnoreParens();
86       break;
87     }
88   }
89 
90   for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
91     Visit(callee, *i, dest);
92 }
93 
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);
99 }
100 
101 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
102                                             const StackFrameContext *frameCtx) {
103   return svalBuilder.getRegionManager().
104                     getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
105 }
106 
107 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
108                                           ExplodedNode *Pred,
109                                           ExplodedNodeSet &Dst) {
110   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
111   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
112   ProgramStateRef state = Pred->getState();
113   const LocationContext *LCtx = Pred->getLocationContext();
114 
115   // Bind the temporary object to the value of the expression. Then bind
116   // the expression to the location of the object.
117   SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
118 
119   const MemRegion *R =
120     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
121 
122   state = state->bindLoc(loc::MemRegionVal(R), V);
123   Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
124 }
125 
126 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
127                                              ExplodedNode *Pred,
128                                              ExplodedNodeSet &Dst) {
129   VisitCXXConstructExpr(expr, 0, Pred, Dst);
130 }
131 
132 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
133                                        const MemRegion *Dest,
134                                        ExplodedNode *Pred,
135                                        ExplodedNodeSet &destNodes) {
136 
137   const CXXConstructorDecl *CD = E->getConstructor();
138   assert(CD);
139 
140 #if 0
141   if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
142     // FIXME: invalidate the object.
143     return;
144 #endif
145 
146   // Evaluate other arguments.
147   ExplodedNodeSet argsEvaluated;
148   const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
149   evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
150 
151 #if 0
152   // Is the constructor elidable?
153   if (E->isElidable()) {
154     VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
155     // FIXME: this is here to force propagation if VisitAggExpr doesn't
156     if (destNodes.empty())
157       destNodes.Add(Pred);
158     return;
159   }
160 #endif
161 
162   // Perform the previsit of the constructor.
163   ExplodedNodeSet destPreVisit;
164   getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
165                                             *this);
166 
167   // Evaluate the constructor.  Currently we don't now allow checker-specific
168   // implementations of specific constructors (as we do with ordinary
169   // function calls.  We can re-evaluate this in the future.
170 
171 #if 0
172   // Inlining currently isn't fully implemented.
173 
174   if (AMgr.shouldInlineCall()) {
175     if (!Dest)
176       Dest =
177         svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
178                                                   Pred->getLocationContext());
179 
180     // The callee stack frame context used to create the 'this'
181     // parameter region.
182     const StackFrameContext *SFC =
183       AMgr.getStackFrame(CD, Pred->getLocationContext(),
184                          E, currentBuilderContext->getBlock(),
185                          currentStmtIdx);
186 
187     // Create the 'this' region.
188     const CXXThisRegion *ThisR =
189       getCXXThisRegion(E->getConstructor()->getParent(), SFC);
190 
191     CallEnter Loc(E, SFC, Pred->getLocationContext());
192 
193     StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
194     for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
195                                   NE = argsEvaluated.end(); NI != NE; ++NI) {
196       ProgramStateRef state = (*NI)->getState();
197       // Setup 'this' region, so that the ctor is evaluated on the object pointed
198       // by 'Dest'.
199       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
200       Bldr.generateNode(Loc, *NI, state);
201     }
202   }
203 #endif
204 
205   // Default semantics: invalidate all regions passed as arguments.
206   ExplodedNodeSet destCall;
207   {
208     StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext);
209     for (ExplodedNodeSet::iterator
210         i = destPreVisit.begin(), e = destPreVisit.end();
211         i != e; ++i)
212     {
213       ExplodedNode *Pred = *i;
214       const LocationContext *LC = Pred->getLocationContext();
215       ProgramStateRef state = Pred->getState();
216 
217       state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
218       Bldr.generateNode(E, Pred, state);
219     }
220   }
221   // Do the post visit.
222   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
223 }
224 
225 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
226                                       const MemRegion *Dest,
227                                       const Stmt *S,
228                                       ExplodedNode *Pred,
229                                       ExplodedNodeSet &Dst) {
230   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
231   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
232     return;
233 
234   // Create the context for 'this' region.
235   const StackFrameContext *SFC =
236     AnalysisDeclContexts.getContext(DD)->
237       getStackFrame(Pred->getLocationContext(), S,
238       currentBuilderContext->getBlock(), currentStmtIdx);
239 
240   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
241 
242   CallEnter PP(S, SFC, Pred->getLocationContext());
243 
244   ProgramStateRef state = Pred->getState();
245   state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
246   Bldr.generateNode(PP, Pred, state);
247 }
248 
249 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
250                                    ExplodedNodeSet &Dst) {
251   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
252 
253   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
254   const LocationContext *LCtx = Pred->getLocationContext();
255   DefinedOrUnknownSVal symVal =
256     svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
257   const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
258   QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
259   const ElementRegion *EleReg =
260     getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
261 
262   if (CNE->isArray()) {
263     // FIXME: allocating an array requires simulating the constructors.
264     // For now, just return a symbolicated region.
265     ProgramStateRef state = Pred->getState();
266     state = state->BindExpr(CNE, Pred->getLocationContext(),
267                             loc::MemRegionVal(EleReg));
268     Bldr.generateNode(CNE, Pred, state);
269     return;
270   }
271 
272   // FIXME: Update for AST changes.
273 #if 0
274   // Evaluate constructor arguments.
275   const FunctionProtoType *FnType = NULL;
276   const CXXConstructorDecl *CD = CNE->getConstructor();
277   if (CD)
278     FnType = CD->getType()->getAs<FunctionProtoType>();
279   ExplodedNodeSet argsEvaluated;
280   Bldr.takeNodes(Pred);
281   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
282                 FnType, Pred, argsEvaluated);
283   Bldr.addNodes(argsEvaluated);
284 
285   // Initialize the object region and bind the 'new' expression.
286   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
287                                  E = argsEvaluated.end(); I != E; ++I) {
288 
289     ProgramStateRef state = (*I)->getState();
290 
291     // Accumulate list of regions that are invalidated.
292     // FIXME: Eventually we should unify the logic for constructor
293     // processing in one place.
294     SmallVector<const MemRegion*, 10> regionsToInvalidate;
295     for (CXXNewExpr::const_arg_iterator
296           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
297           ai != ae; ++ai)
298     {
299       SVal val = state->getSVal(*ai, (*I)->getLocationContext());
300       if (const MemRegion *region = val.getAsRegion())
301         regionsToInvalidate.push_back(region);
302     }
303 
304     if (ObjTy->isRecordType()) {
305       regionsToInvalidate.push_back(EleReg);
306       // Invalidate the regions.
307       // TODO: Pass the call to new information as the last argument, to limit
308       // the globals which will get invalidated.
309       state = state->invalidateRegions(regionsToInvalidate,
310                                        CNE, blockCount, 0, 0);
311 
312     } else {
313       // Invalidate the regions.
314       // TODO: Pass the call to new information as the last argument, to limit
315       // the globals which will get invalidated.
316       state = state->invalidateRegions(regionsToInvalidate,
317                                        CNE, blockCount, 0, 0);
318 
319       if (CNE->hasInitializer()) {
320         SVal V = state->getSVal(*CNE->constructor_arg_begin(),
321                                 (*I)->getLocationContext());
322         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
323       } else {
324         // Explicitly set to undefined, because currently we retrieve symbolic
325         // value from symbolic region.
326         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
327       }
328     }
329     state = state->BindExpr(CNE, (*I)->getLocationContext(),
330                             loc::MemRegionVal(EleReg));
331     Bldr.generateNode(CNE, *I, state);
332   }
333 #endif
334 }
335 
336 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
337                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
338   // Should do more checking.
339   ExplodedNodeSet Argevaluated;
340   Visit(CDE->getArgument(), Pred, Argevaluated);
341   StmtNodeBuilder Bldr(Argevaluated, Dst, *currentBuilderContext);
342   for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
343                                  E = Argevaluated.end(); I != E; ++I) {
344     ProgramStateRef state = (*I)->getState();
345     Bldr.generateNode(CDE, *I, state);
346   }
347 }
348 
349 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
350                                     ExplodedNodeSet &Dst) {
351   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
352 
353   // Get the this object region from StoreManager.
354   const LocationContext *LCtx = Pred->getLocationContext();
355   const MemRegion *R =
356     svalBuilder.getRegionManager().getCXXThisRegion(
357                                   getContext().getCanonicalType(TE->getType()),
358                                                     LCtx);
359 
360   ProgramStateRef state = Pred->getState();
361   SVal V = state->getSVal(loc::MemRegionVal(R));
362   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
363 }
364