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, which override the default analysis-wide settings. 52 enum InliningModes { 53 /// Follow the default settings for inlining callees. 54 Inline_Regular = 0, 55 /// Do minimal inlining of callees. 56 Inline_Minimal = 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 /// Called by CoreEngine. Used to processing branching behavior 228 /// at static initalizers. 229 void processStaticInitializer(const DeclStmt *DS, 230 NodeBuilderContext& BuilderCtx, 231 ExplodedNode *Pred, 232 ExplodedNodeSet &Dst, 233 const CFGBlock *DstT, 234 const CFGBlock *DstF); 235 236 /// processIndirectGoto - Called by CoreEngine. Used to generate successor 237 /// nodes by processing the 'effects' of a computed goto jump. 238 void processIndirectGoto(IndirectGotoNodeBuilder& builder); 239 240 /// ProcessSwitch - Called by CoreEngine. Used to generate successor 241 /// nodes by processing the 'effects' of a switch statement. 242 void processSwitch(SwitchNodeBuilder& builder); 243 244 /// Called by CoreEngine. Used to generate end-of-path 245 /// nodes when the control reaches the end of a function. 246 void processEndOfFunction(NodeBuilderContext& BC, 247 ExplodedNode *Pred); 248 249 /// Remove dead bindings/symbols before exiting a function. 250 void removeDeadOnEndOfFunction(NodeBuilderContext& BC, 251 ExplodedNode *Pred, 252 ExplodedNodeSet &Dst); 253 254 /// Generate the entry node of the callee. 255 void processCallEnter(CallEnter CE, ExplodedNode *Pred); 256 257 /// Generate the sequence of nodes that simulate the call exit and the post 258 /// visit for CallExpr. 259 void processCallExit(ExplodedNode *Pred); 260 261 /// Called by CoreEngine when the analysis worklist has terminated. 262 void processEndWorklist(bool hasWorkRemaining); 263 264 /// evalAssume - Callback function invoked by the ConstraintManager when 265 /// making assumptions about state values. 266 ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption); 267 268 /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a 269 /// region change should trigger a processRegionChanges update. 270 bool wantsRegionChangeUpdate(ProgramStateRef state); 271 272 /// processRegionChanges - Called by ProgramStateManager whenever a change is made 273 /// to the store. Used to update checkers that track region values. 274 ProgramStateRef 275 processRegionChanges(ProgramStateRef state, 276 const InvalidatedSymbols *invalidated, 277 ArrayRef<const MemRegion *> ExplicitRegions, 278 ArrayRef<const MemRegion *> Regions, 279 const CallEvent *Call); 280 281 /// printState - Called by ProgramStateManager to print checker-specific data. 282 void printState(raw_ostream &Out, ProgramStateRef State, 283 const char *NL, const char *Sep); 284 getStateManager()285 virtual ProgramStateManager& getStateManager() { return StateMgr; } 286 getStoreManager()287 StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } 288 getConstraintManager()289 ConstraintManager& getConstraintManager() { 290 return StateMgr.getConstraintManager(); 291 } 292 293 // FIXME: Remove when we migrate over to just using SValBuilder. getBasicVals()294 BasicValueFactory& getBasicVals() { 295 return StateMgr.getBasicVals(); 296 } 297 298 // FIXME: Remove when we migrate over to just using ValueManager. getSymbolManager()299 SymbolManager& getSymbolManager() { return SymMgr; } getSymbolManager()300 const SymbolManager& getSymbolManager() const { return SymMgr; } 301 302 // Functions for external checking of whether we have unfinished work wasBlocksExhausted()303 bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } hasEmptyWorkList()304 bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); } hasWorkRemaining()305 bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); } 306 getCoreEngine()307 const CoreEngine &getCoreEngine() const { return Engine; } 308 309 public: 310 /// Visit - Transfer function logic for all statements. Dispatches to 311 /// other functions that handle specific kinds of statements. 312 void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); 313 314 /// VisitArraySubscriptExpr - Transfer function for array accesses. 315 void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex, 316 ExplodedNode *Pred, 317 ExplodedNodeSet &Dst); 318 319 /// VisitGCCAsmStmt - Transfer function logic for inline asm. 320 void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, 321 ExplodedNodeSet &Dst); 322 323 /// VisitMSAsmStmt - Transfer function logic for MS inline asm. 324 void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, 325 ExplodedNodeSet &Dst); 326 327 /// VisitBlockExpr - Transfer function logic for BlockExprs. 328 void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 329 ExplodedNodeSet &Dst); 330 331 /// VisitBinaryOperator - Transfer function logic for binary operators. 332 void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred, 333 ExplodedNodeSet &Dst); 334 335 336 /// VisitCall - Transfer function for function calls. 337 void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 338 ExplodedNodeSet &Dst); 339 340 /// VisitCast - Transfer function logic for all casts (implicit and explicit). 341 void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, 342 ExplodedNodeSet &Dst); 343 344 /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. 345 void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 346 ExplodedNode *Pred, ExplodedNodeSet &Dst); 347 348 /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs. 349 void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, 350 ExplodedNode *Pred, ExplodedNodeSet &Dst); 351 352 /// VisitDeclStmt - Transfer function logic for DeclStmts. 353 void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, 354 ExplodedNodeSet &Dst); 355 356 /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose 357 void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, 358 ExplodedNode *Pred, ExplodedNodeSet &Dst); 359 360 void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, 361 ExplodedNodeSet &Dst); 362 363 /// VisitLogicalExpr - Transfer function logic for '&&', '||' 364 void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, 365 ExplodedNodeSet &Dst); 366 367 /// VisitMemberExpr - Transfer function for member expressions. 368 void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, 369 ExplodedNodeSet &Dst); 370 371 /// Transfer function logic for ObjCAtSynchronizedStmts. 372 void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, 373 ExplodedNode *Pred, ExplodedNodeSet &Dst); 374 375 /// Transfer function logic for computing the lvalue of an Objective-C ivar. 376 void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, 377 ExplodedNodeSet &Dst); 378 379 /// VisitObjCForCollectionStmt - Transfer function logic for 380 /// ObjCForCollectionStmt. 381 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 382 ExplodedNode *Pred, ExplodedNodeSet &Dst); 383 384 void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, 385 ExplodedNodeSet &Dst); 386 387 /// VisitReturnStmt - Transfer function logic for return statements. 388 void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, 389 ExplodedNodeSet &Dst); 390 391 /// VisitOffsetOfExpr - Transfer function for offsetof. 392 void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, 393 ExplodedNodeSet &Dst); 394 395 /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. 396 void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, 397 ExplodedNode *Pred, ExplodedNodeSet &Dst); 398 399 /// VisitUnaryOperator - Transfer function logic for unary operators. 400 void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, 401 ExplodedNodeSet &Dst); 402 403 /// Handle ++ and -- (both pre- and post-increment). 404 void VisitIncrementDecrementOperator(const UnaryOperator* U, 405 ExplodedNode *Pred, 406 ExplodedNodeSet &Dst); 407 408 void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, 409 ExplodedNodeSet &Dst); 410 411 void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 412 ExplodedNodeSet & Dst); 413 414 void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, 415 ExplodedNodeSet &Dst); 416 417 void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, 418 const Stmt *S, bool IsBaseDtor, 419 ExplodedNode *Pred, ExplodedNodeSet &Dst); 420 421 void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 422 ExplodedNodeSet &Dst); 423 424 void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, 425 ExplodedNodeSet &Dst); 426 427 /// Create a C++ temporary object for an rvalue. 428 void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 429 ExplodedNode *Pred, 430 ExplodedNodeSet &Dst); 431 432 /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic 433 /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) 434 /// with those assumptions. 435 void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 436 const Expr *Ex); 437 438 std::pair<const ProgramPointTag *, const ProgramPointTag*> 439 geteagerlyAssumeBinOpBifurcationTags(); 440 evalMinus(SVal X)441 SVal evalMinus(SVal X) { 442 return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X; 443 } 444 evalComplement(SVal X)445 SVal evalComplement(SVal X) { 446 return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X; 447 } 448 449 public: 450 evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,NonLoc R,QualType T)451 SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, 452 NonLoc L, NonLoc R, QualType T) { 453 return svalBuilder.evalBinOpNN(state, op, L, R, T); 454 } 455 evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,SVal R,QualType T)456 SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, 457 NonLoc L, SVal R, QualType T) { 458 return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, 459 R.castAs<NonLoc>(), T) : R; 460 } 461 evalBinOp(ProgramStateRef ST,BinaryOperator::Opcode Op,SVal LHS,SVal RHS,QualType T)462 SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, 463 SVal LHS, SVal RHS, QualType T) { 464 return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); 465 } 466 467 protected: 468 /// evalBind - Handle the semantics of binding a value to a specific location. 469 /// This method is used by evalStore, VisitDeclStmt, and others. 470 void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, 471 SVal location, SVal Val, bool atDeclInit = false, 472 const ProgramPoint *PP = 0); 473 474 /// Call PointerEscape callback when a value escapes as a result of bind. 475 ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, 476 SVal Loc, SVal Val); 477 /// Call PointerEscape callback when a value escapes as a result of 478 /// region invalidation. 479 /// \param[in] IsConst Specifies that the pointer is const. 480 ProgramStateRef notifyCheckersOfPointerEscape( 481 ProgramStateRef State, 482 const InvalidatedSymbols *Invalidated, 483 ArrayRef<const MemRegion *> ExplicitRegions, 484 ArrayRef<const MemRegion *> Regions, 485 const CallEvent *Call, 486 bool IsConst); 487 488 public: 489 // FIXME: 'tag' should be removed, and a LocationContext should be used 490 // instead. 491 // FIXME: Comment on the meaning of the arguments, when 'St' may not 492 // be the same as Pred->state, and when 'location' may not be the 493 // same as state->getLValue(Ex). 494 /// Simulate a read of the result of Ex. 495 void evalLoad(ExplodedNodeSet &Dst, 496 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 497 const Expr *BoundExpr, 498 ExplodedNode *Pred, 499 ProgramStateRef St, 500 SVal location, 501 const ProgramPointTag *tag = 0, 502 QualType LoadTy = QualType()); 503 504 // FIXME: 'tag' should be removed, and a LocationContext should be used 505 // instead. 506 void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, 507 ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, 508 const ProgramPointTag *tag = 0); 509 510 /// \brief Create a new state in which the call return value is binded to the 511 /// call origin expression. 512 ProgramStateRef bindReturnValue(const CallEvent &Call, 513 const LocationContext *LCtx, 514 ProgramStateRef State); 515 516 /// Evaluate a call, running pre- and post-call checks and allowing checkers 517 /// to be responsible for handling the evaluation of the call itself. 518 void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, 519 const CallEvent &Call); 520 521 /// \brief Default implementation of call evaluation. 522 void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, 523 const CallEvent &Call); 524 private: 525 void evalLoadCommon(ExplodedNodeSet &Dst, 526 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 527 const Expr *BoundEx, 528 ExplodedNode *Pred, 529 ProgramStateRef St, 530 SVal location, 531 const ProgramPointTag *tag, 532 QualType LoadTy); 533 534 // FIXME: 'tag' should be removed, and a LocationContext should be used 535 // instead. 536 void evalLocation(ExplodedNodeSet &Dst, 537 const Stmt *NodeEx, /* This will eventually be a CFGStmt */ 538 const Stmt *BoundEx, 539 ExplodedNode *Pred, 540 ProgramStateRef St, SVal location, 541 const ProgramPointTag *tag, bool isLoad); 542 543 /// Count the stack depth and determine if the call is recursive. 544 void examineStackFrames(const Decl *D, const LocationContext *LCtx, 545 bool &IsRecursive, unsigned &StackDepth); 546 547 /// Checks our policies and decides weither the given call should be inlined. 548 bool shouldInlineCall(const CallEvent &Call, const Decl *D, 549 const ExplodedNode *Pred); 550 551 bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 552 ExplodedNode *Pred, ProgramStateRef State); 553 554 /// \brief Conservatively evaluate call by invalidating regions and binding 555 /// a conjured return value. 556 void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, 557 ExplodedNode *Pred, ProgramStateRef State); 558 559 /// \brief Either inline or process the call conservatively (or both), based 560 /// on DynamicDispatchBifurcation data. 561 void BifurcateCall(const MemRegion *BifurReg, 562 const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 563 ExplodedNode *Pred); 564 565 bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); 566 567 /// Models a trivial copy or move constructor or trivial assignment operator 568 /// call with a simple bind. 569 void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 570 const CallEvent &Call); 571 572 /// If the value of the given expression is a NonLoc, copy it into a new 573 /// temporary object region, and replace the value of the expression with 574 /// that. 575 /// 576 /// If \p ResultE is provided, the new region will be bound to this expression 577 /// instead of \p E. 578 ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, 579 const LocationContext *LC, 580 const Expr *E, 581 const Expr *ResultE = 0); 582 }; 583 584 /// Traits for storing the call processing policy inside GDM. 585 /// The GDM stores the corresponding CallExpr pointer. 586 // FIXME: This does not use the nice trait macros because it must be accessible 587 // from multiple translation units. 588 struct ReplayWithoutInlining{}; 589 template <> 590 struct ProgramStateTrait<ReplayWithoutInlining> : 591 public ProgramStatePartialTrait<const void*> { 592 static void *GDMIndex() { static int index = 0; return &index; } 593 }; 594 595 } // end ento namespace 596 597 } // end clang namespace 598 599 #endif 600