1218887Sdim//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim//  This file defines a meta-engine for path-sensitive dataflow analysis that
11218887Sdim//  is built on CoreEngine, but provides the boilerplate to execute transfer
12218887Sdim//  functions and build the ExplodedGraph at the expression level.
13218887Sdim//
14218887Sdim//===----------------------------------------------------------------------===//
15218887Sdim
16218887Sdim#ifndef LLVM_CLANG_GR_EXPRENGINE
17218887Sdim#define LLVM_CLANG_GR_EXPRENGINE
18218887Sdim
19249423Sdim#include "clang/AST/Expr.h"
20249423Sdim#include "clang/AST/Type.h"
21243830Sdim#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
22249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
23218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
24218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
25226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
26234353Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
27249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
28218887Sdim
29218887Sdimnamespace clang {
30218887Sdim
31234353Sdimclass AnalysisDeclContextManager;
32234353Sdimclass CXXCatchStmt;
33234353Sdimclass CXXConstructExpr;
34234353Sdimclass CXXDeleteExpr;
35234353Sdimclass CXXNewExpr;
36234353Sdimclass CXXTemporaryObjectExpr;
37234353Sdimclass CXXThisExpr;
38234353Sdimclass MaterializeTemporaryExpr;
39234353Sdimclass ObjCAtSynchronizedStmt;
40218887Sdimclass ObjCForCollectionStmt;
41234353Sdim
42218887Sdimnamespace ento {
43218887Sdim
44218887Sdimclass AnalysisManager;
45239462Sdimclass CallEvent;
46239462Sdimclass SimpleCall;
47249423Sdimclass CXXConstructorCall;
48218887Sdim
49218887Sdimclass ExprEngine : public SubEngine {
50249423Sdimpublic:
51249423Sdim  /// The modes of inlining, which override the default analysis-wide settings.
52249423Sdim  enum InliningModes {
53249423Sdim    /// Follow the default settings for inlining callees.
54249423Sdim    Inline_Regular = 0,
55249423Sdim    /// Do minimal inlining of callees.
56249423Sdim    Inline_Minimal = 0x1
57249423Sdim  };
58249423Sdim
59249423Sdimprivate:
60218887Sdim  AnalysisManager &AMgr;
61234353Sdim
62234353Sdim  AnalysisDeclContextManager &AnalysisDeclContexts;
63218887Sdim
64218887Sdim  CoreEngine Engine;
65218887Sdim
66218887Sdim  /// G - the simulation graph.
67218887Sdim  ExplodedGraph& G;
68218887Sdim
69218887Sdim  /// StateMgr - Object that manages the data for all created states.
70226633Sdim  ProgramStateManager StateMgr;
71218887Sdim
72218887Sdim  /// SymMgr - Object that manages the symbol information.
73218887Sdim  SymbolManager& SymMgr;
74218887Sdim
75218887Sdim  /// svalBuilder - SValBuilder object that creates SVals from expressions.
76218887Sdim  SValBuilder &svalBuilder;
77218887Sdim
78243830Sdim  unsigned int currStmtIdx;
79243830Sdim  const NodeBuilderContext *currBldrCtx;
80226633Sdim
81243830Sdim  /// Helper object to determine if an Objective-C message expression
82243830Sdim  /// implicitly never returns.
83243830Sdim  ObjCNoReturn ObjCNoRet;
84243830Sdim
85226633Sdim  /// Whether or not GC is enabled in this analysis.
86226633Sdim  bool ObjCGCEnabled;
87218887Sdim
88218887Sdim  /// The BugReporter associated with this engine.  It is important that
89218887Sdim  ///  this object be placed at the very end of member variables so that its
90218887Sdim  ///  destructor is called before the rest of the ExprEngine is destroyed.
91218887Sdim  GRBugReporter BR;
92218887Sdim
93243830Sdim  /// The functions which have been analyzed through inlining. This is owned by
94243830Sdim  /// AnalysisConsumer. It can be null.
95243830Sdim  SetOfConstDecls *VisitedCallees;
96243830Sdim
97249423Sdim  /// The flag, which specifies the mode of inlining for the engine.
98249423Sdim  InliningModes HowToInline;
99249423Sdim
100218887Sdimpublic:
101234353Sdim  ExprEngine(AnalysisManager &mgr, bool gcEnabled,
102243830Sdim             SetOfConstDecls *VisitedCalleesIn,
103249423Sdim             FunctionSummariesTy *FS,
104249423Sdim             InliningModes HowToInlineIn);
105218887Sdim
106218887Sdim  ~ExprEngine();
107218887Sdim
108234353Sdim  /// Returns true if there is still simulation state on the worklist.
109234353Sdim  bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
110234353Sdim    return Engine.ExecuteWorkList(L, Steps, 0);
111218887Sdim  }
112218887Sdim
113218887Sdim  /// Execute the work list with an initial state. Nodes that reaches the exit
114218887Sdim  /// of the function are added into the Dst set, which represent the exit
115234353Sdim  /// state of the function call. Returns true if there is still simulation
116234353Sdim  /// state on the worklist.
117234353Sdim  bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
118234353Sdim                                       ProgramStateRef InitState,
119218887Sdim                                       ExplodedNodeSet &Dst) {
120234353Sdim    return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
121218887Sdim  }
122218887Sdim
123218887Sdim  /// getContext - Return the ASTContext associated with this analysis.
124226633Sdim  ASTContext &getContext() const { return AMgr.getASTContext(); }
125218887Sdim
126218887Sdim  virtual AnalysisManager &getAnalysisManager() { return AMgr; }
127218887Sdim
128219077Sdim  CheckerManager &getCheckerManager() const {
129219077Sdim    return *AMgr.getCheckerManager();
130219077Sdim  }
131219077Sdim
132218887Sdim  SValBuilder &getSValBuilder() { return svalBuilder; }
133218887Sdim
134218887Sdim  BugReporter& getBugReporter() { return BR; }
135218887Sdim
136234353Sdim  const NodeBuilderContext &getBuilderContext() {
137243830Sdim    assert(currBldrCtx);
138243830Sdim    return *currBldrCtx;
139234353Sdim  }
140218887Sdim
141226633Sdim  bool isObjCGCEnabled() { return ObjCGCEnabled; }
142218887Sdim
143234353Sdim  const Stmt *getStmt() const;
144234353Sdim
145234353Sdim  void GenerateAutoTransition(ExplodedNode *N);
146234353Sdim  void enqueueEndOfPath(ExplodedNodeSet &S);
147234353Sdim  void GenerateCallExitNode(ExplodedNode *N);
148234353Sdim
149249423Sdim  /// Visualize the ExplodedGraph created by executing the simulation.
150218887Sdim  void ViewGraph(bool trim = false);
151218887Sdim
152249423Sdim  /// Visualize a trimmed ExplodedGraph that only contains paths to the given
153249423Sdim  /// nodes.
154249423Sdim  void ViewGraph(ArrayRef<const ExplodedNode*> Nodes);
155218887Sdim
156218887Sdim  /// getInitialState - Return the initial state used for the root vertex
157218887Sdim  ///  in the ExplodedGraph.
158234353Sdim  ProgramStateRef getInitialState(const LocationContext *InitLoc);
159218887Sdim
160218887Sdim  ExplodedGraph& getGraph() { return G; }
161218887Sdim  const ExplodedGraph& getGraph() const { return G; }
162218887Sdim
163239462Sdim  /// \brief Run the analyzer's garbage collection - remove dead symbols and
164249423Sdim  /// bindings from the state.
165239462Sdim  ///
166249423Sdim  /// Checkers can participate in this process with two callbacks:
167249423Sdim  /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
168249423Sdim  /// class for more information.
169249423Sdim  ///
170249423Sdim  /// \param Node The predecessor node, from which the processing should start.
171249423Sdim  /// \param Out The returned set of output nodes.
172249423Sdim  /// \param ReferenceStmt The statement which is about to be processed.
173249423Sdim  ///        Everything needed for this statement should be considered live.
174249423Sdim  ///        A null statement means that everything in child LocationContexts
175249423Sdim  ///        is dead.
176249423Sdim  /// \param LC The location context of the \p ReferenceStmt. A null location
177249423Sdim  ///        context means that we have reached the end of analysis and that
178249423Sdim  ///        all statements and local variables should be considered dead.
179249423Sdim  /// \param DiagnosticStmt Used as a location for any warnings that should
180249423Sdim  ///        occur while removing the dead (e.g. leaks). By default, the
181249423Sdim  ///        \p ReferenceStmt is used.
182249423Sdim  /// \param K Denotes whether this is a pre- or post-statement purge. This
183249423Sdim  ///        must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
184249423Sdim  ///        entire location context is being cleared, in which case the
185249423Sdim  ///        \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
186249423Sdim  ///        it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
187249423Sdim  ///        and \p ReferenceStmt must be valid (non-null).
188239462Sdim  void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
189249423Sdim            const Stmt *ReferenceStmt, const LocationContext *LC,
190249423Sdim            const Stmt *DiagnosticStmt = 0,
191239462Sdim            ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
192239462Sdim
193218887Sdim  /// processCFGElement - Called by CoreEngine. Used to generate new successor
194218887Sdim  ///  nodes by processing the 'effects' of a CFG element.
195234353Sdim  void processCFGElement(const CFGElement E, ExplodedNode *Pred,
196234353Sdim                         unsigned StmtIdx, NodeBuilderContext *Ctx);
197218887Sdim
198234353Sdim  void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
199218887Sdim
200234353Sdim  void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
201218887Sdim
202234353Sdim  void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
203218887Sdim
204218887Sdim  void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
205234353Sdim                               ExplodedNode *Pred, ExplodedNodeSet &Dst);
206234353Sdim  void ProcessBaseDtor(const CFGBaseDtor D,
207234353Sdim                       ExplodedNode *Pred, ExplodedNodeSet &Dst);
208234353Sdim  void ProcessMemberDtor(const CFGMemberDtor D,
209234353Sdim                         ExplodedNode *Pred, ExplodedNodeSet &Dst);
210218887Sdim  void ProcessTemporaryDtor(const CFGTemporaryDtor D,
211234353Sdim                            ExplodedNode *Pred, ExplodedNodeSet &Dst);
212218887Sdim
213218887Sdim  /// Called by CoreEngine when processing the entrance of a CFGBlock.
214234353Sdim  virtual void processCFGBlockEntrance(const BlockEdge &L,
215243830Sdim                                       NodeBuilderWithSinks &nodeBuilder,
216243830Sdim                                       ExplodedNode *Pred);
217218887Sdim
218218887Sdim  /// ProcessBranch - Called by CoreEngine.  Used to generate successor
219218887Sdim  ///  nodes by processing the 'effects' of a branch condition.
220226633Sdim  void processBranch(const Stmt *Condition, const Stmt *Term,
221234353Sdim                     NodeBuilderContext& BuilderCtx,
222234353Sdim                     ExplodedNode *Pred,
223234353Sdim                     ExplodedNodeSet &Dst,
224234353Sdim                     const CFGBlock *DstT,
225234353Sdim                     const CFGBlock *DstF);
226218887Sdim
227249423Sdim  /// Called by CoreEngine.  Used to processing branching behavior
228249423Sdim  /// at static initalizers.
229249423Sdim  void processStaticInitializer(const DeclStmt *DS,
230249423Sdim                                NodeBuilderContext& BuilderCtx,
231249423Sdim                                ExplodedNode *Pred,
232249423Sdim                                ExplodedNodeSet &Dst,
233249423Sdim                                const CFGBlock *DstT,
234249423Sdim                                const CFGBlock *DstF);
235249423Sdim
236218887Sdim  /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
237218887Sdim  ///  nodes by processing the 'effects' of a computed goto jump.
238218887Sdim  void processIndirectGoto(IndirectGotoNodeBuilder& builder);
239218887Sdim
240218887Sdim  /// ProcessSwitch - Called by CoreEngine.  Used to generate successor
241218887Sdim  ///  nodes by processing the 'effects' of a switch statement.
242218887Sdim  void processSwitch(SwitchNodeBuilder& builder);
243218887Sdim
244249423Sdim  /// Called by CoreEngine.  Used to generate end-of-path
245249423Sdim  /// nodes when the control reaches the end of a function.
246243830Sdim  void processEndOfFunction(NodeBuilderContext& BC,
247243830Sdim                            ExplodedNode *Pred);
248218887Sdim
249243830Sdim  /// Remove dead bindings/symbols before exiting a function.
250243830Sdim  void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
251243830Sdim                                 ExplodedNode *Pred,
252243830Sdim                                 ExplodedNodeSet &Dst);
253243830Sdim
254218887Sdim  /// Generate the entry node of the callee.
255234353Sdim  void processCallEnter(CallEnter CE, ExplodedNode *Pred);
256218887Sdim
257239462Sdim  /// Generate the sequence of nodes that simulate the call exit and the post
258239462Sdim  /// visit for CallExpr.
259234353Sdim  void processCallExit(ExplodedNode *Pred);
260218887Sdim
261218887Sdim  /// Called by CoreEngine when the analysis worklist has terminated.
262218887Sdim  void processEndWorklist(bool hasWorkRemaining);
263218887Sdim
264218887Sdim  /// evalAssume - Callback function invoked by the ConstraintManager when
265218887Sdim  ///  making assumptions about state values.
266234353Sdim  ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption);
267218887Sdim
268226633Sdim  /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
269218887Sdim  ///  region change should trigger a processRegionChanges update.
270234353Sdim  bool wantsRegionChangeUpdate(ProgramStateRef state);
271218887Sdim
272226633Sdim  /// processRegionChanges - Called by ProgramStateManager whenever a change is made
273218887Sdim  ///  to the store. Used to update checkers that track region values.
274234353Sdim  ProgramStateRef
275234353Sdim  processRegionChanges(ProgramStateRef state,
276249423Sdim                       const InvalidatedSymbols *invalidated,
277226633Sdim                       ArrayRef<const MemRegion *> ExplicitRegions,
278234353Sdim                       ArrayRef<const MemRegion *> Regions,
279239462Sdim                       const CallEvent *Call);
280218887Sdim
281226633Sdim  /// printState - Called by ProgramStateManager to print checker-specific data.
282234353Sdim  void printState(raw_ostream &Out, ProgramStateRef State,
283226633Sdim                  const char *NL, const char *Sep);
284218887Sdim
285226633Sdim  virtual ProgramStateManager& getStateManager() { return StateMgr; }
286226633Sdim
287218887Sdim  StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
288218887Sdim
289218887Sdim  ConstraintManager& getConstraintManager() {
290218887Sdim    return StateMgr.getConstraintManager();
291218887Sdim  }
292218887Sdim
293218887Sdim  // FIXME: Remove when we migrate over to just using SValBuilder.
294218887Sdim  BasicValueFactory& getBasicVals() {
295218887Sdim    return StateMgr.getBasicVals();
296218887Sdim  }
297218887Sdim
298218887Sdim  // FIXME: Remove when we migrate over to just using ValueManager.
299218887Sdim  SymbolManager& getSymbolManager() { return SymMgr; }
300218887Sdim  const SymbolManager& getSymbolManager() const { return SymMgr; }
301218887Sdim
302218887Sdim  // Functions for external checking of whether we have unfinished work
303221345Sdim  bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
304218887Sdim  bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
305221345Sdim  bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
306218887Sdim
307218887Sdim  const CoreEngine &getCoreEngine() const { return Engine; }
308218887Sdim
309218887Sdimpublic:
310218887Sdim  /// Visit - Transfer function logic for all statements.  Dispatches to
311218887Sdim  ///  other functions that handle specific kinds of statements.
312226633Sdim  void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
313218887Sdim
314218887Sdim  /// VisitArraySubscriptExpr - Transfer function for array accesses.
315226633Sdim  void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex,
316226633Sdim                                   ExplodedNode *Pred,
317226633Sdim                                   ExplodedNodeSet &Dst);
318218887Sdim
319243830Sdim  /// VisitGCCAsmStmt - Transfer function logic for inline asm.
320243830Sdim  void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
321243830Sdim                       ExplodedNodeSet &Dst);
322239462Sdim
323239462Sdim  /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
324239462Sdim  void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
325239462Sdim                      ExplodedNodeSet &Dst);
326243830Sdim
327218887Sdim  /// VisitBlockExpr - Transfer function logic for BlockExprs.
328218887Sdim  void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
329218887Sdim                      ExplodedNodeSet &Dst);
330218887Sdim
331218887Sdim  /// VisitBinaryOperator - Transfer function logic for binary operators.
332226633Sdim  void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
333226633Sdim                           ExplodedNodeSet &Dst);
334218887Sdim
335218887Sdim
336218887Sdim  /// VisitCall - Transfer function for function calls.
337226633Sdim  void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
338226633Sdim                     ExplodedNodeSet &Dst);
339218887Sdim
340218887Sdim  /// VisitCast - Transfer function logic for all casts (implicit and explicit).
341218887Sdim  void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
342218887Sdim                ExplodedNodeSet &Dst);
343218887Sdim
344218887Sdim  /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
345226633Sdim  void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
346226633Sdim                                ExplodedNode *Pred, ExplodedNodeSet &Dst);
347218887Sdim
348218887Sdim  /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
349226633Sdim  void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
350226633Sdim                              ExplodedNode *Pred, ExplodedNodeSet &Dst);
351218887Sdim
352218887Sdim  /// VisitDeclStmt - Transfer function logic for DeclStmts.
353226633Sdim  void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
354226633Sdim                     ExplodedNodeSet &Dst);
355218887Sdim
356218887Sdim  /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
357226633Sdim  void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
358226633Sdim                        ExplodedNode *Pred, ExplodedNodeSet &Dst);
359218887Sdim
360226633Sdim  void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
361226633Sdim                         ExplodedNodeSet &Dst);
362218887Sdim
363218887Sdim  /// VisitLogicalExpr - Transfer function logic for '&&', '||'
364226633Sdim  void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
365226633Sdim                        ExplodedNodeSet &Dst);
366218887Sdim
367218887Sdim  /// VisitMemberExpr - Transfer function for member expressions.
368226633Sdim  void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
369226633Sdim                           ExplodedNodeSet &Dst);
370218887Sdim
371218887Sdim  /// Transfer function logic for ObjCAtSynchronizedStmts.
372218887Sdim  void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
373218887Sdim                                   ExplodedNode *Pred, ExplodedNodeSet &Dst);
374218887Sdim
375218887Sdim  /// Transfer function logic for computing the lvalue of an Objective-C ivar.
376226633Sdim  void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred,
377226633Sdim                                ExplodedNodeSet &Dst);
378218887Sdim
379218887Sdim  /// VisitObjCForCollectionStmt - Transfer function logic for
380218887Sdim  ///  ObjCForCollectionStmt.
381226633Sdim  void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
382226633Sdim                                  ExplodedNode *Pred, ExplodedNodeSet &Dst);
383218887Sdim
384239462Sdim  void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
385226633Sdim                        ExplodedNodeSet &Dst);
386218887Sdim
387218887Sdim  /// VisitReturnStmt - Transfer function logic for return statements.
388226633Sdim  void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
389226633Sdim                       ExplodedNodeSet &Dst);
390218887Sdim
391218887Sdim  /// VisitOffsetOfExpr - Transfer function for offsetof.
392226633Sdim  void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
393226633Sdim                         ExplodedNodeSet &Dst);
394218887Sdim
395221345Sdim  /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
396226633Sdim  void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
397226633Sdim                              ExplodedNode *Pred, ExplodedNodeSet &Dst);
398218887Sdim
399218887Sdim  /// VisitUnaryOperator - Transfer function logic for unary operators.
400226633Sdim  void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
401226633Sdim                          ExplodedNodeSet &Dst);
402218887Sdim
403234353Sdim  /// Handle ++ and -- (both pre- and post-increment).
404234353Sdim  void VisitIncrementDecrementOperator(const UnaryOperator* U,
405234353Sdim                                       ExplodedNode *Pred,
406234353Sdim                                       ExplodedNodeSet &Dst);
407234353Sdim
408234353Sdim  void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
409234353Sdim                         ExplodedNodeSet &Dst);
410234353Sdim
411218887Sdim  void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
412218887Sdim                        ExplodedNodeSet & Dst);
413218887Sdim
414239462Sdim  void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
415239462Sdim                             ExplodedNodeSet &Dst);
416218887Sdim
417243830Sdim  void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
418243830Sdim                          const Stmt *S, bool IsBaseDtor,
419218887Sdim                          ExplodedNode *Pred, ExplodedNodeSet &Dst);
420218887Sdim
421218887Sdim  void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
422218887Sdim                       ExplodedNodeSet &Dst);
423218887Sdim
424218887Sdim  void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
425218887Sdim                          ExplodedNodeSet &Dst);
426218887Sdim
427218887Sdim  /// Create a C++ temporary object for an rvalue.
428226633Sdim  void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
429226633Sdim                                ExplodedNode *Pred,
430218887Sdim                                ExplodedNodeSet &Dst);
431221345Sdim
432243830Sdim  /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
433218887Sdim  ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)
434218887Sdim  ///  with those assumptions.
435243830Sdim  void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
436218887Sdim                         const Expr *Ex);
437226633Sdim
438226633Sdim  std::pair<const ProgramPointTag *, const ProgramPointTag*>
439243830Sdim    geteagerlyAssumeBinOpBifurcationTags();
440218887Sdim
441218887Sdim  SVal evalMinus(SVal X) {
442249423Sdim    return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
443218887Sdim  }
444218887Sdim
445218887Sdim  SVal evalComplement(SVal X) {
446249423Sdim    return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
447218887Sdim  }
448218887Sdim
449218887Sdimpublic:
450218887Sdim
451234353Sdim  SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
452218887Sdim                 NonLoc L, NonLoc R, QualType T) {
453218887Sdim    return svalBuilder.evalBinOpNN(state, op, L, R, T);
454218887Sdim  }
455218887Sdim
456234353Sdim  SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
457218887Sdim                 NonLoc L, SVal R, QualType T) {
458249423Sdim    return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
459249423Sdim                                                 R.castAs<NonLoc>(), T) : R;
460218887Sdim  }
461218887Sdim
462234353Sdim  SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
463218887Sdim                 SVal LHS, SVal RHS, QualType T) {
464218887Sdim    return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
465218887Sdim  }
466218887Sdim
467218887Sdimprotected:
468218887Sdim  /// evalBind - Handle the semantics of binding a value to a specific location.
469218887Sdim  ///  This method is used by evalStore, VisitDeclStmt, and others.
470226633Sdim  void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
471243830Sdim                SVal location, SVal Val, bool atDeclInit = false,
472243830Sdim                const ProgramPoint *PP = 0);
473218887Sdim
474249423Sdim  /// Call PointerEscape callback when a value escapes as a result of bind.
475249423Sdim  ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
476249423Sdim                                              SVal Loc, SVal Val);
477249423Sdim  /// Call PointerEscape callback when a value escapes as a result of
478249423Sdim  /// region invalidation.
479249423Sdim  /// \param[in] IsConst Specifies that the pointer is const.
480249423Sdim  ProgramStateRef notifyCheckersOfPointerEscape(
481249423Sdim                            ProgramStateRef State,
482249423Sdim                            const InvalidatedSymbols *Invalidated,
483249423Sdim                            ArrayRef<const MemRegion *> ExplicitRegions,
484249423Sdim                            ArrayRef<const MemRegion *> Regions,
485249423Sdim                            const CallEvent *Call,
486249423Sdim                            bool IsConst);
487249423Sdim
488218887Sdimpublic:
489218887Sdim  // FIXME: 'tag' should be removed, and a LocationContext should be used
490218887Sdim  // instead.
491218887Sdim  // FIXME: Comment on the meaning of the arguments, when 'St' may not
492218887Sdim  // be the same as Pred->state, and when 'location' may not be the
493218887Sdim  // same as state->getLValue(Ex).
494218887Sdim  /// Simulate a read of the result of Ex.
495234353Sdim  void evalLoad(ExplodedNodeSet &Dst,
496234353Sdim                const Expr *NodeEx,  /* Eventually will be a CFGStmt */
497234353Sdim                const Expr *BoundExpr,
498234353Sdim                ExplodedNode *Pred,
499234353Sdim                ProgramStateRef St,
500234353Sdim                SVal location,
501234353Sdim                const ProgramPointTag *tag = 0,
502218887Sdim                QualType LoadTy = QualType());
503218887Sdim
504218887Sdim  // FIXME: 'tag' should be removed, and a LocationContext should be used
505218887Sdim  // instead.
506226633Sdim  void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
507234353Sdim                 ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
508226633Sdim                 const ProgramPointTag *tag = 0);
509239462Sdim
510239462Sdim  /// \brief Create a new state in which the call return value is binded to the
511239462Sdim  /// call origin expression.
512239462Sdim  ProgramStateRef bindReturnValue(const CallEvent &Call,
513239462Sdim                                  const LocationContext *LCtx,
514239462Sdim                                  ProgramStateRef State);
515239462Sdim
516239462Sdim  /// Evaluate a call, running pre- and post-call checks and allowing checkers
517239462Sdim  /// to be responsible for handling the evaluation of the call itself.
518239462Sdim  void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
519239462Sdim                const CallEvent &Call);
520239462Sdim
521239462Sdim  /// \brief Default implementation of call evaluation.
522239462Sdim  void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
523239462Sdim                       const CallEvent &Call);
524218887Sdimprivate:
525234353Sdim  void evalLoadCommon(ExplodedNodeSet &Dst,
526234353Sdim                      const Expr *NodeEx,  /* Eventually will be a CFGStmt */
527234353Sdim                      const Expr *BoundEx,
528234353Sdim                      ExplodedNode *Pred,
529234353Sdim                      ProgramStateRef St,
530234353Sdim                      SVal location,
531234353Sdim                      const ProgramPointTag *tag,
532218887Sdim                      QualType LoadTy);
533218887Sdim
534218887Sdim  // FIXME: 'tag' should be removed, and a LocationContext should be used
535218887Sdim  // instead.
536234353Sdim  void evalLocation(ExplodedNodeSet &Dst,
537234353Sdim                    const Stmt *NodeEx, /* This will eventually be a CFGStmt */
538234353Sdim                    const Stmt *BoundEx,
539234353Sdim                    ExplodedNode *Pred,
540234353Sdim                    ProgramStateRef St, SVal location,
541226633Sdim                    const ProgramPointTag *tag, bool isLoad);
542218887Sdim
543243830Sdim  /// Count the stack depth and determine if the call is recursive.
544243830Sdim  void examineStackFrames(const Decl *D, const LocationContext *LCtx,
545243830Sdim                          bool &IsRecursive, unsigned &StackDepth);
546243830Sdim
547249423Sdim  /// Checks our policies and decides weither the given call should be inlined.
548249423Sdim  bool shouldInlineCall(const CallEvent &Call, const Decl *D,
549249423Sdim                        const ExplodedNode *Pred);
550249423Sdim
551239462Sdim  bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
552239462Sdim                  ExplodedNode *Pred, ProgramStateRef State);
553234353Sdim
554239462Sdim  /// \brief Conservatively evaluate call by invalidating regions and binding
555239462Sdim  /// a conjured return value.
556239462Sdim  void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
557239462Sdim                            ExplodedNode *Pred, ProgramStateRef State);
558239462Sdim
559239462Sdim  /// \brief Either inline or process the call conservatively (or both), based
560239462Sdim  /// on DynamicDispatchBifurcation data.
561239462Sdim  void BifurcateCall(const MemRegion *BifurReg,
562239462Sdim                     const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
563239462Sdim                     ExplodedNode *Pred);
564239462Sdim
565234353Sdim  bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
566249423Sdim
567249423Sdim  /// Models a trivial copy or move constructor or trivial assignment operator
568249423Sdim  /// call with a simple bind.
569249423Sdim  void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
570249423Sdim                          const CallEvent &Call);
571249423Sdim
572249423Sdim  /// If the value of the given expression is a NonLoc, copy it into a new
573249423Sdim  /// temporary object region, and replace the value of the expression with
574249423Sdim  /// that.
575249423Sdim  ///
576249423Sdim  /// If \p ResultE is provided, the new region will be bound to this expression
577249423Sdim  /// instead of \p E.
578249423Sdim  ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
579249423Sdim                                                const LocationContext *LC,
580249423Sdim                                                const Expr *E,
581249423Sdim                                                const Expr *ResultE = 0);
582218887Sdim};
583218887Sdim
584234353Sdim/// Traits for storing the call processing policy inside GDM.
585234353Sdim/// The GDM stores the corresponding CallExpr pointer.
586243830Sdim// FIXME: This does not use the nice trait macros because it must be accessible
587243830Sdim// from multiple translation units.
588234353Sdimstruct ReplayWithoutInlining{};
589234353Sdimtemplate <>
590234353Sdimstruct ProgramStateTrait<ReplayWithoutInlining> :
591249423Sdim  public ProgramStatePartialTrait<const void*> {
592234353Sdim  static void *GDMIndex() { static int index = 0; return &index; }
593234353Sdim};
594234353Sdim
595218887Sdim} // end ento namespace
596218887Sdim
597218887Sdim} // end clang namespace
598218887Sdim
599218887Sdim#endif
600