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_SA_CORE_CHECKERMANAGER_H
15 #define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
17 #include "clang/Analysis/ProgramPoint.h"
18 #include "clang/Basic/LangOptions.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
20 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/ADT/SmallVector.h"
34 class AnalysisManager;
41 class ExplodedNodeSet;
45 struct NodeBuilderContext;
49 template <typename T> class CheckerFn;
51 template <typename RET, typename P1, typename P2, typename P3, typename P4,
53 class CheckerFn<RET(P1, P2, P3, P4, P5)> {
54 typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
58 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
59 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
60 return Fn(Checker, p1, p2, p3, p4, p5);
64 template <typename RET, typename P1, typename P2, typename P3, typename P4>
65 class CheckerFn<RET(P1, P2, P3, P4)> {
66 typedef RET (*Func)(void *, P1, P2, P3, P4);
70 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
71 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
72 return Fn(Checker, p1, p2, p3, p4);
76 template <typename RET, typename P1, typename P2, typename P3>
77 class CheckerFn<RET(P1, P2, P3)> {
78 typedef RET (*Func)(void *, P1, P2, P3);
82 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
83 RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
86 template <typename RET, typename P1, typename P2>
87 class CheckerFn<RET(P1, P2)> {
88 typedef RET (*Func)(void *, P1, P2);
92 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
93 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
96 template <typename RET, typename P1>
97 class CheckerFn<RET(P1)> {
98 typedef RET (*Func)(void *, P1);
101 CheckerBase *Checker;
102 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
103 RET operator()(P1 p1) const { return Fn(Checker, p1); }
106 template <typename RET>
107 class CheckerFn<RET()> {
108 typedef RET (*Func)(void *);
111 CheckerBase *Checker;
112 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
113 RET operator()() const { return Fn(Checker); }
116 /// \brief Describes the different reasons a pointer escapes
118 enum PointerEscapeKind {
119 /// A pointer escapes due to binding its value to a location
120 /// that the analyzer cannot track.
123 /// The pointer has been passed to a function call directly.
124 PSK_DirectEscapeOnCall,
126 /// The pointer has been passed to a function indirectly.
127 /// For example, the pointer is accessible through an
128 /// argument to a function.
129 PSK_IndirectEscapeOnCall,
131 /// The reason for pointer escape is unknown. For example,
132 /// a region containing this pointer is invalidated.
136 class CheckerManager {
137 const LangOptions LangOpts;
138 AnalyzerOptionsRef AOptions;
140 CheckerManager(const LangOptions &langOpts,
141 AnalyzerOptionsRef AOptions)
142 : LangOpts(langOpts),
143 AOptions(AOptions) {}
147 bool hasPathSensitiveCheckers() const;
149 void finishedCheckerRegistration();
151 const LangOptions &getLangOpts() const { return LangOpts; }
152 AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
154 typedef CheckerBase *CheckerRef;
155 typedef const void *CheckerTag;
156 typedef CheckerFn<void ()> CheckerDtor;
158 //===----------------------------------------------------------------------===//
160 //===----------------------------------------------------------------------===//
162 /// \brief Used to register checkers.
164 /// \returns a pointer to the checker object.
165 template <typename CHECKER>
166 CHECKER *registerChecker() {
167 CheckerTag tag = getTag<CHECKER>();
168 CheckerRef &ref = CheckerTags[tag];
170 return static_cast<CHECKER *>(ref); // already registered.
172 CHECKER *checker = new CHECKER();
173 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
174 CHECKER::_register(checker, *this);
179 template <typename CHECKER>
180 CHECKER *registerChecker(AnalyzerOptions &AOpts) {
181 CheckerTag tag = getTag<CHECKER>();
182 CheckerRef &ref = CheckerTags[tag];
184 return static_cast<CHECKER *>(ref); // already registered.
186 CHECKER *checker = new CHECKER(AOpts);
187 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
188 CHECKER::_register(checker, *this);
193 //===----------------------------------------------------------------------===//
194 // Functions for running checkers for AST traversing..
195 //===----------------------------------------------------------------------===//
197 /// \brief Run checkers handling Decls.
198 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
201 /// \brief Run checkers handling Decls containing a Stmt body.
202 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
205 //===----------------------------------------------------------------------===//
206 // Functions for running checkers for path-sensitive checking.
207 //===----------------------------------------------------------------------===//
209 /// \brief Run checkers for pre-visiting Stmts.
211 /// The notification is performed for every explored CFGElement, which does
212 /// not include the control flow statements such as IfStmt.
214 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
215 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
216 const ExplodedNodeSet &Src,
219 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
222 /// \brief Run checkers for post-visiting Stmts.
224 /// The notification is performed for every explored CFGElement, which does
225 /// not include the control flow statements such as IfStmt.
227 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
228 void runCheckersForPostStmt(ExplodedNodeSet &Dst,
229 const ExplodedNodeSet &Src,
232 bool wasInlined = false) {
233 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
236 /// \brief Run checkers for visiting Stmts.
237 void runCheckersForStmt(bool isPreVisit,
238 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
239 const Stmt *S, ExprEngine &Eng,
240 bool wasInlined = false);
242 /// \brief Run checkers for pre-visiting obj-c messages.
243 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
244 const ExplodedNodeSet &Src,
245 const ObjCMethodCall &msg,
247 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
250 /// \brief Run checkers for post-visiting obj-c messages.
251 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
252 const ExplodedNodeSet &Src,
253 const ObjCMethodCall &msg,
255 bool wasInlined = false) {
256 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
260 /// \brief Run checkers for visiting obj-c messages.
261 void runCheckersForObjCMessage(bool isPreVisit,
262 ExplodedNodeSet &Dst,
263 const ExplodedNodeSet &Src,
264 const ObjCMethodCall &msg, ExprEngine &Eng,
265 bool wasInlined = false);
267 /// \brief Run checkers for pre-visiting obj-c messages.
268 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
269 const CallEvent &Call, ExprEngine &Eng) {
270 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
273 /// \brief Run checkers for post-visiting obj-c messages.
274 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
275 const CallEvent &Call, ExprEngine &Eng,
276 bool wasInlined = false) {
277 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
281 /// \brief Run checkers for visiting obj-c messages.
282 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
283 const ExplodedNodeSet &Src,
284 const CallEvent &Call, ExprEngine &Eng,
285 bool wasInlined = false);
287 /// \brief Run checkers for load/store of a location.
288 void runCheckersForLocation(ExplodedNodeSet &Dst,
289 const ExplodedNodeSet &Src,
296 /// \brief Run checkers for binding of a value to a location.
297 void runCheckersForBind(ExplodedNodeSet &Dst,
298 const ExplodedNodeSet &Src,
299 SVal location, SVal val,
300 const Stmt *S, ExprEngine &Eng,
301 const ProgramPoint &PP);
303 /// \brief Run checkers for end of analysis.
304 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
307 /// \brief Run checkers on end of function.
308 void runCheckersForEndFunction(NodeBuilderContext &BC,
309 ExplodedNodeSet &Dst,
313 /// \brief Run checkers for branch condition.
314 void runCheckersForBranchCondition(const Stmt *condition,
315 ExplodedNodeSet &Dst, ExplodedNode *Pred,
318 /// \brief Run checkers for live symbols.
320 /// Allows modifying SymbolReaper object. For example, checkers can explicitly
321 /// register symbols of interest as live. These symbols will not be marked
322 /// dead and removed.
323 void runCheckersForLiveSymbols(ProgramStateRef state,
324 SymbolReaper &SymReaper);
326 /// \brief Run checkers for dead symbols.
328 /// Notifies checkers when symbols become dead. For example, this allows
329 /// checkers to aggressively clean up/reduce the checker state and produce
330 /// precise diagnostics.
331 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
332 const ExplodedNodeSet &Src,
333 SymbolReaper &SymReaper, const Stmt *S,
335 ProgramPoint::Kind K);
337 /// \brief True if at least one checker wants to check region changes.
338 bool wantsRegionChangeUpdate(ProgramStateRef state);
340 /// \brief Run checkers for region changes.
342 /// This corresponds to the check::RegionChanges callback.
343 /// \param state The current program state.
344 /// \param invalidated A set of all symbols potentially touched by the change.
345 /// \param ExplicitRegions The regions explicitly requested for invalidation.
346 /// For example, in the case of a function call, these would be arguments.
347 /// \param Regions The transitive closure of accessible regions,
348 /// i.e. all regions that may have been touched by this change.
349 /// \param Call The call expression wrapper if the regions are invalidated
352 runCheckersForRegionChanges(ProgramStateRef state,
353 const InvalidatedSymbols *invalidated,
354 ArrayRef<const MemRegion *> ExplicitRegions,
355 ArrayRef<const MemRegion *> Regions,
356 const CallEvent *Call);
358 /// \brief Run checkers when pointers escape.
360 /// This notifies the checkers about pointer escape, which occurs whenever
361 /// the analyzer cannot track the symbol any more. For example, as a
362 /// result of assigning a pointer into a global or when it's passed to a
363 /// function call the analyzer cannot model.
365 /// \param State The state at the point of escape.
366 /// \param Escaped The list of escaped symbols.
367 /// \param Call The corresponding CallEvent, if the symbols escape as
368 /// parameters to the given call.
369 /// \param IsConst Specifies if the pointer is const.
370 /// \returns Checkers can modify the state by returning a new one.
372 runCheckersForPointerEscape(ProgramStateRef State,
373 const InvalidatedSymbols &Escaped,
374 const CallEvent *Call,
375 PointerEscapeKind Kind,
376 bool IsConst = false);
378 /// \brief Run checkers for handling assumptions on symbolic values.
379 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
380 SVal Cond, bool Assumption);
382 /// \brief Run checkers for evaluating a call.
384 /// Warning: Currently, the CallEvent MUST come from a CallExpr!
385 void runCheckersForEvalCall(ExplodedNodeSet &Dst,
386 const ExplodedNodeSet &Src,
387 const CallEvent &CE, ExprEngine &Eng);
389 /// \brief Run checkers for the entire Translation Unit.
390 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
391 AnalysisManager &mgr,
394 /// \brief Run checkers for debug-printing a ProgramState.
396 /// Unlike most other callbacks, any checker can simply implement the virtual
397 /// method CheckerBase::printState if it has custom data to print.
398 /// \param Out The output stream
399 /// \param State The state being printed
400 /// \param NL The preferred representation of a newline.
401 /// \param Sep The preferred separator between different kinds of data.
402 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
403 const char *NL, const char *Sep);
405 //===----------------------------------------------------------------------===//
406 // Internal registration functions for AST traversing.
407 //===----------------------------------------------------------------------===//
409 // Functions used by the registration mechanism, checkers should not touch
412 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
415 typedef bool (*HandlesDeclFunc)(const Decl *D);
416 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
418 void _registerForBody(CheckDeclFunc checkfn);
420 //===----------------------------------------------------------------------===//
421 // Internal registration functions for path-sensitive checking.
422 //===----------------------------------------------------------------------===//
424 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
426 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
427 CheckObjCMessageFunc;
429 typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
432 typedef CheckerFn<void (const SVal &location, bool isLoad,
437 typedef CheckerFn<void (const SVal &location, const SVal &val,
438 const Stmt *S, CheckerContext &)>
441 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
442 CheckEndAnalysisFunc;
444 typedef CheckerFn<void (CheckerContext &)>
445 CheckEndFunctionFunc;
447 typedef CheckerFn<void (const Stmt *, CheckerContext &)>
448 CheckBranchConditionFunc;
450 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
451 CheckDeadSymbolsFunc;
453 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
455 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
456 const InvalidatedSymbols *symbols,
457 ArrayRef<const MemRegion *> ExplicitRegions,
458 ArrayRef<const MemRegion *> Regions,
459 const CallEvent *Call)>
460 CheckRegionChangesFunc;
462 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
464 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
465 const InvalidatedSymbols &Escaped,
466 const CallEvent *Call,
467 PointerEscapeKind Kind,
469 CheckPointerEscapeFunc;
471 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
472 const SVal &cond, bool assumption)>
475 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
478 typedef CheckerFn<void (const TranslationUnitDecl *,
479 AnalysisManager&, BugReporter &)>
480 CheckEndOfTranslationUnit;
482 typedef bool (*HandlesStmtFunc)(const Stmt *D);
483 void _registerForPreStmt(CheckStmtFunc checkfn,
484 HandlesStmtFunc isForStmtFn);
485 void _registerForPostStmt(CheckStmtFunc checkfn,
486 HandlesStmtFunc isForStmtFn);
488 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
489 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
491 void _registerForPreCall(CheckCallFunc checkfn);
492 void _registerForPostCall(CheckCallFunc checkfn);
494 void _registerForLocation(CheckLocationFunc checkfn);
496 void _registerForBind(CheckBindFunc checkfn);
498 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
500 void _registerForEndFunction(CheckEndFunctionFunc checkfn);
502 void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
504 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
506 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
508 void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
509 WantsRegionChangeUpdateFunc wantUpdateFn);
511 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
513 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
515 void _registerForEvalAssume(EvalAssumeFunc checkfn);
517 void _registerForEvalCall(EvalCallFunc checkfn);
519 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
521 //===----------------------------------------------------------------------===//
522 // Internal registration functions for events.
523 //===----------------------------------------------------------------------===//
525 typedef void *EventTag;
526 typedef CheckerFn<void (const void *event)> CheckEventFunc;
528 template <typename EVENT>
529 void _registerListenerForEvent(CheckEventFunc checkfn) {
530 EventInfo &info = Events[getTag<EVENT>()];
531 info.Checkers.push_back(checkfn);
534 template <typename EVENT>
535 void _registerDispatcherForEvent() {
536 EventInfo &info = Events[getTag<EVENT>()];
537 info.HasDispatcher = true;
540 template <typename EVENT>
541 void _dispatchEvent(const EVENT &event) const {
542 EventsTy::const_iterator I = Events.find(getTag<EVENT>());
543 if (I == Events.end())
545 const EventInfo &info = I->second;
546 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
547 info.Checkers[i](&event);
550 //===----------------------------------------------------------------------===//
551 // Implementation details.
552 //===----------------------------------------------------------------------===//
555 template <typename CHECKER>
556 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
558 template <typename T>
559 static void *getTag() { static int tag; return &tag; }
561 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
563 std::vector<CheckerDtor> CheckerDtors;
565 struct DeclCheckerInfo {
566 CheckDeclFunc CheckFn;
567 HandlesDeclFunc IsForDeclFn;
569 std::vector<DeclCheckerInfo> DeclCheckers;
571 std::vector<CheckDeclFunc> BodyCheckers;
573 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
574 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
575 CachedDeclCheckersMapTy CachedDeclCheckersMap;
577 struct StmtCheckerInfo {
578 CheckStmtFunc CheckFn;
579 HandlesStmtFunc IsForStmtFn;
582 std::vector<StmtCheckerInfo> StmtCheckers;
584 struct CachedStmtCheckersKey {
588 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
589 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
590 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
592 static CachedStmtCheckersKey getSentinel() {
593 return CachedStmtCheckersKey(~0U, 0);
595 unsigned getHashValue() const {
596 llvm::FoldingSetNodeID ID;
597 ID.AddInteger(StmtKind);
598 ID.AddBoolean(IsPreVisit);
599 return ID.ComputeHash();
601 bool operator==(const CachedStmtCheckersKey &RHS) const {
602 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
605 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
607 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
608 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
609 CachedStmtCheckersMapTy;
610 CachedStmtCheckersMapTy CachedStmtCheckersMap;
612 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
614 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
615 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
617 std::vector<CheckCallFunc> PreCallCheckers;
618 std::vector<CheckCallFunc> PostCallCheckers;
620 std::vector<CheckLocationFunc> LocationCheckers;
622 std::vector<CheckBindFunc> BindCheckers;
624 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
626 std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
628 std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
630 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
632 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
634 struct RegionChangesCheckerInfo {
635 CheckRegionChangesFunc CheckFn;
636 WantsRegionChangeUpdateFunc WantUpdateFn;
638 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
640 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
642 std::vector<EvalAssumeFunc> EvalAssumeCheckers;
644 std::vector<EvalCallFunc> EvalCallCheckers;
646 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
649 SmallVector<CheckEventFunc, 4> Checkers;
651 EventInfo() : HasDispatcher(false) { }
654 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
658 } // end ento namespace
660 } // end clang namespace
663 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
664 /// in DenseMap and DenseSets.
666 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
667 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
669 return clang::ento::CheckerManager::CachedStmtCheckersKey();
671 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
673 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
677 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
678 return S.getHashValue();
681 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
682 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
686 } // end namespace llvm