]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.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 / ExprEngineCallAndReturn.cpp
1 //=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- 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 ExprEngine's support for calls and returns.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/Analysis/Support/SaveAndRestore.h"
19
20 using namespace clang;
21 using namespace ento;
22
23 namespace {
24   // Trait class for recording returned expression in the state.
25   struct ReturnExpr {
26     static int TagInt;
27     typedef const Stmt *data_type;
28   };
29   int ReturnExpr::TagInt; 
30 }
31
32 void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
33   const ProgramState *state =
34     B.getState()->enterStackFrame(B.getCalleeContext());
35   B.generateNode(state);
36 }
37
38 void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
39   const ProgramState *state = B.getState();
40   const ExplodedNode *Pred = B.getPredecessor();
41   const StackFrameContext *calleeCtx = 
42     cast<StackFrameContext>(Pred->getLocationContext());
43   const Stmt *CE = calleeCtx->getCallSite();
44   
45   // If the callee returns an expression, bind its value to CallExpr.
46   const Stmt *ReturnedExpr = state->get<ReturnExpr>();
47   if (ReturnedExpr) {
48     SVal RetVal = state->getSVal(ReturnedExpr);
49     state = state->BindExpr(CE, RetVal);
50     // Clear the return expr GDM.
51     state = state->remove<ReturnExpr>();
52   }
53   
54   // Bind the constructed object value to CXXConstructExpr.
55   if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
56     const CXXThisRegion *ThisR =
57     getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
58     
59     SVal ThisV = state->getSVal(ThisR);
60     // Always bind the region to the CXXConstructExpr.
61     state = state->BindExpr(CCE, ThisV);
62   }
63   
64   B.generateNode(state);
65 }
66
67 const ProgramState *
68 ExprEngine::invalidateArguments(const ProgramState *State,
69                                 const CallOrObjCMessage &Call,
70                                 const LocationContext *LC) {
71   SmallVector<const MemRegion *, 8> RegionsToInvalidate;
72
73   if (Call.isObjCMessage()) {
74     // Invalidate all instance variables of the receiver of an ObjC message.
75     // FIXME: We should be able to do better with inter-procedural analysis.
76     if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion())
77       RegionsToInvalidate.push_back(MR);
78
79   } else if (Call.isCXXCall()) {
80     // Invalidate all instance variables for the callee of a C++ method call.
81     // FIXME: We should be able to do better with inter-procedural analysis.
82     // FIXME: We can probably do better for const versus non-const methods.
83     if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion())
84       RegionsToInvalidate.push_back(Callee);
85
86   } else if (Call.isFunctionCall()) {
87     // Block calls invalidate all captured-by-reference values.
88     if (const MemRegion *Callee = Call.getFunctionCallee().getAsRegion()) {
89       if (isa<BlockDataRegion>(Callee))
90         RegionsToInvalidate.push_back(Callee);
91     }
92   }
93
94   for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) {
95     SVal V = Call.getArgSVal(idx);
96
97     // If we are passing a location wrapped as an integer, unwrap it and
98     // invalidate the values referred by the location.
99     if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
100       V = Wrapped->getLoc();
101     else if (!isa<Loc>(V))
102       continue;
103
104     if (const MemRegion *R = V.getAsRegion()) {
105       // Invalidate the value of the variable passed by reference.
106
107       // Are we dealing with an ElementRegion?  If the element type is
108       // a basic integer type (e.g., char, int) and the underying region
109       // is a variable region then strip off the ElementRegion.
110       // FIXME: We really need to think about this for the general case
111       //   as sometimes we are reasoning about arrays and other times
112       //   about (char*), etc., is just a form of passing raw bytes.
113       //   e.g., void *p = alloca(); foo((char*)p);
114       if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
115         // Checking for 'integral type' is probably too promiscuous, but
116         // we'll leave it in for now until we have a systematic way of
117         // handling all of these cases.  Eventually we need to come up
118         // with an interface to StoreManager so that this logic can be
119         // approriately delegated to the respective StoreManagers while
120         // still allowing us to do checker-specific logic (e.g.,
121         // invalidating reference counts), probably via callbacks.
122         if (ER->getElementType()->isIntegralOrEnumerationType()) {
123           const MemRegion *superReg = ER->getSuperRegion();
124           if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
125               isa<ObjCIvarRegion>(superReg))
126             R = cast<TypedRegion>(superReg);
127         }
128         // FIXME: What about layers of ElementRegions?
129       }
130
131       // Mark this region for invalidation.  We batch invalidate regions
132       // below for efficiency.
133       RegionsToInvalidate.push_back(R);
134     } else {
135       // Nuke all other arguments passed by reference.
136       // FIXME: is this necessary or correct? This handles the non-Region
137       //  cases.  Is it ever valid to store to these?
138       State = State->unbindLoc(cast<Loc>(V));
139     }
140   }
141
142   // Invalidate designated regions using the batch invalidation API.
143
144   // FIXME: We can have collisions on the conjured symbol if the
145   //  expression *I also creates conjured symbols.  We probably want
146   //  to identify conjured symbols by an expression pair: the enclosing
147   //  expression (the context) and the expression itself.  This should
148   //  disambiguate conjured symbols.
149   assert(Builder && "Invalidating arguments outside of a statement context");
150   unsigned Count = Builder->getCurrentBlockCount();
151   StoreManager::InvalidatedSymbols IS;
152
153   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
154   //  global variables.
155   return State->invalidateRegions(RegionsToInvalidate,
156                                   Call.getOriginExpr(), Count,
157                                   &IS, doesInvalidateGlobals(Call));
158
159 }
160
161 void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
162                                ExplodedNodeSet &dst) {
163   // Perform the previsit of the CallExpr.
164   ExplodedNodeSet dstPreVisit;
165   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
166   
167   // Now evaluate the call itself.
168   class DefaultEval : public GraphExpander {
169     ExprEngine &Eng;
170     const CallExpr *CE;
171   public:
172     
173     DefaultEval(ExprEngine &eng, const CallExpr *ce)
174     : Eng(eng), CE(ce) {}
175     virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
176       // Should we inline the call?
177       if (Eng.getAnalysisManager().shouldInlineCall() &&
178           Eng.InlineCall(Dst, CE, Pred)) {
179         return;
180       }
181
182       // First handle the return value.
183       StmtNodeBuilder &Builder = Eng.getBuilder();
184       assert(&Builder && "StmtNodeBuilder must be defined.");
185
186       // Get the callee.
187       const Expr *Callee = CE->getCallee()->IgnoreParens();
188       const ProgramState *state = Pred->getState();
189       SVal L = state->getSVal(Callee);
190
191       // Figure out the result type. We do this dance to handle references.
192       QualType ResultTy;
193       if (const FunctionDecl *FD = L.getAsFunctionDecl())
194         ResultTy = FD->getResultType();
195       else
196         ResultTy = CE->getType();
197
198       if (CE->isLValue())
199         ResultTy = Eng.getContext().getPointerType(ResultTy);
200
201       // Conjure a symbol value to use as the result.
202       SValBuilder &SVB = Eng.getSValBuilder();
203       unsigned Count = Builder.getCurrentBlockCount();
204       SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
205
206       // Generate a new state with the return value set.
207       state = state->BindExpr(CE, RetVal);
208
209       // Invalidate the arguments.
210       const LocationContext *LC = Pred->getLocationContext();
211       state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
212
213       // And make the result node.
214       Eng.MakeNode(Dst, CE, Pred, state);
215     }
216   };
217   
218   // Finally, evaluate the function call.  We try each of the checkers
219   // to see if the can evaluate the function call.
220   ExplodedNodeSet dstCallEvaluated;
221   DefaultEval defEval(*this, CE);
222   getCheckerManager().runCheckersForEvalCall(dstCallEvaluated,
223                                              dstPreVisit,
224                                              CE, *this, &defEval);
225   
226   // Finally, perform the post-condition check of the CallExpr and store
227   // the created nodes in 'Dst'.
228   getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
229                                              *this);
230 }
231
232 void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
233                                  ExplodedNodeSet &Dst) {
234   ExplodedNodeSet Src;
235   if (const Expr *RetE = RS->getRetValue()) {
236     // Record the returned expression in the state. It will be used in
237     // processCallExit to bind the return value to the call expr.
238     {
239       static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
240       const ProgramState *state = Pred->getState();
241       state = state->set<ReturnExpr>(RetE);
242       Pred = Builder->generateNode(RetE, state, Pred, &tag);
243     }
244     // We may get a NULL Pred because we generated a cached node.
245     if (Pred)
246       Visit(RetE, Pred, Src);
247   }
248   else {
249     Src.Add(Pred);
250   }
251   
252   getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
253 }