1e580d831SEugene Zelenko //===- CheckerManager.cpp - Static Analyzer Checker Manager ---------------===//
2556c45e9SArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6556c45e9SArgyrios Kyrtzidis //
7556c45e9SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8556c45e9SArgyrios Kyrtzidis //
9556c45e9SArgyrios Kyrtzidis // Defines the Static Analyzer Checker Manager.
10556c45e9SArgyrios Kyrtzidis //
11556c45e9SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
12556c45e9SArgyrios Kyrtzidis 
13556c45e9SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/CheckerManager.h"
1424ffc08fSArgyrios Kyrtzidis #include "clang/AST/DeclBase.h"
15e580d831SEugene Zelenko #include "clang/AST/Stmt.h"
163a02247dSChandler Carruth #include "clang/Analysis/ProgramPoint.h"
17b7ca72a1SCsaba Dabis #include "clang/Basic/JsonSupport.h"
18e580d831SEugene Zelenko #include "clang/Basic/LLVM.h"
19748c139aSKristof Umann #include "clang/Driver/DriverDiagnostic.h"
203a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/Checker.h"
213a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
223a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23e580d831SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
24e580d831SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
25e580d831SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
26e580d831SEugene Zelenko #include "llvm/ADT/SmallVector.h"
27e580d831SEugene Zelenko #include "llvm/Support/Casting.h"
28e580d831SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
29*9b5c9c46SBalazs Benics #include "llvm/Support/FormatVariadic.h"
30e580d831SEugene Zelenko #include <cassert>
31e580d831SEugene Zelenko #include <vector>
32556c45e9SArgyrios Kyrtzidis 
33556c45e9SArgyrios Kyrtzidis using namespace clang;
34556c45e9SArgyrios Kyrtzidis using namespace ento;
35556c45e9SArgyrios Kyrtzidis 
hasPathSensitiveCheckers() const366a1c7607SArgyrios Kyrtzidis bool CheckerManager::hasPathSensitiveCheckers() const {
373dae0191SBalazs Benics   const auto IfAnyAreNonEmpty = [](const auto &... Callbacks) -> bool {
383dae0191SBalazs Benics     bool Result = false;
393dae0191SBalazs Benics     // FIXME: Use fold expressions in C++17.
403dae0191SBalazs Benics     LLVM_ATTRIBUTE_UNUSED int Unused[]{0, (Result |= !Callbacks.empty())...};
413dae0191SBalazs Benics     return Result;
423dae0191SBalazs Benics   };
433dae0191SBalazs Benics   return IfAnyAreNonEmpty(
443dae0191SBalazs Benics       StmtCheckers, PreObjCMessageCheckers, ObjCMessageNilCheckers,
453dae0191SBalazs Benics       PostObjCMessageCheckers, PreCallCheckers, PostCallCheckers,
463dae0191SBalazs Benics       LocationCheckers, BindCheckers, EndAnalysisCheckers,
473dae0191SBalazs Benics       BeginFunctionCheckers, EndFunctionCheckers, BranchConditionCheckers,
483dae0191SBalazs Benics       NewAllocatorCheckers, LiveSymbolsCheckers, DeadSymbolsCheckers,
493dae0191SBalazs Benics       RegionChangesCheckers, PointerEscapeCheckers, EvalAssumeCheckers,
503dae0191SBalazs Benics       EvalCallCheckers, EndOfTranslationUnitCheckers);
516a1c7607SArgyrios Kyrtzidis }
526a1c7607SArgyrios Kyrtzidis 
finishedCheckerRegistration()53a15dfec3SArgyrios Kyrtzidis void CheckerManager::finishedCheckerRegistration() {
54a15dfec3SArgyrios Kyrtzidis #ifndef NDEBUG
55a15dfec3SArgyrios Kyrtzidis   // Make sure that for every event that has listeners, there is at least
56a15dfec3SArgyrios Kyrtzidis   // one dispatcher registered for it.
57e580d831SEugene Zelenko   for (const auto &Event : Events)
58e580d831SEugene Zelenko     assert(Event.second.HasDispatcher &&
59e580d831SEugene Zelenko            "No dispatcher registered for an event");
60a15dfec3SArgyrios Kyrtzidis #endif
61a15dfec3SArgyrios Kyrtzidis }
62a15dfec3SArgyrios Kyrtzidis 
reportInvalidCheckerOptionValue(const CheckerBase * C,StringRef OptionName,StringRef ExpectedValueDesc) const63748c139aSKristof Umann void CheckerManager::reportInvalidCheckerOptionValue(
6457f70d18SAdam Balogh     const CheckerBase *C, StringRef OptionName,
6557f70d18SAdam Balogh     StringRef ExpectedValueDesc) const {
66748c139aSKristof Umann 
672aac0c47SKristóf Umann   getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
68748c139aSKristof Umann       << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
69748c139aSKristof Umann       << ExpectedValueDesc;
70748c139aSKristof Umann }
71748c139aSKristof Umann 
72ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
73ed35cf27SArgyrios Kyrtzidis // Functions for running checkers for AST traversing..
74ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
75ed35cf27SArgyrios Kyrtzidis 
runCheckersOnASTDecl(const Decl * D,AnalysisManager & mgr,BugReporter & BR)7624ffc08fSArgyrios Kyrtzidis void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
7724ffc08fSArgyrios Kyrtzidis                                           BugReporter &BR) {
7824ffc08fSArgyrios Kyrtzidis   assert(D);
7924ffc08fSArgyrios Kyrtzidis 
8024ffc08fSArgyrios Kyrtzidis   unsigned DeclKind = D->getKind();
810dbb783cSCraig Topper   CachedDeclCheckers *checkers = nullptr;
8224ffc08fSArgyrios Kyrtzidis   CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
8324ffc08fSArgyrios Kyrtzidis   if (CCI != CachedDeclCheckersMap.end()) {
8424ffc08fSArgyrios Kyrtzidis     checkers = &(CCI->second);
8524ffc08fSArgyrios Kyrtzidis   } else {
8624ffc08fSArgyrios Kyrtzidis     // Find the checkers that should run for this Decl and cache them.
8724ffc08fSArgyrios Kyrtzidis     checkers = &CachedDeclCheckersMap[DeclKind];
88e580d831SEugene Zelenko     for (const auto &info : DeclCheckers)
8924ffc08fSArgyrios Kyrtzidis       if (info.IsForDeclFn(D))
90ed35cf27SArgyrios Kyrtzidis         checkers->push_back(info.CheckFn);
9124ffc08fSArgyrios Kyrtzidis   }
9224ffc08fSArgyrios Kyrtzidis 
9324ffc08fSArgyrios Kyrtzidis   assert(checkers);
9496484286SMark de Wever   for (const auto &checker : *checkers)
95e580d831SEugene Zelenko     checker(D, mgr, BR);
9624ffc08fSArgyrios Kyrtzidis }
9724ffc08fSArgyrios Kyrtzidis 
runCheckersOnASTBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR)9824ffc08fSArgyrios Kyrtzidis void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
9924ffc08fSArgyrios Kyrtzidis                                           BugReporter &BR) {
10024ffc08fSArgyrios Kyrtzidis   assert(D && D->hasBody());
10124ffc08fSArgyrios Kyrtzidis 
10296484286SMark de Wever   for (const auto &BodyChecker : BodyCheckers)
103e580d831SEugene Zelenko     BodyChecker(D, mgr, BR);
104ed35cf27SArgyrios Kyrtzidis }
105ed35cf27SArgyrios Kyrtzidis 
106ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
107ed35cf27SArgyrios Kyrtzidis // Functions for running checkers for path-sensitive checking.
108ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
109ed35cf27SArgyrios Kyrtzidis 
110ed35cf27SArgyrios Kyrtzidis template <typename CHECK_CTX>
expandGraphWithCheckers(CHECK_CTX checkCtx,ExplodedNodeSet & Dst,const ExplodedNodeSet & Src)111d0732a66SArgyrios Kyrtzidis static void expandGraphWithCheckers(CHECK_CTX checkCtx,
112ed35cf27SArgyrios Kyrtzidis                                     ExplodedNodeSet &Dst,
11368cab73aSArgyrios Kyrtzidis                                     const ExplodedNodeSet &Src) {
1140bb9d1b9SAnna Zaks   const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
1150bb9d1b9SAnna Zaks   if (Src.empty())
1160bb9d1b9SAnna Zaks     return;
117ed35cf27SArgyrios Kyrtzidis 
118da02a25aSArgyrios Kyrtzidis   typename CHECK_CTX::CheckersTy::const_iterator
119da02a25aSArgyrios Kyrtzidis       I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120da02a25aSArgyrios Kyrtzidis   if (I == E) {
121ed35cf27SArgyrios Kyrtzidis     Dst.insert(Src);
122ed35cf27SArgyrios Kyrtzidis     return;
123ed35cf27SArgyrios Kyrtzidis   }
124ed35cf27SArgyrios Kyrtzidis 
12568cab73aSArgyrios Kyrtzidis   ExplodedNodeSet Tmp1, Tmp2;
12668cab73aSArgyrios Kyrtzidis   const ExplodedNodeSet *PrevSet = &Src;
127ed35cf27SArgyrios Kyrtzidis 
128da02a25aSArgyrios Kyrtzidis   for (; I != E; ++I) {
1290dbb783cSCraig Topper     ExplodedNodeSet *CurrSet = nullptr;
130ed35cf27SArgyrios Kyrtzidis     if (I+1 == E)
131ed35cf27SArgyrios Kyrtzidis       CurrSet = &Dst;
132ed35cf27SArgyrios Kyrtzidis     else {
13368cab73aSArgyrios Kyrtzidis       CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
134ed35cf27SArgyrios Kyrtzidis       CurrSet->clear();
135ed35cf27SArgyrios Kyrtzidis     }
136ed35cf27SArgyrios Kyrtzidis 
1370bb9d1b9SAnna Zaks     NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138e580d831SEugene Zelenko     for (const auto &NI : *PrevSet)
139e580d831SEugene Zelenko       checkCtx.runChecker(*I, B, NI);
1400bb9d1b9SAnna Zaks 
1410bb9d1b9SAnna Zaks     // If all the produced transitions are sinks, stop.
1420bb9d1b9SAnna Zaks     if (CurrSet->empty())
1430bb9d1b9SAnna Zaks       return;
1440bb9d1b9SAnna Zaks 
145ed35cf27SArgyrios Kyrtzidis     // Update which NodeSet is the current one.
146ed35cf27SArgyrios Kyrtzidis     PrevSet = CurrSet;
14724ffc08fSArgyrios Kyrtzidis   }
14824ffc08fSArgyrios Kyrtzidis }
14924ffc08fSArgyrios Kyrtzidis 
150ed35cf27SArgyrios Kyrtzidis namespace {
151e580d831SEugene Zelenko 
152ed35cf27SArgyrios Kyrtzidis   struct CheckStmtContext {
153e580d831SEugene Zelenko     using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
154e580d831SEugene Zelenko 
155ed35cf27SArgyrios Kyrtzidis     bool IsPreVisit;
156ed35cf27SArgyrios Kyrtzidis     const CheckersTy &Checkers;
157ed35cf27SArgyrios Kyrtzidis     const Stmt *S;
158ed35cf27SArgyrios Kyrtzidis     ExprEngine &Eng;
159c2d249ceSJordan Rose     bool WasInlined;
160ed35cf27SArgyrios Kyrtzidis 
CheckStmtContext__anon915fba8f0211::CheckStmtContext161ed35cf27SArgyrios Kyrtzidis     CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
162161046edSTed Kremenek                      const Stmt *s, ExprEngine &eng, bool wasInlined = false)
163161046edSTed Kremenek         : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
164c2d249ceSJordan Rose           WasInlined(wasInlined) {}
165ed35cf27SArgyrios Kyrtzidis 
checkers_begin__anon915fba8f0211::CheckStmtContext166e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0211::CheckStmtContext167e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
168e580d831SEugene Zelenko 
runChecker__anon915fba8f0211::CheckStmtContext169ed35cf27SArgyrios Kyrtzidis     void runChecker(CheckerManager::CheckStmtFunc checkFn,
1700bb9d1b9SAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
171ed35cf27SArgyrios Kyrtzidis       // FIXME: Remove respondsToCallback from CheckerContext;
172754eafb7SAnna Zaks       ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
173754eafb7SAnna Zaks                                            ProgramPoint::PostStmtKind;
174754eafb7SAnna Zaks       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
175754eafb7SAnna Zaks                                 Pred->getLocationContext(), checkFn.Checker);
176c2d249ceSJordan Rose       CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
177ed35cf27SArgyrios Kyrtzidis       checkFn(S, C);
178ed35cf27SArgyrios Kyrtzidis     }
179ed35cf27SArgyrios Kyrtzidis   };
180e580d831SEugene Zelenko 
181e580d831SEugene Zelenko } // namespace
18224ffc08fSArgyrios Kyrtzidis 
1839fc8faf9SAdrian Prantl /// Run checkers for visiting Stmts.
runCheckersForStmt(bool isPreVisit,ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const Stmt * S,ExprEngine & Eng,bool WasInlined)184ed35cf27SArgyrios Kyrtzidis void CheckerManager::runCheckersForStmt(bool isPreVisit,
185ed35cf27SArgyrios Kyrtzidis                                         ExplodedNodeSet &Dst,
18668cab73aSArgyrios Kyrtzidis                                         const ExplodedNodeSet &Src,
187ed35cf27SArgyrios Kyrtzidis                                         const Stmt *S,
188161046edSTed Kremenek                                         ExprEngine &Eng,
189c2d249ceSJordan Rose                                         bool WasInlined) {
19091c98670SBenjamin Kramer   CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
191c2d249ceSJordan Rose                      S, Eng, WasInlined);
192d0732a66SArgyrios Kyrtzidis   expandGraphWithCheckers(C, Dst, Src);
193ed35cf27SArgyrios Kyrtzidis }
194ed35cf27SArgyrios Kyrtzidis 
195ed35cf27SArgyrios Kyrtzidis namespace {
196e580d831SEugene Zelenko 
197ed35cf27SArgyrios Kyrtzidis   struct CheckObjCMessageContext {
198e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
199ca5ab2b0SDevin Coughlin 
200ca5ab2b0SDevin Coughlin     ObjCMessageVisitKind Kind;
201ca5ab2b0SDevin Coughlin     bool WasInlined;
202ed35cf27SArgyrios Kyrtzidis     const CheckersTy &Checkers;
203547060b3SJordan Rose     const ObjCMethodCall &Msg;
204ed35cf27SArgyrios Kyrtzidis     ExprEngine &Eng;
205ed35cf27SArgyrios Kyrtzidis 
CheckObjCMessageContext__anon915fba8f0311::CheckObjCMessageContext206ca5ab2b0SDevin Coughlin     CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
207ca5ab2b0SDevin Coughlin                             const CheckersTy &checkers,
208c2d249ceSJordan Rose                             const ObjCMethodCall &msg, ExprEngine &eng,
209c2d249ceSJordan Rose                             bool wasInlined)
210e580d831SEugene Zelenko         : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
211e580d831SEugene Zelenko           Eng(eng) {}
212e580d831SEugene Zelenko 
checkers_begin__anon915fba8f0311::CheckObjCMessageContext213e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0311::CheckObjCMessageContext214e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
215ed35cf27SArgyrios Kyrtzidis 
runChecker__anon915fba8f0311::CheckObjCMessageContext216ed35cf27SArgyrios Kyrtzidis     void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
2170bb9d1b9SAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
218ca5ab2b0SDevin Coughlin       bool IsPreVisit;
219ca5ab2b0SDevin Coughlin 
220ca5ab2b0SDevin Coughlin       switch (Kind) {
221ca5ab2b0SDevin Coughlin         case ObjCMessageVisitKind::Pre:
222ca5ab2b0SDevin Coughlin           IsPreVisit = true;
223ca5ab2b0SDevin Coughlin           break;
224ca5ab2b0SDevin Coughlin         case ObjCMessageVisitKind::MessageNil:
225ca5ab2b0SDevin Coughlin         case ObjCMessageVisitKind::Post:
226ca5ab2b0SDevin Coughlin           IsPreVisit = false;
227ca5ab2b0SDevin Coughlin           break;
228ca5ab2b0SDevin Coughlin       }
229ca5ab2b0SDevin Coughlin 
230fcd016e5SJordan Rose       const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
231c2d249ceSJordan Rose       CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
232754eafb7SAnna Zaks 
233fcd016e5SJordan Rose       checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
234ed35cf27SArgyrios Kyrtzidis     }
235ed35cf27SArgyrios Kyrtzidis   };
236e580d831SEugene Zelenko 
237e580d831SEugene Zelenko } // namespace
238ed35cf27SArgyrios Kyrtzidis 
2399fc8faf9SAdrian Prantl /// Run checkers for visiting obj-c messages.
runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng,bool WasInlined)240ca5ab2b0SDevin Coughlin void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
241ed35cf27SArgyrios Kyrtzidis                                                ExplodedNodeSet &Dst,
24268cab73aSArgyrios Kyrtzidis                                                const ExplodedNodeSet &Src,
243547060b3SJordan Rose                                                const ObjCMethodCall &msg,
244c2d249ceSJordan Rose                                                ExprEngine &Eng,
245c2d249ceSJordan Rose                                                bool WasInlined) {
246f2be30deSKirstóf Umann   const auto &checkers = getObjCMessageCheckers(visitKind);
247ca5ab2b0SDevin Coughlin   CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
248d0732a66SArgyrios Kyrtzidis   expandGraphWithCheckers(C, Dst, Src);
249ed35cf27SArgyrios Kyrtzidis }
250ed35cf27SArgyrios Kyrtzidis 
251ca5ab2b0SDevin Coughlin const std::vector<CheckerManager::CheckObjCMessageFunc> &
getObjCMessageCheckers(ObjCMessageVisitKind Kind) const25257f70d18SAdam Balogh CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) const {
253ca5ab2b0SDevin Coughlin   switch (Kind) {
254ca5ab2b0SDevin Coughlin   case ObjCMessageVisitKind::Pre:
255ca5ab2b0SDevin Coughlin     return PreObjCMessageCheckers;
256ca5ab2b0SDevin Coughlin     break;
257ca5ab2b0SDevin Coughlin   case ObjCMessageVisitKind::Post:
258ca5ab2b0SDevin Coughlin     return PostObjCMessageCheckers;
259ca5ab2b0SDevin Coughlin   case ObjCMessageVisitKind::MessageNil:
260ca5ab2b0SDevin Coughlin     return ObjCMessageNilCheckers;
261ca5ab2b0SDevin Coughlin   }
26202c6abc5SAaron Ballman   llvm_unreachable("Unknown Kind");
263ca5ab2b0SDevin Coughlin }
264e580d831SEugene Zelenko 
265ed35cf27SArgyrios Kyrtzidis namespace {
266e580d831SEugene Zelenko 
267afe7c2c2SJordan Rose   // FIXME: This has all the same signatures as CheckObjCMessageContext.
268afe7c2c2SJordan Rose   // Is there a way we can merge the two?
269afe7c2c2SJordan Rose   struct CheckCallContext {
270e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
271e580d831SEugene Zelenko 
272c2d249ceSJordan Rose     bool IsPreVisit, WasInlined;
273afe7c2c2SJordan Rose     const CheckersTy &Checkers;
274afe7c2c2SJordan Rose     const CallEvent &Call;
275afe7c2c2SJordan Rose     ExprEngine &Eng;
276afe7c2c2SJordan Rose 
CheckCallContext__anon915fba8f0411::CheckCallContext277afe7c2c2SJordan Rose     CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
278c2d249ceSJordan Rose                      const CallEvent &call, ExprEngine &eng,
279c2d249ceSJordan Rose                      bool wasInlined)
280c2d249ceSJordan Rose         : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
281c2d249ceSJordan Rose           Call(call), Eng(eng) {}
282afe7c2c2SJordan Rose 
checkers_begin__anon915fba8f0411::CheckCallContext283e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0411::CheckCallContext284e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
285e580d831SEugene Zelenko 
runChecker__anon915fba8f0411::CheckCallContext286afe7c2c2SJordan Rose     void runChecker(CheckerManager::CheckCallFunc checkFn,
287afe7c2c2SJordan Rose                     NodeBuilder &Bldr, ExplodedNode *Pred) {
288681cce99SJordan Rose       const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
289c2d249ceSJordan Rose       CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
290afe7c2c2SJordan Rose 
291fcd016e5SJordan Rose       checkFn(*Call.cloneWithState(Pred->getState()), C);
292afe7c2c2SJordan Rose     }
293afe7c2c2SJordan Rose   };
294e580d831SEugene Zelenko 
295e580d831SEugene Zelenko } // namespace
296afe7c2c2SJordan Rose 
2979fc8faf9SAdrian Prantl /// Run checkers for visiting an abstract call event.
runCheckersForCallEvent(bool isPreVisit,ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const CallEvent & Call,ExprEngine & Eng,bool WasInlined)298afe7c2c2SJordan Rose void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
299afe7c2c2SJordan Rose                                              ExplodedNodeSet &Dst,
300afe7c2c2SJordan Rose                                              const ExplodedNodeSet &Src,
301afe7c2c2SJordan Rose                                              const CallEvent &Call,
302c2d249ceSJordan Rose                                              ExprEngine &Eng,
303c2d249ceSJordan Rose                                              bool WasInlined) {
304afe7c2c2SJordan Rose   CheckCallContext C(isPreVisit,
305afe7c2c2SJordan Rose                      isPreVisit ? PreCallCheckers
306afe7c2c2SJordan Rose                                 : PostCallCheckers,
307c2d249ceSJordan Rose                      Call, Eng, WasInlined);
308afe7c2c2SJordan Rose   expandGraphWithCheckers(C, Dst, Src);
309afe7c2c2SJordan Rose }
310afe7c2c2SJordan Rose 
311afe7c2c2SJordan Rose namespace {
312e580d831SEugene Zelenko 
313ed35cf27SArgyrios Kyrtzidis   struct CheckLocationContext {
314e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
315e580d831SEugene Zelenko 
316ed35cf27SArgyrios Kyrtzidis     const CheckersTy &Checkers;
317ed35cf27SArgyrios Kyrtzidis     SVal Loc;
318ed35cf27SArgyrios Kyrtzidis     bool IsLoad;
319a85f38baSTed Kremenek     const Stmt *NodeEx; /* Will become a CFGStmt */
320a85f38baSTed Kremenek     const Stmt *BoundEx;
321ed35cf27SArgyrios Kyrtzidis     ExprEngine &Eng;
322ed35cf27SArgyrios Kyrtzidis 
CheckLocationContext__anon915fba8f0511::CheckLocationContext323ed35cf27SArgyrios Kyrtzidis     CheckLocationContext(const CheckersTy &checkers,
324a85f38baSTed Kremenek                          SVal loc, bool isLoad, const Stmt *NodeEx,
325a85f38baSTed Kremenek                          const Stmt *BoundEx,
326a85f38baSTed Kremenek                          ExprEngine &eng)
327a85f38baSTed Kremenek         : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
328a85f38baSTed Kremenek           BoundEx(BoundEx), Eng(eng) {}
329ed35cf27SArgyrios Kyrtzidis 
checkers_begin__anon915fba8f0511::CheckLocationContext330e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0511::CheckLocationContext331e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
332e580d831SEugene Zelenko 
runChecker__anon915fba8f0511::CheckLocationContext333ed35cf27SArgyrios Kyrtzidis     void runChecker(CheckerManager::CheckLocationFunc checkFn,
3340bb9d1b9SAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
335754eafb7SAnna Zaks       ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
336754eafb7SAnna Zaks                                        ProgramPoint::PreStoreKind;
337a85f38baSTed Kremenek       const ProgramPoint &L =
338a85f38baSTed Kremenek         ProgramPoint::getProgramPoint(NodeEx, K,
339a85f38baSTed Kremenek                                       Pred->getLocationContext(),
340a85f38baSTed Kremenek                                       checkFn.Checker);
341b473816bSAnna Zaks       CheckerContext C(Bldr, Eng, Pred, L);
342a85f38baSTed Kremenek       checkFn(Loc, IsLoad, BoundEx, C);
343ed35cf27SArgyrios Kyrtzidis     }
344ed35cf27SArgyrios Kyrtzidis   };
345e580d831SEugene Zelenko 
346e580d831SEugene Zelenko } // namespace
347ed35cf27SArgyrios Kyrtzidis 
3489fc8faf9SAdrian Prantl /// Run checkers for load/store of a location.
349e594034fSAnna Zaks 
runCheckersForLocation(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,SVal location,bool isLoad,const Stmt * NodeEx,const Stmt * BoundEx,ExprEngine & Eng)350ed35cf27SArgyrios Kyrtzidis void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
35168cab73aSArgyrios Kyrtzidis                                             const ExplodedNodeSet &Src,
352ed35cf27SArgyrios Kyrtzidis                                             SVal location, bool isLoad,
353a85f38baSTed Kremenek                                             const Stmt *NodeEx,
354a85f38baSTed Kremenek                                             const Stmt *BoundEx,
355a85f38baSTed Kremenek                                             ExprEngine &Eng) {
356a85f38baSTed Kremenek   CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
357a85f38baSTed Kremenek                          BoundEx, Eng);
358d0732a66SArgyrios Kyrtzidis   expandGraphWithCheckers(C, Dst, Src);
35924ffc08fSArgyrios Kyrtzidis }
36024ffc08fSArgyrios Kyrtzidis 
361183f0fb4SArgyrios Kyrtzidis namespace {
362e580d831SEugene Zelenko 
363183f0fb4SArgyrios Kyrtzidis   struct CheckBindContext {
364e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
365e580d831SEugene Zelenko 
366183f0fb4SArgyrios Kyrtzidis     const CheckersTy &Checkers;
367183f0fb4SArgyrios Kyrtzidis     SVal Loc;
368183f0fb4SArgyrios Kyrtzidis     SVal Val;
369183f0fb4SArgyrios Kyrtzidis     const Stmt *S;
370183f0fb4SArgyrios Kyrtzidis     ExprEngine &Eng;
3710a0aa84dSJordan Rose     const ProgramPoint &PP;
372183f0fb4SArgyrios Kyrtzidis 
CheckBindContext__anon915fba8f0611::CheckBindContext373183f0fb4SArgyrios Kyrtzidis     CheckBindContext(const CheckersTy &checkers,
374e594034fSAnna Zaks                      SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
3750a0aa84dSJordan Rose                      const ProgramPoint &pp)
3760a0aa84dSJordan Rose         : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
377183f0fb4SArgyrios Kyrtzidis 
checkers_begin__anon915fba8f0611::CheckBindContext378e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0611::CheckBindContext379e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
380e580d831SEugene Zelenko 
runChecker__anon915fba8f0611::CheckBindContext381183f0fb4SArgyrios Kyrtzidis     void runChecker(CheckerManager::CheckBindFunc checkFn,
3820bb9d1b9SAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
3830a0aa84dSJordan Rose       const ProgramPoint &L = PP.withTag(checkFn.Checker);
384b473816bSAnna Zaks       CheckerContext C(Bldr, Eng, Pred, L);
385754eafb7SAnna Zaks 
3863e0f415dSAnna Zaks       checkFn(Loc, Val, S, C);
387183f0fb4SArgyrios Kyrtzidis     }
388183f0fb4SArgyrios Kyrtzidis   };
389e580d831SEugene Zelenko 
390e580d831SEugene Zelenko } // namespace
391183f0fb4SArgyrios Kyrtzidis 
3929fc8faf9SAdrian Prantl /// Run checkers for binding of a value to a location.
runCheckersForBind(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,SVal location,SVal val,const Stmt * S,ExprEngine & Eng,const ProgramPoint & PP)393183f0fb4SArgyrios Kyrtzidis void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
394183f0fb4SArgyrios Kyrtzidis                                         const ExplodedNodeSet &Src,
395183f0fb4SArgyrios Kyrtzidis                                         SVal location, SVal val,
396e594034fSAnna Zaks                                         const Stmt *S, ExprEngine &Eng,
3970a0aa84dSJordan Rose                                         const ProgramPoint &PP) {
3980a0aa84dSJordan Rose   CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
399183f0fb4SArgyrios Kyrtzidis   expandGraphWithCheckers(C, Dst, Src);
400183f0fb4SArgyrios Kyrtzidis }
401183f0fb4SArgyrios Kyrtzidis 
runCheckersForEndAnalysis(ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)402bf61d97aSArgyrios Kyrtzidis void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
403bf61d97aSArgyrios Kyrtzidis                                                BugReporter &BR,
404bf61d97aSArgyrios Kyrtzidis                                                ExprEngine &Eng) {
40596484286SMark de Wever   for (const auto &EndAnalysisChecker : EndAnalysisCheckers)
406e580d831SEugene Zelenko     EndAnalysisChecker(G, BR, Eng);
407bf61d97aSArgyrios Kyrtzidis }
408bf61d97aSArgyrios Kyrtzidis 
4098d922aa7SDevin Coughlin namespace {
410e580d831SEugene Zelenko 
4118d922aa7SDevin Coughlin struct CheckBeginFunctionContext {
412e580d831SEugene Zelenko   using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
413e580d831SEugene Zelenko 
4148d922aa7SDevin Coughlin   const CheckersTy &Checkers;
4158d922aa7SDevin Coughlin   ExprEngine &Eng;
4168d922aa7SDevin Coughlin   const ProgramPoint &PP;
4178d922aa7SDevin Coughlin 
CheckBeginFunctionContext__anon915fba8f0711::CheckBeginFunctionContext4188d922aa7SDevin Coughlin   CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
4198d922aa7SDevin Coughlin                             const ProgramPoint &PP)
4208d922aa7SDevin Coughlin       : Checkers(Checkers), Eng(Eng), PP(PP) {}
4218d922aa7SDevin Coughlin 
checkers_begin__anon915fba8f0711::CheckBeginFunctionContext422e580d831SEugene Zelenko   CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0711::CheckBeginFunctionContext423e580d831SEugene Zelenko   CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
424e580d831SEugene Zelenko 
runChecker__anon915fba8f0711::CheckBeginFunctionContext4258d922aa7SDevin Coughlin   void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
4268d922aa7SDevin Coughlin                   NodeBuilder &Bldr, ExplodedNode *Pred) {
4278d922aa7SDevin Coughlin     const ProgramPoint &L = PP.withTag(checkFn.Checker);
4288d922aa7SDevin Coughlin     CheckerContext C(Bldr, Eng, Pred, L);
4298d922aa7SDevin Coughlin 
4308d922aa7SDevin Coughlin     checkFn(C);
4318d922aa7SDevin Coughlin   }
4328d922aa7SDevin Coughlin };
433e580d831SEugene Zelenko 
434e580d831SEugene Zelenko } // namespace
4358d922aa7SDevin Coughlin 
runCheckersForBeginFunction(ExplodedNodeSet & Dst,const BlockEdge & L,ExplodedNode * Pred,ExprEngine & Eng)4368d922aa7SDevin Coughlin void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
4378d922aa7SDevin Coughlin                                                  const BlockEdge &L,
4388d922aa7SDevin Coughlin                                                  ExplodedNode *Pred,
4398d922aa7SDevin Coughlin                                                  ExprEngine &Eng) {
4408d922aa7SDevin Coughlin   ExplodedNodeSet Src;
4418d922aa7SDevin Coughlin   Src.insert(Pred);
4428d922aa7SDevin Coughlin   CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
4438d922aa7SDevin Coughlin   expandGraphWithCheckers(C, Dst, Src);
4448d922aa7SDevin Coughlin }
4458d922aa7SDevin Coughlin 
4469fc8faf9SAdrian Prantl /// Run checkers for end of path.
4473eae3341SAnna Zaks // Note, We do not chain the checker output (like in expandGraphWithCheckers)
4483eae3341SAnna Zaks // for this callback since end of path nodes are expected to be final.
runCheckersForEndFunction(NodeBuilderContext & BC,ExplodedNodeSet & Dst,ExplodedNode * Pred,ExprEngine & Eng,const ReturnStmt * RS)4493fdcc0bdSAnna Zaks void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
4503eae3341SAnna Zaks                                                ExplodedNodeSet &Dst,
4512510608eSAnna Zaks                                                ExplodedNode *Pred,
452ed8c05ccSReka Kovacs                                                ExprEngine &Eng,
453ed8c05ccSReka Kovacs                                                const ReturnStmt *RS) {
4540e912f3bSAleksei Sidorin   // We define the builder outside of the loop because if at least one checker
4550e912f3bSAleksei Sidorin   // creates a successor for Pred, we do not need to generate an
4563eae3341SAnna Zaks   // autotransition for it.
4573eae3341SAnna Zaks   NodeBuilder Bldr(Pred, Dst, BC);
45896484286SMark de Wever   for (const auto &checkFn : EndFunctionCheckers) {
45933e5a158SGeorge Karpenkov     const ProgramPoint &L =
46033e5a158SGeorge Karpenkov         FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
461b473816bSAnna Zaks     CheckerContext C(Bldr, Eng, Pred, L);
462ed8c05ccSReka Kovacs     checkFn(RS, C);
463506220feSArgyrios Kyrtzidis   }
464506220feSArgyrios Kyrtzidis }
465506220feSArgyrios Kyrtzidis 
466f380534aSAnna Zaks namespace {
467e580d831SEugene Zelenko 
468f380534aSAnna Zaks   struct CheckBranchConditionContext {
469e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
470e580d831SEugene Zelenko 
471f380534aSAnna Zaks     const CheckersTy &Checkers;
472f380534aSAnna Zaks     const Stmt *Condition;
473f380534aSAnna Zaks     ExprEngine &Eng;
474f380534aSAnna Zaks 
CheckBranchConditionContext__anon915fba8f0811::CheckBranchConditionContext475f380534aSAnna Zaks     CheckBranchConditionContext(const CheckersTy &checkers,
476f380534aSAnna Zaks                                 const Stmt *Cond, ExprEngine &eng)
477f380534aSAnna Zaks         : Checkers(checkers), Condition(Cond), Eng(eng) {}
478f380534aSAnna Zaks 
checkers_begin__anon915fba8f0811::CheckBranchConditionContext479e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0811::CheckBranchConditionContext480e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
481e580d831SEugene Zelenko 
runChecker__anon915fba8f0811::CheckBranchConditionContext482f380534aSAnna Zaks     void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
483f380534aSAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
484f380534aSAnna Zaks       ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
485f380534aSAnna Zaks                                      checkFn.Checker);
486b473816bSAnna Zaks       CheckerContext C(Bldr, Eng, Pred, L);
487f380534aSAnna Zaks       checkFn(Condition, C);
488f380534aSAnna Zaks     }
489f380534aSAnna Zaks   };
490e580d831SEugene Zelenko 
491e580d831SEugene Zelenko } // namespace
492f380534aSAnna Zaks 
4939fc8faf9SAdrian Prantl /// Run checkers for branch condition.
runCheckersForBranchCondition(const Stmt * Condition,ExplodedNodeSet & Dst,ExplodedNode * Pred,ExprEngine & Eng)494f380534aSAnna Zaks void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
495f380534aSAnna Zaks                                                    ExplodedNodeSet &Dst,
496a99b41f3SAnna Zaks                                                    ExplodedNode *Pred,
497753b3ca3SArgyrios Kyrtzidis                                                    ExprEngine &Eng) {
498f380534aSAnna Zaks   ExplodedNodeSet Src;
499f380534aSAnna Zaks   Src.insert(Pred);
500f380534aSAnna Zaks   CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
501f380534aSAnna Zaks   expandGraphWithCheckers(C, Dst, Src);
502753b3ca3SArgyrios Kyrtzidis }
503753b3ca3SArgyrios Kyrtzidis 
50413b2026bSArtem Dergachev namespace {
505e580d831SEugene Zelenko 
50613b2026bSArtem Dergachev   struct CheckNewAllocatorContext {
507e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
508e580d831SEugene Zelenko 
50913b2026bSArtem Dergachev     const CheckersTy &Checkers;
510f2be30deSKirstóf Umann     const CXXAllocatorCall &Call;
51113b2026bSArtem Dergachev     bool WasInlined;
51213b2026bSArtem Dergachev     ExprEngine &Eng;
51313b2026bSArtem Dergachev 
CheckNewAllocatorContext__anon915fba8f0911::CheckNewAllocatorContext514f2be30deSKirstóf Umann     CheckNewAllocatorContext(const CheckersTy &Checkers,
515f2be30deSKirstóf Umann                              const CXXAllocatorCall &Call, bool WasInlined,
516f2be30deSKirstóf Umann                              ExprEngine &Eng)
517f2be30deSKirstóf Umann         : Checkers(Checkers), Call(Call), WasInlined(WasInlined), Eng(Eng) {}
51813b2026bSArtem Dergachev 
checkers_begin__anon915fba8f0911::CheckNewAllocatorContext519e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0911::CheckNewAllocatorContext520e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
521e580d831SEugene Zelenko 
runChecker__anon915fba8f0911::CheckNewAllocatorContext52213b2026bSArtem Dergachev     void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
52313b2026bSArtem Dergachev                     NodeBuilder &Bldr, ExplodedNode *Pred) {
524f2be30deSKirstóf Umann       ProgramPoint L =
525f2be30deSKirstóf Umann           PostAllocatorCall(Call.getOriginExpr(), Pred->getLocationContext());
52613b2026bSArtem Dergachev       CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
527f2be30deSKirstóf Umann       checkFn(cast<CXXAllocatorCall>(*Call.cloneWithState(Pred->getState())),
528f2be30deSKirstóf Umann               C);
52913b2026bSArtem Dergachev     }
53013b2026bSArtem Dergachev   };
531e580d831SEugene Zelenko 
532e580d831SEugene Zelenko } // namespace
53313b2026bSArtem Dergachev 
runCheckersForNewAllocator(const CXXAllocatorCall & Call,ExplodedNodeSet & Dst,ExplodedNode * Pred,ExprEngine & Eng,bool WasInlined)534f2be30deSKirstóf Umann void CheckerManager::runCheckersForNewAllocator(const CXXAllocatorCall &Call,
535f2be30deSKirstóf Umann                                                 ExplodedNodeSet &Dst,
536f2be30deSKirstóf Umann                                                 ExplodedNode *Pred,
537f2be30deSKirstóf Umann                                                 ExprEngine &Eng,
538f2be30deSKirstóf Umann                                                 bool WasInlined) {
53913b2026bSArtem Dergachev   ExplodedNodeSet Src;
54013b2026bSArtem Dergachev   Src.insert(Pred);
541f2be30deSKirstóf Umann   CheckNewAllocatorContext C(NewAllocatorCheckers, Call, WasInlined, Eng);
54213b2026bSArtem Dergachev   expandGraphWithCheckers(C, Dst, Src);
54313b2026bSArtem Dergachev }
54413b2026bSArtem Dergachev 
5459fc8faf9SAdrian Prantl /// Run checkers for live symbols.
runCheckersForLiveSymbols(ProgramStateRef state,SymbolReaper & SymReaper)54649b1e38eSTed Kremenek void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
547c26f15dbSArgyrios Kyrtzidis                                                SymbolReaper &SymReaper) {
54896484286SMark de Wever   for (const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
549e580d831SEugene Zelenko     LiveSymbolsChecker(state, SymReaper);
550c26f15dbSArgyrios Kyrtzidis }
551c26f15dbSArgyrios Kyrtzidis 
552c26f15dbSArgyrios Kyrtzidis namespace {
553e580d831SEugene Zelenko 
554c26f15dbSArgyrios Kyrtzidis   struct CheckDeadSymbolsContext {
555e580d831SEugene Zelenko     using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
556e580d831SEugene Zelenko 
557c26f15dbSArgyrios Kyrtzidis     const CheckersTy &Checkers;
558c26f15dbSArgyrios Kyrtzidis     SymbolReaper &SR;
559c26f15dbSArgyrios Kyrtzidis     const Stmt *S;
560c26f15dbSArgyrios Kyrtzidis     ExprEngine &Eng;
5617e53bd6fSAnna Zaks     ProgramPoint::Kind ProgarmPointKind;
562c26f15dbSArgyrios Kyrtzidis 
CheckDeadSymbolsContext__anon915fba8f0a11::CheckDeadSymbolsContext563c26f15dbSArgyrios Kyrtzidis     CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
5647e53bd6fSAnna Zaks                             const Stmt *s, ExprEngine &eng,
5657e53bd6fSAnna Zaks                             ProgramPoint::Kind K)
5667e53bd6fSAnna Zaks         : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
567c26f15dbSArgyrios Kyrtzidis 
checkers_begin__anon915fba8f0a11::CheckDeadSymbolsContext568e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
checkers_end__anon915fba8f0a11::CheckDeadSymbolsContext569e580d831SEugene Zelenko     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
570e580d831SEugene Zelenko 
runChecker__anon915fba8f0a11::CheckDeadSymbolsContext571c26f15dbSArgyrios Kyrtzidis     void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
5720bb9d1b9SAnna Zaks                     NodeBuilder &Bldr, ExplodedNode *Pred) {
5737e53bd6fSAnna Zaks       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
574754eafb7SAnna Zaks                                 Pred->getLocationContext(), checkFn.Checker);
575b473816bSAnna Zaks       CheckerContext C(Bldr, Eng, Pred, L);
576754eafb7SAnna Zaks 
5777e53bd6fSAnna Zaks       // Note, do not pass the statement to the checkers without letting them
5787e53bd6fSAnna Zaks       // differentiate if we ran remove dead bindings before or after the
5797e53bd6fSAnna Zaks       // statement.
580c26f15dbSArgyrios Kyrtzidis       checkFn(SR, C);
581c26f15dbSArgyrios Kyrtzidis     }
582c26f15dbSArgyrios Kyrtzidis   };
583e580d831SEugene Zelenko 
584e580d831SEugene Zelenko } // namespace
585c26f15dbSArgyrios Kyrtzidis 
5869fc8faf9SAdrian Prantl /// Run checkers for dead symbols.
runCheckersForDeadSymbols(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,SymbolReaper & SymReaper,const Stmt * S,ExprEngine & Eng,ProgramPoint::Kind K)587c26f15dbSArgyrios Kyrtzidis void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
588c26f15dbSArgyrios Kyrtzidis                                                const ExplodedNodeSet &Src,
589c26f15dbSArgyrios Kyrtzidis                                                SymbolReaper &SymReaper,
590c26f15dbSArgyrios Kyrtzidis                                                const Stmt *S,
5917e53bd6fSAnna Zaks                                                ExprEngine &Eng,
5927e53bd6fSAnna Zaks                                                ProgramPoint::Kind K) {
5937e53bd6fSAnna Zaks   CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
594c26f15dbSArgyrios Kyrtzidis   expandGraphWithCheckers(C, Dst, Src);
595c26f15dbSArgyrios Kyrtzidis }
596c26f15dbSArgyrios Kyrtzidis 
5979fc8faf9SAdrian Prantl /// Run checkers for region changes.
59849b1e38eSTed Kremenek ProgramStateRef
runCheckersForRegionChanges(ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > ExplicitRegions,ArrayRef<const MemRegion * > Regions,const LocationContext * LCtx,const CallEvent * Call)59949b1e38eSTed Kremenek CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
600dc15415dSAnna Zaks                                             const InvalidatedSymbols *invalidated,
6011fad6631SJordy Rose                                             ArrayRef<const MemRegion *> ExplicitRegions,
6023d34834bSAnna Zaks                                             ArrayRef<const MemRegion *> Regions,
603b570195cSAnna Zaks                                             const LocationContext *LCtx,
604742920c8SJordan Rose                                             const CallEvent *Call) {
60596484286SMark de Wever   for (const auto &RegionChangesChecker : RegionChangesCheckers) {
606c26f15dbSArgyrios Kyrtzidis     // If any checker declares the state infeasible (or if it starts that way),
607c26f15dbSArgyrios Kyrtzidis     // bail out.
608c26f15dbSArgyrios Kyrtzidis     if (!state)
6090dbb783cSCraig Topper       return nullptr;
610e580d831SEugene Zelenko     state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
611b570195cSAnna Zaks                                  LCtx, Call);
612c26f15dbSArgyrios Kyrtzidis   }
613c26f15dbSArgyrios Kyrtzidis   return state;
614c26f15dbSArgyrios Kyrtzidis }
615c26f15dbSArgyrios Kyrtzidis 
6169fc8faf9SAdrian Prantl /// Run checkers to process symbol escape event.
617dc15415dSAnna Zaks ProgramStateRef
runCheckersForPointerEscape(ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)618dc15415dSAnna Zaks CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
619dc15415dSAnna Zaks                                    const InvalidatedSymbols &Escaped,
620acdc13cbSAnna Zaks                                    const CallEvent *Call,
621333481b9SAnna Zaks                                    PointerEscapeKind Kind,
622424ad95fSAnton Yartsev                                    RegionAndSymbolInvalidationTraits *ETraits) {
6230dbb783cSCraig Topper   assert((Call != nullptr ||
624acdc13cbSAnna Zaks           (Kind != PSK_DirectEscapeOnCall &&
625acdc13cbSAnna Zaks            Kind != PSK_IndirectEscapeOnCall)) &&
626acdc13cbSAnna Zaks          "Call must not be NULL when escaping on call");
62796484286SMark de Wever   for (const auto &PointerEscapeChecker : PointerEscapeCheckers) {
628333481b9SAnna Zaks     // If any checker declares the state infeasible (or if it starts that
629333481b9SAnna Zaks     //  way), bail out.
630dc15415dSAnna Zaks     if (!State)
6310dbb783cSCraig Topper       return nullptr;
632e580d831SEugene Zelenko     State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
633dc15415dSAnna Zaks   }
634dc15415dSAnna Zaks   return State;
635dc15415dSAnna Zaks }
636dc15415dSAnna Zaks 
6379fc8faf9SAdrian Prantl /// Run checkers for handling assumptions on symbolic values.
63849b1e38eSTed Kremenek ProgramStateRef
runCheckersForEvalAssume(ProgramStateRef state,SVal Cond,bool Assumption)63949b1e38eSTed Kremenek CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
640183f0fb4SArgyrios Kyrtzidis                                          SVal Cond, bool Assumption) {
64196484286SMark de Wever   for (const auto &EvalAssumeChecker : EvalAssumeCheckers) {
642183f0fb4SArgyrios Kyrtzidis     // If any checker declares the state infeasible (or if it starts that way),
643183f0fb4SArgyrios Kyrtzidis     // bail out.
644183f0fb4SArgyrios Kyrtzidis     if (!state)
6450dbb783cSCraig Topper       return nullptr;
646e580d831SEugene Zelenko     state = EvalAssumeChecker(state, Cond, Assumption);
647183f0fb4SArgyrios Kyrtzidis   }
648183f0fb4SArgyrios Kyrtzidis   return state;
649183f0fb4SArgyrios Kyrtzidis }
650183f0fb4SArgyrios Kyrtzidis 
6519fc8faf9SAdrian Prantl /// Run checkers for evaluating a call.
652da02a25aSArgyrios Kyrtzidis /// Only one checker will evaluate the call.
runCheckersForEvalCall(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const CallEvent & Call,ExprEngine & Eng,const EvalCallOptions & CallOpts)653da02a25aSArgyrios Kyrtzidis void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
654da02a25aSArgyrios Kyrtzidis                                             const ExplodedNodeSet &Src,
655ce6c99a5SJordan Rose                                             const CallEvent &Call,
65637c1bf21SNithin Vadukkumchery Rajendrakumar                                             ExprEngine &Eng,
65737c1bf21SNithin Vadukkumchery Rajendrakumar                                             const EvalCallOptions &CallOpts) {
658f2be30deSKirstóf Umann   for (auto *const Pred : Src) {
659*9b5c9c46SBalazs Benics     Optional<CheckerNameRef> evaluatorChecker;
66077f8661dSAnna Zaks 
6610bb9d1b9SAnna Zaks     ExplodedNodeSet checkDst;
6620bb9d1b9SAnna Zaks     NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
66388b690ddSJordan Rose 
66488b690ddSJordan Rose     // Check if any of the EvalCall callbacks can evaluate the call.
66596484286SMark de Wever     for (const auto &EvalCallChecker : EvalCallCheckers) {
66644820630SArtem Dergachev       // TODO: Support the situation when the call doesn't correspond
66744820630SArtem Dergachev       // to any Expr.
66844820630SArtem Dergachev       ProgramPoint L = ProgramPoint::getProgramPoint(
66937c1bf21SNithin Vadukkumchery Rajendrakumar           Call.getOriginExpr(), ProgramPoint::PostStmtKind,
67037c1bf21SNithin Vadukkumchery Rajendrakumar           Pred->getLocationContext(), EvalCallChecker.Checker);
6718c57c4baSAnna Zaks       bool evaluated = false;
6728c57c4baSAnna Zaks       { // CheckerContext generates transitions(populates checkDest) on
6738c57c4baSAnna Zaks         // destruction, so introduce the scope to make sure it gets properly
6748c57c4baSAnna Zaks         // populated.
675b473816bSAnna Zaks         CheckerContext C(B, Eng, Pred, L);
67644820630SArtem Dergachev         evaluated = EvalCallChecker(Call, C);
6778c57c4baSAnna Zaks       }
678*9b5c9c46SBalazs Benics #ifndef NDEBUG
679*9b5c9c46SBalazs Benics       if (evaluated && evaluatorChecker) {
680*9b5c9c46SBalazs Benics         const auto toString = [](const CallEvent &Call) -> std::string {
681*9b5c9c46SBalazs Benics           std::string Buf;
682*9b5c9c46SBalazs Benics           llvm::raw_string_ostream OS(Buf);
683*9b5c9c46SBalazs Benics           Call.dump(OS);
684*9b5c9c46SBalazs Benics           OS.flush();
685*9b5c9c46SBalazs Benics           return Buf;
686*9b5c9c46SBalazs Benics         };
687*9b5c9c46SBalazs Benics         std::string AssertionMessage = llvm::formatv(
688*9b5c9c46SBalazs Benics             "The '{0}' call has been already evaluated by the {1} checker, "
689*9b5c9c46SBalazs Benics             "while the {2} checker also tried to evaluate the same call. At "
690*9b5c9c46SBalazs Benics             "most one checker supposed to evaluate a call.",
691*9b5c9c46SBalazs Benics             toString(Call), evaluatorChecker->getName(),
692*9b5c9c46SBalazs Benics             EvalCallChecker.Checker->getCheckerName());
693*9b5c9c46SBalazs Benics         llvm_unreachable(AssertionMessage.c_str());
694*9b5c9c46SBalazs Benics       }
695*9b5c9c46SBalazs Benics #endif
696da02a25aSArgyrios Kyrtzidis       if (evaluated) {
697*9b5c9c46SBalazs Benics         evaluatorChecker = EvalCallChecker.Checker->getCheckerName();
698da02a25aSArgyrios Kyrtzidis         Dst.insert(checkDst);
699da02a25aSArgyrios Kyrtzidis #ifdef NDEBUG
700da02a25aSArgyrios Kyrtzidis         break; // on release don't check that no other checker also evals.
701da02a25aSArgyrios Kyrtzidis #endif
702da02a25aSArgyrios Kyrtzidis       }
703da02a25aSArgyrios Kyrtzidis     }
704da02a25aSArgyrios Kyrtzidis 
70577f8661dSAnna Zaks     // If none of the checkers evaluated the call, ask ExprEngine to handle it.
706*9b5c9c46SBalazs Benics     if (!evaluatorChecker) {
7073136cf9dSAnna Zaks       NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
70837c1bf21SNithin Vadukkumchery Rajendrakumar       Eng.defaultEvalCall(B, Pred, Call, CallOpts);
7093136cf9dSAnna Zaks     }
710da02a25aSArgyrios Kyrtzidis   }
711da02a25aSArgyrios Kyrtzidis }
712da02a25aSArgyrios Kyrtzidis 
7139fc8faf9SAdrian Prantl /// Run checkers for the entire Translation Unit.
runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR)714e69ab05fSTed Kremenek void CheckerManager::runCheckersOnEndOfTranslationUnit(
715e69ab05fSTed Kremenek                                                   const TranslationUnitDecl *TU,
716e69ab05fSTed Kremenek                                                   AnalysisManager &mgr,
717e69ab05fSTed Kremenek                                                   BugReporter &BR) {
71896484286SMark de Wever   for (const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
719e580d831SEugene Zelenko     EndOfTranslationUnitChecker(TU, mgr, BR);
720e69ab05fSTed Kremenek }
721e69ab05fSTed Kremenek 
runCheckersForPrintStateJson(raw_ostream & Out,ProgramStateRef State,const char * NL,unsigned int Space,bool IsDot) const722b7ca72a1SCsaba Dabis void CheckerManager::runCheckersForPrintStateJson(raw_ostream &Out,
72349b1e38eSTed Kremenek                                                   ProgramStateRef State,
724b7ca72a1SCsaba Dabis                                                   const char *NL,
725b7ca72a1SCsaba Dabis                                                   unsigned int Space,
726b7ca72a1SCsaba Dabis                                                   bool IsDot) const {
727b7ca72a1SCsaba Dabis   Indent(Out, Space, IsDot) << "\"checker_messages\": ";
728b7ca72a1SCsaba Dabis 
729b7ca72a1SCsaba Dabis   // Create a temporary stream to see whether we have any message.
730b7ca72a1SCsaba Dabis   SmallString<1024> TempBuf;
731b7ca72a1SCsaba Dabis   llvm::raw_svector_ostream TempOut(TempBuf);
732b7ca72a1SCsaba Dabis   unsigned int InnerSpace = Space + 2;
733b7ca72a1SCsaba Dabis 
734b7ca72a1SCsaba Dabis   // Create the new-line in JSON with enough space.
735b7ca72a1SCsaba Dabis   SmallString<128> NewLine;
736b7ca72a1SCsaba Dabis   llvm::raw_svector_ostream NLOut(NewLine);
737b7ca72a1SCsaba Dabis   NLOut << "\", " << NL;                     // Inject the ending and a new line
738b7ca72a1SCsaba Dabis   Indent(NLOut, InnerSpace, IsDot) << "\"";  // then begin the next message.
739b7ca72a1SCsaba Dabis 
740b7ca72a1SCsaba Dabis   ++Space;
741b7ca72a1SCsaba Dabis   bool HasMessage = false;
742b7ca72a1SCsaba Dabis 
743b7ca72a1SCsaba Dabis   // Store the last CheckerTag.
744b7ca72a1SCsaba Dabis   const void *LastCT = nullptr;
745b7ca72a1SCsaba Dabis   for (const auto &CT : CheckerTags) {
746b7ca72a1SCsaba Dabis     // See whether the current checker has a message.
747b7ca72a1SCsaba Dabis     CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
748b7ca72a1SCsaba Dabis 
749b7ca72a1SCsaba Dabis     if (TempBuf.empty())
750b7ca72a1SCsaba Dabis       continue;
751b7ca72a1SCsaba Dabis 
752b7ca72a1SCsaba Dabis     if (!HasMessage) {
753b7ca72a1SCsaba Dabis       Out << '[' << NL;
754b7ca72a1SCsaba Dabis       HasMessage = true;
755b7ca72a1SCsaba Dabis     }
756b7ca72a1SCsaba Dabis 
757b7ca72a1SCsaba Dabis     LastCT = &CT;
758b7ca72a1SCsaba Dabis     TempBuf.clear();
759b7ca72a1SCsaba Dabis   }
760b7ca72a1SCsaba Dabis 
761b7ca72a1SCsaba Dabis   for (const auto &CT : CheckerTags) {
762b7ca72a1SCsaba Dabis     // See whether the current checker has a message.
763b7ca72a1SCsaba Dabis     CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
764b7ca72a1SCsaba Dabis 
765b7ca72a1SCsaba Dabis     if (TempBuf.empty())
766b7ca72a1SCsaba Dabis       continue;
767b7ca72a1SCsaba Dabis 
768b7ca72a1SCsaba Dabis     Indent(Out, Space, IsDot)
76972649423SKristof Umann         << "{ \"checker\": \"" << CT.second->getCheckerName().getName()
770b7ca72a1SCsaba Dabis         << "\", \"messages\": [" << NL;
771b7ca72a1SCsaba Dabis     Indent(Out, InnerSpace, IsDot)
772b7ca72a1SCsaba Dabis         << '\"' << TempBuf.str().trim() << '\"' << NL;
773b7ca72a1SCsaba Dabis     Indent(Out, Space, IsDot) << "]}";
774b7ca72a1SCsaba Dabis 
775b7ca72a1SCsaba Dabis     if (&CT != LastCT)
776b7ca72a1SCsaba Dabis       Out << ',';
777b7ca72a1SCsaba Dabis     Out << NL;
778b7ca72a1SCsaba Dabis 
779b7ca72a1SCsaba Dabis     TempBuf.clear();
780b7ca72a1SCsaba Dabis   }
781b7ca72a1SCsaba Dabis 
782b7ca72a1SCsaba Dabis   // It is the last element of the 'program_state' so do not add a comma.
783b7ca72a1SCsaba Dabis   if (HasMessage)
784b7ca72a1SCsaba Dabis     Indent(Out, --Space, IsDot) << "]";
785b7ca72a1SCsaba Dabis   else
786b7ca72a1SCsaba Dabis     Out << "null";
787b7ca72a1SCsaba Dabis 
788b7ca72a1SCsaba Dabis   Out << NL;
78958a20d31SJordy Rose }
79058a20d31SJordy Rose 
791ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
792ed35cf27SArgyrios Kyrtzidis // Internal registration functions for AST traversing.
793ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
794ed35cf27SArgyrios Kyrtzidis 
_registerForDecl(CheckDeclFunc checkfn,HandlesDeclFunc isForDeclFn)795ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
796ed35cf27SArgyrios Kyrtzidis                                       HandlesDeclFunc isForDeclFn) {
797ed35cf27SArgyrios Kyrtzidis   DeclCheckerInfo info = { checkfn, isForDeclFn };
798ed35cf27SArgyrios Kyrtzidis   DeclCheckers.push_back(info);
79924ffc08fSArgyrios Kyrtzidis }
800ed35cf27SArgyrios Kyrtzidis 
_registerForBody(CheckDeclFunc checkfn)801ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
802ed35cf27SArgyrios Kyrtzidis   BodyCheckers.push_back(checkfn);
803ed35cf27SArgyrios Kyrtzidis }
804ed35cf27SArgyrios Kyrtzidis 
805ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
806ed35cf27SArgyrios Kyrtzidis // Internal registration functions for path-sensitive checking.
807ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
808ed35cf27SArgyrios Kyrtzidis 
_registerForPreStmt(CheckStmtFunc checkfn,HandlesStmtFunc isForStmtFn)809ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
810ed35cf27SArgyrios Kyrtzidis                                          HandlesStmtFunc isForStmtFn) {
811ed35cf27SArgyrios Kyrtzidis   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
812ed35cf27SArgyrios Kyrtzidis   StmtCheckers.push_back(info);
813ed35cf27SArgyrios Kyrtzidis }
814e580d831SEugene Zelenko 
_registerForPostStmt(CheckStmtFunc checkfn,HandlesStmtFunc isForStmtFn)815ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
816ed35cf27SArgyrios Kyrtzidis                                           HandlesStmtFunc isForStmtFn) {
817ed35cf27SArgyrios Kyrtzidis   StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
818ed35cf27SArgyrios Kyrtzidis   StmtCheckers.push_back(info);
819ed35cf27SArgyrios Kyrtzidis }
820ed35cf27SArgyrios Kyrtzidis 
_registerForPreObjCMessage(CheckObjCMessageFunc checkfn)821ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
822ed35cf27SArgyrios Kyrtzidis   PreObjCMessageCheckers.push_back(checkfn);
823ed35cf27SArgyrios Kyrtzidis }
824ca5ab2b0SDevin Coughlin 
_registerForObjCMessageNil(CheckObjCMessageFunc checkfn)825ca5ab2b0SDevin Coughlin void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
826ca5ab2b0SDevin Coughlin   ObjCMessageNilCheckers.push_back(checkfn);
827ca5ab2b0SDevin Coughlin }
828ca5ab2b0SDevin Coughlin 
_registerForPostObjCMessage(CheckObjCMessageFunc checkfn)829ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
830ed35cf27SArgyrios Kyrtzidis   PostObjCMessageCheckers.push_back(checkfn);
831ed35cf27SArgyrios Kyrtzidis }
832ed35cf27SArgyrios Kyrtzidis 
_registerForPreCall(CheckCallFunc checkfn)833afe7c2c2SJordan Rose void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
834afe7c2c2SJordan Rose   PreCallCheckers.push_back(checkfn);
835afe7c2c2SJordan Rose }
_registerForPostCall(CheckCallFunc checkfn)836afe7c2c2SJordan Rose void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
837afe7c2c2SJordan Rose   PostCallCheckers.push_back(checkfn);
838afe7c2c2SJordan Rose }
839afe7c2c2SJordan Rose 
_registerForLocation(CheckLocationFunc checkfn)840ed35cf27SArgyrios Kyrtzidis void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
841ed35cf27SArgyrios Kyrtzidis   LocationCheckers.push_back(checkfn);
842ed35cf27SArgyrios Kyrtzidis }
843ed35cf27SArgyrios Kyrtzidis 
_registerForBind(CheckBindFunc checkfn)844183f0fb4SArgyrios Kyrtzidis void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
845183f0fb4SArgyrios Kyrtzidis   BindCheckers.push_back(checkfn);
846183f0fb4SArgyrios Kyrtzidis }
847183f0fb4SArgyrios Kyrtzidis 
_registerForEndAnalysis(CheckEndAnalysisFunc checkfn)848bf61d97aSArgyrios Kyrtzidis void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
849bf61d97aSArgyrios Kyrtzidis   EndAnalysisCheckers.push_back(checkfn);
850bf61d97aSArgyrios Kyrtzidis }
851bf61d97aSArgyrios Kyrtzidis 
_registerForBeginFunction(CheckBeginFunctionFunc checkfn)8528d922aa7SDevin Coughlin void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
8538d922aa7SDevin Coughlin   BeginFunctionCheckers.push_back(checkfn);
8548d922aa7SDevin Coughlin }
8558d922aa7SDevin Coughlin 
_registerForEndFunction(CheckEndFunctionFunc checkfn)8563fdcc0bdSAnna Zaks void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
8573fdcc0bdSAnna Zaks   EndFunctionCheckers.push_back(checkfn);
858506220feSArgyrios Kyrtzidis }
859506220feSArgyrios Kyrtzidis 
_registerForBranchCondition(CheckBranchConditionFunc checkfn)860753b3ca3SArgyrios Kyrtzidis void CheckerManager::_registerForBranchCondition(
861753b3ca3SArgyrios Kyrtzidis                                              CheckBranchConditionFunc checkfn) {
862753b3ca3SArgyrios Kyrtzidis   BranchConditionCheckers.push_back(checkfn);
863753b3ca3SArgyrios Kyrtzidis }
864753b3ca3SArgyrios Kyrtzidis 
_registerForNewAllocator(CheckNewAllocatorFunc checkfn)86513b2026bSArtem Dergachev void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
86613b2026bSArtem Dergachev   NewAllocatorCheckers.push_back(checkfn);
86713b2026bSArtem Dergachev }
86813b2026bSArtem Dergachev 
_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn)869c26f15dbSArgyrios Kyrtzidis void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
870c26f15dbSArgyrios Kyrtzidis   LiveSymbolsCheckers.push_back(checkfn);
871c26f15dbSArgyrios Kyrtzidis }
872c26f15dbSArgyrios Kyrtzidis 
_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn)873c26f15dbSArgyrios Kyrtzidis void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
874c26f15dbSArgyrios Kyrtzidis   DeadSymbolsCheckers.push_back(checkfn);
875c26f15dbSArgyrios Kyrtzidis }
876c26f15dbSArgyrios Kyrtzidis 
_registerForRegionChanges(CheckRegionChangesFunc checkfn)8771485992eSAnna Zaks void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
8781485992eSAnna Zaks   RegionChangesCheckers.push_back(checkfn);
879c26f15dbSArgyrios Kyrtzidis }
880c26f15dbSArgyrios Kyrtzidis 
_registerForPointerEscape(CheckPointerEscapeFunc checkfn)881dc15415dSAnna Zaks void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
882dc15415dSAnna Zaks   PointerEscapeCheckers.push_back(checkfn);
883dc15415dSAnna Zaks }
884dc15415dSAnna Zaks 
_registerForConstPointerEscape(CheckPointerEscapeFunc checkfn)885333481b9SAnna Zaks void CheckerManager::_registerForConstPointerEscape(
886333481b9SAnna Zaks                                           CheckPointerEscapeFunc checkfn) {
887333481b9SAnna Zaks   PointerEscapeCheckers.push_back(checkfn);
888333481b9SAnna Zaks }
889333481b9SAnna Zaks 
_registerForEvalAssume(EvalAssumeFunc checkfn)890183f0fb4SArgyrios Kyrtzidis void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
891183f0fb4SArgyrios Kyrtzidis   EvalAssumeCheckers.push_back(checkfn);
892183f0fb4SArgyrios Kyrtzidis }
893183f0fb4SArgyrios Kyrtzidis 
_registerForEvalCall(EvalCallFunc checkfn)894da02a25aSArgyrios Kyrtzidis void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
895da02a25aSArgyrios Kyrtzidis   EvalCallCheckers.push_back(checkfn);
896da02a25aSArgyrios Kyrtzidis }
897da02a25aSArgyrios Kyrtzidis 
_registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn)898e69ab05fSTed Kremenek void CheckerManager::_registerForEndOfTranslationUnit(
899e69ab05fSTed Kremenek                                             CheckEndOfTranslationUnit checkfn) {
900e69ab05fSTed Kremenek   EndOfTranslationUnitCheckers.push_back(checkfn);
901e69ab05fSTed Kremenek }
902e69ab05fSTed Kremenek 
903ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
904ed35cf27SArgyrios Kyrtzidis // Implementation details.
905ed35cf27SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
906ed35cf27SArgyrios Kyrtzidis 
90791c98670SBenjamin Kramer const CheckerManager::CachedStmtCheckers &
getCachedStmtCheckersFor(const Stmt * S,bool isPreVisit)908ed35cf27SArgyrios Kyrtzidis CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
909ed35cf27SArgyrios Kyrtzidis   assert(S);
910ed35cf27SArgyrios Kyrtzidis 
91191c98670SBenjamin Kramer   unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
91291c98670SBenjamin Kramer   CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
91391c98670SBenjamin Kramer   if (CCI != CachedStmtCheckersMap.end())
91491c98670SBenjamin Kramer     return CCI->second;
915ed35cf27SArgyrios Kyrtzidis 
91691c98670SBenjamin Kramer   // Find the checkers that should run for this Stmt and cache them.
91791c98670SBenjamin Kramer   CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
918e580d831SEugene Zelenko   for (const auto &Info : StmtCheckers)
91991c98670SBenjamin Kramer     if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
92091c98670SBenjamin Kramer       Checkers.push_back(Info.CheckFn);
92191c98670SBenjamin Kramer   return Checkers;
922ed35cf27SArgyrios Kyrtzidis }
923