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