Checker.h revision 9be6e7ce5788e50c62d40c59b0bbc2ea423683f7
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// 35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// The LLVM Compiler Infrastructure 45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// 55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// This file is distributed under the University of Illinois Open Source 65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// License. See LICENSE.TXT for details. 75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// 85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//===----------------------------------------------------------------------===// 95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// 105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// This file defines Checker, used to create and register checkers. 115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// 125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//===----------------------------------------------------------------------===// 135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef LLVM_CLANG_SA_CORE_CHECKER 155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define LLVM_CLANG_SA_CORE_CHECKER 165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "clang/StaticAnalyzer/Core/CheckerManager.h" 185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "llvm/Support/Casting.h" 205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace clang { 225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace ento { 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project class BugReporter; 245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace check { 265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct _VoidCheck { 285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _register(void *checker, CheckerManager &mgr) { } 295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}; 305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttemplate <typename DECL> 325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass ASTDecl { 335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project template <typename CHECKER> 345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project BugReporter &BR) { 365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR); 375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static bool _handlesDecl(const Decl *D) { 405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return llvm::isa<DECL>(D); 415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpublic: 435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project template <typename CHECKER> 445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _register(CHECKER *checker, CheckerManager &mgr) { 455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project _checkDecl<CHECKER>), 475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project _handlesDecl); 485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}; 505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass ASTCodeBody { 525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project template <typename CHECKER> 535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project BugReporter &BR) { 555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpublic: 595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project template <typename CHECKER> 605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _register(CHECKER *checker, CheckerManager &mgr) { 615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project _checkBody<CHECKER>)); 635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}; 655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass EndOfTranslationUnit { 675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project template <typename CHECKER> 685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project static void _checkEndOfTranslationUnit(void *checker, 695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project const TranslationUnitDecl *TU, 70 AnalysisManager& mgr, 71 BugReporter &BR) { 72 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 73 } 74 75public: 76 template <typename CHECKER> 77 static void _register(CHECKER *checker, CheckerManager &mgr){ 78 mgr._registerForEndOfTranslationUnit( 79 CheckerManager::CheckEndOfTranslationUnit(checker, 80 _checkEndOfTranslationUnit<CHECKER>)); 81 } 82}; 83 84template <typename STMT> 85class PreStmt { 86 template <typename CHECKER> 87 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 88 ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C); 89 } 90 91 static bool _handlesStmt(const Stmt *S) { 92 return llvm::isa<STMT>(S); 93 } 94public: 95 template <typename CHECKER> 96 static void _register(CHECKER *checker, CheckerManager &mgr) { 97 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 98 _checkStmt<CHECKER>), 99 _handlesStmt); 100 } 101}; 102 103template <typename STMT> 104class PostStmt { 105 template <typename CHECKER> 106 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 107 ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C); 108 } 109 110 static bool _handlesStmt(const Stmt *S) { 111 return llvm::isa<STMT>(S); 112 } 113public: 114 template <typename CHECKER> 115 static void _register(CHECKER *checker, CheckerManager &mgr) { 116 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 117 _checkStmt<CHECKER>), 118 _handlesStmt); 119 } 120}; 121 122class PreObjCMessage { 123 template <typename CHECKER> 124 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 125 CheckerContext &C) { 126 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 127 } 128 129public: 130 template <typename CHECKER> 131 static void _register(CHECKER *checker, CheckerManager &mgr) { 132 mgr._registerForPreObjCMessage( 133 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 134 } 135}; 136 137class PostObjCMessage { 138 template <typename CHECKER> 139 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 140 CheckerContext &C) { 141 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 142 } 143 144public: 145 template <typename CHECKER> 146 static void _register(CHECKER *checker, CheckerManager &mgr) { 147 mgr._registerForPostObjCMessage( 148 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 149 } 150}; 151 152class Location { 153 template <typename CHECKER> 154 static void _checkLocation(void *checker, const SVal &location, bool isLoad, 155 CheckerContext &C) { 156 ((const CHECKER *)checker)->checkLocation(location, isLoad, C); 157 } 158 159public: 160 template <typename CHECKER> 161 static void _register(CHECKER *checker, CheckerManager &mgr) { 162 mgr._registerForLocation( 163 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 164 } 165}; 166 167class Bind { 168 template <typename CHECKER> 169 static void _checkBind(void *checker, const SVal &location, const SVal &val, 170 CheckerContext &C) { 171 ((const CHECKER *)checker)->checkBind(location, val, C); 172 } 173 174public: 175 template <typename CHECKER> 176 static void _register(CHECKER *checker, CheckerManager &mgr) { 177 mgr._registerForBind( 178 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 179 } 180}; 181 182class EndAnalysis { 183 template <typename CHECKER> 184 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 185 BugReporter &BR, ExprEngine &Eng) { 186 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 187 } 188 189public: 190 template <typename CHECKER> 191 static void _register(CHECKER *checker, CheckerManager &mgr) { 192 mgr._registerForEndAnalysis( 193 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 194 } 195}; 196 197class EndPath { 198 template <typename CHECKER> 199 static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, 200 ExprEngine &Eng) { 201 ((const CHECKER *)checker)->checkEndPath(B, Eng); 202 } 203 204public: 205 template <typename CHECKER> 206 static void _register(CHECKER *checker, CheckerManager &mgr) { 207 mgr._registerForEndPath( 208 CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); 209 } 210}; 211 212class BranchCondition { 213 template <typename CHECKER> 214 static void _checkBranchCondition(void *checker, const Stmt *condition, 215 BranchNodeBuilder &B, ExprEngine &Eng) { 216 ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); 217 } 218 219public: 220 template <typename CHECKER> 221 static void _register(CHECKER *checker, CheckerManager &mgr) { 222 mgr._registerForBranchCondition( 223 CheckerManager::CheckBranchConditionFunc(checker, 224 _checkBranchCondition<CHECKER>)); 225 } 226}; 227 228class LiveSymbols { 229 template <typename CHECKER> 230 static void _checkLiveSymbols(void *checker, const GRState *state, 231 SymbolReaper &SR) { 232 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 233 } 234 235public: 236 template <typename CHECKER> 237 static void _register(CHECKER *checker, CheckerManager &mgr) { 238 mgr._registerForLiveSymbols( 239 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 240 } 241}; 242 243class DeadSymbols { 244 template <typename CHECKER> 245 static void _checkDeadSymbols(void *checker, 246 SymbolReaper &SR, CheckerContext &C) { 247 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 248 } 249 250public: 251 template <typename CHECKER> 252 static void _register(CHECKER *checker, CheckerManager &mgr) { 253 mgr._registerForDeadSymbols( 254 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 255 } 256}; 257 258class RegionChanges { 259 template <typename CHECKER> 260 static const GRState *_checkRegionChanges(void *checker, const GRState *state, 261 const StoreManager::InvalidatedSymbols *invalidated, 262 const MemRegion * const *Begin, 263 const MemRegion * const *End) { 264 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 265 Begin, End); 266 } 267 template <typename CHECKER> 268 static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) { 269 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 270 } 271 272public: 273 template <typename CHECKER> 274 static void _register(CHECKER *checker, CheckerManager &mgr) { 275 mgr._registerForRegionChanges( 276 CheckerManager::CheckRegionChangesFunc(checker, 277 _checkRegionChanges<CHECKER>), 278 CheckerManager::WantsRegionChangeUpdateFunc(checker, 279 _wantsRegionChangeUpdate<CHECKER>)); 280 } 281}; 282 283template <typename EVENT> 284class Event { 285 template <typename CHECKER> 286 static void _checkEvent(void *checker, const void *event) { 287 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 288 } 289public: 290 template <typename CHECKER> 291 static void _register(CHECKER *checker, CheckerManager &mgr) { 292 mgr._registerListenerForEvent<EVENT>( 293 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 294 } 295}; 296 297} // end check namespace 298 299namespace eval { 300 301class Assume { 302 template <typename CHECKER> 303 static const GRState *_evalAssume(void *checker, const GRState *state, 304 const SVal &cond, bool assumption) { 305 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 306 } 307 308public: 309 template <typename CHECKER> 310 static void _register(CHECKER *checker, CheckerManager &mgr) { 311 mgr._registerForEvalAssume( 312 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 313 } 314}; 315 316class Call { 317 template <typename CHECKER> 318 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 319 return ((const CHECKER *)checker)->evalCall(CE, C); 320 } 321 322public: 323 template <typename CHECKER> 324 static void _register(CHECKER *checker, CheckerManager &mgr) { 325 mgr._registerForEvalCall( 326 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 327 } 328}; 329 330} // end eval namespace 331 332template <typename CHECK1, typename CHECK2=check::_VoidCheck, 333 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 334 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 335 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 336 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 337 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck> 338class Checker; 339 340template <> 341class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 342 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 343 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 344 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> { 345public: 346 static void _register(void *checker, CheckerManager &mgr) { } 347}; 348 349template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 350 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 351 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12> 352class Checker 353 : public CHECK1, 354 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 355 CHECK9, CHECK10, CHECK11, CHECK12> { 356public: 357 template <typename CHECKER> 358 static void _register(CHECKER *checker, CheckerManager &mgr) { 359 CHECK1::_register(checker, mgr); 360 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9, 361 CHECK10, CHECK11,CHECK12>::_register(checker, mgr); 362 } 363}; 364 365template <typename EVENT> 366class EventDispatcher { 367 CheckerManager *Mgr; 368public: 369 EventDispatcher() : Mgr(0) { } 370 371 template <typename CHECKER> 372 static void _register(CHECKER *checker, CheckerManager &mgr) { 373 mgr._registerDispatcherForEvent<EVENT>(); 374 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 375 } 376 377 void dispatchEvent(const EVENT &event) const { 378 Mgr->_dispatchEvent(event); 379 } 380}; 381 382/// \brief We dereferenced a location that may be null. 383struct ImplicitNullDerefEvent { 384 SVal Location; 385 bool IsLoad; 386 ExplodedNode *SinkNode; 387 BugReporter *BR; 388}; 389 390} // end ento namespace 391 392} // end clang namespace 393 394#endif 395