1 //===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Defines the Static Analyzer Checker Manager.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
16 #include "clang/Analysis/ProgramPoint.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringRef.h"
28 class AnalyzerOptions;
32 class LocationContext;
34 class TranslationUnitDecl;
38 class AnalysisManager;
43 class CheckerRegistry;
46 class ExplodedNodeSet;
49 struct NodeBuilderContext;
51 class RegionAndSymbolInvalidationTraits;
55 template <typename T> class CheckerFn;
57 template <typename RET, typename... Ps>
58 class CheckerFn<RET(Ps...)> {
59 using Func = RET (*)(void *, Ps...);
66 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
68 RET operator()(Ps... ps) const {
69 return Fn(Checker, ps...);
73 /// Describes the different reasons a pointer escapes
75 enum PointerEscapeKind {
76 /// A pointer escapes due to binding its value to a location
77 /// that the analyzer cannot track.
80 /// The pointer has been passed to a function call directly.
81 PSK_DirectEscapeOnCall,
83 /// The pointer has been passed to a function indirectly.
84 /// For example, the pointer is accessible through an
85 /// argument to a function.
86 PSK_IndirectEscapeOnCall,
88 /// The reason for pointer escape is unknown. For example,
89 /// a region containing this pointer is invalidated.
93 // This wrapper is used to ensure that only StringRefs originating from the
94 // CheckerRegistry are used as check names. We want to make sure all check
95 // name strings have a lifetime that keeps them alive at least until the path
96 // diagnostics have been processed.
98 friend class ::clang::ento::CheckerRegistry;
102 explicit CheckName(StringRef Name) : Name(Name) {}
105 CheckName() = default;
107 StringRef getName() const { return Name; }
110 enum class ObjCMessageVisitKind {
116 class CheckerManager {
118 const LangOptions LangOpts;
119 AnalyzerOptions &AOptions;
120 CheckName CurrentCheckName;
123 CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions)
124 : Context(Context), LangOpts(Context.getLangOpts()), AOptions(AOptions) {}
128 void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
129 CheckName getCurrentCheckName() const { return CurrentCheckName; }
131 bool hasPathSensitiveCheckers() const;
133 void finishedCheckerRegistration();
135 const LangOptions &getLangOpts() const { return LangOpts; }
136 AnalyzerOptions &getAnalyzerOptions() { return AOptions; }
137 ASTContext &getASTContext() { return Context; }
139 /// Emits an error through a DiagnosticsEngine about an invalid user supplied
140 /// checker option value.
141 void reportInvalidCheckerOptionValue(const CheckerBase *C,
142 StringRef OptionName,
143 StringRef ExpectedValueDesc);
145 using CheckerRef = CheckerBase *;
146 using CheckerTag = const void *;
147 using CheckerDtor = CheckerFn<void ()>;
149 //===----------------------------------------------------------------------===//
150 // Checker registration.
151 //===----------------------------------------------------------------------===//
153 /// Used to register checkers.
154 /// All arguments are automatically passed through to the checker
157 /// \returns a pointer to the checker object.
158 template <typename CHECKER, typename... AT>
159 CHECKER *registerChecker(AT &&... Args) {
160 CheckerTag tag = getTag<CHECKER>();
161 CheckerRef &ref = CheckerTags[tag];
162 assert(!ref && "Checker already registered, use getChecker!");
164 CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
165 checker->Name = CurrentCheckName;
166 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
167 CHECKER::_register(checker, *this);
172 template <typename CHECKER>
173 CHECKER *getChecker() {
174 CheckerTag tag = getTag<CHECKER>();
175 assert(CheckerTags.count(tag) != 0 &&
176 "Requested checker is not registered! Maybe you should add it as a "
177 "dependency in Checkers.td?");
178 return static_cast<CHECKER *>(CheckerTags[tag]);
181 //===----------------------------------------------------------------------===//
182 // Functions for running checkers for AST traversing.
183 //===----------------------------------------------------------------------===//
185 /// Run checkers handling Decls.
186 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
189 /// Run checkers handling Decls containing a Stmt body.
190 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
193 //===----------------------------------------------------------------------===//
194 // Functions for running checkers for path-sensitive checking.
195 //===----------------------------------------------------------------------===//
197 /// Run checkers for pre-visiting Stmts.
199 /// The notification is performed for every explored CFGElement, which does
200 /// not include the control flow statements such as IfStmt.
202 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
203 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
204 const ExplodedNodeSet &Src,
207 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
210 /// Run checkers for post-visiting Stmts.
212 /// The notification is performed for every explored CFGElement, which does
213 /// not include the control flow statements such as IfStmt.
215 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
216 void runCheckersForPostStmt(ExplodedNodeSet &Dst,
217 const ExplodedNodeSet &Src,
220 bool wasInlined = false) {
221 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
224 /// Run checkers for visiting Stmts.
225 void runCheckersForStmt(bool isPreVisit,
226 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
227 const Stmt *S, ExprEngine &Eng,
228 bool wasInlined = false);
230 /// Run checkers for pre-visiting obj-c messages.
231 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
232 const ExplodedNodeSet &Src,
233 const ObjCMethodCall &msg,
235 runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
238 /// Run checkers for post-visiting obj-c messages.
239 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
240 const ExplodedNodeSet &Src,
241 const ObjCMethodCall &msg,
243 bool wasInlined = false) {
244 runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
248 /// Run checkers for visiting an obj-c message to nil.
249 void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
250 const ExplodedNodeSet &Src,
251 const ObjCMethodCall &msg,
253 runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
257 /// Run checkers for visiting obj-c messages.
258 void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
259 ExplodedNodeSet &Dst,
260 const ExplodedNodeSet &Src,
261 const ObjCMethodCall &msg, ExprEngine &Eng,
262 bool wasInlined = false);
264 /// Run checkers for pre-visiting obj-c messages.
265 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
266 const CallEvent &Call, ExprEngine &Eng) {
267 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
270 /// Run checkers for post-visiting obj-c messages.
271 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
272 const CallEvent &Call, ExprEngine &Eng,
273 bool wasInlined = false) {
274 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
278 /// Run checkers for visiting obj-c messages.
279 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
280 const ExplodedNodeSet &Src,
281 const CallEvent &Call, ExprEngine &Eng,
282 bool wasInlined = false);
284 /// Run checkers for load/store of a location.
285 void runCheckersForLocation(ExplodedNodeSet &Dst,
286 const ExplodedNodeSet &Src,
293 /// Run checkers for binding of a value to a location.
294 void runCheckersForBind(ExplodedNodeSet &Dst,
295 const ExplodedNodeSet &Src,
296 SVal location, SVal val,
297 const Stmt *S, ExprEngine &Eng,
298 const ProgramPoint &PP);
300 /// Run checkers for end of analysis.
301 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
304 /// Run checkers on beginning of function.
305 void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
310 /// Run checkers on end of function.
311 void runCheckersForEndFunction(NodeBuilderContext &BC,
312 ExplodedNodeSet &Dst,
315 const ReturnStmt *RS);
317 /// Run checkers for branch condition.
318 void runCheckersForBranchCondition(const Stmt *condition,
319 ExplodedNodeSet &Dst, ExplodedNode *Pred,
322 /// Run checkers between C++ operator new and constructor calls.
323 void runCheckersForNewAllocator(const CXXNewExpr *NE, SVal Target,
324 ExplodedNodeSet &Dst,
327 bool wasInlined = false);
329 /// Run checkers for live symbols.
331 /// Allows modifying SymbolReaper object. For example, checkers can explicitly
332 /// register symbols of interest as live. These symbols will not be marked
333 /// dead and removed.
334 void runCheckersForLiveSymbols(ProgramStateRef state,
335 SymbolReaper &SymReaper);
337 /// Run checkers for dead symbols.
339 /// Notifies checkers when symbols become dead. For example, this allows
340 /// checkers to aggressively clean up/reduce the checker state and produce
341 /// precise diagnostics.
342 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
343 const ExplodedNodeSet &Src,
344 SymbolReaper &SymReaper, const Stmt *S,
346 ProgramPoint::Kind K);
348 /// Run checkers for region changes.
350 /// This corresponds to the check::RegionChanges callback.
351 /// \param state The current program state.
352 /// \param invalidated A set of all symbols potentially touched by the change.
353 /// \param ExplicitRegions The regions explicitly requested for invalidation.
354 /// For example, in the case of a function call, these would be arguments.
355 /// \param Regions The transitive closure of accessible regions,
356 /// i.e. all regions that may have been touched by this change.
357 /// \param Call The call expression wrapper if the regions are invalidated
360 runCheckersForRegionChanges(ProgramStateRef state,
361 const InvalidatedSymbols *invalidated,
362 ArrayRef<const MemRegion *> ExplicitRegions,
363 ArrayRef<const MemRegion *> Regions,
364 const LocationContext *LCtx,
365 const CallEvent *Call);
367 /// Run checkers when pointers escape.
369 /// This notifies the checkers about pointer escape, which occurs whenever
370 /// the analyzer cannot track the symbol any more. For example, as a
371 /// result of assigning a pointer into a global or when it's passed to a
372 /// function call the analyzer cannot model.
374 /// \param State The state at the point of escape.
375 /// \param Escaped The list of escaped symbols.
376 /// \param Call The corresponding CallEvent, if the symbols escape as
377 /// parameters to the given call.
378 /// \param Kind The reason of pointer escape.
379 /// \param ITraits Information about invalidation for a particular
381 /// \returns Checkers can modify the state by returning a new one.
383 runCheckersForPointerEscape(ProgramStateRef State,
384 const InvalidatedSymbols &Escaped,
385 const CallEvent *Call,
386 PointerEscapeKind Kind,
387 RegionAndSymbolInvalidationTraits *ITraits);
389 /// Run checkers for handling assumptions on symbolic values.
390 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
391 SVal Cond, bool Assumption);
393 /// Run checkers for evaluating a call.
395 /// Warning: Currently, the CallEvent MUST come from a CallExpr!
396 void runCheckersForEvalCall(ExplodedNodeSet &Dst,
397 const ExplodedNodeSet &Src,
398 const CallEvent &CE, ExprEngine &Eng);
400 /// Run checkers for the entire Translation Unit.
401 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
402 AnalysisManager &mgr,
405 /// Run checkers for debug-printing a ProgramState.
407 /// Unlike most other callbacks, any checker can simply implement the virtual
408 /// method CheckerBase::printState if it has custom data to print.
410 /// \param Out The output stream
411 /// \param State The state being printed
412 /// \param NL The preferred representation of a newline.
413 /// \param Space The preferred space between the left side and the message.
414 /// \param IsDot Whether the message will be printed in 'dot' format.
415 void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State,
416 const char *NL = "\n",
417 unsigned int Space = 0,
418 bool IsDot = false) const;
420 //===----------------------------------------------------------------------===//
421 // Internal registration functions for AST traversing.
422 //===----------------------------------------------------------------------===//
424 // Functions used by the registration mechanism, checkers should not touch
427 using CheckDeclFunc =
428 CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
430 using HandlesDeclFunc = bool (*)(const Decl *D);
432 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
434 void _registerForBody(CheckDeclFunc checkfn);
436 //===----------------------------------------------------------------------===//
437 // Internal registration functions for path-sensitive checking.
438 //===----------------------------------------------------------------------===//
440 using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
442 using CheckObjCMessageFunc =
443 CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
445 using CheckCallFunc =
446 CheckerFn<void (const CallEvent &, CheckerContext &)>;
448 using CheckLocationFunc =
449 CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,
452 using CheckBindFunc =
453 CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
456 using CheckEndAnalysisFunc =
457 CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
459 using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
461 using CheckEndFunctionFunc =
462 CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
464 using CheckBranchConditionFunc =
465 CheckerFn<void (const Stmt *, CheckerContext &)>;
467 using CheckNewAllocatorFunc =
468 CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>;
470 using CheckDeadSymbolsFunc =
471 CheckerFn<void (SymbolReaper &, CheckerContext &)>;
473 using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
475 using CheckRegionChangesFunc =
476 CheckerFn<ProgramStateRef (ProgramStateRef,
477 const InvalidatedSymbols *symbols,
478 ArrayRef<const MemRegion *> ExplicitRegions,
479 ArrayRef<const MemRegion *> Regions,
480 const LocationContext *LCtx,
481 const CallEvent *Call)>;
483 using CheckPointerEscapeFunc =
484 CheckerFn<ProgramStateRef (ProgramStateRef,
485 const InvalidatedSymbols &Escaped,
486 const CallEvent *Call, PointerEscapeKind Kind,
487 RegionAndSymbolInvalidationTraits *ITraits)>;
489 using EvalAssumeFunc =
490 CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,
493 using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
495 using CheckEndOfTranslationUnit =
496 CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
499 using HandlesStmtFunc = bool (*)(const Stmt *D);
501 void _registerForPreStmt(CheckStmtFunc checkfn,
502 HandlesStmtFunc isForStmtFn);
503 void _registerForPostStmt(CheckStmtFunc checkfn,
504 HandlesStmtFunc isForStmtFn);
506 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
507 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
509 void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
511 void _registerForPreCall(CheckCallFunc checkfn);
512 void _registerForPostCall(CheckCallFunc checkfn);
514 void _registerForLocation(CheckLocationFunc checkfn);
516 void _registerForBind(CheckBindFunc checkfn);
518 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
520 void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
521 void _registerForEndFunction(CheckEndFunctionFunc checkfn);
523 void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
525 void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
527 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
529 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
531 void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
533 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
535 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
537 void _registerForEvalAssume(EvalAssumeFunc checkfn);
539 void _registerForEvalCall(EvalCallFunc checkfn);
541 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
543 //===----------------------------------------------------------------------===//
544 // Internal registration functions for events.
545 //===----------------------------------------------------------------------===//
547 using EventTag = void *;
548 using CheckEventFunc = CheckerFn<void (const void *event)>;
550 template <typename EVENT>
551 void _registerListenerForEvent(CheckEventFunc checkfn) {
552 EventInfo &info = Events[&EVENT::Tag];
553 info.Checkers.push_back(checkfn);
556 template <typename EVENT>
557 void _registerDispatcherForEvent() {
558 EventInfo &info = Events[&EVENT::Tag];
559 info.HasDispatcher = true;
562 template <typename EVENT>
563 void _dispatchEvent(const EVENT &event) const {
564 EventsTy::const_iterator I = Events.find(&EVENT::Tag);
565 if (I == Events.end())
567 const EventInfo &info = I->second;
568 for (const auto Checker : info.Checkers)
572 //===----------------------------------------------------------------------===//
573 // Implementation details.
574 //===----------------------------------------------------------------------===//
577 template <typename CHECKER>
578 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
580 template <typename T>
581 static void *getTag() { static int tag; return &tag; }
583 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
585 std::vector<CheckerDtor> CheckerDtors;
587 struct DeclCheckerInfo {
588 CheckDeclFunc CheckFn;
589 HandlesDeclFunc IsForDeclFn;
591 std::vector<DeclCheckerInfo> DeclCheckers;
593 std::vector<CheckDeclFunc> BodyCheckers;
595 using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
596 using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
597 CachedDeclCheckersMapTy CachedDeclCheckersMap;
599 struct StmtCheckerInfo {
600 CheckStmtFunc CheckFn;
601 HandlesStmtFunc IsForStmtFn;
604 std::vector<StmtCheckerInfo> StmtCheckers;
606 using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
607 using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
608 CachedStmtCheckersMapTy CachedStmtCheckersMap;
610 const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
613 /// Returns the checkers that have registered for callbacks of the
615 const std::vector<CheckObjCMessageFunc> &
616 getObjCMessageCheckers(ObjCMessageVisitKind Kind);
618 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
619 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
620 std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
622 std::vector<CheckCallFunc> PreCallCheckers;
623 std::vector<CheckCallFunc> PostCallCheckers;
625 std::vector<CheckLocationFunc> LocationCheckers;
627 std::vector<CheckBindFunc> BindCheckers;
629 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
631 std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
632 std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
634 std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
636 std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
638 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
640 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
642 std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
644 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
646 std::vector<EvalAssumeFunc> EvalAssumeCheckers;
648 std::vector<EvalCallFunc> EvalCallCheckers;
650 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
653 SmallVector<CheckEventFunc, 4> Checkers;
654 bool HasDispatcher = false;
656 EventInfo() = default;
659 using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
667 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H