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