]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
MFC
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Core / CheckerManager.cpp
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
385     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
386     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
387
388     CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
389                             const Stmt *s, ExprEngine &eng)
390       : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
391
392     void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
393                     NodeBuilder &Bldr, ExplodedNode *Pred) {
394       ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind;
395       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
396                                 Pred->getLocationContext(), checkFn.Checker);
397       CheckerContext C(Bldr, Eng, Pred, L);
398
399       checkFn(SR, C);
400     }
401   };
402 }
403
404 /// \brief Run checkers for dead symbols.
405 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
406                                                const ExplodedNodeSet &Src,
407                                                SymbolReaper &SymReaper,
408                                                const Stmt *S,
409                                                ExprEngine &Eng) {
410   CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
411   expandGraphWithCheckers(C, Dst, Src);
412 }
413
414 /// \brief True if at least one checker wants to check region changes.
415 bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
416   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
417     if (RegionChangesCheckers[i].WantUpdateFn(state))
418       return true;
419
420   return false;
421 }
422
423 /// \brief Run checkers for region changes.
424 ProgramStateRef 
425 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
426                             const StoreManager::InvalidatedSymbols *invalidated,
427                                     ArrayRef<const MemRegion *> ExplicitRegions,
428                                           ArrayRef<const MemRegion *> Regions,
429                                           const CallOrObjCMessage *Call) {
430   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
431     // If any checker declares the state infeasible (or if it starts that way),
432     // bail out.
433     if (!state)
434       return NULL;
435     state = RegionChangesCheckers[i].CheckFn(state, invalidated, 
436                                              ExplicitRegions, Regions, Call);
437   }
438   return state;
439 }
440
441 /// \brief Run checkers for handling assumptions on symbolic values.
442 ProgramStateRef 
443 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
444                                          SVal Cond, bool Assumption) {
445   for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
446     // If any checker declares the state infeasible (or if it starts that way),
447     // bail out.
448     if (!state)
449       return NULL;
450     state = EvalAssumeCheckers[i](state, Cond, Assumption);
451   }
452   return state;
453 }
454
455 /// \brief Run checkers for evaluating a call.
456 /// Only one checker will evaluate the call.
457 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
458                                             const ExplodedNodeSet &Src,
459                                             const CallExpr *CE,
460                                             ExprEngine &Eng,
461                                             GraphExpander *defaultEval) {
462   if (EvalCallCheckers.empty()   &&
463       InlineCallCheckers.empty() &&
464       defaultEval == 0) {
465     Dst.insert(Src);
466     return;
467   }
468
469   for (ExplodedNodeSet::iterator
470          NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
471
472     ExplodedNode *Pred = *NI;
473     bool anyEvaluated = false;
474
475     // First, check if any of the InlineCall callbacks can evaluate the call.
476     assert(InlineCallCheckers.size() <= 1 &&
477            "InlineCall is a special hacky callback to allow intrusive"
478            "evaluation of the call (which simulates inlining). It is "
479            "currently only used by OSAtomicChecker and should go away "
480            "at some point.");
481     for (std::vector<InlineCallFunc>::iterator
482            EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end();
483          EI != EE; ++EI) {
484       ExplodedNodeSet checkDst;
485       bool evaluated = (*EI)(CE, Eng, Pred, checkDst);
486       assert(!(evaluated && anyEvaluated)
487              && "There are more than one checkers evaluating the call");
488       if (evaluated) {
489         anyEvaluated = true;
490         Dst.insert(checkDst);
491 #ifdef NDEBUG
492         break; // on release don't check that no other checker also evals.
493 #endif
494       }
495     }
496
497 #ifdef NDEBUG // on release don't check that no other checker also evals.
498     if (anyEvaluated) {
499       break;
500     }
501 #endif
502
503     ExplodedNodeSet checkDst;
504     NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
505     // Next, check if any of the EvalCall callbacks can evaluate the call.
506     for (std::vector<EvalCallFunc>::iterator
507            EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
508          EI != EE; ++EI) {
509       ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
510       const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
511                                 Pred->getLocationContext(), EI->Checker);
512       bool evaluated = false;
513       { // CheckerContext generates transitions(populates checkDest) on
514         // destruction, so introduce the scope to make sure it gets properly
515         // populated.
516         CheckerContext C(B, Eng, Pred, L);
517         evaluated = (*EI)(CE, C);
518       }
519       assert(!(evaluated && anyEvaluated)
520              && "There are more than one checkers evaluating the call");
521       if (evaluated) {
522         anyEvaluated = true;
523         Dst.insert(checkDst);
524 #ifdef NDEBUG
525         break; // on release don't check that no other checker also evals.
526 #endif
527       }
528     }
529     
530     // If none of the checkers evaluated the call, ask ExprEngine to handle it.
531     if (!anyEvaluated) {
532       if (defaultEval)
533         defaultEval->expandGraph(Dst, Pred);
534       else
535         Dst.insert(Pred);
536     }
537   }
538 }
539
540 /// \brief Run checkers for the entire Translation Unit.
541 void CheckerManager::runCheckersOnEndOfTranslationUnit(
542                                                   const TranslationUnitDecl *TU,
543                                                   AnalysisManager &mgr,
544                                                   BugReporter &BR) {
545   for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
546     EndOfTranslationUnitCheckers[i](TU, mgr, BR);
547 }
548
549 void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
550                                               ProgramStateRef State,
551                                               const char *NL, const char *Sep) {
552   for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
553         I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
554     I->second->printState(Out, State, NL, Sep);
555 }
556
557 //===----------------------------------------------------------------------===//
558 // Internal registration functions for AST traversing.
559 //===----------------------------------------------------------------------===//
560
561 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
562                                       HandlesDeclFunc isForDeclFn) {
563   DeclCheckerInfo info = { checkfn, isForDeclFn };
564   DeclCheckers.push_back(info);
565 }
566
567 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
568   BodyCheckers.push_back(checkfn);
569 }
570
571 //===----------------------------------------------------------------------===//
572 // Internal registration functions for path-sensitive checking.
573 //===----------------------------------------------------------------------===//
574
575 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
576                                          HandlesStmtFunc isForStmtFn) {
577   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
578   StmtCheckers.push_back(info);
579 }
580 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
581                                           HandlesStmtFunc isForStmtFn) {
582   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
583   StmtCheckers.push_back(info);
584 }
585
586 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
587   PreObjCMessageCheckers.push_back(checkfn);
588 }
589 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
590   PostObjCMessageCheckers.push_back(checkfn);
591 }
592
593 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
594   LocationCheckers.push_back(checkfn);
595 }
596
597 void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
598   BindCheckers.push_back(checkfn);
599 }
600
601 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
602   EndAnalysisCheckers.push_back(checkfn);
603 }
604
605 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
606   EndPathCheckers.push_back(checkfn);
607 }
608
609 void CheckerManager::_registerForBranchCondition(
610                                              CheckBranchConditionFunc checkfn) {
611   BranchConditionCheckers.push_back(checkfn);
612 }
613
614 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
615   LiveSymbolsCheckers.push_back(checkfn);
616 }
617
618 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
619   DeadSymbolsCheckers.push_back(checkfn);
620 }
621
622 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
623                                      WantsRegionChangeUpdateFunc wantUpdateFn) {
624   RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
625   RegionChangesCheckers.push_back(info);
626 }
627
628 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
629   EvalAssumeCheckers.push_back(checkfn);
630 }
631
632 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
633   EvalCallCheckers.push_back(checkfn);
634 }
635
636 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) {
637   InlineCallCheckers.push_back(checkfn);
638 }
639
640 void CheckerManager::_registerForEndOfTranslationUnit(
641                                             CheckEndOfTranslationUnit checkfn) {
642   EndOfTranslationUnitCheckers.push_back(checkfn);
643 }
644
645 //===----------------------------------------------------------------------===//
646 // Implementation details.
647 //===----------------------------------------------------------------------===//
648
649 CheckerManager::CachedStmtCheckers *
650 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
651   assert(S);
652
653   CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
654   CachedStmtCheckers *checkers = 0;
655   CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
656   if (CCI != CachedStmtCheckersMap.end()) {
657     checkers = &(CCI->second);
658   } else {
659     // Find the checkers that should run for this Stmt and cache them.
660     checkers = &CachedStmtCheckersMap[key];
661     for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
662       StmtCheckerInfo &info = StmtCheckers[i];
663       if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
664         checkers->push_back(info.CheckFn);
665     }
666   }
667
668   assert(checkers);
669   return checkers;
670 }
671
672 CheckerManager::~CheckerManager() {
673   for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
674     CheckerDtors[i]();
675 }
676
677 // Anchor for the vtable.
678 GraphExpander::~GraphExpander() { }