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);
53 StringRef ExpectedValueDesc)
const {
56 << (llvm::Twine() +
C->getTagDescription() +
":" + OptionName).str()
69 auto [CCI, Inserted] = CachedDeclCheckersMap.try_emplace(DeclKind);
73 for (
const auto &info : DeclCheckers)
74 if (info.IsForDeclFn(
D))
75 checkers->push_back(info.CheckFn);
79 for (
const auto &checker : *checkers)
87 for (
const auto &BodyChecker : BodyCheckers)
88 BodyChecker(
D, mgr, BR);
95template <
typename CHECK_CTX>
103 typename CHECK_CTX::CheckersTy::const_iterator
104 I = checkCtx.checkers_begin(),
E = checkCtx.checkers_end();
113 for (; I !=
E; ++I) {
118 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
123 for (
const auto &NI : *PrevSet)
124 checkCtx.runChecker(*I, B, NI);
127 if (CurrSet->
empty())
137 struct CheckStmtContext {
141 const CheckersTy &Checkers;
146 CheckStmtContext(
bool isPreVisit,
const CheckersTy &checkers,
148 : IsPreVisit(isPreVisit), Checkers(checkers), S(
s), Eng(eng),
149 WasInlined(wasInlined) {}
151 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
152 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
175 CheckStmtContext
C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
182 struct CheckObjCMessageContext {
183 using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
187 const CheckersTy &Checkers;
192 const CheckersTy &checkers,
195 :
Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
198 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
199 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
206 case ObjCMessageVisitKind::Pre:
209 case ObjCMessageVisitKind::MessageNil:
210 case ObjCMessageVisitKind::Post:
231 const auto &checkers = getObjCMessageCheckers(visitKind);
232 CheckObjCMessageContext
C(visitKind, checkers, msg, Eng, WasInlined);
236const std::vector<CheckerManager::CheckObjCMessageFunc> &
240 return PreObjCMessageCheckers;
243 return PostObjCMessageCheckers;
245 return ObjCMessageNilCheckers;
247 llvm_unreachable(
"Unknown Kind");
254 struct CheckCallContext {
255 using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
257 bool IsPreVisit, WasInlined;
258 const CheckersTy &Checkers;
262 CheckCallContext(
bool isPreVisit,
const CheckersTy &checkers,
265 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
266 Call(call), Eng(eng) {}
268 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
269 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
289 CheckCallContext
C(isPreVisit,
290 isPreVisit ? PreCallCheckers
292 Call, Eng, WasInlined);
298 struct CheckLocationContext {
299 using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
301 const CheckersTy &Checkers;
308 CheckLocationContext(
const CheckersTy &checkers,
309 SVal loc,
bool isLoad,
const Stmt *NodeEx,
312 : Checkers(checkers),
Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
313 BoundEx(BoundEx), Eng(eng) {}
315 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
316 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
327 checkFn(
Loc, IsLoad, BoundEx,
C);
337 SVal location,
bool isLoad,
341 CheckLocationContext
C(LocationCheckers, location, isLoad, NodeEx,
348 struct CheckBindContext {
349 using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
351 const CheckersTy &Checkers;
358 CheckBindContext(
const CheckersTy &checkers,
361 : Checkers(checkers),
Loc(loc), Val(val), S(
s), Eng(eng), PP(pp) {}
363 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
364 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
371 checkFn(
Loc, Val, S,
C);
383 CheckBindContext
C(BindCheckers, location, val, S, Eng, PP);
390 for (
const auto &EndAnalysisChecker : EndAnalysisCheckers)
391 EndAnalysisChecker(G, BR, Eng);
396struct CheckBeginFunctionContext {
397 using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
399 const CheckersTy &Checkers;
403 CheckBeginFunctionContext(
const CheckersTy &Checkers,
ExprEngine &Eng,
405 : Checkers(Checkers), Eng(Eng), PP(PP) {}
407 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
408 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
427 CheckBeginFunctionContext
C(BeginFunctionCheckers, Eng, L);
443 for (
const auto &checkFn : EndFunctionCheckers) {
453 struct CheckBranchConditionContext {
454 using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
456 const CheckersTy &Checkers;
460 CheckBranchConditionContext(
const CheckersTy &checkers,
462 : Checkers(checkers),
Condition(Cond), Eng(eng) {}
464 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
465 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
485 CheckBranchConditionContext
C(BranchConditionCheckers,
Condition, Eng);
491 struct CheckNewAllocatorContext {
492 using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
494 const CheckersTy &Checkers;
499 CheckNewAllocatorContext(
const CheckersTy &Checkers,
502 : Checkers(Checkers),
Call(
Call), WasInlined(WasInlined), Eng(Eng) {}
504 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
505 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
512 checkFn(cast<CXXAllocatorCall>(*
Call.cloneWithState(Pred->
getState())),
526 CheckNewAllocatorContext
C(NewAllocatorCheckers,
Call, WasInlined, Eng);
533 for (
const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
534 LiveSymbolsChecker(state, SymReaper);
539 struct CheckDeadSymbolsContext {
540 using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
542 const CheckersTy &Checkers;
548 CheckDeadSymbolsContext(
const CheckersTy &checkers,
SymbolReaper &sr,
551 : Checkers(checkers), SR(sr), S(
s), Eng(eng), ProgarmPointKind(K) {}
553 CheckersTy::const_iterator checkers_begin() {
return Checkers.begin(); }
554 CheckersTy::const_iterator checkers_end() {
return Checkers.end(); }
578 CheckDeadSymbolsContext
C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
590 for (
const auto &RegionChangesChecker : RegionChangesCheckers) {
595 state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
608 assert((
Call !=
nullptr ||
611 "Call must not be NULL when escaping on call");
612 for (
const auto &PointerEscapeChecker : PointerEscapeCheckers) {
617 State = PointerEscapeChecker(State, Escaped,
Call, Kind, ETraits);
625 SVal Cond,
bool Assumption) {
626 for (
const auto &EvalAssumeChecker : EvalAssumeCheckers) {
631 state = EvalAssumeChecker(state, Cond, Assumption);
643 for (
auto *
const Pred : Src) {
644 std::optional<CheckerNameRef> evaluatorChecker;
650 for (
const auto &EvalCallChecker : EvalCallCheckers) {
655 Pred->getLocationContext(), EvalCallChecker.Checker);
656 bool evaluated =
false;
661 evaluated = EvalCallChecker(
Call,
C);
664 if (evaluated && evaluatorChecker) {
667 llvm::raw_string_ostream
OS(Buf);
671 std::string AssertionMessage = llvm::formatv(
672 "The '{0}' call has been already evaluated by the {1} checker, "
673 "while the {2} checker also tried to evaluate the same call. At "
674 "most one checker supposed to evaluate a call.",
676 EvalCallChecker.Checker->getCheckerName());
677 llvm_unreachable(AssertionMessage.c_str());
681 evaluatorChecker = EvalCallChecker.Checker->getCheckerName();
690 if (!evaluatorChecker) {
702 for (
const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
703 EndOfTranslationUnitChecker(TU, mgr, BR);
711 Indent(Out, Space, IsDot) <<
"\"checker_messages\": ";
715 llvm::raw_svector_ostream TempOut(TempBuf);
716 unsigned int InnerSpace = Space + 2;
720 llvm::raw_svector_ostream NLOut(
NewLine);
721 NLOut <<
"\", " << NL;
722 Indent(NLOut, InnerSpace, IsDot) <<
"\"";
725 bool HasMessage =
false;
728 const void *LastCT =
nullptr;
729 for (
const auto &CT : CheckerTags) {
731 CT.second->printState(TempOut, State,
NewLine.c_str(),
"");
745 for (
const auto &CT : CheckerTags) {
747 CT.second->printState(TempOut, State,
NewLine.c_str(),
"");
752 Indent(Out, Space, IsDot)
753 <<
"{ \"checker\": \"" << CT.second->getCheckerName().getName()
754 <<
"\", \"messages\": [" << NL;
755 Indent(Out, InnerSpace, IsDot)
756 <<
'\"' << TempBuf.str().trim() <<
'\"' << NL;
757 Indent(Out, Space, IsDot) <<
"]}";
768 Indent(Out, --Space, IsDot) <<
"]";
781 DeclCheckerInfo info = { checkfn, isForDeclFn };
782 DeclCheckers.push_back(info);
786 BodyCheckers.push_back(checkfn);
795 StmtCheckerInfo info = { checkfn, isForStmtFn,
true };
796 StmtCheckers.push_back(info);
801 StmtCheckerInfo info = { checkfn, isForStmtFn,
false };
802 StmtCheckers.push_back(info);
806 PreObjCMessageCheckers.push_back(checkfn);
810 ObjCMessageNilCheckers.push_back(checkfn);
814 PostObjCMessageCheckers.push_back(checkfn);
818 PreCallCheckers.push_back(checkfn);
821 PostCallCheckers.push_back(checkfn);
825 LocationCheckers.push_back(checkfn);
829 BindCheckers.push_back(checkfn);
833 EndAnalysisCheckers.push_back(checkfn);
837 BeginFunctionCheckers.push_back(checkfn);
841 EndFunctionCheckers.push_back(checkfn);
846 BranchConditionCheckers.push_back(checkfn);
850 NewAllocatorCheckers.push_back(checkfn);
854 LiveSymbolsCheckers.push_back(checkfn);
858 DeadSymbolsCheckers.push_back(checkfn);
862 RegionChangesCheckers.push_back(checkfn);
866 PointerEscapeCheckers.push_back(checkfn);
871 PointerEscapeCheckers.push_back(checkfn);
875 EvalAssumeCheckers.push_back(checkfn);
879 EvalCallCheckers.push_back(checkfn);
884 EndOfTranslationUnitCheckers.push_back(checkfn);
892CheckerManager::getCachedStmtCheckersFor(
const Stmt *S,
bool isPreVisit) {
895 unsigned Key = (S->getStmtClass() << 1) |
unsigned(isPreVisit);
896 auto [CCI, Inserted] = CachedStmtCheckersMap.try_emplace(Key);
897 CachedStmtCheckers &Checkers = CCI->second;
900 for (
const auto &Info : StmtCheckers)
901 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
902 Checkers.push_back(Info.CheckFn);
enum clang::sema::@1718::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 _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.
Hints for figuring out of a call should be inlined during evalCall().