clang API Documentation
00001 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines Checker, used to create and register checkers. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_SA_CORE_CHECKER 00015 #define LLVM_CLANG_SA_CORE_CHECKER 00016 00017 #include "clang/Analysis/ProgramPoint.h" 00018 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 00020 #include "llvm/Support/Casting.h" 00021 00022 namespace clang { 00023 namespace ento { 00024 class BugReporter; 00025 00026 namespace check { 00027 00028 struct _VoidCheck { 00029 static void _register(void *checker, CheckerManager &mgr) { } 00030 }; 00031 00032 template <typename DECL> 00033 class ASTDecl { 00034 template <typename CHECKER> 00035 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 00036 BugReporter &BR) { 00037 ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR); 00038 } 00039 00040 static bool _handlesDecl(const Decl *D) { 00041 return llvm::isa<DECL>(D); 00042 } 00043 public: 00044 template <typename CHECKER> 00045 static void _register(CHECKER *checker, CheckerManager &mgr) { 00046 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 00047 _checkDecl<CHECKER>), 00048 _handlesDecl); 00049 } 00050 }; 00051 00052 class ASTCodeBody { 00053 template <typename CHECKER> 00054 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 00055 BugReporter &BR) { 00056 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 00057 } 00058 00059 public: 00060 template <typename CHECKER> 00061 static void _register(CHECKER *checker, CheckerManager &mgr) { 00062 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 00063 _checkBody<CHECKER>)); 00064 } 00065 }; 00066 00067 class EndOfTranslationUnit { 00068 template <typename CHECKER> 00069 static void _checkEndOfTranslationUnit(void *checker, 00070 const TranslationUnitDecl *TU, 00071 AnalysisManager& mgr, 00072 BugReporter &BR) { 00073 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 00074 } 00075 00076 public: 00077 template <typename CHECKER> 00078 static void _register(CHECKER *checker, CheckerManager &mgr){ 00079 mgr._registerForEndOfTranslationUnit( 00080 CheckerManager::CheckEndOfTranslationUnit(checker, 00081 _checkEndOfTranslationUnit<CHECKER>)); 00082 } 00083 }; 00084 00085 template <typename STMT> 00086 class PreStmt { 00087 template <typename CHECKER> 00088 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 00089 ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C); 00090 } 00091 00092 static bool _handlesStmt(const Stmt *S) { 00093 return llvm::isa<STMT>(S); 00094 } 00095 public: 00096 template <typename CHECKER> 00097 static void _register(CHECKER *checker, CheckerManager &mgr) { 00098 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 00099 _checkStmt<CHECKER>), 00100 _handlesStmt); 00101 } 00102 }; 00103 00104 template <typename STMT> 00105 class PostStmt { 00106 template <typename CHECKER> 00107 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 00108 ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C); 00109 } 00110 00111 static bool _handlesStmt(const Stmt *S) { 00112 return llvm::isa<STMT>(S); 00113 } 00114 public: 00115 template <typename CHECKER> 00116 static void _register(CHECKER *checker, CheckerManager &mgr) { 00117 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 00118 _checkStmt<CHECKER>), 00119 _handlesStmt); 00120 } 00121 }; 00122 00123 class PreObjCMessage { 00124 template <typename CHECKER> 00125 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 00126 CheckerContext &C) { 00127 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 00128 } 00129 00130 public: 00131 template <typename CHECKER> 00132 static void _register(CHECKER *checker, CheckerManager &mgr) { 00133 mgr._registerForPreObjCMessage( 00134 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 00135 } 00136 }; 00137 00138 class PostObjCMessage { 00139 template <typename CHECKER> 00140 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 00141 CheckerContext &C) { 00142 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 00143 } 00144 00145 public: 00146 template <typename CHECKER> 00147 static void _register(CHECKER *checker, CheckerManager &mgr) { 00148 mgr._registerForPostObjCMessage( 00149 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 00150 } 00151 }; 00152 00153 class Location { 00154 template <typename CHECKER> 00155 static void _checkLocation(void *checker, 00156 const SVal &location, bool isLoad, const Stmt *S, 00157 CheckerContext &C) { 00158 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 00159 } 00160 00161 public: 00162 template <typename CHECKER> 00163 static void _register(CHECKER *checker, CheckerManager &mgr) { 00164 mgr._registerForLocation( 00165 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 00166 } 00167 }; 00168 00169 class Bind { 00170 template <typename CHECKER> 00171 static void _checkBind(void *checker, 00172 const SVal &location, const SVal &val, const Stmt *S, 00173 CheckerContext &C) { 00174 ((const CHECKER *)checker)->checkBind(location, val, S, C); 00175 } 00176 00177 public: 00178 template <typename CHECKER> 00179 static void _register(CHECKER *checker, CheckerManager &mgr) { 00180 mgr._registerForBind( 00181 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 00182 } 00183 }; 00184 00185 class EndAnalysis { 00186 template <typename CHECKER> 00187 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 00188 BugReporter &BR, ExprEngine &Eng) { 00189 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 00190 } 00191 00192 public: 00193 template <typename CHECKER> 00194 static void _register(CHECKER *checker, CheckerManager &mgr) { 00195 mgr._registerForEndAnalysis( 00196 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 00197 } 00198 }; 00199 00200 class EndPath { 00201 template <typename CHECKER> 00202 static void _checkEndPath(void *checker, 00203 CheckerContext &C) { 00204 ((const CHECKER *)checker)->checkEndPath(C); 00205 } 00206 00207 public: 00208 template <typename CHECKER> 00209 static void _register(CHECKER *checker, CheckerManager &mgr) { 00210 mgr._registerForEndPath( 00211 CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); 00212 } 00213 }; 00214 00215 class BranchCondition { 00216 template <typename CHECKER> 00217 static void _checkBranchCondition(void *checker, const Stmt *Condition, 00218 CheckerContext & C) { 00219 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 00220 } 00221 00222 public: 00223 template <typename CHECKER> 00224 static void _register(CHECKER *checker, CheckerManager &mgr) { 00225 mgr._registerForBranchCondition( 00226 CheckerManager::CheckBranchConditionFunc(checker, 00227 _checkBranchCondition<CHECKER>)); 00228 } 00229 }; 00230 00231 class LiveSymbols { 00232 template <typename CHECKER> 00233 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 00234 SymbolReaper &SR) { 00235 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 00236 } 00237 00238 public: 00239 template <typename CHECKER> 00240 static void _register(CHECKER *checker, CheckerManager &mgr) { 00241 mgr._registerForLiveSymbols( 00242 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 00243 } 00244 }; 00245 00246 class DeadSymbols { 00247 template <typename CHECKER> 00248 static void _checkDeadSymbols(void *checker, 00249 SymbolReaper &SR, CheckerContext &C) { 00250 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 00251 } 00252 00253 public: 00254 template <typename CHECKER> 00255 static void _register(CHECKER *checker, CheckerManager &mgr) { 00256 mgr._registerForDeadSymbols( 00257 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 00258 } 00259 }; 00260 00261 class RegionChanges { 00262 template <typename CHECKER> 00263 static ProgramStateRef 00264 _checkRegionChanges(void *checker, 00265 ProgramStateRef state, 00266 const StoreManager::InvalidatedSymbols *invalidated, 00267 ArrayRef<const MemRegion *> Explicits, 00268 ArrayRef<const MemRegion *> Regions, 00269 const CallOrObjCMessage *Call) { 00270 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 00271 Explicits, Regions, Call); 00272 } 00273 template <typename CHECKER> 00274 static bool _wantsRegionChangeUpdate(void *checker, 00275 ProgramStateRef state) { 00276 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 00277 } 00278 00279 public: 00280 template <typename CHECKER> 00281 static void _register(CHECKER *checker, CheckerManager &mgr) { 00282 mgr._registerForRegionChanges( 00283 CheckerManager::CheckRegionChangesFunc(checker, 00284 _checkRegionChanges<CHECKER>), 00285 CheckerManager::WantsRegionChangeUpdateFunc(checker, 00286 _wantsRegionChangeUpdate<CHECKER>)); 00287 } 00288 }; 00289 00290 template <typename EVENT> 00291 class Event { 00292 template <typename CHECKER> 00293 static void _checkEvent(void *checker, const void *event) { 00294 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 00295 } 00296 public: 00297 template <typename CHECKER> 00298 static void _register(CHECKER *checker, CheckerManager &mgr) { 00299 mgr._registerListenerForEvent<EVENT>( 00300 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 00301 } 00302 }; 00303 00304 } // end check namespace 00305 00306 namespace eval { 00307 00308 class Assume { 00309 template <typename CHECKER> 00310 static ProgramStateRef _evalAssume(void *checker, 00311 ProgramStateRef state, 00312 const SVal &cond, 00313 bool assumption) { 00314 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 00315 } 00316 00317 public: 00318 template <typename CHECKER> 00319 static void _register(CHECKER *checker, CheckerManager &mgr) { 00320 mgr._registerForEvalAssume( 00321 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 00322 } 00323 }; 00324 00325 class Call { 00326 template <typename CHECKER> 00327 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 00328 return ((const CHECKER *)checker)->evalCall(CE, C); 00329 } 00330 00331 public: 00332 template <typename CHECKER> 00333 static void _register(CHECKER *checker, CheckerManager &mgr) { 00334 mgr._registerForEvalCall( 00335 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 00336 } 00337 }; 00338 00339 class InlineCall { 00340 template <typename CHECKER> 00341 static bool _inlineCall(void *checker, const CallExpr *CE, 00342 ExprEngine &Eng, 00343 ExplodedNode *Pred, 00344 ExplodedNodeSet &Dst) { 00345 return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst); 00346 } 00347 00348 public: 00349 template <typename CHECKER> 00350 static void _register(CHECKER *checker, CheckerManager &mgr) { 00351 mgr._registerForInlineCall( 00352 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>)); 00353 } 00354 }; 00355 00356 } // end eval namespace 00357 00358 class CheckerBase : public ProgramPointTag { 00359 public: 00360 StringRef getTagDescription() const; 00361 00362 /// See CheckerManager::runCheckersForPrintState. 00363 virtual void printState(raw_ostream &Out, ProgramStateRef State, 00364 const char *NL, const char *Sep) const { } 00365 }; 00366 00367 template <typename CHECK1, typename CHECK2=check::_VoidCheck, 00368 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 00369 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 00370 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 00371 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 00372 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 00373 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 00374 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, 00375 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck> 00376 class Checker; 00377 00378 template <> 00379 class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 00380 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 00381 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 00382 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 00383 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 00384 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> 00385 : public CheckerBase 00386 { 00387 virtual void anchor(); 00388 public: 00389 static void _register(void *checker, CheckerManager &mgr) { } 00390 }; 00391 00392 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 00393 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 00394 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 00395 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 00396 typename CHECK17,typename CHECK18> 00397 class Checker 00398 : public CHECK1, 00399 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 00400 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 00401 CHECK16,CHECK17,CHECK18> { 00402 public: 00403 template <typename CHECKER> 00404 static void _register(CHECKER *checker, CheckerManager &mgr) { 00405 CHECK1::_register(checker, mgr); 00406 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 00407 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 00408 CHECK16,CHECK17,CHECK18>::_register(checker, mgr); 00409 } 00410 }; 00411 00412 template <typename EVENT> 00413 class EventDispatcher { 00414 CheckerManager *Mgr; 00415 public: 00416 EventDispatcher() : Mgr(0) { } 00417 00418 template <typename CHECKER> 00419 static void _register(CHECKER *checker, CheckerManager &mgr) { 00420 mgr._registerDispatcherForEvent<EVENT>(); 00421 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 00422 } 00423 00424 void dispatchEvent(const EVENT &event) const { 00425 Mgr->_dispatchEvent(event); 00426 } 00427 }; 00428 00429 /// \brief We dereferenced a location that may be null. 00430 struct ImplicitNullDerefEvent { 00431 SVal Location; 00432 bool IsLoad; 00433 ExplodedNode *SinkNode; 00434 BugReporter *BR; 00435 }; 00436 00437 } // end ento namespace 00438 00439 } // end clang namespace 00440 00441 #endif