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_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