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