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