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