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