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