21 using namespace clang;
25 return !StmtCheckers.empty() ||
26 !PreObjCMessageCheckers.empty() ||
27 !PostObjCMessageCheckers.empty() ||
28 !PreCallCheckers.empty() ||
29 !PostCallCheckers.empty() ||
30 !LocationCheckers.empty() ||
31 !BindCheckers.empty() ||
32 !EndAnalysisCheckers.empty() ||
33 !EndFunctionCheckers.empty() ||
34 !BranchConditionCheckers.empty() ||
35 !LiveSymbolsCheckers.empty() ||
36 !DeadSymbolsCheckers.empty() ||
37 !RegionChangesCheckers.empty() ||
38 !EvalAssumeCheckers.empty() ||
39 !EvalCallCheckers.empty();
46 for (llvm::DenseMap<EventTag, EventInfo>::iterator
47 I = Events.begin(), E = Events.end(); I != E; ++I)
48 assert(I->second.HasDispatcher &&
"No dispatcher registered for an event");
60 unsigned DeclKind = D->
getKind();
62 CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
63 if (CCI != CachedDeclCheckersMap.end()) {
64 checkers = &(CCI->second);
67 checkers = &CachedDeclCheckersMap[DeclKind];
68 for (
unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
69 DeclCheckerInfo &info = DeclCheckers[i];
70 if (info.IsForDeclFn(D))
71 checkers->push_back(info.CheckFn);
76 for (CachedDeclCheckers::iterator
77 I = checkers->begin(), E = checkers->end(); I != E; ++I)
85 for (
unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
86 BodyCheckers[i](D, mgr, BR);
93 template <
typename CHECK_CTX>
101 typename CHECK_CTX::CheckersTy::const_iterator
102 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
111 for (; I != E; ++I) {
116 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
123 checkCtx.runChecker(*I, B, *NI);
127 if (CurrSet->
empty())
136 struct CheckStmtContext {
139 const CheckersTy &Checkers;
144 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
145 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
147 CheckStmtContext(
bool isPreVisit,
const CheckersTy &checkers,
149 : IsPreVisit(isPreVisit), Checkers(checkers),
S(s), Eng(eng),
150 WasInlined(wasInlined) {}
172 CheckStmtContext
C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
178 struct CheckObjCMessageContext {
179 typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
180 bool IsPreVisit, WasInlined;
181 const CheckersTy &Checkers;
185 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
186 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
188 CheckObjCMessageContext(
bool isPreVisit,
const CheckersTy &checkers,
191 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
192 Msg(msg), Eng(eng) { }
211 CheckObjCMessageContext
C(isPreVisit,
212 isPreVisit ? PreObjCMessageCheckers
213 : PostObjCMessageCheckers,
214 msg, Eng, WasInlined);
221 struct CheckCallContext {
222 typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy;
223 bool IsPreVisit, WasInlined;
224 const CheckersTy &Checkers;
228 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
229 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
231 CheckCallContext(
bool isPreVisit,
const CheckersTy &checkers,
234 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
235 Call(call), Eng(eng) { }
242 checkFn(*Call.cloneWithState(Pred->
getState()),
C);
254 CheckCallContext
C(isPreVisit,
255 isPreVisit ? PreCallCheckers
257 Call, Eng, WasInlined);
262 struct CheckLocationContext {
263 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
264 const CheckersTy &Checkers;
271 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
272 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
274 CheckLocationContext(
const CheckersTy &checkers,
275 SVal loc,
bool isLoad,
const Stmt *NodeEx,
278 : Checkers(checkers),
Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
279 BoundEx(BoundEx), Eng(eng) {}
290 checkFn(
Loc, IsLoad, BoundEx,
C);
299 SVal location,
bool isLoad,
303 CheckLocationContext
C(LocationCheckers, location, isLoad, NodeEx,
309 struct CheckBindContext {
310 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
311 const CheckersTy &Checkers;
318 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
319 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
321 CheckBindContext(
const CheckersTy &checkers,
324 : Checkers(checkers),
Loc(loc), Val(val),
S(s), Eng(eng), PP(pp) {}
331 checkFn(
Loc, Val,
S,
C);
342 CheckBindContext
C(BindCheckers, location, val, S, Eng, PP);
349 for (
unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
350 EndAnalysisCheckers[i](G, BR, Eng);
365 for (
unsigned i = 0, e = EndFunctionCheckers.size(); i != e; ++i) {
377 struct CheckBranchConditionContext {
378 typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
379 const CheckersTy &Checkers;
380 const Stmt *Condition;
383 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
384 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
386 CheckBranchConditionContext(
const CheckersTy &checkers,
388 : Checkers(checkers), Condition(Cond), Eng(eng) {}
395 checkFn(Condition,
C);
407 CheckBranchConditionContext
C(BranchConditionCheckers, Condition, Eng);
414 for (
unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
415 LiveSymbolsCheckers[i](state, SymReaper);
419 struct CheckDeadSymbolsContext {
420 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
421 const CheckersTy &Checkers;
427 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
428 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
430 CheckDeadSymbolsContext(
const CheckersTy &checkers,
SymbolReaper &sr,
433 : Checkers(checkers), SR(sr),
S(s), Eng(eng), ProgarmPointKind(K) { }
456 CheckDeadSymbolsContext
C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
462 for (
unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
463 if (RegionChangesCheckers[i].WantUpdateFn(state))
476 for (
unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
481 state = RegionChangesCheckers[i].CheckFn(state, invalidated,
482 ExplicitRegions, Regions, Call);
494 assert((Call !=
nullptr ||
497 "Call must not be NULL when escaping on call");
498 for (
unsigned i = 0, e = PointerEscapeCheckers.size(); i != e; ++i) {
503 State = PointerEscapeCheckers[i](
State, Escaped, Call,
Kind, ETraits);
511 SVal Cond,
bool Assumption) {
512 for (
unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
517 state = EvalAssumeCheckers[i](state, Cond, Assumption);
530 NI = Src.
begin(), NE = Src.
end(); NI != NE; ++NI) {
532 bool anyEvaluated =
false;
538 for (std::vector<EvalCallFunc>::iterator
539 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
544 bool evaluated =
false;
549 evaluated = (*EI)(CE,
C);
551 assert(!(evaluated && anyEvaluated)
552 &&
"There are more than one checkers evaluating the call");
575 for (
unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
576 EndOfTranslationUnitCheckers[i](TU, mgr, BR);
581 const char *NL,
const char *Sep) {
582 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
583 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
584 I->second->printState(Out, State, NL, Sep);
592 HandlesDeclFunc isForDeclFn) {
593 DeclCheckerInfo info = { checkfn, isForDeclFn };
594 DeclCheckers.push_back(info);
598 BodyCheckers.push_back(checkfn);
606 HandlesStmtFunc isForStmtFn) {
607 StmtCheckerInfo info = { checkfn, isForStmtFn,
true };
608 StmtCheckers.push_back(info);
611 HandlesStmtFunc isForStmtFn) {
612 StmtCheckerInfo info = { checkfn, isForStmtFn,
false };
613 StmtCheckers.push_back(info);
617 PreObjCMessageCheckers.push_back(checkfn);
620 PostObjCMessageCheckers.push_back(checkfn);
624 PreCallCheckers.push_back(checkfn);
627 PostCallCheckers.push_back(checkfn);
631 LocationCheckers.push_back(checkfn);
635 BindCheckers.push_back(checkfn);
639 EndAnalysisCheckers.push_back(checkfn);
643 EndFunctionCheckers.push_back(checkfn);
648 BranchConditionCheckers.push_back(checkfn);
652 LiveSymbolsCheckers.push_back(checkfn);
656 DeadSymbolsCheckers.push_back(checkfn);
661 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
662 RegionChangesCheckers.push_back(info);
666 PointerEscapeCheckers.push_back(checkfn);
671 PointerEscapeCheckers.push_back(checkfn);
675 EvalAssumeCheckers.push_back(checkfn);
679 EvalCallCheckers.push_back(checkfn);
684 EndOfTranslationUnitCheckers.push_back(checkfn);
692 CheckerManager::getCachedStmtCheckersFor(
const Stmt *
S,
bool isPreVisit) {
695 unsigned Key = (S->getStmtClass() << 1) |
unsigned(isPreVisit);
696 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
697 if (CCI != CachedStmtCheckersMap.end())
701 CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
702 for (
unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
703 StmtCheckerInfo &Info = StmtCheckers[i];
704 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
705 Checkers.push_back(Info.CheckFn);
711 for (
unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
void _registerForRegionChanges(CheckRegionChangesFunc checkfn, WantsRegionChangeUpdateFunc wantUpdateFn)
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn)
Information about invalidation for a particular region/symbol.
static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src)
void runCheckersForObjCMessage(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on end of function.
void finishedCheckerRegistration()
const NodeBuilderContext & getBuilderContext()
void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)
Run checkers for load/store of a location.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag)
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
ImplTy::iterator iterator
void _registerForPreCall(CheckCallFunc checkfn)
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call. May be null.
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn)
Represents any expression that calls an Objective-C method.
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn)
bool wantsRegionChangeUpdate(ProgramStateRef state)
True if at least one checker wants to check region changes.
bool hasPathSensitiveCheckers() const
void runCheckersOnASTDecl(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls.
const LocationContext * getLocationContext() const
void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep)
Run checkers for debug-printing a ProgramState.
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void _registerForBody(CheckDeclFunc checkfn)
const ProgramStateRef & getState() const
This is the simplest builder which generates nodes in the ExplodedGraph.
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn)
void _registerForLocation(CheckLocationFunc checkfn)
The pointer has been passed to a function call directly.
void _registerForPointerEscape(CheckPointerEscapeFunc checkfn)
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng)
Run checkers for evaluating a call.
void _registerForPostCall(CheckCallFunc checkfn)
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn)
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
ProgramPoint withTag(const ProgramPointTag *tag) const
void _registerForBranchCondition(CheckBranchConditionFunc checkfn)
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
A class responsible for cleaning up unused symbols.
void runCheckersOnASTBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls containing a Stmt body.
void insert(const ExplodedNodeSet &S)
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting Stmts.
for(auto typeArg:T->getTypeArgsAsWritten())
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn)
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn)
Represents an abstract call to a function or method along a particular path.
void _registerForEndFunction(CheckEndFunctionFunc checkfn)
void _registerForEvalAssume(EvalAssumeFunc checkfn)
void _registerForPostStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void _registerForEvalCall(EvalCallFunc checkfn)
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call)
Default implementation of call evaluation.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const CallEvent *Call)
Run checkers for region changes.
TranslationUnitDecl - The top declaration context.
void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn)
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &mgr, BugReporter &BR)
Run checkers for the entire Translation Unit.
void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void _registerForBind(CheckBindFunc checkfn)
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...