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 
24 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
25                                           ExplodedNode *Pred,
26                                           ExplodedNodeSet &Dst) {
27   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
28   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
29   ProgramStateRef state = Pred->getState();
30   const LocationContext *LCtx = Pred->getLocationContext();
31 
32   // Bind the temporary object to the value of the expression. Then bind
33   // the expression to the location of the object.
34   SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
35 
36   const MemRegion *R =
37     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
38 
39   state = state->bindLoc(loc::MemRegionVal(R), V);
40   Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
41 }
42 
43 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
44                                              ExplodedNode *Pred,
45                                              ExplodedNodeSet &Dst) {
46   VisitCXXConstructExpr(expr, 0, Pred, Dst);
47 }
48 
49 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
50                                        const MemRegion *Dest,
51                                        ExplodedNode *Pred,
52                                        ExplodedNodeSet &destNodes) {
53 
54 #if 0
55   const CXXConstructorDecl *CD = E->getConstructor();
56   assert(CD);
57 #endif
58 
59 #if 0
60   if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
61     // FIXME: invalidate the object.
62     return;
63 #endif
64 
65 #if 0
66   // Is the constructor elidable?
67   if (E->isElidable()) {
68     destNodes.Add(Pred);
69     return;
70   }
71 #endif
72 
73   // Perform the previsit of the constructor.
74   ExplodedNodeSet SrcNodes;
75   SrcNodes.Add(Pred);
76   ExplodedNodeSet TmpNodes;
77   getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this);
78 
79   // Evaluate the constructor.  Currently we don't now allow checker-specific
80   // implementations of specific constructors (as we do with ordinary
81   // function calls.  We can re-evaluate this in the future.
82 
83 #if 0
84   // Inlining currently isn't fully implemented.
85 
86   if (AMgr.shouldInlineCall()) {
87     if (!Dest)
88       Dest =
89         svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
90                                                   Pred->getLocationContext());
91 
92     // The callee stack frame context used to create the 'this'
93     // parameter region.
94     const StackFrameContext *SFC =
95       AMgr.getStackFrame(CD, Pred->getLocationContext(),
96                          E, currentBuilderContext->getBlock(),
97                          currentStmtIdx);
98 
99     // Create the 'this' region.
100     const CXXThisRegion *ThisR =
101       getCXXThisRegion(E->getConstructor()->getParent(), SFC);
102 
103     CallEnter Loc(E, SFC, Pred->getLocationContext());
104 
105     StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext);
106     for (ExplodedNodeSet::iterator NI = SrcNodes.begin(),
107                                    NE = SrcNodes.end(); NI != NE; ++NI) {
108       ProgramStateRef state = (*NI)->getState();
109       // Setup 'this' region, so that the ctor is evaluated on the object pointed
110       // by 'Dest'.
111       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
112       Bldr.generateNode(Loc, *NI, state);
113     }
114   }
115 #endif
116 
117   // Default semantics: invalidate all regions passed as arguments.
118   ExplodedNodeSet destCall;
119   {
120     StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext);
121     for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end();
122          i != e; ++i)
123     {
124       ExplodedNode *Pred = *i;
125       const LocationContext *LC = Pred->getLocationContext();
126       ProgramStateRef state = Pred->getState();
127 
128       state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
129       Bldr.generateNode(E, Pred, state);
130     }
131   }
132   // Do the post visit.
133   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
134 }
135 
136 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
137                                       const MemRegion *Dest,
138                                       const Stmt *S,
139                                       ExplodedNode *Pred,
140                                       ExplodedNodeSet &Dst) {
141   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
142   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
143     return;
144 
145   // Create the context for 'this' region.
146   const StackFrameContext *SFC =
147     AnalysisDeclContexts.getContext(DD)->
148       getStackFrame(Pred->getLocationContext(), S,
149       currentBuilderContext->getBlock(), currentStmtIdx);
150 
151   CallEnter PP(S, SFC, Pred->getLocationContext());
152   ProgramStateRef state = Pred->getState();
153   state = state->bindLoc(svalBuilder.getCXXThis(DD->getParent(), SFC),
154                          loc::MemRegionVal(Dest));
155   Bldr.generateNode(PP, Pred, state);
156 }
157 
158 static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
159   // FIXME: Copied from ExprEngineCallAndReturn.cpp
160   QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType();
161   if (PointeeTy != QualType() && PointeeTy.isConstQualified() &&
162       !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) {
163     return true;
164   }
165   return false;
166 }
167 
168 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
169                                    ExplodedNodeSet &Dst) {
170   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
171 
172   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
173   const LocationContext *LCtx = Pred->getLocationContext();
174   DefinedOrUnknownSVal symVal =
175     svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
176   const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
177   QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
178   const ElementRegion *EleReg =
179     getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
180   ProgramStateRef State = Pred->getState();
181 
182   if (CNE->isArray()) {
183     // FIXME: allocating an array requires simulating the constructors.
184     // For now, just return a symbolicated region.
185     State = State->BindExpr(CNE, Pred->getLocationContext(),
186                             loc::MemRegionVal(EleReg));
187     Bldr.generateNode(CNE, Pred, State);
188     return;
189   }
190 
191   FunctionDecl *FD = CNE->getOperatorNew();
192   if (FD && FD->isReservedGlobalPlacementOperator()) {
193     // Non-array placement new should always return the placement location.
194     SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
195     State = State->BindExpr(CNE, LCtx, PlacementLoc);
196     // FIXME: Once we have proper support for CXXConstructExprs inside
197     // CXXNewExpr, we need to make sure that the constructed object is not
198     // immediately invalidated here. (The placement call should happen before
199     // the constructor call anyway.)
200   }
201 
202   // Invalidate placement args.
203 
204   // FIXME: This is largely copied from invalidateArguments, because
205   // CallOrObjCMessage is not general enough to handle new-expressions yet.
206   SmallVector<const MemRegion *, 4> RegionsToInvalidate;
207 
208   unsigned Index = 0;
209   for (CXXNewExpr::const_arg_iterator I = CNE->placement_arg_begin(),
210                                       E = CNE->placement_arg_end();
211        I != E; ++I) {
212     // Pre-increment the argument index to skip over the implicit size arg.
213     ++Index;
214     if (FD && Index < FD->getNumParams())
215       if (isPointerToConst(FD->getParamDecl(Index)))
216         continue;
217 
218     SVal V = State->getSVal(*I, LCtx);
219 
220     // If we are passing a location wrapped as an integer, unwrap it and
221     // invalidate the values referred by the location.
222     if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
223       V = Wrapped->getLoc();
224     else if (!isa<Loc>(V))
225       continue;
226 
227     if (const MemRegion *R = V.getAsRegion()) {
228       // Invalidate the value of the variable passed by reference.
229 
230       // Are we dealing with an ElementRegion?  If the element type is
231       // a basic integer type (e.g., char, int) and the underlying region
232       // is a variable region then strip off the ElementRegion.
233       // FIXME: We really need to think about this for the general case
234       //   as sometimes we are reasoning about arrays and other times
235       //   about (char*), etc., is just a form of passing raw bytes.
236       //   e.g., void *p = alloca(); foo((char*)p);
237       if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
238         // Checking for 'integral type' is probably too promiscuous, but
239         // we'll leave it in for now until we have a systematic way of
240         // handling all of these cases.  Eventually we need to come up
241         // with an interface to StoreManager so that this logic can be
242         // appropriately delegated to the respective StoreManagers while
243         // still allowing us to do checker-specific logic (e.g.,
244         // invalidating reference counts), probably via callbacks.
245         if (ER->getElementType()->isIntegralOrEnumerationType()) {
246           const MemRegion *superReg = ER->getSuperRegion();
247           if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
248               isa<ObjCIvarRegion>(superReg))
249             R = cast<TypedRegion>(superReg);
250         }
251         // FIXME: What about layers of ElementRegions?
252       }
253 
254       // Mark this region for invalidation.  We batch invalidate regions
255       // below for efficiency.
256       RegionsToInvalidate.push_back(R);
257     } else {
258       // Nuke all other arguments passed by reference.
259       // FIXME: is this necessary or correct? This handles the non-Region
260       //  cases.  Is it ever valid to store to these?
261       State = State->unbindLoc(cast<Loc>(V));
262     }
263   }
264 
265   // Invalidate designated regions using the batch invalidation API.
266 
267   // FIXME: We can have collisions on the conjured symbol if the
268   //  expression *I also creates conjured symbols.  We probably want
269   //  to identify conjured symbols by an expression pair: the enclosing
270   //  expression (the context) and the expression itself.  This should
271   //  disambiguate conjured symbols.
272   unsigned Count = currentBuilderContext->getCurrentBlockCount();
273 
274   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
275   //  global variables.
276   State = State->invalidateRegions(RegionsToInvalidate, CNE, Count, LCtx);
277   Bldr.generateNode(CNE, Pred, State);
278   return;
279 
280   // FIXME: The below code is long-since dead. However, constructor handling
281   // in new-expressions is far from complete. See PR12014 for more details.
282 #if 0
283   // Evaluate constructor arguments.
284   const FunctionProtoType *FnType = NULL;
285   const CXXConstructorDecl *CD = CNE->getConstructor();
286   if (CD)
287     FnType = CD->getType()->getAs<FunctionProtoType>();
288   ExplodedNodeSet argsEvaluated;
289   Bldr.takeNodes(Pred);
290   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
291                 FnType, Pred, argsEvaluated);
292   Bldr.addNodes(argsEvaluated);
293 
294   // Initialize the object region and bind the 'new' expression.
295   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
296                                  E = argsEvaluated.end(); I != E; ++I) {
297 
298     ProgramStateRef state = (*I)->getState();
299 
300     // Accumulate list of regions that are invalidated.
301     // FIXME: Eventually we should unify the logic for constructor
302     // processing in one place.
303     SmallVector<const MemRegion*, 10> regionsToInvalidate;
304     for (CXXNewExpr::const_arg_iterator
305           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
306           ai != ae; ++ai)
307     {
308       SVal val = state->getSVal(*ai, (*I)->getLocationContext());
309       if (const MemRegion *region = val.getAsRegion())
310         regionsToInvalidate.push_back(region);
311     }
312 
313     if (ObjTy->isRecordType()) {
314       regionsToInvalidate.push_back(EleReg);
315       // Invalidate the regions.
316       // TODO: Pass the call to new information as the last argument, to limit
317       // the globals which will get invalidated.
318       state = state->invalidateRegions(regionsToInvalidate,
319                                        CNE, blockCount, 0, 0);
320 
321     } else {
322       // Invalidate the regions.
323       // TODO: Pass the call to new information as the last argument, to limit
324       // the globals which will get invalidated.
325       state = state->invalidateRegions(regionsToInvalidate,
326                                        CNE, blockCount, 0, 0);
327 
328       if (CNE->hasInitializer()) {
329         SVal V = state->getSVal(*CNE->constructor_arg_begin(),
330                                 (*I)->getLocationContext());
331         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
332       } else {
333         // Explicitly set to undefined, because currently we retrieve symbolic
334         // value from symbolic region.
335         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
336       }
337     }
338     state = state->BindExpr(CNE, (*I)->getLocationContext(),
339                             loc::MemRegionVal(EleReg));
340     Bldr.generateNode(CNE, *I, state);
341   }
342 #endif
343 }
344 
345 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
346                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
347   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
348   ProgramStateRef state = Pred->getState();
349   Bldr.generateNode(CDE, Pred, state);
350 }
351 
352 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
353                                    ExplodedNode *Pred,
354                                    ExplodedNodeSet &Dst) {
355   const VarDecl *VD = CS->getExceptionDecl();
356   if (!VD) {
357     Dst.Add(Pred);
358     return;
359   }
360 
361   const LocationContext *LCtx = Pred->getLocationContext();
362   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
363                                  currentBuilderContext->getCurrentBlockCount());
364   ProgramStateRef state = Pred->getState();
365   state = state->bindLoc(state->getLValue(VD, LCtx), V);
366 
367   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
368   Bldr.generateNode(CS, Pred, state);
369 }
370 
371 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
372                                     ExplodedNodeSet &Dst) {
373   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
374 
375   // Get the this object region from StoreManager.
376   const LocationContext *LCtx = Pred->getLocationContext();
377   const MemRegion *R =
378     svalBuilder.getRegionManager().getCXXThisRegion(
379                                   getContext().getCanonicalType(TE->getType()),
380                                                     LCtx);
381 
382   ProgramStateRef state = Pred->getState();
383   SVal V = state->getSVal(loc::MemRegionVal(R));
384   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
385 }
386