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