• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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