clang API Documentation

ExprEngine.h
Go to the documentation of this file.
00001 //===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines a meta-engine for path-sensitive dataflow analysis that
00011 //  is built on CoreEngine, but provides the boilerplate to execute transfer
00012 //  functions and build the ExplodedGraph at the expression level.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_CLANG_GR_EXPRENGINE
00017 #define LLVM_CLANG_GR_EXPRENGINE
00018 
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
00021 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
00022 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00023 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
00024 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
00025 #include "clang/AST/Expr.h"
00026 #include "clang/AST/Type.h"
00027 
00028 namespace clang {
00029 
00030 class AnalysisDeclContextManager;
00031 class CXXCatchStmt;
00032 class CXXConstructExpr;
00033 class CXXDeleteExpr;
00034 class CXXNewExpr;
00035 class CXXTemporaryObjectExpr;
00036 class CXXThisExpr;
00037 class MaterializeTemporaryExpr;
00038 class ObjCAtSynchronizedStmt;
00039 class ObjCForCollectionStmt;
00040   
00041 namespace ento {
00042 
00043 class AnalysisManager;
00044 class CallOrObjCMessage;
00045 class ObjCMessage;
00046 
00047 class ExprEngine : public SubEngine {
00048   AnalysisManager &AMgr;
00049   
00050   AnalysisDeclContextManager &AnalysisDeclContexts;
00051 
00052   CoreEngine Engine;
00053 
00054   /// G - the simulation graph.
00055   ExplodedGraph& G;
00056 
00057   /// StateMgr - Object that manages the data for all created states.
00058   ProgramStateManager StateMgr;
00059 
00060   /// SymMgr - Object that manages the symbol information.
00061   SymbolManager& SymMgr;
00062 
00063   /// svalBuilder - SValBuilder object that creates SVals from expressions.
00064   SValBuilder &svalBuilder;
00065 
00066   /// EntryNode - The immediate predecessor node.
00067   ExplodedNode *EntryNode;
00068 
00069   /// CleanedState - The state for EntryNode "cleaned" of all dead
00070   ///  variables and symbols (as determined by a liveness analysis).
00071   ProgramStateRef CleanedState;
00072 
00073   /// currentStmt - The current block-level statement.
00074   const Stmt *currentStmt;
00075   unsigned int currentStmtIdx;
00076   const NodeBuilderContext *currentBuilderContext;
00077 
00078   /// Obj-C Class Identifiers.
00079   IdentifierInfo* NSExceptionII;
00080 
00081   /// Obj-C Selectors.
00082   Selector* NSExceptionInstanceRaiseSelectors;
00083   Selector RaiseSel;
00084   
00085   /// Whether or not GC is enabled in this analysis.
00086   bool ObjCGCEnabled;
00087 
00088   /// The BugReporter associated with this engine.  It is important that
00089   ///  this object be placed at the very end of member variables so that its
00090   ///  destructor is called before the rest of the ExprEngine is destroyed.
00091   GRBugReporter BR;
00092 
00093 public:
00094   ExprEngine(AnalysisManager &mgr, bool gcEnabled,
00095              SetOfConstDecls *VisitedCallees,
00096              FunctionSummariesTy *FS);
00097 
00098   ~ExprEngine();
00099 
00100   /// Returns true if there is still simulation state on the worklist.
00101   bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
00102     return Engine.ExecuteWorkList(L, Steps, 0);
00103   }
00104 
00105   /// Execute the work list with an initial state. Nodes that reaches the exit
00106   /// of the function are added into the Dst set, which represent the exit
00107   /// state of the function call. Returns true if there is still simulation
00108   /// state on the worklist.
00109   bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
00110                                        ProgramStateRef InitState, 
00111                                        ExplodedNodeSet &Dst) {
00112     return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
00113   }
00114 
00115   /// getContext - Return the ASTContext associated with this analysis.
00116   ASTContext &getContext() const { return AMgr.getASTContext(); }
00117 
00118   virtual AnalysisManager &getAnalysisManager() { return AMgr; }
00119 
00120   CheckerManager &getCheckerManager() const {
00121     return *AMgr.getCheckerManager();
00122   }
00123 
00124   SValBuilder &getSValBuilder() { return svalBuilder; }
00125 
00126   BugReporter& getBugReporter() { return BR; }
00127 
00128   const NodeBuilderContext &getBuilderContext() {
00129     assert(currentBuilderContext);
00130     return *currentBuilderContext;
00131   }
00132 
00133   bool isObjCGCEnabled() { return ObjCGCEnabled; }
00134 
00135   const Stmt *getStmt() const;
00136 
00137   void GenerateAutoTransition(ExplodedNode *N);
00138   void enqueueEndOfPath(ExplodedNodeSet &S);
00139   void GenerateCallExitNode(ExplodedNode *N);
00140 
00141   /// ViewGraph - Visualize the ExplodedGraph created by executing the
00142   ///  simulation.
00143   void ViewGraph(bool trim = false);
00144 
00145   void ViewGraph(ExplodedNode** Beg, ExplodedNode** End);
00146 
00147   /// getInitialState - Return the initial state used for the root vertex
00148   ///  in the ExplodedGraph.
00149   ProgramStateRef getInitialState(const LocationContext *InitLoc);
00150 
00151   ExplodedGraph& getGraph() { return G; }
00152   const ExplodedGraph& getGraph() const { return G; }
00153 
00154   /// \brief Run the analyzer's garbage collection - remove dead symbols and
00155   /// bindings.
00156   ///
00157   /// \param Node - The predecessor node, from which the processing should 
00158   /// start.
00159   /// \param Out - The returned set of output nodes.
00160   /// \param ReferenceStmt - Run garbage collection using the symbols, 
00161   /// which are live before the given statement.
00162   /// \param LC - The location context of the ReferenceStmt.
00163   /// \param DiagnosticStmt - the statement used to associate the diagnostic 
00164   /// message, if any warnings should occur while removing the dead (leaks 
00165   /// are usually reported here).
00166   /// \param K - In some cases it is possible to use PreStmt kind. (Do 
00167   /// not use it unless you know what you are doing.) 
00168   void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
00169             const Stmt *ReferenceStmt, const LocationContext *LC,
00170             const Stmt *DiagnosticStmt,
00171             ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
00172 
00173   /// processCFGElement - Called by CoreEngine. Used to generate new successor
00174   ///  nodes by processing the 'effects' of a CFG element.
00175   void processCFGElement(const CFGElement E, ExplodedNode *Pred,
00176                          unsigned StmtIdx, NodeBuilderContext *Ctx);
00177 
00178   void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
00179 
00180   void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
00181 
00182   void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
00183 
00184   void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, 
00185                                ExplodedNode *Pred, ExplodedNodeSet &Dst);
00186   void ProcessBaseDtor(const CFGBaseDtor D,
00187                        ExplodedNode *Pred, ExplodedNodeSet &Dst);
00188   void ProcessMemberDtor(const CFGMemberDtor D,
00189                          ExplodedNode *Pred, ExplodedNodeSet &Dst);
00190   void ProcessTemporaryDtor(const CFGTemporaryDtor D, 
00191                             ExplodedNode *Pred, ExplodedNodeSet &Dst);
00192 
00193   /// Called by CoreEngine when processing the entrance of a CFGBlock.
00194   virtual void processCFGBlockEntrance(const BlockEdge &L,
00195                                        NodeBuilderWithSinks &nodeBuilder);
00196   
00197   /// ProcessBranch - Called by CoreEngine.  Used to generate successor
00198   ///  nodes by processing the 'effects' of a branch condition.
00199   void processBranch(const Stmt *Condition, const Stmt *Term, 
00200                      NodeBuilderContext& BuilderCtx,
00201                      ExplodedNode *Pred,
00202                      ExplodedNodeSet &Dst,
00203                      const CFGBlock *DstT,
00204                      const CFGBlock *DstF);
00205 
00206   /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
00207   ///  nodes by processing the 'effects' of a computed goto jump.
00208   void processIndirectGoto(IndirectGotoNodeBuilder& builder);
00209 
00210   /// ProcessSwitch - Called by CoreEngine.  Used to generate successor
00211   ///  nodes by processing the 'effects' of a switch statement.
00212   void processSwitch(SwitchNodeBuilder& builder);
00213 
00214   /// ProcessEndPath - Called by CoreEngine.  Used to generate end-of-path
00215   ///  nodes when the control reaches the end of a function.
00216   void processEndOfFunction(NodeBuilderContext& BC);
00217 
00218   /// Generate the entry node of the callee.
00219   void processCallEnter(CallEnter CE, ExplodedNode *Pred);
00220 
00221   /// Generate the sequence of nodes that simulate the call exit and the post
00222   /// visit for CallExpr.
00223   void processCallExit(ExplodedNode *Pred);
00224 
00225   /// Called by CoreEngine when the analysis worklist has terminated.
00226   void processEndWorklist(bool hasWorkRemaining);
00227 
00228   /// evalAssume - Callback function invoked by the ConstraintManager when
00229   ///  making assumptions about state values.
00230   ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption);
00231 
00232   /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
00233   ///  region change should trigger a processRegionChanges update.
00234   bool wantsRegionChangeUpdate(ProgramStateRef state);
00235 
00236   /// processRegionChanges - Called by ProgramStateManager whenever a change is made
00237   ///  to the store. Used to update checkers that track region values.
00238   ProgramStateRef 
00239   processRegionChanges(ProgramStateRef state,
00240                        const StoreManager::InvalidatedSymbols *invalidated,
00241                        ArrayRef<const MemRegion *> ExplicitRegions,
00242                        ArrayRef<const MemRegion *> Regions,
00243                        const CallOrObjCMessage *Call);
00244 
00245   /// printState - Called by ProgramStateManager to print checker-specific data.
00246   void printState(raw_ostream &Out, ProgramStateRef State,
00247                   const char *NL, const char *Sep);
00248 
00249   virtual ProgramStateManager& getStateManager() { return StateMgr; }
00250 
00251   StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
00252 
00253   ConstraintManager& getConstraintManager() {
00254     return StateMgr.getConstraintManager();
00255   }
00256 
00257   // FIXME: Remove when we migrate over to just using SValBuilder.
00258   BasicValueFactory& getBasicVals() {
00259     return StateMgr.getBasicVals();
00260   }
00261   const BasicValueFactory& getBasicVals() const {
00262     return StateMgr.getBasicVals();
00263   }
00264 
00265   // FIXME: Remove when we migrate over to just using ValueManager.
00266   SymbolManager& getSymbolManager() { return SymMgr; }
00267   const SymbolManager& getSymbolManager() const { return SymMgr; }
00268 
00269   // Functions for external checking of whether we have unfinished work
00270   bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
00271   bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
00272   bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
00273 
00274   const CoreEngine &getCoreEngine() const { return Engine; }
00275 
00276 public:
00277   /// Visit - Transfer function logic for all statements.  Dispatches to
00278   ///  other functions that handle specific kinds of statements.
00279   void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
00280 
00281   /// VisitArraySubscriptExpr - Transfer function for array accesses.
00282   void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex,
00283                                    ExplodedNode *Pred,
00284                                    ExplodedNodeSet &Dst);
00285 
00286   /// VisitAsmStmt - Transfer function logic for inline asm.
00287   void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst);
00288   
00289   /// VisitBlockExpr - Transfer function logic for BlockExprs.
00290   void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 
00291                       ExplodedNodeSet &Dst);
00292 
00293   /// VisitBinaryOperator - Transfer function logic for binary operators.
00294   void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred, 
00295                            ExplodedNodeSet &Dst);
00296 
00297 
00298   /// VisitCall - Transfer function for function calls.
00299   void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
00300                      ExplodedNodeSet &Dst);
00301 
00302   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
00303   void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
00304                 ExplodedNodeSet &Dst);
00305 
00306   /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
00307   void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 
00308                                 ExplodedNode *Pred, ExplodedNodeSet &Dst);
00309 
00310   /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
00311   void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
00312                               ExplodedNode *Pred, ExplodedNodeSet &Dst);
00313   
00314   /// VisitDeclStmt - Transfer function logic for DeclStmts.
00315   void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, 
00316                      ExplodedNodeSet &Dst);
00317 
00318   /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
00319   void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, 
00320                         ExplodedNode *Pred, ExplodedNodeSet &Dst);
00321   
00322   void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
00323                          ExplodedNodeSet &Dst);
00324 
00325   /// VisitLogicalExpr - Transfer function logic for '&&', '||'
00326   void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
00327                         ExplodedNodeSet &Dst);
00328 
00329   /// VisitMemberExpr - Transfer function for member expressions.
00330   void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, 
00331                            ExplodedNodeSet &Dst);
00332 
00333   /// Transfer function logic for ObjCAtSynchronizedStmts.
00334   void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
00335                                    ExplodedNode *Pred, ExplodedNodeSet &Dst);
00336 
00337   /// Transfer function logic for computing the lvalue of an Objective-C ivar.
00338   void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred,
00339                                 ExplodedNodeSet &Dst);
00340 
00341   /// VisitObjCForCollectionStmt - Transfer function logic for
00342   ///  ObjCForCollectionStmt.
00343   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 
00344                                   ExplodedNode *Pred, ExplodedNodeSet &Dst);
00345 
00346   void VisitObjCMessage(const ObjCMessage &msg, ExplodedNode *Pred,
00347                         ExplodedNodeSet &Dst);
00348 
00349   /// VisitReturnStmt - Transfer function logic for return statements.
00350   void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, 
00351                        ExplodedNodeSet &Dst);
00352   
00353   /// VisitOffsetOfExpr - Transfer function for offsetof.
00354   void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
00355                          ExplodedNodeSet &Dst);
00356 
00357   /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
00358   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
00359                               ExplodedNode *Pred, ExplodedNodeSet &Dst);
00360 
00361   /// VisitUnaryOperator - Transfer function logic for unary operators.
00362   void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, 
00363                           ExplodedNodeSet &Dst);
00364 
00365   /// Handle ++ and -- (both pre- and post-increment).
00366   void VisitIncrementDecrementOperator(const UnaryOperator* U,
00367                                        ExplodedNode *Pred,
00368                                        ExplodedNodeSet &Dst);
00369   
00370   void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
00371                          ExplodedNodeSet &Dst);
00372 
00373   void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 
00374                         ExplodedNodeSet & Dst);
00375 
00376   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
00377                                    ExplodedNode *Pred, ExplodedNodeSet &Dst);
00378 
00379   void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
00380                              ExplodedNode *Pred, ExplodedNodeSet &Dst);
00381 
00382   void VisitCXXDestructor(const CXXDestructorDecl *DD,
00383                           const MemRegion *Dest, const Stmt *S,
00384                           ExplodedNode *Pred, ExplodedNodeSet &Dst);
00385 
00386   void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
00387                        ExplodedNodeSet &Dst);
00388 
00389   void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
00390                           ExplodedNodeSet &Dst);
00391 
00392   /// Create a C++ temporary object for an rvalue.
00393   void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
00394                                 ExplodedNode *Pred, 
00395                                 ExplodedNodeSet &Dst);
00396 
00397   /// Synthesize CXXThisRegion.
00398   const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD,
00399                                         const StackFrameContext *SFC);
00400 
00401   const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl,
00402                                         const StackFrameContext *frameCtx);
00403   
00404   /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
00405   ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)
00406   ///  with those assumptions.
00407   void evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 
00408                          const Expr *Ex);
00409   
00410   std::pair<const ProgramPointTag *, const ProgramPointTag*>
00411     getEagerlyAssumeTags();
00412 
00413   SVal evalMinus(SVal X) {
00414     return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
00415   }
00416 
00417   SVal evalComplement(SVal X) {
00418     return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
00419   }
00420 
00421 public:
00422 
00423   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
00424                  NonLoc L, NonLoc R, QualType T) {
00425     return svalBuilder.evalBinOpNN(state, op, L, R, T);
00426   }
00427 
00428   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
00429                  NonLoc L, SVal R, QualType T) {
00430     return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
00431   }
00432 
00433   SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
00434                  SVal LHS, SVal RHS, QualType T) {
00435     return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
00436   }
00437   
00438 protected:
00439   void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg,
00440                        ExplodedNode *Pred, ProgramStateRef state,
00441                        bool GenSink);
00442 
00443   ProgramStateRef invalidateArguments(ProgramStateRef State,
00444                                           const CallOrObjCMessage &Call,
00445                                           const LocationContext *LC);
00446 
00447   ProgramStateRef MarkBranch(ProgramStateRef state,
00448                                  const Stmt *Terminator,
00449                                  const LocationContext *LCtx,
00450                                  bool branchTaken);
00451 
00452   /// evalBind - Handle the semantics of binding a value to a specific location.
00453   ///  This method is used by evalStore, VisitDeclStmt, and others.
00454   void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
00455                 SVal location, SVal Val, bool atDeclInit = false);
00456 
00457 public:
00458   // FIXME: 'tag' should be removed, and a LocationContext should be used
00459   // instead.
00460   // FIXME: Comment on the meaning of the arguments, when 'St' may not
00461   // be the same as Pred->state, and when 'location' may not be the
00462   // same as state->getLValue(Ex).
00463   /// Simulate a read of the result of Ex.
00464   void evalLoad(ExplodedNodeSet &Dst,
00465                 const Expr *NodeEx,  /* Eventually will be a CFGStmt */
00466                 const Expr *BoundExpr,
00467                 ExplodedNode *Pred,
00468                 ProgramStateRef St,
00469                 SVal location,
00470                 const ProgramPointTag *tag = 0,
00471                 QualType LoadTy = QualType());
00472 
00473   // FIXME: 'tag' should be removed, and a LocationContext should be used
00474   // instead.
00475   void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
00476                  ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
00477                  const ProgramPointTag *tag = 0);
00478 private:
00479   void evalLoadCommon(ExplodedNodeSet &Dst,
00480                       const Expr *NodeEx,  /* Eventually will be a CFGStmt */
00481                       const Expr *BoundEx,
00482                       ExplodedNode *Pred,
00483                       ProgramStateRef St,
00484                       SVal location,
00485                       const ProgramPointTag *tag,
00486                       QualType LoadTy);
00487 
00488   // FIXME: 'tag' should be removed, and a LocationContext should be used
00489   // instead.
00490   void evalLocation(ExplodedNodeSet &Dst,
00491                     const Stmt *NodeEx, /* This will eventually be a CFGStmt */
00492                     const Stmt *BoundEx,
00493                     ExplodedNode *Pred,
00494                     ProgramStateRef St, SVal location,
00495                     const ProgramPointTag *tag, bool isLoad);
00496 
00497   bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred);
00498   bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
00499 
00500   bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
00501 };
00502 
00503 /// Traits for storing the call processing policy inside GDM.
00504 /// The GDM stores the corresponding CallExpr pointer.
00505 struct ReplayWithoutInlining{};
00506 template <>
00507 struct ProgramStateTrait<ReplayWithoutInlining> :
00508   public ProgramStatePartialTrait<void*> {
00509   static void *GDMIndex() { static int index = 0; return &index; }
00510 };
00511 
00512 } // end ento namespace
00513 
00514 } // end clang namespace
00515 
00516 #endif