1 //===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Defines the Static Analyzer Checker Manager.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
17 #include "clang/Analysis/ProgramPoint.h"
18 #include "clang/Basic/LangOptions.h"
19 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/SmallVector.h"
33 class CheckerRegistry;
35 class AnalysisManager;
41 class ExplodedNodeSet;
45 struct NodeBuilderContext;
49 template <typename T> class CheckerFn;
51 template <typename RET, typename... Ps>
52 class CheckerFn<RET(Ps...)> {
53 typedef RET (*Func)(void *, Ps...);
57 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
58 RET operator()(Ps... ps) const {
59 return Fn(Checker, ps...);
63 /// \brief Describes the different reasons a pointer escapes
65 enum PointerEscapeKind {
66 /// A pointer escapes due to binding its value to a location
67 /// that the analyzer cannot track.
70 /// The pointer has been passed to a function call directly.
71 PSK_DirectEscapeOnCall,
73 /// The pointer has been passed to a function indirectly.
74 /// For example, the pointer is accessible through an
75 /// argument to a function.
76 PSK_IndirectEscapeOnCall,
78 /// The reason for pointer escape is unknown. For example,
79 /// a region containing this pointer is invalidated.
83 // This wrapper is used to ensure that only StringRefs originating from the
84 // CheckerRegistry are used as check names. We want to make sure all check
85 // name strings have a lifetime that keeps them alive at least until the path
86 // diagnostics have been processed.
89 friend class ::clang::ento::CheckerRegistry;
90 explicit CheckName(StringRef Name) : Name(Name) {}
93 CheckName() = default;
94 StringRef getName() const { return Name; }
97 enum class ObjCMessageVisitKind {
103 class CheckerManager {
104 const LangOptions LangOpts;
105 AnalyzerOptionsRef AOptions;
106 CheckName CurrentCheckName;
109 CheckerManager(const LangOptions &langOpts, AnalyzerOptionsRef AOptions)
110 : LangOpts(langOpts), AOptions(std::move(AOptions)) {}
114 void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
115 CheckName getCurrentCheckName() const { return CurrentCheckName; }
117 bool hasPathSensitiveCheckers() const;
119 void finishedCheckerRegistration();
121 const LangOptions &getLangOpts() const { return LangOpts; }
122 AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
124 typedef CheckerBase *CheckerRef;
125 typedef const void *CheckerTag;
126 typedef CheckerFn<void ()> CheckerDtor;
128 //===----------------------------------------------------------------------===//
130 //===----------------------------------------------------------------------===//
132 /// \brief Used to register checkers.
134 /// \returns a pointer to the checker object.
135 template <typename CHECKER>
136 CHECKER *registerChecker() {
137 CheckerTag tag = getTag<CHECKER>();
138 CheckerRef &ref = CheckerTags[tag];
140 return static_cast<CHECKER *>(ref); // already registered.
142 CHECKER *checker = new CHECKER();
143 checker->Name = CurrentCheckName;
144 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
145 CHECKER::_register(checker, *this);
150 template <typename CHECKER>
151 CHECKER *registerChecker(AnalyzerOptions &AOpts) {
152 CheckerTag tag = getTag<CHECKER>();
153 CheckerRef &ref = CheckerTags[tag];
155 return static_cast<CHECKER *>(ref); // already registered.
157 CHECKER *checker = new CHECKER(AOpts);
158 checker->Name = CurrentCheckName;
159 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
160 CHECKER::_register(checker, *this);
165 //===----------------------------------------------------------------------===//
166 // Functions for running checkers for AST traversing..
167 //===----------------------------------------------------------------------===//
169 /// \brief Run checkers handling Decls.
170 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
173 /// \brief Run checkers handling Decls containing a Stmt body.
174 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
177 //===----------------------------------------------------------------------===//
178 // Functions for running checkers for path-sensitive checking.
179 //===----------------------------------------------------------------------===//
181 /// \brief Run checkers for pre-visiting Stmts.
183 /// The notification is performed for every explored CFGElement, which does
184 /// not include the control flow statements such as IfStmt.
186 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
187 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
188 const ExplodedNodeSet &Src,
191 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
194 /// \brief Run checkers for post-visiting Stmts.
196 /// The notification is performed for every explored CFGElement, which does
197 /// not include the control flow statements such as IfStmt.
199 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
200 void runCheckersForPostStmt(ExplodedNodeSet &Dst,
201 const ExplodedNodeSet &Src,
204 bool wasInlined = false) {
205 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
208 /// \brief Run checkers for visiting Stmts.
209 void runCheckersForStmt(bool isPreVisit,
210 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
211 const Stmt *S, ExprEngine &Eng,
212 bool wasInlined = false);
214 /// \brief Run checkers for pre-visiting obj-c messages.
215 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
216 const ExplodedNodeSet &Src,
217 const ObjCMethodCall &msg,
219 runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
222 /// \brief Run checkers for post-visiting obj-c messages.
223 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
224 const ExplodedNodeSet &Src,
225 const ObjCMethodCall &msg,
227 bool wasInlined = false) {
228 runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
232 /// \brief Run checkers for visiting an obj-c message to nil.
233 void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
234 const ExplodedNodeSet &Src,
235 const ObjCMethodCall &msg,
237 runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
242 /// \brief Run checkers for visiting obj-c messages.
243 void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
244 ExplodedNodeSet &Dst,
245 const ExplodedNodeSet &Src,
246 const ObjCMethodCall &msg, ExprEngine &Eng,
247 bool wasInlined = false);
249 /// \brief Run checkers for pre-visiting obj-c messages.
250 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
251 const CallEvent &Call, ExprEngine &Eng) {
252 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
255 /// \brief Run checkers for post-visiting obj-c messages.
256 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
257 const CallEvent &Call, ExprEngine &Eng,
258 bool wasInlined = false) {
259 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
263 /// \brief Run checkers for visiting obj-c messages.
264 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
265 const ExplodedNodeSet &Src,
266 const CallEvent &Call, ExprEngine &Eng,
267 bool wasInlined = false);
269 /// \brief Run checkers for load/store of a location.
270 void runCheckersForLocation(ExplodedNodeSet &Dst,
271 const ExplodedNodeSet &Src,
278 /// \brief Run checkers for binding of a value to a location.
279 void runCheckersForBind(ExplodedNodeSet &Dst,
280 const ExplodedNodeSet &Src,
281 SVal location, SVal val,
282 const Stmt *S, ExprEngine &Eng,
283 const ProgramPoint &PP);
285 /// \brief Run checkers for end of analysis.
286 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
289 /// \brief Run checkers on begining of function.
290 void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
295 /// \brief Run checkers on end of function.
296 void runCheckersForEndFunction(NodeBuilderContext &BC,
297 ExplodedNodeSet &Dst,
301 /// \brief Run checkers for branch condition.
302 void runCheckersForBranchCondition(const Stmt *condition,
303 ExplodedNodeSet &Dst, ExplodedNode *Pred,
306 /// \brief Run checkers for live symbols.
308 /// Allows modifying SymbolReaper object. For example, checkers can explicitly
309 /// register symbols of interest as live. These symbols will not be marked
310 /// dead and removed.
311 void runCheckersForLiveSymbols(ProgramStateRef state,
312 SymbolReaper &SymReaper);
314 /// \brief Run checkers for dead symbols.
316 /// Notifies checkers when symbols become dead. For example, this allows
317 /// checkers to aggressively clean up/reduce the checker state and produce
318 /// precise diagnostics.
319 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
320 const ExplodedNodeSet &Src,
321 SymbolReaper &SymReaper, const Stmt *S,
323 ProgramPoint::Kind K);
325 /// \brief True if at least one checker wants to check region changes.
326 bool wantsRegionChangeUpdate(ProgramStateRef state);
328 /// \brief Run checkers for region changes.
330 /// This corresponds to the check::RegionChanges callback.
331 /// \param state The current program state.
332 /// \param invalidated A set of all symbols potentially touched by the change.
333 /// \param ExplicitRegions The regions explicitly requested for invalidation.
334 /// For example, in the case of a function call, these would be arguments.
335 /// \param Regions The transitive closure of accessible regions,
336 /// i.e. all regions that may have been touched by this change.
337 /// \param Call The call expression wrapper if the regions are invalidated
340 runCheckersForRegionChanges(ProgramStateRef state,
341 const InvalidatedSymbols *invalidated,
342 ArrayRef<const MemRegion *> ExplicitRegions,
343 ArrayRef<const MemRegion *> Regions,
344 const CallEvent *Call);
346 /// \brief Run checkers when pointers escape.
348 /// This notifies the checkers about pointer escape, which occurs whenever
349 /// the analyzer cannot track the symbol any more. For example, as a
350 /// result of assigning a pointer into a global or when it's passed to a
351 /// function call the analyzer cannot model.
353 /// \param State The state at the point of escape.
354 /// \param Escaped The list of escaped symbols.
355 /// \param Call The corresponding CallEvent, if the symbols escape as
356 /// parameters to the given call.
357 /// \param Kind The reason of pointer escape.
358 /// \param ITraits Information about invalidation for a particular
360 /// \returns Checkers can modify the state by returning a new one.
362 runCheckersForPointerEscape(ProgramStateRef State,
363 const InvalidatedSymbols &Escaped,
364 const CallEvent *Call,
365 PointerEscapeKind Kind,
366 RegionAndSymbolInvalidationTraits *ITraits);
368 /// \brief Run checkers for handling assumptions on symbolic values.
369 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
370 SVal Cond, bool Assumption);
372 /// \brief Run checkers for evaluating a call.
374 /// Warning: Currently, the CallEvent MUST come from a CallExpr!
375 void runCheckersForEvalCall(ExplodedNodeSet &Dst,
376 const ExplodedNodeSet &Src,
377 const CallEvent &CE, ExprEngine &Eng);
379 /// \brief Run checkers for the entire Translation Unit.
380 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
381 AnalysisManager &mgr,
384 /// \brief Run checkers for debug-printing a ProgramState.
386 /// Unlike most other callbacks, any checker can simply implement the virtual
387 /// method CheckerBase::printState if it has custom data to print.
388 /// \param Out The output stream
389 /// \param State The state being printed
390 /// \param NL The preferred representation of a newline.
391 /// \param Sep The preferred separator between different kinds of data.
392 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
393 const char *NL, const char *Sep);
395 //===----------------------------------------------------------------------===//
396 // Internal registration functions for AST traversing.
397 //===----------------------------------------------------------------------===//
399 // Functions used by the registration mechanism, checkers should not touch
402 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
405 typedef bool (*HandlesDeclFunc)(const Decl *D);
406 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
408 void _registerForBody(CheckDeclFunc checkfn);
410 //===----------------------------------------------------------------------===//
411 // Internal registration functions for path-sensitive checking.
412 //===----------------------------------------------------------------------===//
414 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
416 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
417 CheckObjCMessageFunc;
419 typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
422 typedef CheckerFn<void (const SVal &location, bool isLoad,
427 typedef CheckerFn<void (const SVal &location, const SVal &val,
428 const Stmt *S, CheckerContext &)>
431 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
432 CheckEndAnalysisFunc;
434 typedef CheckerFn<void (CheckerContext &)>
435 CheckBeginFunctionFunc;
437 typedef CheckerFn<void (CheckerContext &)>
438 CheckEndFunctionFunc;
440 typedef CheckerFn<void (const Stmt *, CheckerContext &)>
441 CheckBranchConditionFunc;
443 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
444 CheckDeadSymbolsFunc;
446 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
448 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
449 const InvalidatedSymbols *symbols,
450 ArrayRef<const MemRegion *> ExplicitRegions,
451 ArrayRef<const MemRegion *> Regions,
452 const CallEvent *Call)>
453 CheckRegionChangesFunc;
455 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
457 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
458 const InvalidatedSymbols &Escaped,
459 const CallEvent *Call,
460 PointerEscapeKind Kind,
461 RegionAndSymbolInvalidationTraits *ITraits)>
462 CheckPointerEscapeFunc;
464 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
465 const SVal &cond, bool assumption)>
468 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
471 typedef CheckerFn<void (const TranslationUnitDecl *,
472 AnalysisManager&, BugReporter &)>
473 CheckEndOfTranslationUnit;
475 typedef bool (*HandlesStmtFunc)(const Stmt *D);
476 void _registerForPreStmt(CheckStmtFunc checkfn,
477 HandlesStmtFunc isForStmtFn);
478 void _registerForPostStmt(CheckStmtFunc checkfn,
479 HandlesStmtFunc isForStmtFn);
481 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
482 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
484 void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
486 void _registerForPreCall(CheckCallFunc checkfn);
487 void _registerForPostCall(CheckCallFunc checkfn);
489 void _registerForLocation(CheckLocationFunc checkfn);
491 void _registerForBind(CheckBindFunc checkfn);
493 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
495 void _registerForBeginFunction(CheckEndFunctionFunc checkfn);
496 void _registerForEndFunction(CheckEndFunctionFunc checkfn);
498 void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
500 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
502 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
504 void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
505 WantsRegionChangeUpdateFunc wantUpdateFn);
507 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
509 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
511 void _registerForEvalAssume(EvalAssumeFunc checkfn);
513 void _registerForEvalCall(EvalCallFunc checkfn);
515 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
517 //===----------------------------------------------------------------------===//
518 // Internal registration functions for events.
519 //===----------------------------------------------------------------------===//
521 typedef void *EventTag;
522 typedef CheckerFn<void (const void *event)> CheckEventFunc;
524 template <typename EVENT>
525 void _registerListenerForEvent(CheckEventFunc checkfn) {
526 EventInfo &info = Events[getTag<EVENT>()];
527 info.Checkers.push_back(checkfn);
530 template <typename EVENT>
531 void _registerDispatcherForEvent() {
532 EventInfo &info = Events[getTag<EVENT>()];
533 info.HasDispatcher = true;
536 template <typename EVENT>
537 void _dispatchEvent(const EVENT &event) const {
538 EventsTy::const_iterator I = Events.find(getTag<EVENT>());
539 if (I == Events.end())
541 const EventInfo &info = I->second;
542 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
543 info.Checkers[i](&event);
546 //===----------------------------------------------------------------------===//
547 // Implementation details.
548 //===----------------------------------------------------------------------===//
551 template <typename CHECKER>
552 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
554 template <typename T>
555 static void *getTag() { static int tag; return &tag; }
557 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
559 std::vector<CheckerDtor> CheckerDtors;
561 struct DeclCheckerInfo {
562 CheckDeclFunc CheckFn;
563 HandlesDeclFunc IsForDeclFn;
565 std::vector<DeclCheckerInfo> DeclCheckers;
567 std::vector<CheckDeclFunc> BodyCheckers;
569 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
570 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
571 CachedDeclCheckersMapTy CachedDeclCheckersMap;
573 struct StmtCheckerInfo {
574 CheckStmtFunc CheckFn;
575 HandlesStmtFunc IsForStmtFn;
578 std::vector<StmtCheckerInfo> StmtCheckers;
580 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
581 typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
582 CachedStmtCheckersMapTy CachedStmtCheckersMap;
584 const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
587 /// Returns the checkers that have registered for callbacks of the
589 const std::vector<CheckObjCMessageFunc> &
590 getObjCMessageCheckers(ObjCMessageVisitKind Kind);
592 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
593 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
594 std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
596 std::vector<CheckCallFunc> PreCallCheckers;
597 std::vector<CheckCallFunc> PostCallCheckers;
599 std::vector<CheckLocationFunc> LocationCheckers;
601 std::vector<CheckBindFunc> BindCheckers;
603 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
605 std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
606 std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
608 std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
610 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
612 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
614 struct RegionChangesCheckerInfo {
615 CheckRegionChangesFunc CheckFn;
616 WantsRegionChangeUpdateFunc WantUpdateFn;
618 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
620 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
622 std::vector<EvalAssumeFunc> EvalAssumeCheckers;
624 std::vector<EvalCallFunc> EvalCallCheckers;
626 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
629 SmallVector<CheckEventFunc, 4> Checkers;
631 EventInfo() : HasDispatcher(false) { }
634 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
638 } // end ento namespace
640 } // end clang namespace