1 //===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- 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 a meta-engine for path-sensitive dataflow analysis that 11 // is built on CoreEngine, but provides the boilerplate to execute transfer 12 // functions and build the ExplodedGraph at the expression level. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_CLANG_GR_EXPRENGINE 17 #define LLVM_CLANG_GR_EXPRENGINE 18 19 #include "clang/AST/Expr.h" 20 #include "clang/AST/Type.h" 21 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 22 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 23 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 24 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" 25 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 26 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 27 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" 28 29 namespace clang { 30 31 class AnalysisDeclContextManager; 32 class CXXCatchStmt; 33 class CXXConstructExpr; 34 class CXXDeleteExpr; 35 class CXXNewExpr; 36 class CXXTemporaryObjectExpr; 37 class CXXThisExpr; 38 class MaterializeTemporaryExpr; 39 class ObjCAtSynchronizedStmt; 40 class ObjCForCollectionStmt; 41 42 namespace ento { 43 44 class AnalysisManager; 45 class CallEvent; 46 class SimpleCall; 47 class CXXConstructorCall; 48 49 class ExprEngine : public SubEngine { 50 public: 51 /// The modes of inlining. 52 enum InliningModes { 53 /// Do not inline any of the callees. 54 Inline_None = 0, 55 /// Inline all callees. 56 Inline_All = 0x1 57 } ; 58 59 private: 60 AnalysisManager &AMgr; 61 62 AnalysisDeclContextManager &AnalysisDeclContexts; 63 64 CoreEngine Engine; 65 66 /// G - the simulation graph. 67 ExplodedGraph& G; 68 69 /// StateMgr - Object that manages the data for all created states. 70 ProgramStateManager StateMgr; 71 72 /// SymMgr - Object that manages the symbol information. 73 SymbolManager& SymMgr; 74 75 /// svalBuilder - SValBuilder object that creates SVals from expressions. 76 SValBuilder &svalBuilder; 77 78 unsigned int currStmtIdx; 79 const NodeBuilderContext *currBldrCtx; 80 81 /// Helper object to determine if an Objective-C message expression 82 /// implicitly never returns. 83 ObjCNoReturn ObjCNoRet; 84 85 /// Whether or not GC is enabled in this analysis. 86 bool ObjCGCEnabled; 87 88 /// The BugReporter associated with this engine. It is important that 89 /// this object be placed at the very end of member variables so that its 90 /// destructor is called before the rest of the ExprEngine is destroyed. 91 GRBugReporter BR; 92 93 /// The functions which have been analyzed through inlining. This is owned by 94 /// AnalysisConsumer. It can be null. 95 SetOfConstDecls *VisitedCallees; 96 97 /// The flag, which specifies the mode of inlining for the engine. 98 InliningModes HowToInline; 99 100 public: 101 ExprEngine(AnalysisManager &mgr, bool gcEnabled, 102 SetOfConstDecls *VisitedCalleesIn, 103 FunctionSummariesTy *FS, 104 InliningModes HowToInlineIn); 105 106 ~ExprEngine(); 107 108 /// Returns true if there is still simulation state on the worklist. 109 bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { 110 return Engine.ExecuteWorkList(L, Steps, 0); 111 } 112 113 /// Execute the work list with an initial state. Nodes that reaches the exit 114 /// of the function are added into the Dst set, which represent the exit 115 /// state of the function call. Returns true if there is still simulation 116 /// state on the worklist. ExecuteWorkListWithInitialState(const LocationContext * L,unsigned Steps,ProgramStateRef InitState,ExplodedNodeSet & Dst)117 bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, 118 ProgramStateRef InitState, 119 ExplodedNodeSet &Dst) { 120 return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); 121 } 122 123 /// getContext - Return the ASTContext associated with this analysis. getContext()124 ASTContext &getContext() const { return AMgr.getASTContext(); } 125 getAnalysisManager()126 virtual AnalysisManager &getAnalysisManager() { return AMgr; } 127 getCheckerManager()128 CheckerManager &getCheckerManager() const { 129 return *AMgr.getCheckerManager(); 130 } 131 getSValBuilder()132 SValBuilder &getSValBuilder() { return svalBuilder; } 133 getBugReporter()134 BugReporter& getBugReporter() { return BR; } 135 getBuilderContext()136 const NodeBuilderContext &getBuilderContext() { 137 assert(currBldrCtx); 138 return *currBldrCtx; 139 } 140 isObjCGCEnabled()141 bool isObjCGCEnabled() { return ObjCGCEnabled; } 142 143 const Stmt *getStmt() const; 144 145 void GenerateAutoTransition(ExplodedNode *N); 146 void enqueueEndOfPath(ExplodedNodeSet &S); 147 void GenerateCallExitNode(ExplodedNode *N); 148 149 /// Visualize the ExplodedGraph created by executing the simulation. 150 void ViewGraph(bool trim = false); 151 152 /// Visualize a trimmed ExplodedGraph that only contains paths to the given 153 /// nodes. 154 void ViewGraph(ArrayRef<const ExplodedNode*> Nodes); 155 156 /// getInitialState - Return the initial state used for the root vertex 157 /// in the ExplodedGraph. 158 ProgramStateRef getInitialState(const LocationContext *InitLoc); 159 getGraph()160 ExplodedGraph& getGraph() { return G; } getGraph()161 const ExplodedGraph& getGraph() const { return G; } 162 163 /// \brief Run the analyzer's garbage collection - remove dead symbols and 164 /// bindings from the state. 165 /// 166 /// Checkers can participate in this process with two callbacks: 167 /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation 168 /// class for more information. 169 /// 170 /// \param Node The predecessor node, from which the processing should start. 171 /// \param Out The returned set of output nodes. 172 /// \param ReferenceStmt The statement which is about to be processed. 173 /// Everything needed for this statement should be considered live. 174 /// A null statement means that everything in child LocationContexts 175 /// is dead. 176 /// \param LC The location context of the \p ReferenceStmt. A null location 177 /// context means that we have reached the end of analysis and that 178 /// all statements and local variables should be considered dead. 179 /// \param DiagnosticStmt Used as a location for any warnings that should 180 /// occur while removing the dead (e.g. leaks). By default, the 181 /// \p ReferenceStmt is used. 182 /// \param K Denotes whether this is a pre- or post-statement purge. This 183 /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an 184 /// entire location context is being cleared, in which case the 185 /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise, 186 /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default) 187 /// and \p ReferenceStmt must be valid (non-null). 188 void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, 189 const Stmt *ReferenceStmt, const LocationContext *LC, 190 const Stmt *DiagnosticStmt = 0, 191 ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind); 192 193 /// processCFGElement - Called by CoreEngine. Used to generate new successor 194 /// nodes by processing the 'effects' of a CFG element. 195 void processCFGElement(const CFGElement E, ExplodedNode *Pred, 196 unsigned StmtIdx, NodeBuilderContext *Ctx); 197 198 void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); 199 200 void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred); 201 202 void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); 203 204 void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, 205 ExplodedNode *Pred, ExplodedNodeSet &Dst); 206 void ProcessBaseDtor(const CFGBaseDtor D, 207 ExplodedNode *Pred, ExplodedNodeSet &Dst); 208 void ProcessMemberDtor(const CFGMemberDtor D, 209 ExplodedNode *Pred, ExplodedNodeSet &Dst); 210 void ProcessTemporaryDtor(const CFGTemporaryDtor D, 211 ExplodedNode *Pred, ExplodedNodeSet &Dst); 212 213 /// Called by CoreEngine when processing the entrance of a CFGBlock. 214 virtual void processCFGBlockEntrance(const BlockEdge &L, 215 NodeBuilderWithSinks &nodeBuilder, 216 ExplodedNode *Pred); 217 218 /// ProcessBranch - Called by CoreEngine. Used to generate successor 219 /// nodes by processing the 'effects' of a branch condition. 220 void processBranch(const Stmt *Condition, const Stmt *Term, 221 NodeBuilderContext& BuilderCtx, 222 ExplodedNode *Pred, 223 ExplodedNodeSet &Dst, 224 const CFGBlock *DstT, 225 const CFGBlock *DstF); 226 227 /// processIndirectGoto - Called by CoreEngine. Used to generate successor 228 /// nodes by processing the 'effects' of a computed goto jump. 229 void processIndirectGoto(IndirectGotoNodeBuilder& builder); 230 231 /// ProcessSwitch - Called by CoreEngine. Used to generate successor 232 /// nodes by processing the 'effects' of a switch statement. 233 void processSwitch(SwitchNodeBuilder& builder); 234 235 /// Called by CoreEngine. Used to generate end-of-path 236 /// nodes when the control reaches the end of a function. 237 void processEndOfFunction(NodeBuilderContext& BC, 238 ExplodedNode *Pred); 239 240 /// Remove dead bindings/symbols before exiting a function. 241 void removeDeadOnEndOfFunction(NodeBuilderContext& BC, 242 ExplodedNode *Pred, 243 ExplodedNodeSet &Dst); 244 245 /// Generate the entry node of the callee. 246 void processCallEnter(CallEnter CE, ExplodedNode *Pred); 247 248 /// Generate the sequence of nodes that simulate the call exit and the post 249 /// visit for CallExpr. 250 void processCallExit(ExplodedNode *Pred); 251 252 /// Called by CoreEngine when the analysis worklist has terminated. 253 void processEndWorklist(bool hasWorkRemaining); 254 255 /// evalAssume - Callback function invoked by the ConstraintManager when 256 /// making assumptions about state values. 257 ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption); 258 259 /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a 260 /// region change should trigger a processRegionChanges update. 261 bool wantsRegionChangeUpdate(ProgramStateRef state); 262 263 /// processRegionChanges - Called by ProgramStateManager whenever a change is made 264 /// to the store. Used to update checkers that track region values. 265 ProgramStateRef 266 processRegionChanges(ProgramStateRef state, 267 const InvalidatedSymbols *invalidated, 268 ArrayRef<const MemRegion *> ExplicitRegions, 269 ArrayRef<const MemRegion *> Regions, 270 const CallEvent *Call); 271 272 /// printState - Called by ProgramStateManager to print checker-specific data. 273 void printState(raw_ostream &Out, ProgramStateRef State, 274 const char *NL, const char *Sep); 275 getStateManager()276 virtual ProgramStateManager& getStateManager() { return StateMgr; } 277 getStoreManager()278 StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } 279 getConstraintManager()280 ConstraintManager& getConstraintManager() { 281 return StateMgr.getConstraintManager(); 282 } 283 284 // FIXME: Remove when we migrate over to just using SValBuilder. getBasicVals()285 BasicValueFactory& getBasicVals() { 286 return StateMgr.getBasicVals(); 287 } 288 289 // FIXME: Remove when we migrate over to just using ValueManager. getSymbolManager()290 SymbolManager& getSymbolManager() { return SymMgr; } getSymbolManager()291 const SymbolManager& getSymbolManager() const { return SymMgr; } 292 293 // Functions for external checking of whether we have unfinished work wasBlocksExhausted()294 bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } hasEmptyWorkList()295 bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); } hasWorkRemaining()296 bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); } 297 getCoreEngine()298 const CoreEngine &getCoreEngine() const { return Engine; } 299 300 public: 301 /// Visit - Transfer function logic for all statements. Dispatches to 302 /// other functions that handle specific kinds of statements. 303 void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); 304 305 /// VisitArraySubscriptExpr - Transfer function for array accesses. 306 void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex, 307 ExplodedNode *Pred, 308 ExplodedNodeSet &Dst); 309 310 /// VisitGCCAsmStmt - Transfer function logic for inline asm. 311 void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, 312 ExplodedNodeSet &Dst); 313 314 /// VisitMSAsmStmt - Transfer function logic for MS inline asm. 315 void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, 316 ExplodedNodeSet &Dst); 317 318 /// VisitBlockExpr - Transfer function logic for BlockExprs. 319 void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 320 ExplodedNodeSet &Dst); 321 322 /// VisitBinaryOperator - Transfer function logic for binary operators. 323 void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred, 324 ExplodedNodeSet &Dst); 325 326 327 /// VisitCall - Transfer function for function calls. 328 void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 329 ExplodedNodeSet &Dst); 330 331 /// VisitCast - Transfer function logic for all casts (implicit and explicit). 332 void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, 333 ExplodedNodeSet &Dst); 334 335 /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. 336 void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 337 ExplodedNode *Pred, ExplodedNodeSet &Dst); 338 339 /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs. 340 void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, 341 ExplodedNode *Pred, ExplodedNodeSet &Dst); 342 343 /// VisitDeclStmt - Transfer function logic for DeclStmts. 344 void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, 345 ExplodedNodeSet &Dst); 346 347 /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose 348 void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, 349 ExplodedNode *Pred, ExplodedNodeSet &Dst); 350 351 void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, 352 ExplodedNodeSet &Dst); 353 354 /// VisitLogicalExpr - Transfer function logic for '&&', '||' 355 void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, 356 ExplodedNodeSet &Dst); 357 358 /// VisitMemberExpr - Transfer function for member expressions. 359 void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, 360 ExplodedNodeSet &Dst); 361 362 /// Transfer function logic for ObjCAtSynchronizedStmts. 363 void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, 364 ExplodedNode *Pred, ExplodedNodeSet &Dst); 365 366 /// Transfer function logic for computing the lvalue of an Objective-C ivar. 367 void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, 368 ExplodedNodeSet &Dst); 369 370 /// VisitObjCForCollectionStmt - Transfer function logic for 371 /// ObjCForCollectionStmt. 372 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 373 ExplodedNode *Pred, ExplodedNodeSet &Dst); 374 375 void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, 376 ExplodedNodeSet &Dst); 377 378 /// VisitReturnStmt - Transfer function logic for return statements. 379 void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, 380 ExplodedNodeSet &Dst); 381 382 /// VisitOffsetOfExpr - Transfer function for offsetof. 383 void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, 384 ExplodedNodeSet &Dst); 385 386 /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. 387 void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, 388 ExplodedNode *Pred, ExplodedNodeSet &Dst); 389 390 /// VisitUnaryOperator - Transfer function logic for unary operators. 391 void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, 392 ExplodedNodeSet &Dst); 393 394 /// Handle ++ and -- (both pre- and post-increment). 395 void VisitIncrementDecrementOperator(const UnaryOperator* U, 396 ExplodedNode *Pred, 397 ExplodedNodeSet &Dst); 398 399 void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, 400 ExplodedNodeSet &Dst); 401 402 void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 403 ExplodedNodeSet & Dst); 404 405 void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, 406 ExplodedNodeSet &Dst); 407 408 void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, 409 const Stmt *S, bool IsBaseDtor, 410 ExplodedNode *Pred, ExplodedNodeSet &Dst); 411 412 void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 413 ExplodedNodeSet &Dst); 414 415 void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, 416 ExplodedNodeSet &Dst); 417 418 /// Create a C++ temporary object for an rvalue. 419 void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 420 ExplodedNode *Pred, 421 ExplodedNodeSet &Dst); 422 423 /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic 424 /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) 425 /// with those assumptions. 426 void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 427 const Expr *Ex); 428 429 std::pair<const ProgramPointTag *, const ProgramPointTag*> 430 geteagerlyAssumeBinOpBifurcationTags(); 431 evalMinus(SVal X)432 SVal evalMinus(SVal X) { 433 return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X; 434 } 435 evalComplement(SVal X)436 SVal evalComplement(SVal X) { 437 return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X; 438 } 439 440 public: 441 evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,NonLoc R,QualType T)442 SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, 443 NonLoc L, NonLoc R, QualType T) { 444 return svalBuilder.evalBinOpNN(state, op, L, R, T); 445 } 446 evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,SVal R,QualType T)447 SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, 448 NonLoc L, SVal R, QualType T) { 449 return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, 450 R.castAs<NonLoc>(), T) : R; 451 } 452 evalBinOp(ProgramStateRef ST,BinaryOperator::Opcode Op,SVal LHS,SVal RHS,QualType T)453 SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, 454 SVal LHS, SVal RHS, QualType T) { 455 return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); 456 } 457 458 protected: 459 /// evalBind - Handle the semantics of binding a value to a specific location. 460 /// This method is used by evalStore, VisitDeclStmt, and others. 461 void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, 462 SVal location, SVal Val, bool atDeclInit = false, 463 const ProgramPoint *PP = 0); 464 465 /// Call PointerEscape callback when a value escapes as a result of bind. 466 ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, 467 SVal Loc, SVal Val); 468 /// Call PointerEscape callback when a value escapes as a result of 469 /// region invalidation. 470 ProgramStateRef processPointerEscapedOnInvalidateRegions( 471 ProgramStateRef State, 472 const InvalidatedSymbols *Invalidated, 473 ArrayRef<const MemRegion *> ExplicitRegions, 474 ArrayRef<const MemRegion *> Regions, 475 const CallEvent *Call); 476 477 public: 478 // FIXME: 'tag' should be removed, and a LocationContext should be used 479 // instead. 480 // FIXME: Comment on the meaning of the arguments, when 'St' may not 481 // be the same as Pred->state, and when 'location' may not be the 482 // same as state->getLValue(Ex). 483 /// Simulate a read of the result of Ex. 484 void evalLoad(ExplodedNodeSet &Dst, 485 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 486 const Expr *BoundExpr, 487 ExplodedNode *Pred, 488 ProgramStateRef St, 489 SVal location, 490 const ProgramPointTag *tag = 0, 491 QualType LoadTy = QualType()); 492 493 // FIXME: 'tag' should be removed, and a LocationContext should be used 494 // instead. 495 void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, 496 ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, 497 const ProgramPointTag *tag = 0); 498 499 /// \brief Create a new state in which the call return value is binded to the 500 /// call origin expression. 501 ProgramStateRef bindReturnValue(const CallEvent &Call, 502 const LocationContext *LCtx, 503 ProgramStateRef State); 504 505 /// Evaluate a call, running pre- and post-call checks and allowing checkers 506 /// to be responsible for handling the evaluation of the call itself. 507 void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, 508 const CallEvent &Call); 509 510 /// \brief Default implementation of call evaluation. 511 void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, 512 const CallEvent &Call); 513 private: 514 void evalLoadCommon(ExplodedNodeSet &Dst, 515 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 516 const Expr *BoundEx, 517 ExplodedNode *Pred, 518 ProgramStateRef St, 519 SVal location, 520 const ProgramPointTag *tag, 521 QualType LoadTy); 522 523 // FIXME: 'tag' should be removed, and a LocationContext should be used 524 // instead. 525 void evalLocation(ExplodedNodeSet &Dst, 526 const Stmt *NodeEx, /* This will eventually be a CFGStmt */ 527 const Stmt *BoundEx, 528 ExplodedNode *Pred, 529 ProgramStateRef St, SVal location, 530 const ProgramPointTag *tag, bool isLoad); 531 532 /// Count the stack depth and determine if the call is recursive. 533 void examineStackFrames(const Decl *D, const LocationContext *LCtx, 534 bool &IsRecursive, unsigned &StackDepth); 535 536 /// Checks our policies and decides weither the given call should be inlined. 537 bool shouldInlineCall(const CallEvent &Call, const Decl *D, 538 const ExplodedNode *Pred); 539 540 bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 541 ExplodedNode *Pred, ProgramStateRef State); 542 543 /// \brief Conservatively evaluate call by invalidating regions and binding 544 /// a conjured return value. 545 void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, 546 ExplodedNode *Pred, ProgramStateRef State); 547 548 /// \brief Either inline or process the call conservatively (or both), based 549 /// on DynamicDispatchBifurcation data. 550 void BifurcateCall(const MemRegion *BifurReg, 551 const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 552 ExplodedNode *Pred); 553 554 bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); 555 556 /// Models a trivial copy or move constructor or trivial assignment operator 557 /// call with a simple bind. 558 void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 559 const CallEvent &Call); 560 561 /// If the value of the given expression is a NonLoc, copy it into a new 562 /// temporary object region, and replace the value of the expression with 563 /// that. 564 /// 565 /// If \p ResultE is provided, the new region will be bound to this expression 566 /// instead of \p E. 567 ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, 568 const LocationContext *LC, 569 const Expr *E, 570 const Expr *ResultE = 0); 571 }; 572 573 /// Traits for storing the call processing policy inside GDM. 574 /// The GDM stores the corresponding CallExpr pointer. 575 // FIXME: This does not use the nice trait macros because it must be accessible 576 // from multiple translation units. 577 struct ReplayWithoutInlining{}; 578 template <> 579 struct ProgramStateTrait<ReplayWithoutInlining> : 580 public ProgramStatePartialTrait<const void*> { 581 static void *GDMIndex() { static int index = 0; return &index; } 582 }; 583 584 } // end ento namespace 585 586 } // end clang namespace 587 588 #endif 589