1 //===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Defines the Static Analyzer Checker Manager.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
15 #include "clang/StaticAnalyzer/Core/Checker.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
18 #include "clang/Analysis/ProgramPoint.h"
19 #include "clang/AST/DeclBase.h"
20 
21 using namespace clang;
22 using namespace ento;
23 
24 bool CheckerManager::hasPathSensitiveCheckers() const {
25   return !StmtCheckers.empty()              ||
26          !PreObjCMessageCheckers.empty()    ||
27          !PostObjCMessageCheckers.empty()   ||
28          !LocationCheckers.empty()          ||
29          !BindCheckers.empty()              ||
30          !EndAnalysisCheckers.empty()       ||
31          !EndPathCheckers.empty()           ||
32          !BranchConditionCheckers.empty()   ||
33          !LiveSymbolsCheckers.empty()       ||
34          !DeadSymbolsCheckers.empty()       ||
35          !RegionChangesCheckers.empty()     ||
36          !EvalAssumeCheckers.empty()        ||
37          !EvalCallCheckers.empty()          ||
38          !InlineCallCheckers.empty();
39 }
40 
41 void CheckerManager::finishedCheckerRegistration() {
42 #ifndef NDEBUG
43   // Make sure that for every event that has listeners, there is at least
44   // one dispatcher registered for it.
45   for (llvm::DenseMap<EventTag, EventInfo>::iterator
46          I = Events.begin(), E = Events.end(); I != E; ++I)
47     assert(I->second.HasDispatcher && "No dispatcher registered for an event");
48 #endif
49 }
50 
51 //===----------------------------------------------------------------------===//
52 // Functions for running checkers for AST traversing..
53 //===----------------------------------------------------------------------===//
54 
55 void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
56                                           BugReporter &BR) {
57   assert(D);
58 
59   unsigned DeclKind = D->getKind();
60   CachedDeclCheckers *checkers = 0;
61   CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
62   if (CCI != CachedDeclCheckersMap.end()) {
63     checkers = &(CCI->second);
64   } else {
65     // Find the checkers that should run for this Decl and cache them.
66     checkers = &CachedDeclCheckersMap[DeclKind];
67     for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
68       DeclCheckerInfo &info = DeclCheckers[i];
69       if (info.IsForDeclFn(D))
70         checkers->push_back(info.CheckFn);
71     }
72   }
73 
74   assert(checkers);
75   for (CachedDeclCheckers::iterator
76          I = checkers->begin(), E = checkers->end(); I != E; ++I)
77     (*I)(D, mgr, BR);
78 }
79 
80 void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
81                                           BugReporter &BR) {
82   assert(D && D->hasBody());
83 
84   for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
85     BodyCheckers[i](D, mgr, BR);
86 }
87 
88 //===----------------------------------------------------------------------===//
89 // Functions for running checkers for path-sensitive checking.
90 //===----------------------------------------------------------------------===//
91 
92 template <typename CHECK_CTX>
93 static void expandGraphWithCheckers(CHECK_CTX checkCtx,
94                                     ExplodedNodeSet &Dst,
95                                     const ExplodedNodeSet &Src) {
96   const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
97   if (Src.empty())
98     return;
99 
100   typename CHECK_CTX::CheckersTy::const_iterator
101       I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
102   if (I == E) {
103     Dst.insert(Src);
104     return;
105   }
106 
107   ExplodedNodeSet Tmp1, Tmp2;
108   const ExplodedNodeSet *PrevSet = &Src;
109 
110   for (; I != E; ++I) {
111     ExplodedNodeSet *CurrSet = 0;
112     if (I+1 == E)
113       CurrSet = &Dst;
114     else {
115       CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
116       CurrSet->clear();
117     }
118 
119     NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
120     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
121          NI != NE; ++NI) {
122       checkCtx.runChecker(*I, B, *NI);
123     }
124 
125     // If all the produced transitions are sinks, stop.
126     if (CurrSet->empty())
127       return;
128 
129     // Update which NodeSet is the current one.
130     PrevSet = CurrSet;
131   }
132 }
133 
134 namespace {
135   struct CheckStmtContext {
136     typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
137     bool IsPreVisit;
138     const CheckersTy &Checkers;
139     const Stmt *S;
140     ExprEngine &Eng;
141     bool wasInlined;
142 
143     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
144     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
145 
146     CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
147                      const Stmt *s, ExprEngine &eng, bool wasInlined = false)
148       : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
149         wasInlined(wasInlined) {}
150 
151     void runChecker(CheckerManager::CheckStmtFunc checkFn,
152                     NodeBuilder &Bldr, ExplodedNode *Pred) {
153       // FIXME: Remove respondsToCallback from CheckerContext;
154       ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
155                                            ProgramPoint::PostStmtKind;
156       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
157                                 Pred->getLocationContext(), checkFn.Checker);
158       CheckerContext C(Bldr, Eng, Pred, L, wasInlined);
159       checkFn(S, C);
160     }
161   };
162 }
163 
164 /// \brief Run checkers for visiting Stmts.
165 void CheckerManager::runCheckersForStmt(bool isPreVisit,
166                                         ExplodedNodeSet &Dst,
167                                         const ExplodedNodeSet &Src,
168                                         const Stmt *S,
169                                         ExprEngine &Eng,
170                                         bool wasInlined) {
171   CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
172                      S, Eng, wasInlined);
173   expandGraphWithCheckers(C, Dst, Src);
174 }
175 
176 namespace {
177   struct CheckObjCMessageContext {
178     typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
179     bool IsPreVisit;
180     const CheckersTy &Checkers;
181     const ObjCMessage &Msg;
182     ExprEngine &Eng;
183 
184     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
185     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
186 
187     CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
188                             const ObjCMessage &msg, ExprEngine &eng)
189       : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
190 
191     void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
192                     NodeBuilder &Bldr, ExplodedNode *Pred) {
193       ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
194                                            ProgramPoint::PostStmtKind;
195       const ProgramPoint &L =
196         ProgramPoint::getProgramPoint(Msg.getMessageExpr(),
197                                       K, Pred->getLocationContext(),
198                                       checkFn.Checker);
199       CheckerContext C(Bldr, Eng, Pred, L);
200 
201       checkFn(Msg, C);
202     }
203   };
204 }
205 
206 /// \brief Run checkers for visiting obj-c messages.
207 void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
208                                                ExplodedNodeSet &Dst,
209                                                const ExplodedNodeSet &Src,
210                                                const ObjCMessage &msg,
211                                                ExprEngine &Eng) {
212   CheckObjCMessageContext C(isPreVisit,
213                             isPreVisit ? PreObjCMessageCheckers
214                                        : PostObjCMessageCheckers,
215                             msg, Eng);
216   expandGraphWithCheckers(C, Dst, Src);
217 }
218 
219 namespace {
220   struct CheckLocationContext {
221     typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
222     const CheckersTy &Checkers;
223     SVal Loc;
224     bool IsLoad;
225     const Stmt *NodeEx; /* Will become a CFGStmt */
226     const Stmt *BoundEx;
227     ExprEngine &Eng;
228 
229     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
230     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
231 
232     CheckLocationContext(const CheckersTy &checkers,
233                          SVal loc, bool isLoad, const Stmt *NodeEx,
234                          const Stmt *BoundEx,
235                          ExprEngine &eng)
236       : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
237         BoundEx(BoundEx), Eng(eng) {}
238 
239     void runChecker(CheckerManager::CheckLocationFunc checkFn,
240                     NodeBuilder &Bldr, ExplodedNode *Pred) {
241       ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
242                                        ProgramPoint::PreStoreKind;
243       const ProgramPoint &L =
244         ProgramPoint::getProgramPoint(NodeEx, K,
245                                       Pred->getLocationContext(),
246                                       checkFn.Checker);
247       CheckerContext C(Bldr, Eng, Pred, L);
248       checkFn(Loc, IsLoad, BoundEx, C);
249     }
250   };
251 }
252 
253 /// \brief Run checkers for load/store of a location.
254 
255 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
256                                             const ExplodedNodeSet &Src,
257                                             SVal location, bool isLoad,
258                                             const Stmt *NodeEx,
259                                             const Stmt *BoundEx,
260                                             ExprEngine &Eng) {
261   CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
262                          BoundEx, Eng);
263   expandGraphWithCheckers(C, Dst, Src);
264 }
265 
266 namespace {
267   struct CheckBindContext {
268     typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
269     const CheckersTy &Checkers;
270     SVal Loc;
271     SVal Val;
272     const Stmt *S;
273     ExprEngine &Eng;
274     ProgramPoint::Kind PointKind;
275 
276     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
277     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
278 
279     CheckBindContext(const CheckersTy &checkers,
280                      SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
281                      ProgramPoint::Kind PK)
282       : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {}
283 
284     void runChecker(CheckerManager::CheckBindFunc checkFn,
285                     NodeBuilder &Bldr, ExplodedNode *Pred) {
286       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind,
287                                 Pred->getLocationContext(), checkFn.Checker);
288       CheckerContext C(Bldr, Eng, Pred, L);
289 
290       checkFn(Loc, Val, S, C);
291     }
292   };
293 }
294 
295 /// \brief Run checkers for binding of a value to a location.
296 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
297                                         const ExplodedNodeSet &Src,
298                                         SVal location, SVal val,
299                                         const Stmt *S, ExprEngine &Eng,
300                                         ProgramPoint::Kind PointKind) {
301   CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind);
302   expandGraphWithCheckers(C, Dst, Src);
303 }
304 
305 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
306                                                BugReporter &BR,
307                                                ExprEngine &Eng) {
308   for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
309     EndAnalysisCheckers[i](G, BR, Eng);
310 }
311 
312 /// \brief Run checkers for end of path.
313 // Note, We do not chain the checker output (like in expandGraphWithCheckers)
314 // for this callback since end of path nodes are expected to be final.
315 void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC,
316                                            ExplodedNodeSet &Dst,
317                                            ExprEngine &Eng) {
318   ExplodedNode *Pred = BC.Pred;
319 
320   // We define the builder outside of the loop bacause if at least one checkers
321   // creates a sucsessor for Pred, we do not need to generate an
322   // autotransition for it.
323   NodeBuilder Bldr(Pred, Dst, BC);
324   for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
325     CheckEndPathFunc checkFn = EndPathCheckers[i];
326 
327     const ProgramPoint &L = BlockEntrance(BC.Block,
328                                           Pred->getLocationContext(),
329                                           checkFn.Checker);
330     CheckerContext C(Bldr, Eng, Pred, L);
331     checkFn(C);
332   }
333 }
334 
335 namespace {
336   struct CheckBranchConditionContext {
337     typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
338     const CheckersTy &Checkers;
339     const Stmt *Condition;
340     ExprEngine &Eng;
341 
342     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
343     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
344 
345     CheckBranchConditionContext(const CheckersTy &checkers,
346                                 const Stmt *Cond, ExprEngine &eng)
347       : Checkers(checkers), Condition(Cond), Eng(eng) {}
348 
349     void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
350                     NodeBuilder &Bldr, ExplodedNode *Pred) {
351       ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
352                                      checkFn.Checker);
353       CheckerContext C(Bldr, Eng, Pred, L);
354       checkFn(Condition, C);
355     }
356   };
357 }
358 
359 /// \brief Run checkers for branch condition.
360 void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
361                                                    ExplodedNodeSet &Dst,
362                                                    ExplodedNode *Pred,
363                                                    ExprEngine &Eng) {
364   ExplodedNodeSet Src;
365   Src.insert(Pred);
366   CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
367   expandGraphWithCheckers(C, Dst, Src);
368 }
369 
370 /// \brief Run checkers for live symbols.
371 void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
372                                                SymbolReaper &SymReaper) {
373   for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
374     LiveSymbolsCheckers[i](state, SymReaper);
375 }
376 
377 namespace {
378   struct CheckDeadSymbolsContext {
379     typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
380     const CheckersTy &Checkers;
381     SymbolReaper &SR;
382     const Stmt *S;
383     ExprEngine &Eng;
384     ProgramPoint::Kind ProgarmPointKind;
385 
386     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
387     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
388 
389     CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
390                             const Stmt *s, ExprEngine &eng,
391                             ProgramPoint::Kind K)
392       : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
393 
394     void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
395                     NodeBuilder &Bldr, ExplodedNode *Pred) {
396       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
397                                 Pred->getLocationContext(), checkFn.Checker);
398       CheckerContext C(Bldr, Eng, Pred, L);
399 
400       // Note, do not pass the statement to the checkers without letting them
401       // differentiate if we ran remove dead bindings before or after the
402       // statement.
403       checkFn(SR, C);
404     }
405   };
406 }
407 
408 /// \brief Run checkers for dead symbols.
409 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
410                                                const ExplodedNodeSet &Src,
411                                                SymbolReaper &SymReaper,
412                                                const Stmt *S,
413                                                ExprEngine &Eng,
414                                                ProgramPoint::Kind K) {
415   CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
416   expandGraphWithCheckers(C, Dst, Src);
417 }
418 
419 /// \brief True if at least one checker wants to check region changes.
420 bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
421   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
422     if (RegionChangesCheckers[i].WantUpdateFn(state))
423       return true;
424 
425   return false;
426 }
427 
428 /// \brief Run checkers for region changes.
429 ProgramStateRef
430 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
431                             const StoreManager::InvalidatedSymbols *invalidated,
432                                     ArrayRef<const MemRegion *> ExplicitRegions,
433                                           ArrayRef<const MemRegion *> Regions,
434                                           const CallOrObjCMessage *Call) {
435   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
436     // If any checker declares the state infeasible (or if it starts that way),
437     // bail out.
438     if (!state)
439       return NULL;
440     state = RegionChangesCheckers[i].CheckFn(state, invalidated,
441                                              ExplicitRegions, Regions, Call);
442   }
443   return state;
444 }
445 
446 /// \brief Run checkers for handling assumptions on symbolic values.
447 ProgramStateRef
448 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
449                                          SVal Cond, bool Assumption) {
450   for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
451     // If any checker declares the state infeasible (or if it starts that way),
452     // bail out.
453     if (!state)
454       return NULL;
455     state = EvalAssumeCheckers[i](state, Cond, Assumption);
456   }
457   return state;
458 }
459 
460 /// \brief Run checkers for evaluating a call.
461 /// Only one checker will evaluate the call.
462 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
463                                             const ExplodedNodeSet &Src,
464                                             const CallExpr *CE,
465                                             ExprEngine &Eng,
466                                             GraphExpander *defaultEval) {
467   if (EvalCallCheckers.empty()   &&
468       InlineCallCheckers.empty() &&
469       defaultEval == 0) {
470     Dst.insert(Src);
471     return;
472   }
473 
474   for (ExplodedNodeSet::iterator
475          NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
476 
477     ExplodedNode *Pred = *NI;
478     bool anyEvaluated = false;
479 
480     // First, check if any of the InlineCall callbacks can evaluate the call.
481     assert(InlineCallCheckers.size() <= 1 &&
482            "InlineCall is a special hacky callback to allow intrusive"
483            "evaluation of the call (which simulates inlining). It is "
484            "currently only used by OSAtomicChecker and should go away "
485            "at some point.");
486     for (std::vector<InlineCallFunc>::iterator
487            EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end();
488          EI != EE; ++EI) {
489       ExplodedNodeSet checkDst;
490       bool evaluated = (*EI)(CE, Eng, Pred, checkDst);
491       assert(!(evaluated && anyEvaluated)
492              && "There are more than one checkers evaluating the call");
493       if (evaluated) {
494         anyEvaluated = true;
495         Dst.insert(checkDst);
496 #ifdef NDEBUG
497         break; // on release don't check that no other checker also evals.
498 #endif
499       }
500     }
501 
502 #ifdef NDEBUG // on release don't check that no other checker also evals.
503     if (anyEvaluated) {
504       break;
505     }
506 #endif
507 
508     ExplodedNodeSet checkDst;
509     NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
510     // Next, check if any of the EvalCall callbacks can evaluate the call.
511     for (std::vector<EvalCallFunc>::iterator
512            EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
513          EI != EE; ++EI) {
514       ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
515       const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
516                                 Pred->getLocationContext(), EI->Checker);
517       bool evaluated = false;
518       { // CheckerContext generates transitions(populates checkDest) on
519         // destruction, so introduce the scope to make sure it gets properly
520         // populated.
521         CheckerContext C(B, Eng, Pred, L);
522         evaluated = (*EI)(CE, C);
523       }
524       assert(!(evaluated && anyEvaluated)
525              && "There are more than one checkers evaluating the call");
526       if (evaluated) {
527         anyEvaluated = true;
528         Dst.insert(checkDst);
529 #ifdef NDEBUG
530         break; // on release don't check that no other checker also evals.
531 #endif
532       }
533     }
534 
535     // If none of the checkers evaluated the call, ask ExprEngine to handle it.
536     if (!anyEvaluated) {
537       if (defaultEval)
538         defaultEval->expandGraph(Dst, Pred);
539       else
540         Dst.insert(Pred);
541     }
542   }
543 }
544 
545 /// \brief Run checkers for the entire Translation Unit.
546 void CheckerManager::runCheckersOnEndOfTranslationUnit(
547                                                   const TranslationUnitDecl *TU,
548                                                   AnalysisManager &mgr,
549                                                   BugReporter &BR) {
550   for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
551     EndOfTranslationUnitCheckers[i](TU, mgr, BR);
552 }
553 
554 void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
555                                               ProgramStateRef State,
556                                               const char *NL, const char *Sep) {
557   for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
558         I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
559     I->second->printState(Out, State, NL, Sep);
560 }
561 
562 //===----------------------------------------------------------------------===//
563 // Internal registration functions for AST traversing.
564 //===----------------------------------------------------------------------===//
565 
566 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
567                                       HandlesDeclFunc isForDeclFn) {
568   DeclCheckerInfo info = { checkfn, isForDeclFn };
569   DeclCheckers.push_back(info);
570 }
571 
572 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
573   BodyCheckers.push_back(checkfn);
574 }
575 
576 //===----------------------------------------------------------------------===//
577 // Internal registration functions for path-sensitive checking.
578 //===----------------------------------------------------------------------===//
579 
580 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
581                                          HandlesStmtFunc isForStmtFn) {
582   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
583   StmtCheckers.push_back(info);
584 }
585 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
586                                           HandlesStmtFunc isForStmtFn) {
587   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
588   StmtCheckers.push_back(info);
589 }
590 
591 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
592   PreObjCMessageCheckers.push_back(checkfn);
593 }
594 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
595   PostObjCMessageCheckers.push_back(checkfn);
596 }
597 
598 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
599   LocationCheckers.push_back(checkfn);
600 }
601 
602 void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
603   BindCheckers.push_back(checkfn);
604 }
605 
606 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
607   EndAnalysisCheckers.push_back(checkfn);
608 }
609 
610 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
611   EndPathCheckers.push_back(checkfn);
612 }
613 
614 void CheckerManager::_registerForBranchCondition(
615                                              CheckBranchConditionFunc checkfn) {
616   BranchConditionCheckers.push_back(checkfn);
617 }
618 
619 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
620   LiveSymbolsCheckers.push_back(checkfn);
621 }
622 
623 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
624   DeadSymbolsCheckers.push_back(checkfn);
625 }
626 
627 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
628                                      WantsRegionChangeUpdateFunc wantUpdateFn) {
629   RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
630   RegionChangesCheckers.push_back(info);
631 }
632 
633 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
634   EvalAssumeCheckers.push_back(checkfn);
635 }
636 
637 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
638   EvalCallCheckers.push_back(checkfn);
639 }
640 
641 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) {
642   InlineCallCheckers.push_back(checkfn);
643 }
644 
645 void CheckerManager::_registerForEndOfTranslationUnit(
646                                             CheckEndOfTranslationUnit checkfn) {
647   EndOfTranslationUnitCheckers.push_back(checkfn);
648 }
649 
650 //===----------------------------------------------------------------------===//
651 // Implementation details.
652 //===----------------------------------------------------------------------===//
653 
654 CheckerManager::CachedStmtCheckers *
655 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
656   assert(S);
657 
658   CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
659   CachedStmtCheckers *checkers = 0;
660   CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
661   if (CCI != CachedStmtCheckersMap.end()) {
662     checkers = &(CCI->second);
663   } else {
664     // Find the checkers that should run for this Stmt and cache them.
665     checkers = &CachedStmtCheckersMap[key];
666     for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
667       StmtCheckerInfo &info = StmtCheckers[i];
668       if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
669         checkers->push_back(info.CheckFn);
670     }
671   }
672 
673   assert(checkers);
674   return checkers;
675 }
676 
677 CheckerManager::~CheckerManager() {
678   for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
679     CheckerDtors[i]();
680 }
681 
682 // Anchor for the vtable.
683 GraphExpander::~GraphExpander() { }
684