clang API Documentation

CheckerManager.cpp
Go to the documentation of this file.
00001 //===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
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 // Defines the Static Analyzer Checker Manager.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
00015 #include "clang/StaticAnalyzer/Core/Checker.h"
00016 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
00017 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
00018 #include "clang/Analysis/ProgramPoint.h"
00019 #include "clang/AST/DeclBase.h"
00020 
00021 using namespace clang;
00022 using namespace ento;
00023 
00024 bool CheckerManager::hasPathSensitiveCheckers() const {
00025   return !StmtCheckers.empty()              ||
00026          !PreObjCMessageCheckers.empty()    ||
00027          !PostObjCMessageCheckers.empty()   ||
00028          !LocationCheckers.empty()          ||
00029          !BindCheckers.empty()              ||
00030          !EndAnalysisCheckers.empty()       ||
00031          !EndPathCheckers.empty()           ||
00032          !BranchConditionCheckers.empty()   ||
00033          !LiveSymbolsCheckers.empty()       ||
00034          !DeadSymbolsCheckers.empty()       ||
00035          !RegionChangesCheckers.empty()     ||
00036          !EvalAssumeCheckers.empty()        ||
00037          !EvalCallCheckers.empty()          ||
00038          !InlineCallCheckers.empty();
00039 }
00040 
00041 void CheckerManager::finishedCheckerRegistration() {
00042 #ifndef NDEBUG
00043   // Make sure that for every event that has listeners, there is at least
00044   // one dispatcher registered for it.
00045   for (llvm::DenseMap<EventTag, EventInfo>::iterator
00046          I = Events.begin(), E = Events.end(); I != E; ++I)
00047     assert(I->second.HasDispatcher && "No dispatcher registered for an event");
00048 #endif
00049 }
00050 
00051 //===----------------------------------------------------------------------===//
00052 // Functions for running checkers for AST traversing..
00053 //===----------------------------------------------------------------------===//
00054 
00055 void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
00056                                           BugReporter &BR) {
00057   assert(D);
00058 
00059   unsigned DeclKind = D->getKind();
00060   CachedDeclCheckers *checkers = 0;
00061   CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
00062   if (CCI != CachedDeclCheckersMap.end()) {
00063     checkers = &(CCI->second);
00064   } else {
00065     // Find the checkers that should run for this Decl and cache them.
00066     checkers = &CachedDeclCheckersMap[DeclKind];
00067     for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
00068       DeclCheckerInfo &info = DeclCheckers[i];
00069       if (info.IsForDeclFn(D))
00070         checkers->push_back(info.CheckFn);
00071     }
00072   }
00073 
00074   assert(checkers);
00075   for (CachedDeclCheckers::iterator
00076          I = checkers->begin(), E = checkers->end(); I != E; ++I)
00077     (*I)(D, mgr, BR);
00078 }
00079 
00080 void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
00081                                           BugReporter &BR) {
00082   assert(D && D->hasBody());
00083 
00084   for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
00085     BodyCheckers[i](D, mgr, BR);
00086 }
00087 
00088 //===----------------------------------------------------------------------===//
00089 // Functions for running checkers for path-sensitive checking.
00090 //===----------------------------------------------------------------------===//
00091 
00092 template <typename CHECK_CTX>
00093 static void expandGraphWithCheckers(CHECK_CTX checkCtx,
00094                                     ExplodedNodeSet &Dst,
00095                                     const ExplodedNodeSet &Src) {
00096   const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
00097   if (Src.empty())
00098     return;
00099 
00100   typename CHECK_CTX::CheckersTy::const_iterator
00101       I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
00102   if (I == E) {
00103     Dst.insert(Src);
00104     return;
00105   }
00106 
00107   ExplodedNodeSet Tmp1, Tmp2;
00108   const ExplodedNodeSet *PrevSet = &Src;
00109 
00110   for (; I != E; ++I) {
00111     ExplodedNodeSet *CurrSet = 0;
00112     if (I+1 == E)
00113       CurrSet = &Dst;
00114     else {
00115       CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
00116       CurrSet->clear();
00117     }
00118 
00119     NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
00120     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
00121          NI != NE; ++NI) {
00122       checkCtx.runChecker(*I, B, *NI);
00123     }
00124 
00125     // If all the produced transitions are sinks, stop.
00126     if (CurrSet->empty())
00127       return;
00128 
00129     // Update which NodeSet is the current one.
00130     PrevSet = CurrSet;
00131   }
00132 }
00133 
00134 namespace {
00135   struct CheckStmtContext {
00136     typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
00137     bool IsPreVisit;
00138     const CheckersTy &Checkers;
00139     const Stmt *S;
00140     ExprEngine &Eng;
00141     bool wasInlined;
00142 
00143     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00144     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00145 
00146     CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
00147                      const Stmt *s, ExprEngine &eng, bool wasInlined = false)
00148       : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
00149         wasInlined(wasInlined) {}
00150 
00151     void runChecker(CheckerManager::CheckStmtFunc checkFn,
00152                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00153       // FIXME: Remove respondsToCallback from CheckerContext;
00154       ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
00155                                            ProgramPoint::PostStmtKind;
00156       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
00157                                 Pred->getLocationContext(), checkFn.Checker);
00158       CheckerContext C(Bldr, Eng, Pred, L, wasInlined);
00159       checkFn(S, C);
00160     }
00161   };
00162 }
00163 
00164 /// \brief Run checkers for visiting Stmts.
00165 void CheckerManager::runCheckersForStmt(bool isPreVisit,
00166                                         ExplodedNodeSet &Dst,
00167                                         const ExplodedNodeSet &Src,
00168                                         const Stmt *S,
00169                                         ExprEngine &Eng,
00170                                         bool wasInlined) {
00171   CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
00172                      S, Eng, wasInlined);
00173   expandGraphWithCheckers(C, Dst, Src);
00174 }
00175 
00176 namespace {
00177   struct CheckObjCMessageContext {
00178     typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
00179     bool IsPreVisit;
00180     const CheckersTy &Checkers;
00181     const ObjCMessage &Msg;
00182     ExprEngine &Eng;
00183 
00184     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00185     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00186 
00187     CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
00188                             const ObjCMessage &msg, ExprEngine &eng)
00189       : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
00190 
00191     void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
00192                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00193       ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
00194                                            ProgramPoint::PostStmtKind;
00195       const ProgramPoint &L =
00196         ProgramPoint::getProgramPoint(Msg.getMessageExpr(),
00197                                       K, Pred->getLocationContext(),
00198                                       checkFn.Checker);
00199       CheckerContext C(Bldr, Eng, Pred, L);
00200 
00201       checkFn(Msg, C);
00202     }
00203   };
00204 }
00205 
00206 /// \brief Run checkers for visiting obj-c messages.
00207 void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
00208                                                ExplodedNodeSet &Dst,
00209                                                const ExplodedNodeSet &Src,
00210                                                const ObjCMessage &msg,
00211                                                ExprEngine &Eng) {
00212   CheckObjCMessageContext C(isPreVisit,
00213                             isPreVisit ? PreObjCMessageCheckers
00214                                        : PostObjCMessageCheckers,
00215                             msg, Eng);
00216   expandGraphWithCheckers(C, Dst, Src);
00217 }
00218 
00219 namespace {
00220   struct CheckLocationContext {
00221     typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
00222     const CheckersTy &Checkers;
00223     SVal Loc;
00224     bool IsLoad;
00225     const Stmt *NodeEx; /* Will become a CFGStmt */
00226     const Stmt *BoundEx;
00227     ExprEngine &Eng;
00228 
00229     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00230     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00231 
00232     CheckLocationContext(const CheckersTy &checkers,
00233                          SVal loc, bool isLoad, const Stmt *NodeEx,
00234                          const Stmt *BoundEx,
00235                          ExprEngine &eng)
00236       : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
00237         BoundEx(BoundEx), Eng(eng) {}
00238 
00239     void runChecker(CheckerManager::CheckLocationFunc checkFn,
00240                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00241       ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
00242                                        ProgramPoint::PreStoreKind;
00243       const ProgramPoint &L =
00244         ProgramPoint::getProgramPoint(NodeEx, K,
00245                                       Pred->getLocationContext(),
00246                                       checkFn.Checker);
00247       CheckerContext C(Bldr, Eng, Pred, L);
00248       checkFn(Loc, IsLoad, BoundEx, C);
00249     }
00250   };
00251 }
00252 
00253 /// \brief Run checkers for load/store of a location.
00254 
00255 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
00256                                             const ExplodedNodeSet &Src,
00257                                             SVal location, bool isLoad,
00258                                             const Stmt *NodeEx,
00259                                             const Stmt *BoundEx,
00260                                             ExprEngine &Eng) {
00261   CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
00262                          BoundEx, Eng);
00263   expandGraphWithCheckers(C, Dst, Src);
00264 }
00265 
00266 namespace {
00267   struct CheckBindContext {
00268     typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
00269     const CheckersTy &Checkers;
00270     SVal Loc;
00271     SVal Val;
00272     const Stmt *S;
00273     ExprEngine &Eng;
00274     ProgramPoint::Kind PointKind;
00275 
00276     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00277     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00278 
00279     CheckBindContext(const CheckersTy &checkers,
00280                      SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
00281                      ProgramPoint::Kind PK)
00282       : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {}
00283 
00284     void runChecker(CheckerManager::CheckBindFunc checkFn,
00285                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00286       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind,
00287                                 Pred->getLocationContext(), checkFn.Checker);
00288       CheckerContext C(Bldr, Eng, Pred, L);
00289 
00290       checkFn(Loc, Val, S, C);
00291     }
00292   };
00293 }
00294 
00295 /// \brief Run checkers for binding of a value to a location.
00296 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
00297                                         const ExplodedNodeSet &Src,
00298                                         SVal location, SVal val,
00299                                         const Stmt *S, ExprEngine &Eng,
00300                                         ProgramPoint::Kind PointKind) {
00301   CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind);
00302   expandGraphWithCheckers(C, Dst, Src);
00303 }
00304 
00305 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
00306                                                BugReporter &BR,
00307                                                ExprEngine &Eng) {
00308   for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
00309     EndAnalysisCheckers[i](G, BR, Eng);
00310 }
00311 
00312 /// \brief Run checkers for end of path.
00313 // Note, We do not chain the checker output (like in expandGraphWithCheckers)
00314 // for this callback since end of path nodes are expected to be final.
00315 void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC,
00316                                            ExplodedNodeSet &Dst,
00317                                            ExprEngine &Eng) {
00318   ExplodedNode *Pred = BC.Pred;
00319   
00320   // We define the builder outside of the loop bacause if at least one checkers
00321   // creates a sucsessor for Pred, we do not need to generate an 
00322   // autotransition for it.
00323   NodeBuilder Bldr(Pred, Dst, BC);
00324   for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
00325     CheckEndPathFunc checkFn = EndPathCheckers[i];
00326 
00327     const ProgramPoint &L = BlockEntrance(BC.Block,
00328                                           Pred->getLocationContext(),
00329                                           checkFn.Checker);
00330     CheckerContext C(Bldr, Eng, Pred, L);
00331     checkFn(C);
00332   }
00333 }
00334 
00335 namespace {
00336   struct CheckBranchConditionContext {
00337     typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
00338     const CheckersTy &Checkers;
00339     const Stmt *Condition;
00340     ExprEngine &Eng;
00341 
00342     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00343     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00344 
00345     CheckBranchConditionContext(const CheckersTy &checkers,
00346                                 const Stmt *Cond, ExprEngine &eng)
00347       : Checkers(checkers), Condition(Cond), Eng(eng) {}
00348 
00349     void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
00350                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00351       ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
00352                                      checkFn.Checker);
00353       CheckerContext C(Bldr, Eng, Pred, L);
00354       checkFn(Condition, C);
00355     }
00356   };
00357 }
00358 
00359 /// \brief Run checkers for branch condition.
00360 void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
00361                                                    ExplodedNodeSet &Dst,
00362                                                    ExplodedNode *Pred,
00363                                                    ExprEngine &Eng) {
00364   ExplodedNodeSet Src;
00365   Src.insert(Pred);
00366   CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
00367   expandGraphWithCheckers(C, Dst, Src);
00368 }
00369 
00370 /// \brief Run checkers for live symbols.
00371 void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
00372                                                SymbolReaper &SymReaper) {
00373   for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
00374     LiveSymbolsCheckers[i](state, SymReaper);
00375 }
00376 
00377 namespace {
00378   struct CheckDeadSymbolsContext {
00379     typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
00380     const CheckersTy &Checkers;
00381     SymbolReaper &SR;
00382     const Stmt *S;
00383     ExprEngine &Eng;
00384     ProgramPoint::Kind ProgarmPointKind;
00385 
00386     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
00387     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
00388 
00389     CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
00390                             const Stmt *s, ExprEngine &eng,
00391                             ProgramPoint::Kind K)
00392       : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
00393 
00394     void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
00395                     NodeBuilder &Bldr, ExplodedNode *Pred) {
00396       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
00397                                 Pred->getLocationContext(), checkFn.Checker);
00398       CheckerContext C(Bldr, Eng, Pred, L);
00399 
00400       // Note, do not pass the statement to the checkers without letting them
00401       // differentiate if we ran remove dead bindings before or after the
00402       // statement.
00403       checkFn(SR, C);
00404     }
00405   };
00406 }
00407 
00408 /// \brief Run checkers for dead symbols.
00409 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
00410                                                const ExplodedNodeSet &Src,
00411                                                SymbolReaper &SymReaper,
00412                                                const Stmt *S,
00413                                                ExprEngine &Eng,
00414                                                ProgramPoint::Kind K) {
00415   CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
00416   expandGraphWithCheckers(C, Dst, Src);
00417 }
00418 
00419 /// \brief True if at least one checker wants to check region changes.
00420 bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
00421   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
00422     if (RegionChangesCheckers[i].WantUpdateFn(state))
00423       return true;
00424 
00425   return false;
00426 }
00427 
00428 /// \brief Run checkers for region changes.
00429 ProgramStateRef 
00430 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
00431                             const StoreManager::InvalidatedSymbols *invalidated,
00432                                     ArrayRef<const MemRegion *> ExplicitRegions,
00433                                           ArrayRef<const MemRegion *> Regions,
00434                                           const CallOrObjCMessage *Call) {
00435   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
00436     // If any checker declares the state infeasible (or if it starts that way),
00437     // bail out.
00438     if (!state)
00439       return NULL;
00440     state = RegionChangesCheckers[i].CheckFn(state, invalidated, 
00441                                              ExplicitRegions, Regions, Call);
00442   }
00443   return state;
00444 }
00445 
00446 /// \brief Run checkers for handling assumptions on symbolic values.
00447 ProgramStateRef 
00448 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
00449                                          SVal Cond, bool Assumption) {
00450   for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
00451     // If any checker declares the state infeasible (or if it starts that way),
00452     // bail out.
00453     if (!state)
00454       return NULL;
00455     state = EvalAssumeCheckers[i](state, Cond, Assumption);
00456   }
00457   return state;
00458 }
00459 
00460 /// \brief Run checkers for evaluating a call.
00461 /// Only one checker will evaluate the call.
00462 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
00463                                             const ExplodedNodeSet &Src,
00464                                             const CallExpr *CE,
00465                                             ExprEngine &Eng,
00466                                             GraphExpander *defaultEval) {
00467   if (EvalCallCheckers.empty()   &&
00468       InlineCallCheckers.empty() &&
00469       defaultEval == 0) {
00470     Dst.insert(Src);
00471     return;
00472   }
00473 
00474   for (ExplodedNodeSet::iterator
00475          NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
00476 
00477     ExplodedNode *Pred = *NI;
00478     bool anyEvaluated = false;
00479 
00480     // First, check if any of the InlineCall callbacks can evaluate the call.
00481     assert(InlineCallCheckers.size() <= 1 &&
00482            "InlineCall is a special hacky callback to allow intrusive"
00483            "evaluation of the call (which simulates inlining). It is "
00484            "currently only used by OSAtomicChecker and should go away "
00485            "at some point.");
00486     for (std::vector<InlineCallFunc>::iterator
00487            EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end();
00488          EI != EE; ++EI) {
00489       ExplodedNodeSet checkDst;
00490       bool evaluated = (*EI)(CE, Eng, Pred, checkDst);
00491       assert(!(evaluated && anyEvaluated)
00492              && "There are more than one checkers evaluating the call");
00493       if (evaluated) {
00494         anyEvaluated = true;
00495         Dst.insert(checkDst);
00496 #ifdef NDEBUG
00497         break; // on release don't check that no other checker also evals.
00498 #endif
00499       }
00500     }
00501 
00502 #ifdef NDEBUG // on release don't check that no other checker also evals.
00503     if (anyEvaluated) {
00504       break;
00505     }
00506 #endif
00507 
00508     ExplodedNodeSet checkDst;
00509     NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
00510     // Next, check if any of the EvalCall callbacks can evaluate the call.
00511     for (std::vector<EvalCallFunc>::iterator
00512            EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
00513          EI != EE; ++EI) {
00514       ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
00515       const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
00516                                 Pred->getLocationContext(), EI->Checker);
00517       bool evaluated = false;
00518       { // CheckerContext generates transitions(populates checkDest) on
00519         // destruction, so introduce the scope to make sure it gets properly
00520         // populated.
00521         CheckerContext C(B, Eng, Pred, L);
00522         evaluated = (*EI)(CE, C);
00523       }
00524       assert(!(evaluated && anyEvaluated)
00525              && "There are more than one checkers evaluating the call");
00526       if (evaluated) {
00527         anyEvaluated = true;
00528         Dst.insert(checkDst);
00529 #ifdef NDEBUG
00530         break; // on release don't check that no other checker also evals.
00531 #endif
00532       }
00533     }
00534     
00535     // If none of the checkers evaluated the call, ask ExprEngine to handle it.
00536     if (!anyEvaluated) {
00537       if (defaultEval)
00538         defaultEval->expandGraph(Dst, Pred);
00539       else
00540         Dst.insert(Pred);
00541     }
00542   }
00543 }
00544 
00545 /// \brief Run checkers for the entire Translation Unit.
00546 void CheckerManager::runCheckersOnEndOfTranslationUnit(
00547                                                   const TranslationUnitDecl *TU,
00548                                                   AnalysisManager &mgr,
00549                                                   BugReporter &BR) {
00550   for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
00551     EndOfTranslationUnitCheckers[i](TU, mgr, BR);
00552 }
00553 
00554 void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
00555                                               ProgramStateRef State,
00556                                               const char *NL, const char *Sep) {
00557   for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
00558         I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
00559     I->second->printState(Out, State, NL, Sep);
00560 }
00561 
00562 //===----------------------------------------------------------------------===//
00563 // Internal registration functions for AST traversing.
00564 //===----------------------------------------------------------------------===//
00565 
00566 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
00567                                       HandlesDeclFunc isForDeclFn) {
00568   DeclCheckerInfo info = { checkfn, isForDeclFn };
00569   DeclCheckers.push_back(info);
00570 }
00571 
00572 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
00573   BodyCheckers.push_back(checkfn);
00574 }
00575 
00576 //===----------------------------------------------------------------------===//
00577 // Internal registration functions for path-sensitive checking.
00578 //===----------------------------------------------------------------------===//
00579 
00580 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
00581                                          HandlesStmtFunc isForStmtFn) {
00582   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
00583   StmtCheckers.push_back(info);
00584 }
00585 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
00586                                           HandlesStmtFunc isForStmtFn) {
00587   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
00588   StmtCheckers.push_back(info);
00589 }
00590 
00591 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
00592   PreObjCMessageCheckers.push_back(checkfn);
00593 }
00594 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
00595   PostObjCMessageCheckers.push_back(checkfn);
00596 }
00597 
00598 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
00599   LocationCheckers.push_back(checkfn);
00600 }
00601 
00602 void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
00603   BindCheckers.push_back(checkfn);
00604 }
00605 
00606 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
00607   EndAnalysisCheckers.push_back(checkfn);
00608 }
00609 
00610 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
00611   EndPathCheckers.push_back(checkfn);
00612 }
00613 
00614 void CheckerManager::_registerForBranchCondition(
00615                                              CheckBranchConditionFunc checkfn) {
00616   BranchConditionCheckers.push_back(checkfn);
00617 }
00618 
00619 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
00620   LiveSymbolsCheckers.push_back(checkfn);
00621 }
00622 
00623 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
00624   DeadSymbolsCheckers.push_back(checkfn);
00625 }
00626 
00627 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
00628                                      WantsRegionChangeUpdateFunc wantUpdateFn) {
00629   RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
00630   RegionChangesCheckers.push_back(info);
00631 }
00632 
00633 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
00634   EvalAssumeCheckers.push_back(checkfn);
00635 }
00636 
00637 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
00638   EvalCallCheckers.push_back(checkfn);
00639 }
00640 
00641 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) {
00642   InlineCallCheckers.push_back(checkfn);
00643 }
00644 
00645 void CheckerManager::_registerForEndOfTranslationUnit(
00646                                             CheckEndOfTranslationUnit checkfn) {
00647   EndOfTranslationUnitCheckers.push_back(checkfn);
00648 }
00649 
00650 //===----------------------------------------------------------------------===//
00651 // Implementation details.
00652 //===----------------------------------------------------------------------===//
00653 
00654 CheckerManager::CachedStmtCheckers *
00655 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
00656   assert(S);
00657 
00658   CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
00659   CachedStmtCheckers *checkers = 0;
00660   CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
00661   if (CCI != CachedStmtCheckersMap.end()) {
00662     checkers = &(CCI->second);
00663   } else {
00664     // Find the checkers that should run for this Stmt and cache them.
00665     checkers = &CachedStmtCheckersMap[key];
00666     for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
00667       StmtCheckerInfo &info = StmtCheckers[i];
00668       if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
00669         checkers->push_back(info.CheckFn);
00670     }
00671   }
00672 
00673   assert(checkers);
00674   return checkers;
00675 }
00676 
00677 CheckerManager::~CheckerManager() {
00678   for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
00679     CheckerDtors[i]();
00680 }
00681 
00682 // Anchor for the vtable.
00683 GraphExpander::~GraphExpander() { }