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/Basic/LangOptions.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/FoldingSet.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
22 #include "clang/Analysis/ProgramPoint.h"
33 class AnalysisManager;
40 class ExplodedNodeSet;
44 struct NodeBuilderContext;
48 template <typename T> class CheckerFn;
50 template <typename RET, typename P1, typename P2, typename P3, typename P4,
52 class CheckerFn<RET(P1, P2, P3, P4, P5)> {
53 typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
57 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
58 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
59 return Fn(Checker, p1, p2, p3, p4, p5);
63 template <typename RET, typename P1, typename P2, typename P3, typename P4>
64 class CheckerFn<RET(P1, P2, P3, P4)> {
65 typedef RET (*Func)(void *, P1, P2, P3, P4);
69 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
70 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
71 return Fn(Checker, p1, p2, p3, p4);
75 template <typename RET, typename P1, typename P2, typename P3>
76 class CheckerFn<RET(P1, P2, P3)> {
77 typedef RET (*Func)(void *, P1, P2, P3);
81 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
82 RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
85 template <typename RET, typename P1, typename P2>
86 class CheckerFn<RET(P1, P2)> {
87 typedef RET (*Func)(void *, P1, P2);
91 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
92 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
95 template <typename RET, typename P1>
96 class CheckerFn<RET(P1)> {
97 typedef RET (*Func)(void *, P1);
100 CheckerBase *Checker;
101 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
102 RET operator()(P1 p1) const { return Fn(Checker, p1); }
105 template <typename RET>
106 class CheckerFn<RET()> {
107 typedef RET (*Func)(void *);
110 CheckerBase *Checker;
111 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
112 RET operator()() const { return Fn(Checker); }
115 class CheckerManager {
116 const LangOptions LangOpts;
119 CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
122 bool hasPathSensitiveCheckers() const;
124 void finishedCheckerRegistration();
126 const LangOptions &getLangOpts() const { return LangOpts; }
128 typedef CheckerBase *CheckerRef;
129 typedef const void *CheckerTag;
130 typedef CheckerFn<void ()> CheckerDtor;
132 //===----------------------------------------------------------------------===//
134 //===----------------------------------------------------------------------===//
136 /// \brief Used to register checkers.
138 /// \returns a pointer to the checker object.
139 template <typename CHECKER>
140 CHECKER *registerChecker() {
141 CheckerTag tag = getTag<CHECKER>();
142 CheckerRef &ref = CheckerTags[tag];
144 return static_cast<CHECKER *>(ref); // already registered.
146 CHECKER *checker = new CHECKER();
147 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
148 CHECKER::_register(checker, *this);
153 //===----------------------------------------------------------------------===//
154 // Functions for running checkers for AST traversing..
155 //===----------------------------------------------------------------------===//
157 /// \brief Run checkers handling Decls.
158 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
161 /// \brief Run checkers handling Decls containing a Stmt body.
162 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
165 //===----------------------------------------------------------------------===//
166 // Functions for running checkers for path-sensitive checking.
167 //===----------------------------------------------------------------------===//
169 /// \brief Run checkers for pre-visiting Stmts.
171 /// The notification is performed for every explored CFGElement, which does
172 /// not include the control flow statements such as IfStmt.
174 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
175 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
176 const ExplodedNodeSet &Src,
179 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
182 /// \brief Run checkers for post-visiting Stmts.
184 /// The notification is performed for every explored CFGElement, which does
185 /// not include the control flow statements such as IfStmt.
187 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
188 void runCheckersForPostStmt(ExplodedNodeSet &Dst,
189 const ExplodedNodeSet &Src,
192 bool wasInlined = false) {
193 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
196 /// \brief Run checkers for visiting Stmts.
197 void runCheckersForStmt(bool isPreVisit,
198 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
199 const Stmt *S, ExprEngine &Eng,
200 bool wasInlined = false);
202 /// \brief Run checkers for pre-visiting obj-c messages.
203 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
204 const ExplodedNodeSet &Src,
205 const ObjCMethodCall &msg,
207 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
210 /// \brief Run checkers for post-visiting obj-c messages.
211 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
212 const ExplodedNodeSet &Src,
213 const ObjCMethodCall &msg,
215 bool wasInlined = false) {
216 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
220 /// \brief Run checkers for visiting obj-c messages.
221 void runCheckersForObjCMessage(bool isPreVisit,
222 ExplodedNodeSet &Dst,
223 const ExplodedNodeSet &Src,
224 const ObjCMethodCall &msg, ExprEngine &Eng,
225 bool wasInlined = false);
227 /// \brief Run checkers for pre-visiting obj-c messages.
228 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
229 const CallEvent &Call, ExprEngine &Eng) {
230 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
233 /// \brief Run checkers for post-visiting obj-c messages.
234 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
235 const CallEvent &Call, ExprEngine &Eng,
236 bool wasInlined = false) {
237 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
241 /// \brief Run checkers for visiting obj-c messages.
242 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
243 const ExplodedNodeSet &Src,
244 const CallEvent &Call, ExprEngine &Eng,
245 bool wasInlined = false);
247 /// \brief Run checkers for load/store of a location.
248 void runCheckersForLocation(ExplodedNodeSet &Dst,
249 const ExplodedNodeSet &Src,
256 /// \brief Run checkers for binding of a value to a location.
257 void runCheckersForBind(ExplodedNodeSet &Dst,
258 const ExplodedNodeSet &Src,
259 SVal location, SVal val,
260 const Stmt *S, ExprEngine &Eng,
261 const ProgramPoint &PP);
263 /// \brief Run checkers for end of analysis.
264 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
267 /// \brief Run checkers for end of path.
268 void runCheckersForEndPath(NodeBuilderContext &BC,
269 ExplodedNodeSet &Dst,
273 /// \brief Run checkers for branch condition.
274 void runCheckersForBranchCondition(const Stmt *condition,
275 ExplodedNodeSet &Dst, ExplodedNode *Pred,
278 /// \brief Run checkers for live symbols.
280 /// Allows modifying SymbolReaper object. For example, checkers can explicitly
281 /// register symbols of interest as live. These symbols will not be marked
282 /// dead and removed.
283 void runCheckersForLiveSymbols(ProgramStateRef state,
284 SymbolReaper &SymReaper);
286 /// \brief Run checkers for dead symbols.
288 /// Notifies checkers when symbols become dead. For example, this allows
289 /// checkers to aggressively clean up/reduce the checker state and produce
290 /// precise diagnostics.
291 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
292 const ExplodedNodeSet &Src,
293 SymbolReaper &SymReaper, const Stmt *S,
295 ProgramPoint::Kind K);
297 /// \brief True if at least one checker wants to check region changes.
298 bool wantsRegionChangeUpdate(ProgramStateRef state);
300 /// \brief Run checkers for region changes.
302 /// This corresponds to the check::RegionChanges callback.
303 /// \param state The current program state.
304 /// \param invalidated A set of all symbols potentially touched by the change.
305 /// \param ExplicitRegions The regions explicitly requested for invalidation.
306 /// For example, in the case of a function call, these would be arguments.
307 /// \param Regions The transitive closure of accessible regions,
308 /// i.e. all regions that may have been touched by this change.
309 /// \param Call The call expression wrapper if the regions are invalidated
312 runCheckersForRegionChanges(ProgramStateRef state,
313 const StoreManager::InvalidatedSymbols *invalidated,
314 ArrayRef<const MemRegion *> ExplicitRegions,
315 ArrayRef<const MemRegion *> Regions,
316 const CallEvent *Call);
318 /// \brief Run checkers for handling assumptions on symbolic values.
319 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
320 SVal Cond, bool Assumption);
322 /// \brief Run checkers for evaluating a call.
324 /// Warning: Currently, the CallEvent MUST come from a CallExpr!
325 void runCheckersForEvalCall(ExplodedNodeSet &Dst,
326 const ExplodedNodeSet &Src,
327 const CallEvent &CE, ExprEngine &Eng);
329 /// \brief Run checkers for the entire Translation Unit.
330 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
331 AnalysisManager &mgr,
334 /// \brief Run checkers for debug-printing a ProgramState.
336 /// Unlike most other callbacks, any checker can simply implement the virtual
337 /// method CheckerBase::printState if it has custom data to print.
338 /// \param Out The output stream
339 /// \param State The state being printed
340 /// \param NL The preferred representation of a newline.
341 /// \param Sep The preferred separator between different kinds of data.
342 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
343 const char *NL, const char *Sep);
345 //===----------------------------------------------------------------------===//
346 // Internal registration functions for AST traversing.
347 //===----------------------------------------------------------------------===//
349 // Functions used by the registration mechanism, checkers should not touch
352 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
355 typedef bool (*HandlesDeclFunc)(const Decl *D);
356 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
358 void _registerForBody(CheckDeclFunc checkfn);
360 //===----------------------------------------------------------------------===//
361 // Internal registration functions for path-sensitive checking.
362 //===----------------------------------------------------------------------===//
364 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
366 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
367 CheckObjCMessageFunc;
369 typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
372 typedef CheckerFn<void (const SVal &location, bool isLoad,
377 typedef CheckerFn<void (const SVal &location, const SVal &val,
378 const Stmt *S, CheckerContext &)>
381 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
382 CheckEndAnalysisFunc;
384 typedef CheckerFn<void (CheckerContext &)>
387 typedef CheckerFn<void (const Stmt *, CheckerContext &)>
388 CheckBranchConditionFunc;
390 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
391 CheckDeadSymbolsFunc;
393 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
395 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
396 const StoreManager::InvalidatedSymbols *symbols,
397 ArrayRef<const MemRegion *> ExplicitRegions,
398 ArrayRef<const MemRegion *> Regions,
399 const CallEvent *Call)>
400 CheckRegionChangesFunc;
402 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
404 typedef CheckerFn<ProgramStateRef (ProgramStateRef,
405 const SVal &cond, bool assumption)>
408 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
411 typedef CheckerFn<void (const TranslationUnitDecl *,
412 AnalysisManager&, BugReporter &)>
413 CheckEndOfTranslationUnit;
415 typedef bool (*HandlesStmtFunc)(const Stmt *D);
416 void _registerForPreStmt(CheckStmtFunc checkfn,
417 HandlesStmtFunc isForStmtFn);
418 void _registerForPostStmt(CheckStmtFunc checkfn,
419 HandlesStmtFunc isForStmtFn);
421 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
422 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
424 void _registerForPreCall(CheckCallFunc checkfn);
425 void _registerForPostCall(CheckCallFunc checkfn);
427 void _registerForLocation(CheckLocationFunc checkfn);
429 void _registerForBind(CheckBindFunc checkfn);
431 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
433 void _registerForEndPath(CheckEndPathFunc checkfn);
435 void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
437 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
439 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
441 void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
442 WantsRegionChangeUpdateFunc wantUpdateFn);
444 void _registerForEvalAssume(EvalAssumeFunc checkfn);
446 void _registerForEvalCall(EvalCallFunc checkfn);
448 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
450 //===----------------------------------------------------------------------===//
451 // Internal registration functions for events.
452 //===----------------------------------------------------------------------===//
454 typedef void *EventTag;
455 typedef CheckerFn<void (const void *event)> CheckEventFunc;
457 template <typename EVENT>
458 void _registerListenerForEvent(CheckEventFunc checkfn) {
459 EventInfo &info = Events[getTag<EVENT>()];
460 info.Checkers.push_back(checkfn);
463 template <typename EVENT>
464 void _registerDispatcherForEvent() {
465 EventInfo &info = Events[getTag<EVENT>()];
466 info.HasDispatcher = true;
469 template <typename EVENT>
470 void _dispatchEvent(const EVENT &event) const {
471 EventsTy::const_iterator I = Events.find(getTag<EVENT>());
472 if (I == Events.end())
474 const EventInfo &info = I->second;
475 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
476 info.Checkers[i](&event);
479 //===----------------------------------------------------------------------===//
480 // Implementation details.
481 //===----------------------------------------------------------------------===//
484 template <typename CHECKER>
485 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
487 template <typename T>
488 static void *getTag() { static int tag; return &tag; }
490 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
492 std::vector<CheckerDtor> CheckerDtors;
494 struct DeclCheckerInfo {
495 CheckDeclFunc CheckFn;
496 HandlesDeclFunc IsForDeclFn;
498 std::vector<DeclCheckerInfo> DeclCheckers;
500 std::vector<CheckDeclFunc> BodyCheckers;
502 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
503 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
504 CachedDeclCheckersMapTy CachedDeclCheckersMap;
506 struct StmtCheckerInfo {
507 CheckStmtFunc CheckFn;
508 HandlesStmtFunc IsForStmtFn;
511 std::vector<StmtCheckerInfo> StmtCheckers;
513 struct CachedStmtCheckersKey {
517 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
518 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
519 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
521 static CachedStmtCheckersKey getSentinel() {
522 return CachedStmtCheckersKey(~0U, 0);
524 unsigned getHashValue() const {
525 llvm::FoldingSetNodeID ID;
526 ID.AddInteger(StmtKind);
527 ID.AddBoolean(IsPreVisit);
528 return ID.ComputeHash();
530 bool operator==(const CachedStmtCheckersKey &RHS) const {
531 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
534 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
536 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
537 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
538 CachedStmtCheckersMapTy;
539 CachedStmtCheckersMapTy CachedStmtCheckersMap;
541 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
543 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
544 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
546 std::vector<CheckCallFunc> PreCallCheckers;
547 std::vector<CheckCallFunc> PostCallCheckers;
549 std::vector<CheckLocationFunc> LocationCheckers;
551 std::vector<CheckBindFunc> BindCheckers;
553 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
555 std::vector<CheckEndPathFunc> EndPathCheckers;
557 std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
559 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
561 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
563 struct RegionChangesCheckerInfo {
564 CheckRegionChangesFunc CheckFn;
565 WantsRegionChangeUpdateFunc WantUpdateFn;
567 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
569 std::vector<EvalAssumeFunc> EvalAssumeCheckers;
571 std::vector<EvalCallFunc> EvalCallCheckers;
573 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
576 SmallVector<CheckEventFunc, 4> Checkers;
578 EventInfo() : HasDispatcher(false) { }
581 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
585 } // end ento namespace
587 } // end clang namespace
590 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
591 /// in DenseMap and DenseSets.
593 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
594 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
596 return clang::ento::CheckerManager::CachedStmtCheckersKey();
598 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
600 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
604 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
605 return S.getHashValue();
608 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
609 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
613 } // end namespace llvm