]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Core / ExprEngineCXX.cpp
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   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
111   const ProgramState *state = Pred->getState();
112
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);
116
117   const MemRegion *R =
118     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
119                                                  Pred->getLocationContext());
120
121   state = state->bindLoc(loc::MemRegionVal(R), V);
122   MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
123 }
124
125 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
126                                        const MemRegion *Dest,
127                                        ExplodedNode *Pred,
128                                        ExplodedNodeSet &destNodes) {
129
130   const CXXConstructorDecl *CD = E->getConstructor();
131   assert(CD);
132   
133 #if 0
134   if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
135     // FIXME: invalidate the object.
136     return;
137 #endif
138   
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);
143
144 #if 0
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())
150       destNodes.Add(Pred);
151     return;
152   }
153 #endif
154   
155   // Perform the previsit of the constructor.
156   ExplodedNodeSet destPreVisit;
157   getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 
158                                             *this);
159   
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.
163   
164 #if 0
165   // Inlining currently isn't fully implemented.
166
167   if (AMgr.shouldInlineCall()) {
168     if (!Dest)
169       Dest =
170         svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
171                                                   Pred->getLocationContext());
172
173     // The callee stack frame context used to create the 'this'
174     // parameter region.
175     const StackFrameContext *SFC = 
176       AMgr.getStackFrame(CD, Pred->getLocationContext(),
177                          E, Builder->getBlock(), Builder->getIndex());
178
179     // Create the 'this' region.
180     const CXXThisRegion *ThisR =
181       getCXXThisRegion(E->getConstructor()->getParent(), SFC);
182
183     CallEnter Loc(E, SFC, Pred->getLocationContext());
184
185
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
190       // by 'Dest'.
191       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
192       if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
193         destNodes.Add(N);
194     }
195   }
196 #endif
197   
198   // Default semantics: invalidate all regions passed as arguments.
199   ExplodedNodeSet destCall;
200
201   for (ExplodedNodeSet::iterator
202         i = destPreVisit.begin(), e = destPreVisit.end();
203        i != e; ++i)
204   {
205     ExplodedNode *Pred = *i;
206     const LocationContext *LC = Pred->getLocationContext();
207     const ProgramState *state = Pred->getState();
208
209     state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
210     Builder->MakeNode(destCall, E, Pred, state);
211   }
212   
213   // Do the post visit.
214   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);  
215 }
216
217 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
218                                       const MemRegion *Dest,
219                                       const Stmt *S,
220                                       ExplodedNode *Pred, 
221                                       ExplodedNodeSet &Dst) {
222   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
223     return;
224   // Create the context for 'this' region.
225   const StackFrameContext *SFC = AMgr.getStackFrame(DD,
226                                                     Pred->getLocationContext(),
227                                                     S, Builder->getBlock(),
228                                                     Builder->getIndex());
229
230   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
231
232   CallEnter PP(S, SFC, Pred->getLocationContext());
233
234   const ProgramState *state = Pred->getState();
235   state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
236   ExplodedNode *N = Builder->generateNode(PP, state, Pred);
237   if (N)
238     Dst.Add(N);
239 }
240
241 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
242                                    ExplodedNodeSet &Dst) {
243   
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);
251
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);
258     return;
259   }
260
261   // Evaluate constructor arguments.
262   const FunctionProtoType *FnType = NULL;
263   const CXXConstructorDecl *CD = CNE->getConstructor();
264   if (CD)
265     FnType = CD->getType()->getAs<FunctionProtoType>();
266   ExplodedNodeSet argsEvaluated;
267   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
268                 FnType, Pred, argsEvaluated);
269
270   // Initialize the object region and bind the 'new' expression.
271   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 
272                                  E = argsEvaluated.end(); I != E; ++I) {
273
274     const ProgramState *state = (*I)->getState();
275     
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();
282           ai != ae; ++ai)
283     {
284       SVal val = state->getSVal(*ai);
285       if (const MemRegion *region = val.getAsRegion())
286         regionsToInvalidate.push_back(region);
287     }
288
289     if (ObjTy->isRecordType()) {
290       regionsToInvalidate.push_back(EleReg);
291       // Invalidate the regions.
292       state = state->invalidateRegions(regionsToInvalidate,
293                                        CNE, blockCount, 0,
294                                        /* invalidateGlobals = */ true);
295       
296     } else {
297       // Invalidate the regions.
298       state = state->invalidateRegions(regionsToInvalidate,
299                                        CNE, blockCount, 0,
300                                        /* invalidateGlobals = */ true);
301
302       if (CNE->hasInitializer()) {
303         SVal V = state->getSVal(*CNE->constructor_arg_begin());
304         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
305       } else {
306         // Explicitly set to undefined, because currently we retrieve symbolic
307         // value from symbolic region.
308         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
309       }
310     }
311     state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
312     MakeNode(Dst, CNE, *I, state);
313   }
314 }
315
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);
325   }
326 }
327
328 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
329                                     ExplodedNodeSet &Dst) {
330   // Get the this object region from StoreManager.
331   const MemRegion *R =
332     svalBuilder.getRegionManager().getCXXThisRegion(
333                                   getContext().getCanonicalType(TE->getType()),
334                                                Pred->getLocationContext());
335
336   const ProgramState *state = Pred->getState();
337   SVal V = state->getSVal(loc::MemRegionVal(R));
338   MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
339 }