CheckerManager.h revision 263508
167754Smsmith//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===// 267754Smsmith// 367754Smsmith// The LLVM Compiler Infrastructure 470243Smsmith// 567754Smsmith// This file is distributed under the University of Illinois Open Source 667754Smsmith// License. See LICENSE.TXT for details. 767754Smsmith// 867754Smsmith//===----------------------------------------------------------------------===// 967754Smsmith// 1067754Smsmith// Defines the Static Analyzer Checker Manager. 1167754Smsmith// 1270243Smsmith//===----------------------------------------------------------------------===// 1370243Smsmith 1467754Smsmith#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 1567754Smsmith#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 1667754Smsmith 1767754Smsmith#include "clang/Analysis/ProgramPoint.h" 1867754Smsmith#include "clang/Basic/LangOptions.h" 1967754Smsmith#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 2067754Smsmith#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 2167754Smsmith#include "llvm/ADT/DenseMap.h" 2267754Smsmith#include "llvm/ADT/SmallVector.h" 2367754Smsmith#include <vector> 2467754Smsmith 2567754Smsmithnamespace clang { 2667754Smsmith class Decl; 2767754Smsmith class Stmt; 2867754Smsmith class CallExpr; 2967754Smsmith 3067754Smsmithnamespace ento { 3167754Smsmith class CheckerBase; 3267754Smsmith class ExprEngine; 3367754Smsmith class AnalysisManager; 3467754Smsmith class BugReporter; 3567754Smsmith class CheckerContext; 3667754Smsmith class SimpleCall; 3767754Smsmith class ObjCMethodCall; 3867754Smsmith class SVal; 3967754Smsmith class ExplodedNode; 4067754Smsmith class ExplodedNodeSet; 4167754Smsmith class ExplodedGraph; 4267754Smsmith class ProgramState; 4367754Smsmith class NodeBuilder; 4467754Smsmith struct NodeBuilderContext; 4567754Smsmith class MemRegion; 4667754Smsmith class SymbolReaper; 4767754Smsmith 4867754Smsmithtemplate <typename T> class CheckerFn; 4967754Smsmith 5067754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3, typename P4, 5167754Smsmith typename P5> 5267754Smsmithclass CheckerFn<RET(P1, P2, P3, P4, P5)> { 5367754Smsmith typedef RET (*Func)(void *, P1, P2, P3, P4, P5); 5467754Smsmith Func Fn; 5567754Smsmithpublic: 5667754Smsmith CheckerBase *Checker; 5767754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 5867754Smsmith RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { 5967754Smsmith return Fn(Checker, p1, p2, p3, p4, p5); 6067754Smsmith } 6167754Smsmith}; 6267754Smsmith 6367754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3, typename P4> 6467754Smsmithclass CheckerFn<RET(P1, P2, P3, P4)> { 6567754Smsmith typedef RET (*Func)(void *, P1, P2, P3, P4); 6667754Smsmith Func Fn; 6767754Smsmithpublic: 6867754Smsmith CheckerBase *Checker; 6967754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 7067754Smsmith RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 7167754Smsmith return Fn(Checker, p1, p2, p3, p4); 7267754Smsmith } 7367754Smsmith}; 7467754Smsmith 7567754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3> 7667754Smsmithclass CheckerFn<RET(P1, P2, P3)> { 7767754Smsmith typedef RET (*Func)(void *, P1, P2, P3); 7867754Smsmith Func Fn; 7967754Smsmithpublic: 8067754Smsmith CheckerBase *Checker; 8167754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 8267754Smsmith RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 8367754Smsmith}; 8467754Smsmith 8567754Smsmithtemplate <typename RET, typename P1, typename P2> 8667754Smsmithclass CheckerFn<RET(P1, P2)> { 8767754Smsmith typedef RET (*Func)(void *, P1, P2); 8867754Smsmith Func Fn; 8967754Smsmithpublic: 9067754Smsmith CheckerBase *Checker; 9167754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 9267754Smsmith RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 9367754Smsmith}; 9467754Smsmith 9567754Smsmithtemplate <typename RET, typename P1> 9667754Smsmithclass CheckerFn<RET(P1)> { 9767754Smsmith typedef RET (*Func)(void *, P1); 9867754Smsmith Func Fn; 9967754Smsmithpublic: 10067754Smsmith CheckerBase *Checker; 10167754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 10267754Smsmith RET operator()(P1 p1) const { return Fn(Checker, p1); } 10367754Smsmith}; 10467754Smsmith 10567754Smsmithtemplate <typename RET> 10667754Smsmithclass CheckerFn<RET()> { 10767754Smsmith typedef RET (*Func)(void *); 10867754Smsmith Func Fn; 10967754Smsmithpublic: 11067754Smsmith CheckerBase *Checker; 11167754Smsmith CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 11267754Smsmith RET operator()() const { return Fn(Checker); } 11367754Smsmith}; 11467754Smsmith 11567754Smsmith/// \brief Describes the different reasons a pointer escapes 11667754Smsmith/// during analysis. 11767754Smsmithenum PointerEscapeKind { 11867754Smsmith /// A pointer escapes due to binding its value to a location 11967754Smsmith /// that the analyzer cannot track. 12067754Smsmith PSK_EscapeOnBind, 12167754Smsmith 12267754Smsmith /// The pointer has been passed to a function call directly. 12367754Smsmith PSK_DirectEscapeOnCall, 12467754Smsmith 12567754Smsmith /// The pointer has been passed to a function indirectly. 12667754Smsmith /// For example, the pointer is accessible through an 12767754Smsmith /// argument to a function. 12867754Smsmith PSK_IndirectEscapeOnCall, 12967754Smsmith 13067754Smsmith /// The reason for pointer escape is unknown. For example, 13167754Smsmith /// a region containing this pointer is invalidated. 13267754Smsmith PSK_EscapeOther 13367754Smsmith}; 13467754Smsmith 13567754Smsmithclass CheckerManager { 13667754Smsmith const LangOptions LangOpts; 13767754Smsmith AnalyzerOptionsRef AOptions; 13867754Smsmithpublic: 13967754Smsmith CheckerManager(const LangOptions &langOpts, 14067754Smsmith AnalyzerOptionsRef AOptions) 14167754Smsmith : LangOpts(langOpts), 14267754Smsmith AOptions(AOptions) {} 14367754Smsmith 14467754Smsmith ~CheckerManager(); 14567754Smsmith 14667754Smsmith bool hasPathSensitiveCheckers() const; 14767754Smsmith 14867754Smsmith void finishedCheckerRegistration(); 14967754Smsmith 15067754Smsmith const LangOptions &getLangOpts() const { return LangOpts; } 15167754Smsmith AnalyzerOptions &getAnalyzerOptions() { return *AOptions; } 15267754Smsmith 15367754Smsmith typedef CheckerBase *CheckerRef; 15467754Smsmith typedef const void *CheckerTag; 15567754Smsmith typedef CheckerFn<void ()> CheckerDtor; 15667754Smsmith 15767754Smsmith//===----------------------------------------------------------------------===// 15867754Smsmith// registerChecker 15967754Smsmith//===----------------------------------------------------------------------===// 16067754Smsmith 16167754Smsmith /// \brief Used to register checkers. 16267754Smsmith /// 16367754Smsmith /// \returns a pointer to the checker object. 16469450Smsmith template <typename CHECKER> 16567754Smsmith CHECKER *registerChecker() { 16667754Smsmith CheckerTag tag = getTag<CHECKER>(); 16767754Smsmith CheckerRef &ref = CheckerTags[tag]; 16869450Smsmith if (ref) 16967754Smsmith return static_cast<CHECKER *>(ref); // already registered. 17067754Smsmith 17167754Smsmith CHECKER *checker = new CHECKER(); 17267754Smsmith CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 17367754Smsmith CHECKER::_register(checker, *this); 17467754Smsmith ref = checker; 17567754Smsmith return checker; 17667754Smsmith } 17767754Smsmith 17867754Smsmith template <typename CHECKER> 17967754Smsmith CHECKER *registerChecker(AnalyzerOptions &AOpts) { 18067754Smsmith CheckerTag tag = getTag<CHECKER>(); 18167754Smsmith CheckerRef &ref = CheckerTags[tag]; 18267754Smsmith if (ref) 18367754Smsmith return static_cast<CHECKER *>(ref); // already registered. 18467754Smsmith 18567754Smsmith CHECKER *checker = new CHECKER(AOpts); 18667754Smsmith CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 18767754Smsmith CHECKER::_register(checker, *this); 18867754Smsmith ref = checker; 18967754Smsmith return checker; 19067754Smsmith } 19167754Smsmith 19267754Smsmith//===----------------------------------------------------------------------===// 19367754Smsmith// Functions for running checkers for AST traversing.. 19467754Smsmith//===----------------------------------------------------------------------===// 19567754Smsmith 19667754Smsmith /// \brief Run checkers handling Decls. 19767754Smsmith void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 19867754Smsmith BugReporter &BR); 19967754Smsmith 20067754Smsmith /// \brief Run checkers handling Decls containing a Stmt body. 20167754Smsmith void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 20267754Smsmith BugReporter &BR); 20367754Smsmith 20467754Smsmith//===----------------------------------------------------------------------===// 20567754Smsmith// Functions for running checkers for path-sensitive checking. 20667754Smsmith//===----------------------------------------------------------------------===// 20767754Smsmith 20867754Smsmith /// \brief Run checkers for pre-visiting Stmts. 20967754Smsmith /// 21067754Smsmith /// The notification is performed for every explored CFGElement, which does 21167754Smsmith /// not include the control flow statements such as IfStmt. 21267754Smsmith /// 21367754Smsmith /// \sa runCheckersForBranchCondition, runCheckersForPostStmt 21467754Smsmith void runCheckersForPreStmt(ExplodedNodeSet &Dst, 21567754Smsmith const ExplodedNodeSet &Src, 21667754Smsmith const Stmt *S, 21767754Smsmith ExprEngine &Eng) { 21867754Smsmith runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 21967754Smsmith } 22067754Smsmith 22167754Smsmith /// \brief Run checkers for post-visiting Stmts. 22267754Smsmith /// 22367754Smsmith /// The notification is performed for every explored CFGElement, which does 22467754Smsmith /// not include the control flow statements such as IfStmt. 22567754Smsmith /// 22667754Smsmith /// \sa runCheckersForBranchCondition, runCheckersForPreStmt 22767754Smsmith void runCheckersForPostStmt(ExplodedNodeSet &Dst, 22867754Smsmith const ExplodedNodeSet &Src, 22967754Smsmith const Stmt *S, 23067754Smsmith ExprEngine &Eng, 23167754Smsmith bool wasInlined = false) { 23267754Smsmith runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); 23367754Smsmith } 23467754Smsmith 23567754Smsmith /// \brief Run checkers for visiting Stmts. 23667754Smsmith void runCheckersForStmt(bool isPreVisit, 23767754Smsmith ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 23867754Smsmith const Stmt *S, ExprEngine &Eng, 23967754Smsmith bool wasInlined = false); 24067754Smsmith 24167754Smsmith /// \brief Run checkers for pre-visiting obj-c messages. 24267754Smsmith void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 24367754Smsmith const ExplodedNodeSet &Src, 24467754Smsmith const ObjCMethodCall &msg, 24567754Smsmith ExprEngine &Eng) { 24667754Smsmith runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 24767754Smsmith } 24867754Smsmith 24967754Smsmith /// \brief Run checkers for post-visiting obj-c messages. 25067754Smsmith void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 25167754Smsmith const ExplodedNodeSet &Src, 25267754Smsmith const ObjCMethodCall &msg, 25367754Smsmith ExprEngine &Eng, 25467754Smsmith bool wasInlined = false) { 25567754Smsmith runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng, 25667754Smsmith wasInlined); 25767754Smsmith } 25867754Smsmith 25967754Smsmith /// \brief Run checkers for visiting obj-c messages. 26067754Smsmith void runCheckersForObjCMessage(bool isPreVisit, 26167754Smsmith ExplodedNodeSet &Dst, 26267754Smsmith const ExplodedNodeSet &Src, 26367754Smsmith const ObjCMethodCall &msg, ExprEngine &Eng, 26467754Smsmith bool wasInlined = false); 26567754Smsmith 26667754Smsmith /// \brief Run checkers for pre-visiting obj-c messages. 26767754Smsmith void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 26867754Smsmith const CallEvent &Call, ExprEngine &Eng) { 26967754Smsmith runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); 27067754Smsmith } 27167754Smsmith 27267754Smsmith /// \brief Run checkers for post-visiting obj-c messages. 27367754Smsmith void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 27467754Smsmith const CallEvent &Call, ExprEngine &Eng, 27567754Smsmith bool wasInlined = false) { 27667754Smsmith runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng, 27767754Smsmith wasInlined); 27867754Smsmith } 27967754Smsmith 28067754Smsmith /// \brief Run checkers for visiting obj-c messages. 28167754Smsmith void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, 28267754Smsmith const ExplodedNodeSet &Src, 28367754Smsmith const CallEvent &Call, ExprEngine &Eng, 28467754Smsmith bool wasInlined = false); 28567754Smsmith 28667754Smsmith /// \brief Run checkers for load/store of a location. 28767754Smsmith void runCheckersForLocation(ExplodedNodeSet &Dst, 28867754Smsmith const ExplodedNodeSet &Src, 28967754Smsmith SVal location, 29067754Smsmith bool isLoad, 29167754Smsmith const Stmt *NodeEx, 29267754Smsmith const Stmt *BoundEx, 29367754Smsmith ExprEngine &Eng); 29467754Smsmith 29567754Smsmith /// \brief Run checkers for binding of a value to a location. 29667754Smsmith void runCheckersForBind(ExplodedNodeSet &Dst, 29767754Smsmith const ExplodedNodeSet &Src, 29867754Smsmith SVal location, SVal val, 29967754Smsmith const Stmt *S, ExprEngine &Eng, 30067754Smsmith const ProgramPoint &PP); 30167754Smsmith 30267754Smsmith /// \brief Run checkers for end of analysis. 30367754Smsmith void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 30467754Smsmith ExprEngine &Eng); 30567754Smsmith 30667754Smsmith /// \brief Run checkers on end of function. 30767754Smsmith void runCheckersForEndFunction(NodeBuilderContext &BC, 30867754Smsmith ExplodedNodeSet &Dst, 30967754Smsmith ExplodedNode *Pred, 31067754Smsmith ExprEngine &Eng); 31167754Smsmith 31267754Smsmith /// \brief Run checkers for branch condition. 31367754Smsmith void runCheckersForBranchCondition(const Stmt *condition, 31467754Smsmith ExplodedNodeSet &Dst, ExplodedNode *Pred, 31567754Smsmith ExprEngine &Eng); 31667754Smsmith 31767754Smsmith /// \brief Run checkers for live symbols. 31867754Smsmith /// 31967754Smsmith /// Allows modifying SymbolReaper object. For example, checkers can explicitly 32067754Smsmith /// register symbols of interest as live. These symbols will not be marked 32167754Smsmith /// dead and removed. 32267754Smsmith void runCheckersForLiveSymbols(ProgramStateRef state, 32367754Smsmith SymbolReaper &SymReaper); 32467754Smsmith 32567754Smsmith /// \brief Run checkers for dead symbols. 32667754Smsmith /// 32767754Smsmith /// Notifies checkers when symbols become dead. For example, this allows 32867754Smsmith /// checkers to aggressively clean up/reduce the checker state and produce 32967754Smsmith /// precise diagnostics. 33067754Smsmith void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 33167754Smsmith const ExplodedNodeSet &Src, 33267754Smsmith SymbolReaper &SymReaper, const Stmt *S, 33367754Smsmith ExprEngine &Eng, 33467754Smsmith ProgramPoint::Kind K); 33567754Smsmith 33667754Smsmith /// \brief True if at least one checker wants to check region changes. 33767754Smsmith bool wantsRegionChangeUpdate(ProgramStateRef state); 33867754Smsmith 33967754Smsmith /// \brief Run checkers for region changes. 34067754Smsmith /// 34167754Smsmith /// This corresponds to the check::RegionChanges callback. 34267754Smsmith /// \param state The current program state. 34367754Smsmith /// \param invalidated A set of all symbols potentially touched by the change. 34467754Smsmith /// \param ExplicitRegions The regions explicitly requested for invalidation. 34567754Smsmith /// For example, in the case of a function call, these would be arguments. 34667754Smsmith /// \param Regions The transitive closure of accessible regions, 34767754Smsmith /// i.e. all regions that may have been touched by this change. 34867754Smsmith /// \param Call The call expression wrapper if the regions are invalidated 34967754Smsmith /// by a call. 35067754Smsmith ProgramStateRef 35167754Smsmith runCheckersForRegionChanges(ProgramStateRef state, 35267754Smsmith const InvalidatedSymbols *invalidated, 35367754Smsmith ArrayRef<const MemRegion *> ExplicitRegions, 35467754Smsmith ArrayRef<const MemRegion *> Regions, 35567754Smsmith const CallEvent *Call); 35667754Smsmith 35767754Smsmith /// \brief Run checkers when pointers escape. 35867754Smsmith /// 35967754Smsmith /// This notifies the checkers about pointer escape, which occurs whenever 36067754Smsmith /// the analyzer cannot track the symbol any more. For example, as a 36167754Smsmith /// result of assigning a pointer into a global or when it's passed to a 36267754Smsmith /// function call the analyzer cannot model. 36367754Smsmith /// 36467754Smsmith /// \param State The state at the point of escape. 36567754Smsmith /// \param Escaped The list of escaped symbols. 36667754Smsmith /// \param Call The corresponding CallEvent, if the symbols escape as 36767754Smsmith /// parameters to the given call. 36867754Smsmith /// \param Kind The reason of pointer escape. 36967754Smsmith /// \param ITraits Information about invalidation for a particular 37067754Smsmith /// region/symbol. 37167754Smsmith /// \returns Checkers can modify the state by returning a new one. 37269450Smsmith ProgramStateRef 37367754Smsmith runCheckersForPointerEscape(ProgramStateRef State, 37467754Smsmith const InvalidatedSymbols &Escaped, 37567754Smsmith const CallEvent *Call, 37669450Smsmith PointerEscapeKind Kind, 37767754Smsmith RegionAndSymbolInvalidationTraits *ITraits); 37867754Smsmith 37967754Smsmith /// \brief Run checkers for handling assumptions on symbolic values. 38067754Smsmith ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, 38167754Smsmith SVal Cond, bool Assumption); 38267754Smsmith 38367754Smsmith /// \brief Run checkers for evaluating a call. 38467754Smsmith /// 38567754Smsmith /// Warning: Currently, the CallEvent MUST come from a CallExpr! 38667754Smsmith void runCheckersForEvalCall(ExplodedNodeSet &Dst, 38767754Smsmith const ExplodedNodeSet &Src, 38867754Smsmith const CallEvent &CE, ExprEngine &Eng); 38967754Smsmith 39067754Smsmith /// \brief Run checkers for the entire Translation Unit. 39167754Smsmith void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, 39267754Smsmith AnalysisManager &mgr, 39367754Smsmith BugReporter &BR); 39467754Smsmith 39567754Smsmith /// \brief Run checkers for debug-printing a ProgramState. 39667754Smsmith /// 39767754Smsmith /// Unlike most other callbacks, any checker can simply implement the virtual 39867754Smsmith /// method CheckerBase::printState if it has custom data to print. 39967754Smsmith /// \param Out The output stream 40067754Smsmith /// \param State The state being printed 40167754Smsmith /// \param NL The preferred representation of a newline. 40267754Smsmith /// \param Sep The preferred separator between different kinds of data. 40367754Smsmith void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, 40467754Smsmith const char *NL, const char *Sep); 40567754Smsmith 40667754Smsmith//===----------------------------------------------------------------------===// 40767754Smsmith// Internal registration functions for AST traversing. 40867754Smsmith//===----------------------------------------------------------------------===// 40967754Smsmith 410 // Functions used by the registration mechanism, checkers should not touch 411 // these directly. 412 413 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> 414 CheckDeclFunc; 415 416 typedef bool (*HandlesDeclFunc)(const Decl *D); 417 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 418 419 void _registerForBody(CheckDeclFunc checkfn); 420 421//===----------------------------------------------------------------------===// 422// Internal registration functions for path-sensitive checking. 423//===----------------------------------------------------------------------===// 424 425 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; 426 427 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)> 428 CheckObjCMessageFunc; 429 430 typedef CheckerFn<void (const CallEvent &, CheckerContext &)> 431 CheckCallFunc; 432 433 typedef CheckerFn<void (const SVal &location, bool isLoad, 434 const Stmt *S, 435 CheckerContext &)> 436 CheckLocationFunc; 437 438 typedef CheckerFn<void (const SVal &location, const SVal &val, 439 const Stmt *S, CheckerContext &)> 440 CheckBindFunc; 441 442 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> 443 CheckEndAnalysisFunc; 444 445 typedef CheckerFn<void (CheckerContext &)> 446 CheckEndFunctionFunc; 447 448 typedef CheckerFn<void (const Stmt *, CheckerContext &)> 449 CheckBranchConditionFunc; 450 451 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> 452 CheckDeadSymbolsFunc; 453 454 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; 455 456 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 457 const InvalidatedSymbols *symbols, 458 ArrayRef<const MemRegion *> ExplicitRegions, 459 ArrayRef<const MemRegion *> Regions, 460 const CallEvent *Call)> 461 CheckRegionChangesFunc; 462 463 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; 464 465 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 466 const InvalidatedSymbols &Escaped, 467 const CallEvent *Call, 468 PointerEscapeKind Kind, 469 RegionAndSymbolInvalidationTraits *ITraits)> 470 CheckPointerEscapeFunc; 471 472 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 473 const SVal &cond, bool assumption)> 474 EvalAssumeFunc; 475 476 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> 477 EvalCallFunc; 478 479 typedef CheckerFn<void (const TranslationUnitDecl *, 480 AnalysisManager&, BugReporter &)> 481 CheckEndOfTranslationUnit; 482 483 typedef bool (*HandlesStmtFunc)(const Stmt *D); 484 void _registerForPreStmt(CheckStmtFunc checkfn, 485 HandlesStmtFunc isForStmtFn); 486 void _registerForPostStmt(CheckStmtFunc checkfn, 487 HandlesStmtFunc isForStmtFn); 488 489 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 490 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 491 492 void _registerForPreCall(CheckCallFunc checkfn); 493 void _registerForPostCall(CheckCallFunc checkfn); 494 495 void _registerForLocation(CheckLocationFunc checkfn); 496 497 void _registerForBind(CheckBindFunc checkfn); 498 499 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 500 501 void _registerForEndFunction(CheckEndFunctionFunc checkfn); 502 503 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 504 505 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 506 507 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 508 509 void _registerForRegionChanges(CheckRegionChangesFunc checkfn, 510 WantsRegionChangeUpdateFunc wantUpdateFn); 511 512 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn); 513 514 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn); 515 516 void _registerForEvalAssume(EvalAssumeFunc checkfn); 517 518 void _registerForEvalCall(EvalCallFunc checkfn); 519 520 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); 521 522//===----------------------------------------------------------------------===// 523// Internal registration functions for events. 524//===----------------------------------------------------------------------===// 525 526 typedef void *EventTag; 527 typedef CheckerFn<void (const void *event)> CheckEventFunc; 528 529 template <typename EVENT> 530 void _registerListenerForEvent(CheckEventFunc checkfn) { 531 EventInfo &info = Events[getTag<EVENT>()]; 532 info.Checkers.push_back(checkfn); 533 } 534 535 template <typename EVENT> 536 void _registerDispatcherForEvent() { 537 EventInfo &info = Events[getTag<EVENT>()]; 538 info.HasDispatcher = true; 539 } 540 541 template <typename EVENT> 542 void _dispatchEvent(const EVENT &event) const { 543 EventsTy::const_iterator I = Events.find(getTag<EVENT>()); 544 if (I == Events.end()) 545 return; 546 const EventInfo &info = I->second; 547 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) 548 info.Checkers[i](&event); 549 } 550 551//===----------------------------------------------------------------------===// 552// Implementation details. 553//===----------------------------------------------------------------------===// 554 555private: 556 template <typename CHECKER> 557 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 558 559 template <typename T> 560 static void *getTag() { static int tag; return &tag; } 561 562 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 563 564 std::vector<CheckerDtor> CheckerDtors; 565 566 struct DeclCheckerInfo { 567 CheckDeclFunc CheckFn; 568 HandlesDeclFunc IsForDeclFn; 569 }; 570 std::vector<DeclCheckerInfo> DeclCheckers; 571 572 std::vector<CheckDeclFunc> BodyCheckers; 573 574 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 575 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 576 CachedDeclCheckersMapTy CachedDeclCheckersMap; 577 578 struct StmtCheckerInfo { 579 CheckStmtFunc CheckFn; 580 HandlesStmtFunc IsForStmtFn; 581 bool IsPreVisit; 582 }; 583 std::vector<StmtCheckerInfo> StmtCheckers; 584 585 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 586 typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy; 587 CachedStmtCheckersMapTy CachedStmtCheckersMap; 588 589 const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S, 590 bool isPreVisit); 591 592 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 593 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 594 595 std::vector<CheckCallFunc> PreCallCheckers; 596 std::vector<CheckCallFunc> PostCallCheckers; 597 598 std::vector<CheckLocationFunc> LocationCheckers; 599 600 std::vector<CheckBindFunc> BindCheckers; 601 602 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 603 604 std::vector<CheckEndFunctionFunc> EndFunctionCheckers; 605 606 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 607 608 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 609 610 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 611 612 struct RegionChangesCheckerInfo { 613 CheckRegionChangesFunc CheckFn; 614 WantsRegionChangeUpdateFunc WantUpdateFn; 615 }; 616 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; 617 618 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers; 619 620 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 621 622 std::vector<EvalCallFunc> EvalCallCheckers; 623 624 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; 625 626 struct EventInfo { 627 SmallVector<CheckEventFunc, 4> Checkers; 628 bool HasDispatcher; 629 EventInfo() : HasDispatcher(false) { } 630 }; 631 632 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; 633 EventsTy Events; 634}; 635 636} // end ento namespace 637 638} // end clang namespace 639 640#endif 641