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