26#include "llvm/ADT/SmallVector.h"
27#include "llvm/Support/Casting.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/Support/FormatVariadic.h"
38 const auto IfAnyAreNonEmpty = [](
const auto &... Callbacks) ->
bool {
39 return (!Callbacks.empty() || ...);
41 return IfAnyAreNonEmpty(
42 StmtCheckers, PreObjCMessageCheckers, ObjCMessageNilCheckers,
43 PostObjCMessageCheckers, PreCallCheckers, PostCallCheckers,
44 LocationCheckers, BindCheckers, EndAnalysisCheckers,
45 BeginFunctionCheckers, EndFunctionCheckers, BranchConditionCheckers,
46 NewAllocatorCheckers, LiveSymbolsCheckers, DeadSymbolsCheckers,
47 RegionChangesCheckers, PointerEscapeCheckers, EvalAssumeCheckers,
48 EvalCallCheckers, EndOfTranslationUnitCheckers);
55 for (
const auto &Event : Events)
56 assert(Event.second.HasDispatcher &&
57 "No dispatcher registered for an event");
63 StringRef ExpectedValueDesc)
const {
66 << (llvm::Twine() +
C->getTagDescription() +
":" + OptionName).str()
80 CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
81 if (CCI != CachedDeclCheckersMap.end()) {
82 checkers = &(CCI->second);
85 checkers = &CachedDeclCheckersMap[DeclKind];
86 for (
const auto &info : DeclCheckers)
87 if (info.IsForDeclFn(
D))
88 checkers->push_back(info.CheckFn);
92 for (
const auto &checker : *checkers)
100 for (
const auto &BodyChecker : BodyCheckers)
101 BodyChecker(
D, mgr, BR);
108template <
typename CHECK_CTX>
116 typename CHECK_CTX::CheckersTy::const_iterator
117 I = checkCtx.checkers_begin(),
E = checkCtx.checkers_end();
126 for (; I !=
E; ++I) {
131 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
136 for (
const auto &NI : *PrevSet)
137 checkCtx.runChecker(*I, B, NI);
140 if (CurrSet->
empty())
150 struct CheckStmtContext {
154 const CheckersTy &Checkers;
159 CheckStmtContext(
bool isPreVisit,
const CheckersTy &checkers,
161 : IsPreVisit(isPreVisit), Checkers(checkers), S(
s), Eng(eng),
162 WasInlined(wasInlined) {}
164 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
165 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
188 CheckStmtContext
C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
195 struct CheckObjCMessageContext {
196 using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
200 const CheckersTy &Checkers;
205 const CheckersTy &checkers,
208 :
Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
211 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
212 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
219 case ObjCMessageVisitKind::Pre:
222 case ObjCMessageVisitKind::MessageNil:
223 case ObjCMessageVisitKind::Post:
244 const auto &checkers = getObjCMessageCheckers(visitKind);
245 CheckObjCMessageContext
C(visitKind, checkers, msg, Eng, WasInlined);
249const std::vector<CheckerManager::CheckObjCMessageFunc> &
253 return PreObjCMessageCheckers;
256 return PostObjCMessageCheckers;
258 return ObjCMessageNilCheckers;
260 llvm_unreachable(
"Unknown Kind");
267 struct CheckCallContext {
268 using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
270 bool IsPreVisit, WasInlined;
271 const CheckersTy &Checkers;
275 CheckCallContext(
bool isPreVisit,
const CheckersTy &checkers,
278 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
279 Call(call), Eng(eng) {}
281 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
282 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
302 CheckCallContext
C(isPreVisit,
303 isPreVisit ? PreCallCheckers
305 Call, Eng, WasInlined);
311 struct CheckLocationContext {
312 using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
314 const CheckersTy &Checkers;
321 CheckLocationContext(
const CheckersTy &checkers,
322 SVal loc,
bool isLoad,
const Stmt *NodeEx,
325 : Checkers(checkers),
Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
326 BoundEx(BoundEx), Eng(eng) {}
328 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
329 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
340 checkFn(
Loc, IsLoad, BoundEx,
C);
350 SVal location,
bool isLoad,
354 CheckLocationContext
C(LocationCheckers, location, isLoad, NodeEx,
361 struct CheckBindContext {
362 using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
364 const CheckersTy &Checkers;
371 CheckBindContext(
const CheckersTy &checkers,
374 : Checkers(checkers),
Loc(loc), Val(val), S(
s), Eng(eng), PP(pp) {}
376 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
377 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
384 checkFn(
Loc, Val, S,
C);
396 CheckBindContext
C(BindCheckers, location, val, S, Eng, PP);
403 for (
const auto &EndAnalysisChecker : EndAnalysisCheckers)
404 EndAnalysisChecker(G, BR, Eng);
409struct CheckBeginFunctionContext {
410 using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
412 const CheckersTy &Checkers;
416 CheckBeginFunctionContext(
const CheckersTy &Checkers,
ExprEngine &Eng,
418 : Checkers(Checkers), Eng(Eng), PP(PP) {}
420 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
421 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
440 CheckBeginFunctionContext
C(BeginFunctionCheckers, Eng, L);
456 for (
const auto &checkFn : EndFunctionCheckers) {
466 struct CheckBranchConditionContext {
467 using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
469 const CheckersTy &Checkers;
473 CheckBranchConditionContext(
const CheckersTy &checkers,
475 : Checkers(checkers),
Condition(Cond), Eng(eng) {}
477 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
478 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
498 CheckBranchConditionContext
C(BranchConditionCheckers,
Condition, Eng);
504 struct CheckNewAllocatorContext {
505 using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
507 const CheckersTy &Checkers;
512 CheckNewAllocatorContext(
const CheckersTy &Checkers,
515 : Checkers(Checkers),
Call(
Call), WasInlined(WasInlined), Eng(Eng) {}
517 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
518 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
525 checkFn(cast<CXXAllocatorCall>(*
Call.cloneWithState(Pred->
getState())),
539 CheckNewAllocatorContext
C(NewAllocatorCheckers,
Call, WasInlined, Eng);
546 for (
const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
547 LiveSymbolsChecker(state, SymReaper);
552 struct CheckDeadSymbolsContext {
553 using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
555 const CheckersTy &Checkers;
561 CheckDeadSymbolsContext(
const CheckersTy &checkers,
SymbolReaper &sr,
564 : Checkers(checkers), SR(sr), S(
s), Eng(eng), ProgarmPointKind(K) {}
566 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
567 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
591 CheckDeadSymbolsContext
C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
603 for (
const auto &RegionChangesChecker : RegionChangesCheckers) {
608 state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
621 assert((
Call !=
nullptr ||
624 "Call must not be NULL when escaping on call");
625 for (
const auto &PointerEscapeChecker : PointerEscapeCheckers) {
630 State = PointerEscapeChecker(State, Escaped,
Call, Kind, ETraits);
638 SVal Cond,
bool Assumption) {
639 for (
const auto &EvalAssumeChecker : EvalAssumeCheckers) {
644 state = EvalAssumeChecker(state, Cond, Assumption);
656 for (
auto *
const Pred : Src) {
657 std::optional<CheckerNameRef> evaluatorChecker;
663 for (
const auto &EvalCallChecker : EvalCallCheckers) {
668 Pred->getLocationContext(), EvalCallChecker.Checker);
669 bool evaluated =
false;
674 evaluated = EvalCallChecker(
Call,
C);
677 if (evaluated && evaluatorChecker) {
680 llvm::raw_string_ostream
OS(Buf);
685 std::string AssertionMessage = llvm::formatv(
686 "The '{0}' call has been already evaluated by the {1} checker, "
687 "while the {2} checker also tried to evaluate the same call. At "
688 "most one checker supposed to evaluate a call.",
690 EvalCallChecker.Checker->getCheckerName());
691 llvm_unreachable(AssertionMessage.c_str());
695 evaluatorChecker = EvalCallChecker.Checker->getCheckerName();
704 if (!evaluatorChecker) {
716 for (
const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
717 EndOfTranslationUnitChecker(TU, mgr, BR);
725 Indent(Out, Space, IsDot) <<
"\"checker_messages\": ";
729 llvm::raw_svector_ostream TempOut(TempBuf);
730 unsigned int InnerSpace = Space + 2;
734 llvm::raw_svector_ostream NLOut(
NewLine);
735 NLOut <<
"\", " << NL;
736 Indent(NLOut, InnerSpace, IsDot) <<
"\"";
739 bool HasMessage =
false;
742 const void *LastCT =
nullptr;
743 for (
const auto &CT : CheckerTags) {
745 CT.second->printState(TempOut, State,
NewLine.c_str(),
"");
759 for (
const auto &CT : CheckerTags) {
761 CT.second->printState(TempOut, State,
NewLine.c_str(),
"");
766 Indent(Out, Space, IsDot)
767 <<
"{ \"checker\": \"" << CT.second->getCheckerName().getName()
768 <<
"\", \"messages\": [" << NL;
769 Indent(Out, InnerSpace, IsDot)
770 <<
'\"' << TempBuf.str().trim() <<
'\"' << NL;
771 Indent(Out, Space, IsDot) <<
"]}";
782 Indent(Out, --Space, IsDot) <<
"]";
795 DeclCheckerInfo info = { checkfn, isForDeclFn };
796 DeclCheckers.push_back(info);
800 BodyCheckers.push_back(checkfn);
809 StmtCheckerInfo info = { checkfn, isForStmtFn,
true };
810 StmtCheckers.push_back(info);
815 StmtCheckerInfo info = { checkfn, isForStmtFn,
false };
816 StmtCheckers.push_back(info);
820 PreObjCMessageCheckers.push_back(checkfn);
824 ObjCMessageNilCheckers.push_back(checkfn);
828 PostObjCMessageCheckers.push_back(checkfn);
832 PreCallCheckers.push_back(checkfn);
835 PostCallCheckers.push_back(checkfn);
839 LocationCheckers.push_back(checkfn);
843 BindCheckers.push_back(checkfn);
847 EndAnalysisCheckers.push_back(checkfn);
851 BeginFunctionCheckers.push_back(checkfn);
855 EndFunctionCheckers.push_back(checkfn);
860 BranchConditionCheckers.push_back(checkfn);
864 NewAllocatorCheckers.push_back(checkfn);
868 LiveSymbolsCheckers.push_back(checkfn);
872 DeadSymbolsCheckers.push_back(checkfn);
876 RegionChangesCheckers.push_back(checkfn);
880 PointerEscapeCheckers.push_back(checkfn);
885 PointerEscapeCheckers.push_back(checkfn);
889 EvalAssumeCheckers.push_back(checkfn);
893 EvalCallCheckers.push_back(checkfn);
898 EndOfTranslationUnitCheckers.push_back(checkfn);
906CheckerManager::getCachedStmtCheckersFor(
const Stmt *S,
bool isPreVisit) {
909 unsigned Key = (S->getStmtClass() << 1) |
unsigned(isPreVisit);
910 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
911 if (CCI != CachedStmtCheckersMap.end())
915 CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
916 for (
const auto &Info : StmtCheckers)
917 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
918 Checkers.push_back(Info.CheckFn);
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
__device__ __2f16 float __ockl_bool s
Decl - This represents one declaration (or definition), e.g.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag)
ProgramPoint withTag(const ProgramPointTag *tag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Stmt - This represents one statement.
The top declaration context.
BugReporter is a utility class for generating PathDiagnostics for analysis.
Represents the memory allocation call in a C++ new-expression.
Represents an abstract call to a function or method along a particular path.
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
ProgramPoint getProgramPoint(bool IsPreVisit=false, const ProgramPointTag *Tag=nullptr) const
Returns an appropriate ProgramPoint for this call.
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn)
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn)
void _registerForBeginFunction(CheckBeginFunctionFunc checkfn)
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 _registerForNewAllocator(CheckNewAllocatorFunc checkfn)
void _registerForPreCall(CheckCallFunc checkfn)
void finishedCheckerRegistration()
void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn)
bool(*)(const Decl *D) HandlesDeclFunc
void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
void runCheckersOnASTDecl(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls.
void reportInvalidCheckerOptionValue(const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) const
Emits an error through a DiagnosticsEngine about an invalid user supplied checker option value.
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn)
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn)
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &mgr, BugReporter &BR)
Run checkers for the entire Translation Unit.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void _registerForEvalAssume(EvalAssumeFunc checkfn)
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn)
void _registerForBody(CheckDeclFunc checkfn)
DiagnosticsEngine & getDiagnostics() const
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.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
Run checkers for debug-printing a ProgramState.
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn)
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
Run checkers for region changes.
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn)
void _registerForRegionChanges(CheckRegionChangesFunc checkfn)
bool hasPathSensitiveCheckers() const
void _registerForBind(CheckBindFunc checkfn)
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
void _registerForPointerEscape(CheckPointerEscapeFunc checkfn)
void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng, const EvalCallOptions &CallOpts)
Run checkers for evaluating a call.
void _registerForPostStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
void runCheckersForNewAllocator(const CXXAllocatorCall &Call, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)
Run checkers between C++ operator new and constructor calls.
void _registerForBranchCondition(CheckBranchConditionFunc checkfn)
void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting Stmts.
void _registerForEvalCall(EvalCallFunc checkfn)
void _registerForEndFunction(CheckEndFunctionFunc checkfn)
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
void _registerForLocation(CheckLocationFunc checkfn)
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn)
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
bool(*)(const Stmt *D) HandlesStmtFunc
void _registerForPostCall(CheckCallFunc checkfn)
void runCheckersOnASTBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls containing a Stmt body.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
void insert(const ExplodedNodeSet &S)
const ProgramStateRef & getState() const
const LocationContext * getLocationContext() const
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
const NodeBuilderContext & getBuilderContext()
This is the simplest builder which generates nodes in the ExplodedGraph.
Represents any expression that calls an Objective-C method.
Information about invalidation for a particular region/symbol.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
A class responsible for cleaning up unused symbols.
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
llvm::DenseSet< SymbolRef > InvalidatedSymbols
The JSON file list parser is used to communicate input to InstallAPI.
for(const auto &A :T->param_types())
Hints for figuring out of a call should be inlined during evalCall().