1 //===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Defines the Static Analyzer Checker Manager. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H 14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H 15 16 #include "clang/Analysis/ProgramPoint.h" 17 #include "clang/Basic/Diagnostic.h" 18 #include "clang/Basic/LangOptions.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/ADT/StringRef.h" 25 #include <vector> 26 27 namespace clang { 28 29 class AnalyzerOptions; 30 class CallExpr; 31 class CXXNewExpr; 32 class Decl; 33 class LocationContext; 34 class Stmt; 35 class TranslationUnitDecl; 36 37 namespace ento { 38 39 class AnalysisManager; 40 class CXXAllocatorCall; 41 class BugReporter; 42 class CallEvent; 43 class CheckerBase; 44 class CheckerContext; 45 class CheckerRegistry; 46 struct CheckerRegistryData; 47 class ExplodedGraph; 48 class ExplodedNode; 49 class ExplodedNodeSet; 50 class ExprEngine; 51 struct EvalCallOptions; 52 class MemRegion; 53 struct NodeBuilderContext; 54 class ObjCMethodCall; 55 class RegionAndSymbolInvalidationTraits; 56 class SVal; 57 class SymbolReaper; 58 59 template <typename T> class CheckerFn; 60 61 template <typename RET, typename... Ps> 62 class CheckerFn<RET(Ps...)> { 63 using Func = RET (*)(void *, Ps...); 64 65 Func Fn; 66 67 public: 68 CheckerBase *Checker; 69 CheckerFn(CheckerBase * checker,Func fn)70 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {} 71 operator()72 RET operator()(Ps... ps) const { 73 return Fn(Checker, ps...); 74 } 75 }; 76 77 /// Describes the different reasons a pointer escapes 78 /// during analysis. 79 enum PointerEscapeKind { 80 /// A pointer escapes due to binding its value to a location 81 /// that the analyzer cannot track. 82 PSK_EscapeOnBind, 83 84 /// The pointer has been passed to a function call directly. 85 PSK_DirectEscapeOnCall, 86 87 /// The pointer has been passed to a function indirectly. 88 /// For example, the pointer is accessible through an 89 /// argument to a function. 90 PSK_IndirectEscapeOnCall, 91 92 93 /// Escape for a new symbol that was generated into a region 94 /// that the analyzer cannot follow during a conservative call. 95 PSK_EscapeOutParameters, 96 97 /// The reason for pointer escape is unknown. For example, 98 /// a region containing this pointer is invalidated. 99 PSK_EscapeOther 100 }; 101 102 /// This wrapper is used to ensure that only StringRefs originating from the 103 /// CheckerRegistry are used as check names. We want to make sure all checker 104 /// name strings have a lifetime that keeps them alive at least until the path 105 /// diagnostics have been processed, since they are expected to be constexpr 106 /// string literals (most likely generated by TblGen). 107 class CheckerNameRef { 108 friend class ::clang::ento::CheckerRegistry; 109 110 StringRef Name; 111 CheckerNameRef(StringRef Name)112 explicit CheckerNameRef(StringRef Name) : Name(Name) {} 113 114 public: 115 CheckerNameRef() = default; 116 getName()117 StringRef getName() const { return Name; } StringRef()118 operator StringRef() const { return Name; } 119 }; 120 121 enum class ObjCMessageVisitKind { 122 Pre, 123 Post, 124 MessageNil 125 }; 126 127 class CheckerManager { 128 ASTContext *Context = nullptr; 129 const LangOptions LangOpts; 130 const AnalyzerOptions &AOptions; 131 const Preprocessor *PP = nullptr; 132 CheckerNameRef CurrentCheckerName; 133 DiagnosticsEngine &Diags; 134 std::unique_ptr<CheckerRegistryData> RegistryData; 135 136 public: 137 // These constructors are defined in the Frontend library, because 138 // CheckerRegistry, a crucial component of the initialization is in there. 139 // CheckerRegistry cannot be moved to the Core library, because the checker 140 // registration functions are defined in the Checkers library, and the library 141 // dependencies look like this: Core -> Checkers -> Frontend. 142 143 CheckerManager( 144 ASTContext &Context, AnalyzerOptions &AOptions, const Preprocessor &PP, 145 ArrayRef<std::string> plugins, 146 ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns); 147 148 /// Constructs a CheckerManager that ignores all non TblGen-generated 149 /// checkers. Useful for unit testing, unless the checker infrastructure 150 /// itself is tested. CheckerManager(ASTContext & Context,AnalyzerOptions & AOptions,const Preprocessor & PP)151 CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions, 152 const Preprocessor &PP) 153 : CheckerManager(Context, AOptions, PP, {}, {}) {} 154 155 /// Constructs a CheckerManager without requiring an AST. No checker 156 /// registration will take place. Only useful when one needs to print the 157 /// help flags through CheckerRegistryData, and the AST is unavalaible. 158 CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts, 159 DiagnosticsEngine &Diags, ArrayRef<std::string> plugins); 160 161 ~CheckerManager(); 162 setCurrentCheckerName(CheckerNameRef name)163 void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; } getCurrentCheckerName()164 CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; } 165 166 bool hasPathSensitiveCheckers() const; 167 168 void finishedCheckerRegistration(); 169 getLangOpts()170 const LangOptions &getLangOpts() const { return LangOpts; } getAnalyzerOptions()171 const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; } getPreprocessor()172 const Preprocessor &getPreprocessor() const { 173 assert(PP); 174 return *PP; 175 } getCheckerRegistryData()176 const CheckerRegistryData &getCheckerRegistryData() const { 177 return *RegistryData; 178 } getDiagnostics()179 DiagnosticsEngine &getDiagnostics() const { return Diags; } getASTContext()180 ASTContext &getASTContext() const { 181 assert(Context); 182 return *Context; 183 } 184 185 /// Emits an error through a DiagnosticsEngine about an invalid user supplied 186 /// checker option value. 187 void reportInvalidCheckerOptionValue(const CheckerBase *C, 188 StringRef OptionName, 189 StringRef ExpectedValueDesc) const; 190 191 using CheckerRef = CheckerBase *; 192 using CheckerTag = const void *; 193 using CheckerDtor = CheckerFn<void ()>; 194 195 //===----------------------------------------------------------------------===// 196 // Checker registration. 197 //===----------------------------------------------------------------------===// 198 199 /// Used to register checkers. 200 /// All arguments are automatically passed through to the checker 201 /// constructor. 202 /// 203 /// \returns a pointer to the checker object. 204 template <typename CHECKER, typename... AT> registerChecker(AT &&...Args)205 CHECKER *registerChecker(AT &&... Args) { 206 CheckerTag tag = getTag<CHECKER>(); 207 CheckerRef &ref = CheckerTags[tag]; 208 assert(!ref && "Checker already registered, use getChecker!"); 209 210 CHECKER *checker = new CHECKER(std::forward<AT>(Args)...); 211 checker->Name = CurrentCheckerName; 212 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 213 CHECKER::_register(checker, *this); 214 ref = checker; 215 return checker; 216 } 217 218 template <typename CHECKER> getChecker()219 CHECKER *getChecker() { 220 CheckerTag tag = getTag<CHECKER>(); 221 assert(CheckerTags.count(tag) != 0 && 222 "Requested checker is not registered! Maybe you should add it as a " 223 "dependency in Checkers.td?"); 224 return static_cast<CHECKER *>(CheckerTags[tag]); 225 } 226 227 //===----------------------------------------------------------------------===// 228 // Functions for running checkers for AST traversing. 229 //===----------------------------------------------------------------------===// 230 231 /// Run checkers handling Decls. 232 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 233 BugReporter &BR); 234 235 /// Run checkers handling Decls containing a Stmt body. 236 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 237 BugReporter &BR); 238 239 //===----------------------------------------------------------------------===// 240 // Functions for running checkers for path-sensitive checking. 241 //===----------------------------------------------------------------------===// 242 243 /// Run checkers for pre-visiting Stmts. 244 /// 245 /// The notification is performed for every explored CFGElement, which does 246 /// not include the control flow statements such as IfStmt. 247 /// 248 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt runCheckersForPreStmt(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const Stmt * S,ExprEngine & Eng)249 void runCheckersForPreStmt(ExplodedNodeSet &Dst, 250 const ExplodedNodeSet &Src, 251 const Stmt *S, 252 ExprEngine &Eng) { 253 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 254 } 255 256 /// Run checkers for post-visiting Stmts. 257 /// 258 /// The notification is performed for every explored CFGElement, which does 259 /// not include the control flow statements such as IfStmt. 260 /// 261 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt 262 void runCheckersForPostStmt(ExplodedNodeSet &Dst, 263 const ExplodedNodeSet &Src, 264 const Stmt *S, 265 ExprEngine &Eng, 266 bool wasInlined = false) { 267 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); 268 } 269 270 /// Run checkers for visiting Stmts. 271 void runCheckersForStmt(bool isPreVisit, 272 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 273 const Stmt *S, ExprEngine &Eng, 274 bool wasInlined = false); 275 276 /// Run checkers for pre-visiting obj-c messages. runCheckersForPreObjCMessage(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)277 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 278 const ExplodedNodeSet &Src, 279 const ObjCMethodCall &msg, 280 ExprEngine &Eng) { 281 runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng); 282 } 283 284 /// Run checkers for post-visiting obj-c messages. 285 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 286 const ExplodedNodeSet &Src, 287 const ObjCMethodCall &msg, 288 ExprEngine &Eng, 289 bool wasInlined = false) { 290 runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng, 291 wasInlined); 292 } 293 294 /// Run checkers for visiting an obj-c message to nil. runCheckersForObjCMessageNil(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)295 void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst, 296 const ExplodedNodeSet &Src, 297 const ObjCMethodCall &msg, 298 ExprEngine &Eng) { 299 runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg, 300 Eng); 301 } 302 303 /// Run checkers for visiting obj-c messages. 304 void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, 305 ExplodedNodeSet &Dst, 306 const ExplodedNodeSet &Src, 307 const ObjCMethodCall &msg, ExprEngine &Eng, 308 bool wasInlined = false); 309 310 /// Run checkers for pre-visiting obj-c messages. runCheckersForPreCall(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const CallEvent & Call,ExprEngine & Eng)311 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 312 const CallEvent &Call, ExprEngine &Eng) { 313 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); 314 } 315 316 /// Run checkers for post-visiting obj-c messages. 317 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 318 const CallEvent &Call, ExprEngine &Eng, 319 bool wasInlined = false) { 320 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng, 321 wasInlined); 322 } 323 324 /// Run checkers for visiting obj-c messages. 325 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, 326 const ExplodedNodeSet &Src, 327 const CallEvent &Call, ExprEngine &Eng, 328 bool wasInlined = false); 329 330 /// Run checkers for load/store of a location. 331 void runCheckersForLocation(ExplodedNodeSet &Dst, 332 const ExplodedNodeSet &Src, 333 SVal location, 334 bool isLoad, 335 const Stmt *NodeEx, 336 const Stmt *BoundEx, 337 ExprEngine &Eng); 338 339 /// Run checkers for binding of a value to a location. 340 void runCheckersForBind(ExplodedNodeSet &Dst, 341 const ExplodedNodeSet &Src, 342 SVal location, SVal val, 343 const Stmt *S, ExprEngine &Eng, 344 const ProgramPoint &PP); 345 346 /// Run checkers for end of analysis. 347 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 348 ExprEngine &Eng); 349 350 /// Run checkers on beginning of function. 351 void runCheckersForBeginFunction(ExplodedNodeSet &Dst, 352 const BlockEdge &L, 353 ExplodedNode *Pred, 354 ExprEngine &Eng); 355 356 /// Run checkers on end of function. 357 void runCheckersForEndFunction(NodeBuilderContext &BC, 358 ExplodedNodeSet &Dst, 359 ExplodedNode *Pred, 360 ExprEngine &Eng, 361 const ReturnStmt *RS); 362 363 /// Run checkers for branch condition. 364 void runCheckersForBranchCondition(const Stmt *condition, 365 ExplodedNodeSet &Dst, ExplodedNode *Pred, 366 ExprEngine &Eng); 367 368 /// Run checkers between C++ operator new and constructor calls. 369 void runCheckersForNewAllocator(const CXXAllocatorCall &Call, 370 ExplodedNodeSet &Dst, ExplodedNode *Pred, 371 ExprEngine &Eng, bool wasInlined = false); 372 373 /// Run checkers for live symbols. 374 /// 375 /// Allows modifying SymbolReaper object. For example, checkers can explicitly 376 /// register symbols of interest as live. These symbols will not be marked 377 /// dead and removed. 378 void runCheckersForLiveSymbols(ProgramStateRef state, 379 SymbolReaper &SymReaper); 380 381 /// Run checkers for dead symbols. 382 /// 383 /// Notifies checkers when symbols become dead. For example, this allows 384 /// checkers to aggressively clean up/reduce the checker state and produce 385 /// precise diagnostics. 386 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 387 const ExplodedNodeSet &Src, 388 SymbolReaper &SymReaper, const Stmt *S, 389 ExprEngine &Eng, 390 ProgramPoint::Kind K); 391 392 /// Run checkers for region changes. 393 /// 394 /// This corresponds to the check::RegionChanges callback. 395 /// \param state The current program state. 396 /// \param invalidated A set of all symbols potentially touched by the change. 397 /// \param ExplicitRegions The regions explicitly requested for invalidation. 398 /// For example, in the case of a function call, these would be arguments. 399 /// \param Regions The transitive closure of accessible regions, 400 /// i.e. all regions that may have been touched by this change. 401 /// \param Call The call expression wrapper if the regions are invalidated 402 /// by a call. 403 ProgramStateRef 404 runCheckersForRegionChanges(ProgramStateRef state, 405 const InvalidatedSymbols *invalidated, 406 ArrayRef<const MemRegion *> ExplicitRegions, 407 ArrayRef<const MemRegion *> Regions, 408 const LocationContext *LCtx, 409 const CallEvent *Call); 410 411 /// Run checkers when pointers escape. 412 /// 413 /// This notifies the checkers about pointer escape, which occurs whenever 414 /// the analyzer cannot track the symbol any more. For example, as a 415 /// result of assigning a pointer into a global or when it's passed to a 416 /// function call the analyzer cannot model. 417 /// 418 /// \param State The state at the point of escape. 419 /// \param Escaped The list of escaped symbols. 420 /// \param Call The corresponding CallEvent, if the symbols escape as 421 /// parameters to the given call. 422 /// \param Kind The reason of pointer escape. 423 /// \param ITraits Information about invalidation for a particular 424 /// region/symbol. 425 /// \returns Checkers can modify the state by returning a new one. 426 ProgramStateRef 427 runCheckersForPointerEscape(ProgramStateRef State, 428 const InvalidatedSymbols &Escaped, 429 const CallEvent *Call, 430 PointerEscapeKind Kind, 431 RegionAndSymbolInvalidationTraits *ITraits); 432 433 /// Run checkers for handling assumptions on symbolic values. 434 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, 435 SVal Cond, bool Assumption); 436 437 /// Run checkers for evaluating a call. 438 /// 439 /// Warning: Currently, the CallEvent MUST come from a CallExpr! 440 void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 441 const CallEvent &CE, ExprEngine &Eng, 442 const EvalCallOptions &CallOpts); 443 444 /// Run checkers for the entire Translation Unit. 445 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, 446 AnalysisManager &mgr, 447 BugReporter &BR); 448 449 /// Run checkers for debug-printing a ProgramState. 450 /// 451 /// Unlike most other callbacks, any checker can simply implement the virtual 452 /// method CheckerBase::printState if it has custom data to print. 453 /// 454 /// \param Out The output stream 455 /// \param State The state being printed 456 /// \param NL The preferred representation of a newline. 457 /// \param Space The preferred space between the left side and the message. 458 /// \param IsDot Whether the message will be printed in 'dot' format. 459 void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, 460 const char *NL = "\n", 461 unsigned int Space = 0, 462 bool IsDot = false) const; 463 464 //===----------------------------------------------------------------------===// 465 // Internal registration functions for AST traversing. 466 //===----------------------------------------------------------------------===// 467 468 // Functions used by the registration mechanism, checkers should not touch 469 // these directly. 470 471 using CheckDeclFunc = 472 CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>; 473 474 using HandlesDeclFunc = bool (*)(const Decl *D); 475 476 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 477 478 void _registerForBody(CheckDeclFunc checkfn); 479 480 //===----------------------------------------------------------------------===// 481 // Internal registration functions for path-sensitive checking. 482 //===----------------------------------------------------------------------===// 483 484 using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>; 485 486 using CheckObjCMessageFunc = 487 CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>; 488 489 using CheckCallFunc = 490 CheckerFn<void (const CallEvent &, CheckerContext &)>; 491 492 using CheckLocationFunc = 493 CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S, 494 CheckerContext &)>; 495 496 using CheckBindFunc = 497 CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S, 498 CheckerContext &)>; 499 500 using CheckEndAnalysisFunc = 501 CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>; 502 503 using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>; 504 505 using CheckEndFunctionFunc = 506 CheckerFn<void (const ReturnStmt *, CheckerContext &)>; 507 508 using CheckBranchConditionFunc = 509 CheckerFn<void (const Stmt *, CheckerContext &)>; 510 511 using CheckNewAllocatorFunc = 512 CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>; 513 514 using CheckDeadSymbolsFunc = 515 CheckerFn<void (SymbolReaper &, CheckerContext &)>; 516 517 using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>; 518 519 using CheckRegionChangesFunc = 520 CheckerFn<ProgramStateRef (ProgramStateRef, 521 const InvalidatedSymbols *symbols, 522 ArrayRef<const MemRegion *> ExplicitRegions, 523 ArrayRef<const MemRegion *> Regions, 524 const LocationContext *LCtx, 525 const CallEvent *Call)>; 526 527 using CheckPointerEscapeFunc = 528 CheckerFn<ProgramStateRef (ProgramStateRef, 529 const InvalidatedSymbols &Escaped, 530 const CallEvent *Call, PointerEscapeKind Kind, 531 RegionAndSymbolInvalidationTraits *ITraits)>; 532 533 using EvalAssumeFunc = 534 CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, 535 bool assumption)>; 536 537 using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>; 538 539 using CheckEndOfTranslationUnit = 540 CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &, 541 BugReporter &)>; 542 543 using HandlesStmtFunc = bool (*)(const Stmt *D); 544 545 void _registerForPreStmt(CheckStmtFunc checkfn, 546 HandlesStmtFunc isForStmtFn); 547 void _registerForPostStmt(CheckStmtFunc checkfn, 548 HandlesStmtFunc isForStmtFn); 549 550 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 551 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 552 553 void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn); 554 555 void _registerForPreCall(CheckCallFunc checkfn); 556 void _registerForPostCall(CheckCallFunc checkfn); 557 558 void _registerForLocation(CheckLocationFunc checkfn); 559 560 void _registerForBind(CheckBindFunc checkfn); 561 562 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 563 564 void _registerForBeginFunction(CheckBeginFunctionFunc checkfn); 565 void _registerForEndFunction(CheckEndFunctionFunc checkfn); 566 567 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 568 569 void _registerForNewAllocator(CheckNewAllocatorFunc checkfn); 570 571 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 572 573 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 574 575 void _registerForRegionChanges(CheckRegionChangesFunc checkfn); 576 577 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn); 578 579 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn); 580 581 void _registerForEvalAssume(EvalAssumeFunc checkfn); 582 583 void _registerForEvalCall(EvalCallFunc checkfn); 584 585 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); 586 587 //===----------------------------------------------------------------------===// 588 // Internal registration functions for events. 589 //===----------------------------------------------------------------------===// 590 591 using EventTag = void *; 592 using CheckEventFunc = CheckerFn<void (const void *event)>; 593 594 template <typename EVENT> _registerListenerForEvent(CheckEventFunc checkfn)595 void _registerListenerForEvent(CheckEventFunc checkfn) { 596 EventInfo &info = Events[&EVENT::Tag]; 597 info.Checkers.push_back(checkfn); 598 } 599 600 template <typename EVENT> _registerDispatcherForEvent()601 void _registerDispatcherForEvent() { 602 EventInfo &info = Events[&EVENT::Tag]; 603 info.HasDispatcher = true; 604 } 605 606 template <typename EVENT> _dispatchEvent(const EVENT & event)607 void _dispatchEvent(const EVENT &event) const { 608 EventsTy::const_iterator I = Events.find(&EVENT::Tag); 609 if (I == Events.end()) 610 return; 611 const EventInfo &info = I->second; 612 for (const auto &Checker : info.Checkers) 613 Checker(&event); 614 } 615 616 //===----------------------------------------------------------------------===// 617 // Implementation details. 618 //===----------------------------------------------------------------------===// 619 620 private: 621 template <typename CHECKER> destruct(void * obj)622 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 623 624 template <typename T> getTag()625 static void *getTag() { static int tag; return &tag; } 626 627 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 628 629 std::vector<CheckerDtor> CheckerDtors; 630 631 struct DeclCheckerInfo { 632 CheckDeclFunc CheckFn; 633 HandlesDeclFunc IsForDeclFn; 634 }; 635 std::vector<DeclCheckerInfo> DeclCheckers; 636 637 std::vector<CheckDeclFunc> BodyCheckers; 638 639 using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>; 640 using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>; 641 CachedDeclCheckersMapTy CachedDeclCheckersMap; 642 643 struct StmtCheckerInfo { 644 CheckStmtFunc CheckFn; 645 HandlesStmtFunc IsForStmtFn; 646 bool IsPreVisit; 647 }; 648 std::vector<StmtCheckerInfo> StmtCheckers; 649 650 using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>; 651 using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>; 652 CachedStmtCheckersMapTy CachedStmtCheckersMap; 653 654 const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S, 655 bool isPreVisit); 656 657 /// Returns the checkers that have registered for callbacks of the 658 /// given \p Kind. 659 const std::vector<CheckObjCMessageFunc> & 660 getObjCMessageCheckers(ObjCMessageVisitKind Kind) const; 661 662 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 663 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 664 std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers; 665 666 std::vector<CheckCallFunc> PreCallCheckers; 667 std::vector<CheckCallFunc> PostCallCheckers; 668 669 std::vector<CheckLocationFunc> LocationCheckers; 670 671 std::vector<CheckBindFunc> BindCheckers; 672 673 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 674 675 std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers; 676 std::vector<CheckEndFunctionFunc> EndFunctionCheckers; 677 678 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 679 680 std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers; 681 682 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 683 684 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 685 686 std::vector<CheckRegionChangesFunc> RegionChangesCheckers; 687 688 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers; 689 690 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 691 692 std::vector<EvalCallFunc> EvalCallCheckers; 693 694 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; 695 696 struct EventInfo { 697 SmallVector<CheckEventFunc, 4> Checkers; 698 bool HasDispatcher = false; 699 700 EventInfo() = default; 701 }; 702 703 using EventsTy = llvm::DenseMap<EventTag, EventInfo>; 704 EventsTy Events; 705 }; 706 707 } // namespace ento 708 709 } // namespace clang 710 711 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H 712