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_STATICANALYZER_CORE_CHECKER_H 00015 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 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(cast<DECL>(D), mgr, BR); 00038 } 00039 00040 static bool _handlesDecl(const Decl *D) { 00041 return 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(cast<STMT>(S), C); 00090 } 00091 00092 static bool _handlesStmt(const Stmt *S) { 00093 return 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(cast<STMT>(S), C); 00109 } 00110 00111 static bool _handlesStmt(const Stmt *S) { 00112 return 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 ObjCMethodCall &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 ObjCMethodCall &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 PreCall { 00154 template <typename CHECKER> 00155 static void _checkCall(void *checker, const CallEvent &msg, 00156 CheckerContext &C) { 00157 ((const CHECKER *)checker)->checkPreCall(msg, C); 00158 } 00159 00160 public: 00161 template <typename CHECKER> 00162 static void _register(CHECKER *checker, CheckerManager &mgr) { 00163 mgr._registerForPreCall( 00164 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 00165 } 00166 }; 00167 00168 class PostCall { 00169 template <typename CHECKER> 00170 static void _checkCall(void *checker, const CallEvent &msg, 00171 CheckerContext &C) { 00172 ((const CHECKER *)checker)->checkPostCall(msg, C); 00173 } 00174 00175 public: 00176 template <typename CHECKER> 00177 static void _register(CHECKER *checker, CheckerManager &mgr) { 00178 mgr._registerForPostCall( 00179 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 00180 } 00181 }; 00182 00183 class Location { 00184 template <typename CHECKER> 00185 static void _checkLocation(void *checker, 00186 const SVal &location, bool isLoad, const Stmt *S, 00187 CheckerContext &C) { 00188 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 00189 } 00190 00191 public: 00192 template <typename CHECKER> 00193 static void _register(CHECKER *checker, CheckerManager &mgr) { 00194 mgr._registerForLocation( 00195 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 00196 } 00197 }; 00198 00199 class Bind { 00200 template <typename CHECKER> 00201 static void _checkBind(void *checker, 00202 const SVal &location, const SVal &val, const Stmt *S, 00203 CheckerContext &C) { 00204 ((const CHECKER *)checker)->checkBind(location, val, S, C); 00205 } 00206 00207 public: 00208 template <typename CHECKER> 00209 static void _register(CHECKER *checker, CheckerManager &mgr) { 00210 mgr._registerForBind( 00211 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 00212 } 00213 }; 00214 00215 class EndAnalysis { 00216 template <typename CHECKER> 00217 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 00218 BugReporter &BR, ExprEngine &Eng) { 00219 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 00220 } 00221 00222 public: 00223 template <typename CHECKER> 00224 static void _register(CHECKER *checker, CheckerManager &mgr) { 00225 mgr._registerForEndAnalysis( 00226 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 00227 } 00228 }; 00229 00230 class EndFunction { 00231 template <typename CHECKER> 00232 static void _checkEndFunction(void *checker, 00233 CheckerContext &C) { 00234 ((const CHECKER *)checker)->checkEndFunction(C); 00235 } 00236 00237 public: 00238 template <typename CHECKER> 00239 static void _register(CHECKER *checker, CheckerManager &mgr) { 00240 mgr._registerForEndFunction( 00241 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 00242 } 00243 }; 00244 00245 class BranchCondition { 00246 template <typename CHECKER> 00247 static void _checkBranchCondition(void *checker, const Stmt *Condition, 00248 CheckerContext & C) { 00249 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 00250 } 00251 00252 public: 00253 template <typename CHECKER> 00254 static void _register(CHECKER *checker, CheckerManager &mgr) { 00255 mgr._registerForBranchCondition( 00256 CheckerManager::CheckBranchConditionFunc(checker, 00257 _checkBranchCondition<CHECKER>)); 00258 } 00259 }; 00260 00261 class LiveSymbols { 00262 template <typename CHECKER> 00263 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 00264 SymbolReaper &SR) { 00265 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 00266 } 00267 00268 public: 00269 template <typename CHECKER> 00270 static void _register(CHECKER *checker, CheckerManager &mgr) { 00271 mgr._registerForLiveSymbols( 00272 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 00273 } 00274 }; 00275 00276 class DeadSymbols { 00277 template <typename CHECKER> 00278 static void _checkDeadSymbols(void *checker, 00279 SymbolReaper &SR, CheckerContext &C) { 00280 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 00281 } 00282 00283 public: 00284 template <typename CHECKER> 00285 static void _register(CHECKER *checker, CheckerManager &mgr) { 00286 mgr._registerForDeadSymbols( 00287 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 00288 } 00289 }; 00290 00291 class RegionChanges { 00292 template <typename CHECKER> 00293 static ProgramStateRef 00294 _checkRegionChanges(void *checker, 00295 ProgramStateRef state, 00296 const InvalidatedSymbols *invalidated, 00297 ArrayRef<const MemRegion *> Explicits, 00298 ArrayRef<const MemRegion *> Regions, 00299 const CallEvent *Call) { 00300 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 00301 Explicits, Regions, Call); 00302 } 00303 template <typename CHECKER> 00304 static bool _wantsRegionChangeUpdate(void *checker, 00305 ProgramStateRef state) { 00306 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 00307 } 00308 00309 public: 00310 template <typename CHECKER> 00311 static void _register(CHECKER *checker, CheckerManager &mgr) { 00312 mgr._registerForRegionChanges( 00313 CheckerManager::CheckRegionChangesFunc(checker, 00314 _checkRegionChanges<CHECKER>), 00315 CheckerManager::WantsRegionChangeUpdateFunc(checker, 00316 _wantsRegionChangeUpdate<CHECKER>)); 00317 } 00318 }; 00319 00320 class PointerEscape { 00321 template <typename CHECKER> 00322 static ProgramStateRef 00323 _checkPointerEscape(void *Checker, 00324 ProgramStateRef State, 00325 const InvalidatedSymbols &Escaped, 00326 const CallEvent *Call, 00327 PointerEscapeKind Kind, 00328 RegionAndSymbolInvalidationTraits *ETraits) { 00329 00330 if (!ETraits) 00331 return ((const CHECKER *)Checker)->checkPointerEscape(State, 00332 Escaped, 00333 Call, 00334 Kind); 00335 00336 InvalidatedSymbols RegularEscape; 00337 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 00338 E = Escaped.end(); I != E; ++I) 00339 if (!ETraits->hasTrait(*I, 00340 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 00341 !ETraits->hasTrait(*I, 00342 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 00343 RegularEscape.insert(*I); 00344 00345 if (RegularEscape.empty()) 00346 return State; 00347 00348 return ((const CHECKER *)Checker)->checkPointerEscape(State, 00349 RegularEscape, 00350 Call, 00351 Kind); 00352 } 00353 00354 public: 00355 template <typename CHECKER> 00356 static void _register(CHECKER *checker, CheckerManager &mgr) { 00357 mgr._registerForPointerEscape( 00358 CheckerManager::CheckPointerEscapeFunc(checker, 00359 _checkPointerEscape<CHECKER>)); 00360 } 00361 }; 00362 00363 class ConstPointerEscape { 00364 template <typename CHECKER> 00365 static ProgramStateRef 00366 _checkConstPointerEscape(void *Checker, 00367 ProgramStateRef State, 00368 const InvalidatedSymbols &Escaped, 00369 const CallEvent *Call, 00370 PointerEscapeKind Kind, 00371 RegionAndSymbolInvalidationTraits *ETraits) { 00372 00373 if (!ETraits) 00374 return State; 00375 00376 InvalidatedSymbols ConstEscape; 00377 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 00378 E = Escaped.end(); I != E; ++I) 00379 if (ETraits->hasTrait(*I, 00380 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 00381 !ETraits->hasTrait(*I, 00382 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 00383 ConstEscape.insert(*I); 00384 00385 if (ConstEscape.empty()) 00386 return State; 00387 00388 return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 00389 ConstEscape, 00390 Call, 00391 Kind); 00392 } 00393 00394 public: 00395 template <typename CHECKER> 00396 static void _register(CHECKER *checker, CheckerManager &mgr) { 00397 mgr._registerForPointerEscape( 00398 CheckerManager::CheckPointerEscapeFunc(checker, 00399 _checkConstPointerEscape<CHECKER>)); 00400 } 00401 }; 00402 00403 00404 template <typename EVENT> 00405 class Event { 00406 template <typename CHECKER> 00407 static void _checkEvent(void *checker, const void *event) { 00408 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 00409 } 00410 public: 00411 template <typename CHECKER> 00412 static void _register(CHECKER *checker, CheckerManager &mgr) { 00413 mgr._registerListenerForEvent<EVENT>( 00414 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 00415 } 00416 }; 00417 00418 } // end check namespace 00419 00420 namespace eval { 00421 00422 class Assume { 00423 template <typename CHECKER> 00424 static ProgramStateRef _evalAssume(void *checker, 00425 ProgramStateRef state, 00426 const SVal &cond, 00427 bool assumption) { 00428 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 00429 } 00430 00431 public: 00432 template <typename CHECKER> 00433 static void _register(CHECKER *checker, CheckerManager &mgr) { 00434 mgr._registerForEvalAssume( 00435 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 00436 } 00437 }; 00438 00439 class Call { 00440 template <typename CHECKER> 00441 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 00442 return ((const CHECKER *)checker)->evalCall(CE, C); 00443 } 00444 00445 public: 00446 template <typename CHECKER> 00447 static void _register(CHECKER *checker, CheckerManager &mgr) { 00448 mgr._registerForEvalCall( 00449 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 00450 } 00451 }; 00452 00453 } // end eval namespace 00454 00455 class CheckerBase : public ProgramPointTag { 00456 CheckName Name; 00457 friend class ::clang::ento::CheckerManager; 00458 00459 public: 00460 StringRef getTagDescription() const override; 00461 CheckName getCheckName() const; 00462 00463 /// See CheckerManager::runCheckersForPrintState. 00464 virtual void printState(raw_ostream &Out, ProgramStateRef State, 00465 const char *NL, const char *Sep) const { } 00466 }; 00467 00468 /// Dump checker name to stream. 00469 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 00470 00471 /// Tag that can use a checker name as a message provider 00472 /// (see SimpleProgramPointTag). 00473 class CheckerProgramPointTag : public SimpleProgramPointTag { 00474 public: 00475 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 00476 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 00477 }; 00478 00479 template <typename CHECK1, typename CHECK2=check::_VoidCheck, 00480 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 00481 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 00482 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 00483 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 00484 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 00485 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 00486 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, 00487 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck, 00488 typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck, 00489 typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck, 00490 typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck> 00491 class Checker; 00492 00493 template <> 00494 class Checker<check::_VoidCheck> 00495 : public CheckerBase 00496 { 00497 virtual void anchor(); 00498 public: 00499 static void _register(void *checker, CheckerManager &mgr) { } 00500 }; 00501 00502 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 00503 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 00504 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 00505 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 00506 typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20, 00507 typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24> 00508 class Checker 00509 : public CHECK1, 00510 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 00511 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 00512 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 00513 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> { 00514 public: 00515 template <typename CHECKER> 00516 static void _register(CHECKER *checker, CheckerManager &mgr) { 00517 CHECK1::_register(checker, mgr); 00518 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 00519 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 00520 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 00521 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr); 00522 } 00523 }; 00524 00525 template <typename EVENT> 00526 class EventDispatcher { 00527 CheckerManager *Mgr; 00528 public: 00529 EventDispatcher() : Mgr(nullptr) { } 00530 00531 template <typename CHECKER> 00532 static void _register(CHECKER *checker, CheckerManager &mgr) { 00533 mgr._registerDispatcherForEvent<EVENT>(); 00534 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 00535 } 00536 00537 void dispatchEvent(const EVENT &event) const { 00538 Mgr->_dispatchEvent(event); 00539 } 00540 }; 00541 00542 /// \brief We dereferenced a location that may be null. 00543 struct ImplicitNullDerefEvent { 00544 SVal Location; 00545 bool IsLoad; 00546 ExplodedNode *SinkNode; 00547 BugReporter *BR; 00548 }; 00549 00550 /// \brief A helper class which wraps a boolean value set to false by default. 00551 /// 00552 /// This class should behave exactly like 'bool' except that it doesn't need to 00553 /// be explicitly initialized. 00554 struct DefaultBool { 00555 bool val; 00556 DefaultBool() : val(false) {} 00557 /*implicit*/ operator bool&() { return val; } 00558 /*implicit*/ operator const bool&() const { return val; } 00559 DefaultBool &operator=(bool b) { val = b; return *this; } 00560 }; 00561 00562 } // end ento namespace 00563 00564 } // end clang namespace 00565 00566 #endif