clang API Documentation

Checker.h
Go to the documentation of this file.
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