CheckerManager.h revision 35bdbf40624beba3fc00cb72ab444659939c1a6b
1//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Defines the Static Analyzer Checker Manager. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 15#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 16 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 <vector> 23 24namespace clang { 25 class Decl; 26 class Stmt; 27 class CallExpr; 28 29namespace ento { 30 class ExprEngine; 31 class AnalysisManager; 32 class BugReporter; 33 class CheckerContext; 34 class ObjCMessage; 35 class SVal; 36 class ExplodedNode; 37 class ExplodedNodeSet; 38 class ExplodedGraph; 39 class GRState; 40 class EndOfFunctionNodeBuilder; 41 class BranchNodeBuilder; 42 class MemRegion; 43 class SymbolReaper; 44 45class GraphExpander { 46public: 47 virtual ~GraphExpander(); 48 virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; 49}; 50 51template <typename T> class CheckerFn; 52 53template <typename RET, typename P1, typename P2, typename P3, typename P4> 54class CheckerFn<RET(P1, P2, P3, P4)> { 55 typedef RET (*Func)(void *, P1, P2, P3, P4); 56 Func Fn; 57public: 58 void *Checker; 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); 62 } 63}; 64 65template <typename RET, typename P1, typename P2, typename P3> 66class CheckerFn<RET(P1, P2, P3)> { 67 typedef RET (*Func)(void *, P1, P2, P3); 68 Func Fn; 69public: 70 void *Checker; 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); } 73}; 74 75template <typename RET, typename P1, typename P2> 76class CheckerFn<RET(P1, P2)> { 77 typedef RET (*Func)(void *, P1, P2); 78 Func Fn; 79public: 80 void *Checker; 81 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 82 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 83}; 84 85template <typename RET, typename P1> 86class CheckerFn<RET(P1)> { 87 typedef RET (*Func)(void *, P1); 88 Func Fn; 89public: 90 void *Checker; 91 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 92 RET operator()(P1 p1) const { return Fn(Checker, p1); } 93}; 94 95template <typename RET> 96class CheckerFn<RET()> { 97 typedef RET (*Func)(void *); 98 Func Fn; 99public: 100 void *Checker; 101 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 102 RET operator()() const { return Fn(Checker); } 103}; 104 105class CheckerManager { 106 const LangOptions LangOpts; 107 108public: 109 CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } 110 ~CheckerManager(); 111 112 bool hasPathSensitiveCheckers() const; 113 114 void finishedCheckerRegistration(); 115 116 const LangOptions &getLangOptions() const { return LangOpts; } 117 118 typedef void *CheckerRef; 119 typedef void *CheckerTag; 120 typedef CheckerFn<void ()> CheckerDtor; 121 122//===----------------------------------------------------------------------===// 123// registerChecker 124//===----------------------------------------------------------------------===// 125 126 /// \brief Used to register checkers. 127 /// 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]; 133 if (ref) 134 return static_cast<CHECKER *>(ref); // already registered. 135 136 CHECKER *checker = new CHECKER(); 137 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 138 CHECKER::_register(checker, *this); 139 ref = checker; 140 return checker; 141 } 142 143//===----------------------------------------------------------------------===// 144// Functions for running checkers for AST traversing.. 145//===----------------------------------------------------------------------===// 146 147 /// \brief Run checkers handling Decls. 148 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 149 BugReporter &BR); 150 151 /// \brief Run checkers handling Decls containing a Stmt body. 152 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 153 BugReporter &BR); 154 155//===----------------------------------------------------------------------===// 156// Functions for running checkers for path-sensitive checking. 157//===----------------------------------------------------------------------===// 158 159 /// \brief Run checkers for pre-visiting Stmts. 160 void runCheckersForPreStmt(ExplodedNodeSet &Dst, 161 const ExplodedNodeSet &Src, 162 const Stmt *S, 163 ExprEngine &Eng) { 164 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 165 } 166 167 /// \brief Run checkers for post-visiting Stmts. 168 void runCheckersForPostStmt(ExplodedNodeSet &Dst, 169 const ExplodedNodeSet &Src, 170 const Stmt *S, 171 ExprEngine &Eng) { 172 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng); 173 } 174 175 /// \brief Run checkers for visiting Stmts. 176 void runCheckersForStmt(bool isPreVisit, 177 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 178 const Stmt *S, ExprEngine &Eng); 179 180 /// \brief Run checkers for pre-visiting obj-c messages. 181 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 182 const ExplodedNodeSet &Src, 183 const ObjCMessage &msg, 184 ExprEngine &Eng) { 185 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 186 } 187 188 /// \brief Run checkers for post-visiting obj-c messages. 189 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 190 const ExplodedNodeSet &Src, 191 const ObjCMessage &msg, 192 ExprEngine &Eng) { 193 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng); 194 } 195 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); 201 202 /// \brief Run checkers for load/store of a location. 203 void runCheckersForLocation(ExplodedNodeSet &Dst, 204 const ExplodedNodeSet &Src, 205 SVal location, bool isLoad, 206 const Stmt *S, 207 ExprEngine &Eng); 208 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); 214 215 /// \brief Run checkers for end of analysis. 216 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 217 ExprEngine &Eng); 218 219 /// \brief Run checkers for end of path. 220 void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng); 221 222 /// \brief Run checkers for branch condition. 223 void runCheckersForBranchCondition(const Stmt *condition, 224 BranchNodeBuilder &B, ExprEngine &Eng); 225 226 /// \brief Run checkers for live symbols. 227 void runCheckersForLiveSymbols(const GRState *state, 228 SymbolReaper &SymReaper); 229 230 /// \brief Run checkers for dead symbols. 231 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 232 const ExplodedNodeSet &Src, 233 SymbolReaper &SymReaper, const Stmt *S, 234 ExprEngine &Eng); 235 236 /// \brief True if at least one checker wants to check region changes. 237 bool wantsRegionChangeUpdate(const GRState *state); 238 239 /// \brief Run checkers for region changes. 240 const GRState * 241 runCheckersForRegionChanges(const GRState *state, 242 const StoreManager::InvalidatedSymbols *invalidated, 243 const MemRegion * const *Begin, 244 const MemRegion * const *End); 245 246 /// \brief Run checkers for handling assumptions on symbolic values. 247 const GRState *runCheckersForEvalAssume(const GRState *state, 248 SVal Cond, bool Assumption); 249 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); 255 256//===----------------------------------------------------------------------===// 257// Internal registration functions for AST traversing. 258//===----------------------------------------------------------------------===// 259 260 // Functions used by the registration mechanism, checkers should not touch 261 // these directly. 262 263 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> 264 CheckDeclFunc; 265 266 typedef bool (*HandlesDeclFunc)(const Decl *D); 267 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 268 269 void _registerForBody(CheckDeclFunc checkfn); 270 271//===----------------------------------------------------------------------===// 272// Internal registration functions for path-sensitive checking. 273//===----------------------------------------------------------------------===// 274 275 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; 276 277 typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)> 278 CheckObjCMessageFunc; 279 280 typedef CheckerFn<void (const SVal &location, bool isLoad, CheckerContext &)> 281 CheckLocationFunc; 282 283 typedef CheckerFn<void (const SVal &location, const SVal &val, 284 CheckerContext &)> CheckBindFunc; 285 286 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> 287 CheckEndAnalysisFunc; 288 289 typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)> 290 CheckEndPathFunc; 291 292 typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)> 293 CheckBranchConditionFunc; 294 295 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> 296 CheckDeadSymbolsFunc; 297 298 typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc; 299 300 typedef CheckerFn<const GRState * (const GRState *, 301 const StoreManager::InvalidatedSymbols *symbols, 302 const MemRegion * const *begin, 303 const MemRegion * const *end)> 304 CheckRegionChangesFunc; 305 306 typedef CheckerFn<bool (const GRState *)> WantsRegionChangeUpdateFunc; 307 308 typedef CheckerFn<const GRState * (const GRState *, 309 const SVal &cond, bool assumption)> 310 EvalAssumeFunc; 311 312 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> 313 EvalCallFunc; 314 315 typedef bool (*HandlesStmtFunc)(const Stmt *D); 316 void _registerForPreStmt(CheckStmtFunc checkfn, 317 HandlesStmtFunc isForStmtFn); 318 void _registerForPostStmt(CheckStmtFunc checkfn, 319 HandlesStmtFunc isForStmtFn); 320 321 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 322 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 323 324 void _registerForLocation(CheckLocationFunc checkfn); 325 326 void _registerForBind(CheckBindFunc checkfn); 327 328 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 329 330 void _registerForEndPath(CheckEndPathFunc checkfn); 331 332 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 333 334 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 335 336 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 337 338 void _registerForRegionChanges(CheckRegionChangesFunc checkfn, 339 WantsRegionChangeUpdateFunc wantUpdateFn); 340 341 void _registerForEvalAssume(EvalAssumeFunc checkfn); 342 343 void _registerForEvalCall(EvalCallFunc checkfn); 344 345//===----------------------------------------------------------------------===// 346// Internal registration functions for events. 347//===----------------------------------------------------------------------===// 348 349 typedef void *EventTag; 350 typedef CheckerFn<void (const void *event)> CheckEventFunc; 351 352 template <typename EVENT> 353 void _registerListenerForEvent(CheckEventFunc checkfn) { 354 EventInfo &info = Events[getTag<EVENT>()]; 355 info.Checkers.push_back(checkfn); 356 } 357 358 template <typename EVENT> 359 void _registerDispatcherForEvent() { 360 EventInfo &info = Events[getTag<EVENT>()]; 361 info.HasDispatcher = true; 362 } 363 364 template <typename EVENT> 365 void _dispatchEvent(const EVENT &event) const { 366 EventsTy::const_iterator I = Events.find(getTag<EVENT>()); 367 if (I == Events.end()) 368 return; 369 const EventInfo &info = I->second; 370 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) 371 info.Checkers[i](&event); 372 } 373 374//===----------------------------------------------------------------------===// 375// Implementation details. 376//===----------------------------------------------------------------------===// 377 378private: 379 template <typename CHECKER> 380 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 381 382 template <typename T> 383 static void *getTag() { static int tag; return &tag; } 384 385 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 386 387 std::vector<CheckerDtor> CheckerDtors; 388 389 struct DeclCheckerInfo { 390 CheckDeclFunc CheckFn; 391 HandlesDeclFunc IsForDeclFn; 392 }; 393 std::vector<DeclCheckerInfo> DeclCheckers; 394 395 std::vector<CheckDeclFunc> BodyCheckers; 396 397 typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 398 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 399 CachedDeclCheckersMapTy CachedDeclCheckersMap; 400 401 struct StmtCheckerInfo { 402 CheckStmtFunc CheckFn; 403 HandlesStmtFunc IsForStmtFn; 404 bool IsPreVisit; 405 }; 406 std::vector<StmtCheckerInfo> StmtCheckers; 407 408 struct CachedStmtCheckersKey { 409 unsigned StmtKind; 410 bool IsPreVisit; 411 412 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } 413 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) 414 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } 415 416 static CachedStmtCheckersKey getSentinel() { 417 return CachedStmtCheckersKey(~0U, 0); 418 } 419 unsigned getHashValue() const { 420 llvm::FoldingSetNodeID ID; 421 ID.AddInteger(StmtKind); 422 ID.AddBoolean(IsPreVisit); 423 return ID.ComputeHash(); 424 } 425 bool operator==(const CachedStmtCheckersKey &RHS) const { 426 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; 427 } 428 }; 429 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; 430 431 typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 432 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> 433 CachedStmtCheckersMapTy; 434 CachedStmtCheckersMapTy CachedStmtCheckersMap; 435 436 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); 437 438 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 439 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 440 441 std::vector<CheckLocationFunc> LocationCheckers; 442 443 std::vector<CheckBindFunc> BindCheckers; 444 445 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 446 447 std::vector<CheckEndPathFunc> EndPathCheckers; 448 449 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 450 451 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 452 453 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 454 455 struct RegionChangesCheckerInfo { 456 CheckRegionChangesFunc CheckFn; 457 WantsRegionChangeUpdateFunc WantUpdateFn; 458 }; 459 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; 460 461 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 462 463 std::vector<EvalCallFunc> EvalCallCheckers; 464 465 struct EventInfo { 466 llvm::SmallVector<CheckEventFunc, 4> Checkers; 467 bool HasDispatcher; 468 EventInfo() : HasDispatcher(false) { } 469 }; 470 471 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; 472 EventsTy Events; 473}; 474 475} // end ento namespace 476 477} // end clang namespace 478 479namespace llvm { 480 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key 481 /// in DenseMap and DenseSets. 482 template <> 483 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { 484 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 485 getEmptyKey() { 486 return clang::ento::CheckerManager::CachedStmtCheckersKey(); 487 } 488 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 489 getTombstoneKey() { 490 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); 491 } 492 493 static unsigned 494 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { 495 return S.getHashValue(); 496 } 497 498 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, 499 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { 500 return LHS == RHS; 501 } 502 }; 503} // end namespace llvm 504 505#endif 506