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"
31 class AnalysisManager;
37 class ExplodedNodeSet;
40 class EndOfFunctionNodeBuilder;
41 class BranchNodeBuilder;
47 virtual ~GraphExpander();
48 virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
51 template <typename T> class CheckerFn;
53 template <typename RET, typename P1, typename P2, typename P3, typename P4>
54 class CheckerFn<RET(P1, P2, P3, P4)> {
55 typedef RET (*Func)(void *, P1, P2, P3, P4);
59 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
60 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
61 return Fn(Checker, p1, p2, p3, p4);
65 template <typename RET, typename P1, typename P2, typename P3>
66 class CheckerFn<RET(P1, P2, P3)> {
67 typedef RET (*Func)(void *, P1, P2, P3);
71 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
72 RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
75 template <typename RET, typename P1, typename P2>
76 class CheckerFn<RET(P1, P2)> {
77 typedef RET (*Func)(void *, P1, P2);
81 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
82 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
85 template <typename RET, typename P1>
86 class CheckerFn<RET(P1)> {
87 typedef RET (*Func)(void *, P1);
91 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
92 RET operator()(P1 p1) const { return Fn(Checker, p1); }
95 template <typename RET>
96 class CheckerFn<RET()> {
97 typedef RET (*Func)(void *);
101 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
102 RET operator()() const { return Fn(Checker); }
105 class CheckerManager {
106 const LangOptions LangOpts;
109 CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
112 bool hasPathSensitiveCheckers() const;
114 void finishedCheckerRegistration();
116 const LangOptions &getLangOptions() const { return LangOpts; }
118 typedef void *CheckerRef;
119 typedef void *CheckerTag;
120 typedef CheckerFn<void ()> CheckerDtor;
122 //===----------------------------------------------------------------------===//
124 //===----------------------------------------------------------------------===//
126 /// \brief Used to register checkers.
128 /// \returns a pointer to the checker object.
129 template <typename CHECKER>
130 CHECKER *registerChecker() {
131 CheckerTag tag = getTag<CHECKER>();
132 CheckerRef &ref = CheckerTags[tag];
134 return static_cast<CHECKER *>(ref); // already registered.
136 CHECKER *checker = new CHECKER();
137 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
138 CHECKER::_register(checker, *this);
143 //===----------------------------------------------------------------------===//
144 // Functions for running checkers for AST traversing..
145 //===----------------------------------------------------------------------===//
147 /// \brief Run checkers handling Decls.
148 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
151 /// \brief Run checkers handling Decls containing a Stmt body.
152 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
155 //===----------------------------------------------------------------------===//
156 // Functions for running checkers for path-sensitive checking.
157 //===----------------------------------------------------------------------===//
159 /// \brief Run checkers for pre-visiting Stmts.
160 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
161 const ExplodedNodeSet &Src,
164 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
167 /// \brief Run checkers for post-visiting Stmts.
168 void runCheckersForPostStmt(ExplodedNodeSet &Dst,
169 const ExplodedNodeSet &Src,
172 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
175 /// \brief Run checkers for visiting Stmts.
176 void runCheckersForStmt(bool isPreVisit,
177 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
178 const Stmt *S, ExprEngine &Eng);
180 /// \brief Run checkers for pre-visiting obj-c messages.
181 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
182 const ExplodedNodeSet &Src,
183 const ObjCMessage &msg,
185 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
188 /// \brief Run checkers for post-visiting obj-c messages.
189 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
190 const ExplodedNodeSet &Src,
191 const ObjCMessage &msg,
193 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
196 /// \brief Run checkers for visiting obj-c messages.
197 void runCheckersForObjCMessage(bool isPreVisit,
198 ExplodedNodeSet &Dst,
199 const ExplodedNodeSet &Src,
200 const ObjCMessage &msg, ExprEngine &Eng);
202 /// \brief Run checkers for load/store of a location.
203 void runCheckersForLocation(ExplodedNodeSet &Dst,
204 const ExplodedNodeSet &Src,
205 SVal location, bool isLoad,
209 /// \brief Run checkers for binding of a value to a location.
210 void runCheckersForBind(ExplodedNodeSet &Dst,
211 const ExplodedNodeSet &Src,
212 SVal location, SVal val,
213 const Stmt *S, ExprEngine &Eng);
215 /// \brief Run checkers for end of analysis.
216 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
219 /// \brief Run checkers for end of path.
220 void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
222 /// \brief Run checkers for branch condition.
223 void runCheckersForBranchCondition(const Stmt *condition,
224 BranchNodeBuilder &B, ExprEngine &Eng);
226 /// \brief Run checkers for live symbols.
227 void runCheckersForLiveSymbols(const GRState *state,
228 SymbolReaper &SymReaper);
230 /// \brief Run checkers for dead symbols.
231 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
232 const ExplodedNodeSet &Src,
233 SymbolReaper &SymReaper, const Stmt *S,
236 /// \brief True if at least one checker wants to check region changes.
237 bool wantsRegionChangeUpdate(const GRState *state);
239 /// \brief Run checkers for region changes.
241 runCheckersForRegionChanges(const GRState *state,
242 const StoreManager::InvalidatedSymbols *invalidated,
243 const MemRegion * const *Begin,
244 const MemRegion * const *End);
246 /// \brief Run checkers for handling assumptions on symbolic values.
247 const GRState *runCheckersForEvalAssume(const GRState *state,
248 SVal Cond, bool Assumption);
250 /// \brief Run checkers for evaluating a call.
251 void runCheckersForEvalCall(ExplodedNodeSet &Dst,
252 const ExplodedNodeSet &Src,
253 const CallExpr *CE, ExprEngine &Eng,
254 GraphExpander *defaultEval = 0);
256 /// \brief Run checkers for the entire Translation Unit.
257 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl* TU,
258 AnalysisManager &mgr,
261 //===----------------------------------------------------------------------===//
262 // Internal registration functions for AST traversing.
263 //===----------------------------------------------------------------------===//
265 // Functions used by the registration mechanism, checkers should not touch
268 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
271 typedef bool (*HandlesDeclFunc)(const Decl *D);
272 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
274 void _registerForBody(CheckDeclFunc checkfn);
276 //===----------------------------------------------------------------------===//
277 // Internal registration functions for path-sensitive checking.
278 //===----------------------------------------------------------------------===//
280 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
282 typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)>
283 CheckObjCMessageFunc;
285 typedef CheckerFn<void (const SVal &location, bool isLoad, CheckerContext &)>
288 typedef CheckerFn<void (const SVal &location, const SVal &val,
289 CheckerContext &)> CheckBindFunc;
291 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
292 CheckEndAnalysisFunc;
294 typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)>
297 typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)>
298 CheckBranchConditionFunc;
300 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
301 CheckDeadSymbolsFunc;
303 typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc;
305 typedef CheckerFn<const GRState * (const GRState *,
306 const StoreManager::InvalidatedSymbols *symbols,
307 const MemRegion * const *begin,
308 const MemRegion * const *end)>
309 CheckRegionChangesFunc;
311 typedef CheckerFn<bool (const GRState *)> WantsRegionChangeUpdateFunc;
313 typedef CheckerFn<const GRState * (const GRState *,
314 const SVal &cond, bool assumption)>
317 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
320 typedef CheckerFn<void (const TranslationUnitDecl *,
321 AnalysisManager&, BugReporter &)>
322 CheckEndOfTranslationUnit;
324 typedef bool (*HandlesStmtFunc)(const Stmt *D);
325 void _registerForPreStmt(CheckStmtFunc checkfn,
326 HandlesStmtFunc isForStmtFn);
327 void _registerForPostStmt(CheckStmtFunc checkfn,
328 HandlesStmtFunc isForStmtFn);
330 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
331 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
333 void _registerForLocation(CheckLocationFunc checkfn);
335 void _registerForBind(CheckBindFunc checkfn);
337 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
339 void _registerForEndPath(CheckEndPathFunc checkfn);
341 void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
343 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
345 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
347 void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
348 WantsRegionChangeUpdateFunc wantUpdateFn);
350 void _registerForEvalAssume(EvalAssumeFunc checkfn);
352 void _registerForEvalCall(EvalCallFunc checkfn);
354 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
356 //===----------------------------------------------------------------------===//
357 // Internal registration functions for events.
358 //===----------------------------------------------------------------------===//
360 typedef void *EventTag;
361 typedef CheckerFn<void (const void *event)> CheckEventFunc;
363 template <typename EVENT>
364 void _registerListenerForEvent(CheckEventFunc checkfn) {
365 EventInfo &info = Events[getTag<EVENT>()];
366 info.Checkers.push_back(checkfn);
369 template <typename EVENT>
370 void _registerDispatcherForEvent() {
371 EventInfo &info = Events[getTag<EVENT>()];
372 info.HasDispatcher = true;
375 template <typename EVENT>
376 void _dispatchEvent(const EVENT &event) const {
377 EventsTy::const_iterator I = Events.find(getTag<EVENT>());
378 if (I == Events.end())
380 const EventInfo &info = I->second;
381 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
382 info.Checkers[i](&event);
385 //===----------------------------------------------------------------------===//
386 // Implementation details.
387 //===----------------------------------------------------------------------===//
390 template <typename CHECKER>
391 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
393 template <typename T>
394 static void *getTag() { static int tag; return &tag; }
396 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
398 std::vector<CheckerDtor> CheckerDtors;
400 struct DeclCheckerInfo {
401 CheckDeclFunc CheckFn;
402 HandlesDeclFunc IsForDeclFn;
404 std::vector<DeclCheckerInfo> DeclCheckers;
406 std::vector<CheckDeclFunc> BodyCheckers;
408 typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
409 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
410 CachedDeclCheckersMapTy CachedDeclCheckersMap;
412 struct StmtCheckerInfo {
413 CheckStmtFunc CheckFn;
414 HandlesStmtFunc IsForStmtFn;
417 std::vector<StmtCheckerInfo> StmtCheckers;
419 struct CachedStmtCheckersKey {
423 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
424 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
425 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
427 static CachedStmtCheckersKey getSentinel() {
428 return CachedStmtCheckersKey(~0U, 0);
430 unsigned getHashValue() const {
431 llvm::FoldingSetNodeID ID;
432 ID.AddInteger(StmtKind);
433 ID.AddBoolean(IsPreVisit);
434 return ID.ComputeHash();
436 bool operator==(const CachedStmtCheckersKey &RHS) const {
437 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
440 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
442 typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
443 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
444 CachedStmtCheckersMapTy;
445 CachedStmtCheckersMapTy CachedStmtCheckersMap;
447 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
449 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
450 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
452 std::vector<CheckLocationFunc> LocationCheckers;
454 std::vector<CheckBindFunc> BindCheckers;
456 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
458 std::vector<CheckEndPathFunc> EndPathCheckers;
460 std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
462 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
464 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
466 struct RegionChangesCheckerInfo {
467 CheckRegionChangesFunc CheckFn;
468 WantsRegionChangeUpdateFunc WantUpdateFn;
470 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
472 std::vector<EvalAssumeFunc> EvalAssumeCheckers;
474 std::vector<EvalCallFunc> EvalCallCheckers;
476 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
479 llvm::SmallVector<CheckEventFunc, 4> Checkers;
481 EventInfo() : HasDispatcher(false) { }
484 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
488 } // end ento namespace
490 } // end clang namespace
493 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
494 /// in DenseMap and DenseSets.
496 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
497 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
499 return clang::ento::CheckerManager::CachedStmtCheckersKey();
501 static inline clang::ento::CheckerManager::CachedStmtCheckersKey
503 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
507 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
508 return S.getHashValue();
511 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
512 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
516 } // end namespace llvm