1//== Checker.h - Registration mechanism for checkers -------------*- 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// This file defines Checker, used to create and register checkers. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_SA_CORE_CHECKER 15#define LLVM_CLANG_SA_CORE_CHECKER 16 17#include "clang/Analysis/ProgramPoint.h" 18#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 20#include "llvm/Support/Casting.h" 21 22namespace clang { 23namespace ento { 24 class BugReporter; 25 26namespace check { 27 28struct _VoidCheck { 29 static void _register(void *checker, CheckerManager &mgr) { } 30}; 31 32template <typename DECL> 33class ASTDecl { 34 template <typename CHECKER> 35 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 36 BugReporter &BR) { 37 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); 38 } 39 40 static bool _handlesDecl(const Decl *D) { 41 return isa<DECL>(D); 42 } 43public: 44 template <typename CHECKER> 45 static void _register(CHECKER *checker, CheckerManager &mgr) { 46 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 47 _checkDecl<CHECKER>), 48 _handlesDecl); 49 } 50}; 51 52class ASTCodeBody { 53 template <typename CHECKER> 54 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 55 BugReporter &BR) { 56 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 57 } 58 59public: 60 template <typename CHECKER> 61 static void _register(CHECKER *checker, CheckerManager &mgr) { 62 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 63 _checkBody<CHECKER>)); 64 } 65}; 66 67class EndOfTranslationUnit { 68 template <typename CHECKER> 69 static void _checkEndOfTranslationUnit(void *checker, 70 const TranslationUnitDecl *TU, 71 AnalysisManager& mgr, 72 BugReporter &BR) { 73 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 74 } 75 76public: 77 template <typename CHECKER> 78 static void _register(CHECKER *checker, CheckerManager &mgr){ 79 mgr._registerForEndOfTranslationUnit( 80 CheckerManager::CheckEndOfTranslationUnit(checker, 81 _checkEndOfTranslationUnit<CHECKER>)); 82 } 83}; 84 85template <typename STMT> 86class PreStmt { 87 template <typename CHECKER> 88 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 89 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); 90 } 91 92 static bool _handlesStmt(const Stmt *S) { 93 return isa<STMT>(S); 94 } 95public: 96 template <typename CHECKER> 97 static void _register(CHECKER *checker, CheckerManager &mgr) { 98 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 99 _checkStmt<CHECKER>), 100 _handlesStmt); 101 } 102}; 103 104template <typename STMT> 105class PostStmt { 106 template <typename CHECKER> 107 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 108 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); 109 } 110 111 static bool _handlesStmt(const Stmt *S) { 112 return isa<STMT>(S); 113 } 114public: 115 template <typename CHECKER> 116 static void _register(CHECKER *checker, CheckerManager &mgr) { 117 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 118 _checkStmt<CHECKER>), 119 _handlesStmt); 120 } 121}; 122 123class PreObjCMessage { 124 template <typename CHECKER> 125 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 126 CheckerContext &C) { 127 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 128 } 129 130public: 131 template <typename CHECKER> 132 static void _register(CHECKER *checker, CheckerManager &mgr) { 133 mgr._registerForPreObjCMessage( 134 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 135 } 136}; 137 138class PostObjCMessage { 139 template <typename CHECKER> 140 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 141 CheckerContext &C) { 142 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 143 } 144 145public: 146 template <typename CHECKER> 147 static void _register(CHECKER *checker, CheckerManager &mgr) { 148 mgr._registerForPostObjCMessage( 149 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 150 } 151}; 152 153class PreCall { 154 template <typename CHECKER> 155 static void _checkCall(void *checker, const CallEvent &msg, 156 CheckerContext &C) { 157 ((const CHECKER *)checker)->checkPreCall(msg, C); 158 } 159 160public: 161 template <typename CHECKER> 162 static void _register(CHECKER *checker, CheckerManager &mgr) { 163 mgr._registerForPreCall( 164 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 165 } 166}; 167 168class PostCall { 169 template <typename CHECKER> 170 static void _checkCall(void *checker, const CallEvent &msg, 171 CheckerContext &C) { 172 ((const CHECKER *)checker)->checkPostCall(msg, C); 173 } 174 175public: 176 template <typename CHECKER> 177 static void _register(CHECKER *checker, CheckerManager &mgr) { 178 mgr._registerForPostCall( 179 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 180 } 181}; 182 183class Location { 184 template <typename CHECKER> 185 static void _checkLocation(void *checker, 186 const SVal &location, bool isLoad, const Stmt *S, 187 CheckerContext &C) { 188 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 189 } 190 191public: 192 template <typename CHECKER> 193 static void _register(CHECKER *checker, CheckerManager &mgr) { 194 mgr._registerForLocation( 195 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 196 } 197}; 198 199class Bind { 200 template <typename CHECKER> 201 static void _checkBind(void *checker, 202 const SVal &location, const SVal &val, const Stmt *S, 203 CheckerContext &C) { 204 ((const CHECKER *)checker)->checkBind(location, val, S, C); 205 } 206 207public: 208 template <typename CHECKER> 209 static void _register(CHECKER *checker, CheckerManager &mgr) { 210 mgr._registerForBind( 211 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 212 } 213}; 214 215class EndAnalysis { 216 template <typename CHECKER> 217 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 218 BugReporter &BR, ExprEngine &Eng) { 219 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 220 } 221 222public: 223 template <typename CHECKER> 224 static void _register(CHECKER *checker, CheckerManager &mgr) { 225 mgr._registerForEndAnalysis( 226 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 227 } 228}; 229 230class EndFunction { 231 template <typename CHECKER> 232 static void _checkEndFunction(void *checker, 233 CheckerContext &C) { 234 ((const CHECKER *)checker)->checkEndFunction(C); 235 } 236 237public: 238 template <typename CHECKER> 239 static void _register(CHECKER *checker, CheckerManager &mgr) { 240 mgr._registerForEndFunction( 241 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 242 } 243}; 244 245class BranchCondition { 246 template <typename CHECKER> 247 static void _checkBranchCondition(void *checker, const Stmt *Condition, 248 CheckerContext & C) { 249 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 250 } 251 252public: 253 template <typename CHECKER> 254 static void _register(CHECKER *checker, CheckerManager &mgr) { 255 mgr._registerForBranchCondition( 256 CheckerManager::CheckBranchConditionFunc(checker, 257 _checkBranchCondition<CHECKER>)); 258 } 259}; 260 261class LiveSymbols { 262 template <typename CHECKER> 263 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 264 SymbolReaper &SR) { 265 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 266 } 267 268public: 269 template <typename CHECKER> 270 static void _register(CHECKER *checker, CheckerManager &mgr) { 271 mgr._registerForLiveSymbols( 272 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 273 } 274}; 275 276class DeadSymbols { 277 template <typename CHECKER> 278 static void _checkDeadSymbols(void *checker, 279 SymbolReaper &SR, CheckerContext &C) { 280 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 281 } 282 283public: 284 template <typename CHECKER> 285 static void _register(CHECKER *checker, CheckerManager &mgr) { 286 mgr._registerForDeadSymbols( 287 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 288 } 289}; 290 291class RegionChanges { 292 template <typename CHECKER> 293 static ProgramStateRef 294 _checkRegionChanges(void *checker, 295 ProgramStateRef state, 296 const InvalidatedSymbols *invalidated, 297 ArrayRef<const MemRegion *> Explicits, 298 ArrayRef<const MemRegion *> Regions, 299 const CallEvent *Call) { 300 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 301 Explicits, Regions, Call); 302 } 303 template <typename CHECKER> 304 static bool _wantsRegionChangeUpdate(void *checker, 305 ProgramStateRef state) { 306 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 307 } 308 309public: 310 template <typename CHECKER> 311 static void _register(CHECKER *checker, CheckerManager &mgr) { 312 mgr._registerForRegionChanges( 313 CheckerManager::CheckRegionChangesFunc(checker, 314 _checkRegionChanges<CHECKER>), 315 CheckerManager::WantsRegionChangeUpdateFunc(checker, 316 _wantsRegionChangeUpdate<CHECKER>)); 317 } 318}; 319 320class PointerEscape { 321 template <typename CHECKER> 322 static ProgramStateRef 323 _checkPointerEscape(void *checker, 324 ProgramStateRef State, 325 const InvalidatedSymbols &Escaped, 326 const CallEvent *Call, 327 PointerEscapeKind Kind) { 328 return ((const CHECKER *)checker)->checkPointerEscape(State, 329 Escaped, 330 Call, 331 Kind); 332 } 333 334public: 335 template <typename CHECKER> 336 static void _register(CHECKER *checker, CheckerManager &mgr) { 337 mgr._registerForPointerEscape( 338 CheckerManager::CheckPointerEscapeFunc(checker, 339 _checkPointerEscape<CHECKER>)); 340 } 341}; 342 343template <typename EVENT> 344class Event { 345 template <typename CHECKER> 346 static void _checkEvent(void *checker, const void *event) { 347 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 348 } 349public: 350 template <typename CHECKER> 351 static void _register(CHECKER *checker, CheckerManager &mgr) { 352 mgr._registerListenerForEvent<EVENT>( 353 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 354 } 355}; 356 357} // end check namespace 358 359namespace eval { 360 361class Assume { 362 template <typename CHECKER> 363 static ProgramStateRef _evalAssume(void *checker, 364 ProgramStateRef state, 365 const SVal &cond, 366 bool assumption) { 367 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 368 } 369 370public: 371 template <typename CHECKER> 372 static void _register(CHECKER *checker, CheckerManager &mgr) { 373 mgr._registerForEvalAssume( 374 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 375 } 376}; 377 378class Call { 379 template <typename CHECKER> 380 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 381 return ((const CHECKER *)checker)->evalCall(CE, C); 382 } 383 384public: 385 template <typename CHECKER> 386 static void _register(CHECKER *checker, CheckerManager &mgr) { 387 mgr._registerForEvalCall( 388 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 389 } 390}; 391 392} // end eval namespace 393 394class CheckerBase : public ProgramPointTag { 395public: 396 StringRef getTagDescription() const; 397 398 /// See CheckerManager::runCheckersForPrintState. 399 virtual void printState(raw_ostream &Out, ProgramStateRef State, 400 const char *NL, const char *Sep) const { } 401}; 402 403template <typename CHECK1, typename CHECK2=check::_VoidCheck, 404 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 405 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 406 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 407 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 408 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 409 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 410 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, 411 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck, 412 typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck, 413 typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck, 414 typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck> 415class Checker; 416 417template <> 418class Checker<check::_VoidCheck> 419 : public CheckerBase 420{ 421 virtual void anchor(); 422public: 423 static void _register(void *checker, CheckerManager &mgr) { } 424}; 425 426template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 427 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 428 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 429 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 430 typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20, 431 typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24> 432class Checker 433 : public CHECK1, 434 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 435 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 436 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 437 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> { 438public: 439 template <typename CHECKER> 440 static void _register(CHECKER *checker, CheckerManager &mgr) { 441 CHECK1::_register(checker, mgr); 442 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 443 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 444 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 445 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr); 446 } 447}; 448 449template <typename EVENT> 450class EventDispatcher { 451 CheckerManager *Mgr; 452public: 453 EventDispatcher() : Mgr(0) { } 454 455 template <typename CHECKER> 456 static void _register(CHECKER *checker, CheckerManager &mgr) { 457 mgr._registerDispatcherForEvent<EVENT>(); 458 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 459 } 460 461 void dispatchEvent(const EVENT &event) const { 462 Mgr->_dispatchEvent(event); 463 } 464}; 465 466/// \brief We dereferenced a location that may be null. 467struct ImplicitNullDerefEvent { 468 SVal Location; 469 bool IsLoad; 470 ExplodedNode *SinkNode; 471 BugReporter *BR; 472}; 473 474/// \brief A helper class which wraps a boolean value set to false by default. 475struct DefaultBool { 476 bool val; 477 DefaultBool() : val(false) {} 478 operator bool() const { return val; } 479 DefaultBool &operator=(bool b) { val = b; return *this; } 480}; 481 482} // end ento namespace 483 484} // end clang namespace 485 486#endif 487