25#include "llvm/ADT/StringRef.h"
39 StringRef MsgForNamed,
40 StringRef MsgForUnnamed) {
42 [R, Named = MsgForNamed.str(), Unnamed = MsgForUnnamed.str()](
44 if (!isLockRelevant(R, BR))
46 std::string Name = R->getDescriptiveName();
50 OS << Named << Name <<
" here";
61 UntouchedAndPossiblyDestroyed,
62 UnlockedAndPossiblyDestroyed
66 LockState(Kind K) : K(K) {}
69 static LockState getLocked() {
return LockState(Locked); }
70 static LockState getUnlocked() {
return LockState(Unlocked); }
71 static LockState getDestroyed() {
return LockState(Destroyed); }
72 static LockState getUntouchedAndPossiblyDestroyed() {
73 return LockState(UntouchedAndPossiblyDestroyed);
75 static LockState getUnlockedAndPossiblyDestroyed() {
76 return LockState(UnlockedAndPossiblyDestroyed);
79 bool operator==(
const LockState &
X)
const {
return K ==
X.K; }
81 bool isLocked()
const {
return K == Locked; }
82 bool isUnlocked()
const {
return K == Unlocked; }
83 bool isDestroyed()
const {
return K == Destroyed; }
84 bool isUntouchedAndPossiblyDestroyed()
const {
85 return K == UntouchedAndPossiblyDestroyed;
87 bool isUnlockedAndPossiblyDestroyed()
const {
88 return K == UnlockedAndPossiblyDestroyed;
91 void Profile(llvm::FoldingSetNodeID &ID)
const {
ID.AddInteger(K); }
94class PthreadLockChecker :
public Checker<check::PostCall, check::DeadSymbols,
95 check::RegionChanges> {
97 enum LockingSemantics { NotApplicable = 0, PthreadSemantics, XNUSemantics };
99 CK_PthreadLockChecker,
100 CK_FuchsiaLockChecker,
104 bool ChecksEnabled[CK_NumCheckKinds] = {
false};
105 CheckerNameRef CheckNames[CK_NumCheckKinds];
108 typedef void (PthreadLockChecker::*FnCheck)(
const CallEvent &
Call,
110 CheckerKind CheckKind)
const;
111 CallDescriptionMap<FnCheck> PThreadCallbacks = {
113 {{CDM::CLibrary, {
"pthread_mutex_init"}, 2},
114 &PthreadLockChecker::InitAnyLock},
122 {{CDM::CLibrary, {
"pthread_mutex_lock"}, 1},
123 &PthreadLockChecker::AcquirePthreadLock},
124 {{CDM::CLibrary, {
"pthread_rwlock_rdlock"}, 1},
125 &PthreadLockChecker::AcquirePthreadLock},
126 {{CDM::CLibrary, {
"pthread_rwlock_wrlock"}, 1},
127 &PthreadLockChecker::AcquirePthreadLock},
128 {{CDM::CLibrary, {
"lck_mtx_lock"}, 1},
129 &PthreadLockChecker::AcquireXNULock},
130 {{CDM::CLibrary, {
"lck_rw_lock_exclusive"}, 1},
131 &PthreadLockChecker::AcquireXNULock},
132 {{CDM::CLibrary, {
"lck_rw_lock_shared"}, 1},
133 &PthreadLockChecker::AcquireXNULock},
136 {{CDM::CLibrary, {
"pthread_mutex_trylock"}, 1},
137 &PthreadLockChecker::TryPthreadLock},
138 {{CDM::CLibrary, {
"pthread_rwlock_tryrdlock"}, 1},
139 &PthreadLockChecker::TryPthreadLock},
140 {{CDM::CLibrary, {
"pthread_rwlock_trywrlock"}, 1},
141 &PthreadLockChecker::TryPthreadLock},
142 {{CDM::CLibrary, {
"lck_mtx_try_lock"}, 1},
143 &PthreadLockChecker::TryXNULock},
144 {{CDM::CLibrary, {
"lck_rw_try_lock_exclusive"}, 1},
145 &PthreadLockChecker::TryXNULock},
146 {{CDM::CLibrary, {
"lck_rw_try_lock_shared"}, 1},
147 &PthreadLockChecker::TryXNULock},
150 {{CDM::CLibrary, {
"pthread_mutex_unlock"}, 1},
151 &PthreadLockChecker::ReleaseAnyLock},
152 {{CDM::CLibrary, {
"pthread_rwlock_unlock"}, 1},
153 &PthreadLockChecker::ReleaseAnyLock},
154 {{CDM::CLibrary, {
"lck_mtx_unlock"}, 1},
155 &PthreadLockChecker::ReleaseAnyLock},
156 {{CDM::CLibrary, {
"lck_rw_unlock_exclusive"}, 1},
157 &PthreadLockChecker::ReleaseAnyLock},
158 {{CDM::CLibrary, {
"lck_rw_unlock_shared"}, 1},
159 &PthreadLockChecker::ReleaseAnyLock},
160 {{CDM::CLibrary, {
"lck_rw_done"}, 1},
161 &PthreadLockChecker::ReleaseAnyLock},
164 {{CDM::CLibrary, {
"pthread_mutex_destroy"}, 1},
165 &PthreadLockChecker::DestroyPthreadLock},
166 {{CDM::CLibrary, {
"lck_mtx_destroy"}, 2},
167 &PthreadLockChecker::DestroyXNULock},
172 CallDescriptionMap<FnCheck> FuchsiaCallbacks = {
174 {{CDM::CLibrary, {
"spin_lock_init"}, 1},
175 &PthreadLockChecker::InitAnyLock},
178 {{CDM::CLibrary, {
"spin_lock"}, 1},
179 &PthreadLockChecker::AcquirePthreadLock},
180 {{CDM::CLibrary, {
"spin_lock_save"}, 3},
181 &PthreadLockChecker::AcquirePthreadLock},
182 {{CDM::CLibrary, {
"sync_mutex_lock"}, 1},
183 &PthreadLockChecker::AcquirePthreadLock},
184 {{CDM::CLibrary, {
"sync_mutex_lock_with_waiter"}, 1},
185 &PthreadLockChecker::AcquirePthreadLock},
188 {{CDM::CLibrary, {
"spin_trylock"}, 1},
189 &PthreadLockChecker::TryFuchsiaLock},
190 {{CDM::CLibrary, {
"sync_mutex_trylock"}, 1},
191 &PthreadLockChecker::TryFuchsiaLock},
192 {{CDM::CLibrary, {
"sync_mutex_timedlock"}, 2},
193 &PthreadLockChecker::TryFuchsiaLock},
196 {{CDM::CLibrary, {
"spin_unlock"}, 1},
197 &PthreadLockChecker::ReleaseAnyLock},
198 {{CDM::CLibrary, {
"spin_unlock_restore"}, 3},
199 &PthreadLockChecker::ReleaseAnyLock},
200 {{CDM::CLibrary, {
"sync_mutex_unlock"}, 1},
201 &PthreadLockChecker::ReleaseAnyLock},
204 CallDescriptionMap<FnCheck> C11Callbacks = {
206 {{CDM::CLibrary, {
"mtx_init"}, 2}, &PthreadLockChecker::InitAnyLock},
209 {{CDM::CLibrary, {
"mtx_lock"}, 1},
210 &PthreadLockChecker::AcquirePthreadLock},
213 {{CDM::CLibrary, {
"mtx_trylock"}, 1}, &PthreadLockChecker::TryC11Lock},
214 {{CDM::CLibrary, {
"mtx_timedlock"}, 2}, &PthreadLockChecker::TryC11Lock},
217 {{CDM::CLibrary, {
"mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
220 {{CDM::CLibrary, {
"mtx_destroy"}, 1},
221 &PthreadLockChecker::DestroyPthreadLock},
225 const MemRegion *lockR,
227 void reportBug(CheckerContext &
C, std::unique_ptr<BugType> BT[],
228 const Expr *MtxExpr,
const MemRegion *MtxRegion,
229 CheckerKind CheckKind, StringRef Desc)
const;
232 void InitAnyLock(
const CallEvent &
Call, CheckerContext &
C,
233 CheckerKind CheckKind)
const;
234 void InitLockAux(
const CallEvent &
Call, CheckerContext &
C,
235 const Expr *MtxExpr, SVal MtxVal,
236 CheckerKind CheckKind)
const;
239 void AcquirePthreadLock(
const CallEvent &
Call, CheckerContext &
C,
240 CheckerKind CheckKind)
const;
241 void AcquireXNULock(
const CallEvent &
Call, CheckerContext &
C,
242 CheckerKind CheckKind)
const;
243 void TryPthreadLock(
const CallEvent &
Call, CheckerContext &
C,
244 CheckerKind CheckKind)
const;
245 void TryXNULock(
const CallEvent &
Call, CheckerContext &
C,
246 CheckerKind CheckKind)
const;
247 void TryFuchsiaLock(
const CallEvent &
Call, CheckerContext &
C,
248 CheckerKind CheckKind)
const;
249 void TryC11Lock(
const CallEvent &
Call, CheckerContext &
C,
250 CheckerKind CheckKind)
const;
251 void AcquireLockAux(
const CallEvent &
Call, CheckerContext &
C,
252 const Expr *MtxExpr, SVal MtxVal,
bool IsTryLock,
253 LockingSemantics Semantics, CheckerKind CheckKind)
const;
256 void ReleaseAnyLock(
const CallEvent &
Call, CheckerContext &
C,
257 CheckerKind CheckKind)
const;
258 void ReleaseLockAux(
const CallEvent &
Call, CheckerContext &
C,
259 const Expr *MtxExpr, SVal MtxVal,
260 CheckerKind CheckKind)
const;
263 void DestroyPthreadLock(
const CallEvent &
Call, CheckerContext &
C,
264 CheckerKind CheckKind)
const;
265 void DestroyXNULock(
const CallEvent &
Call, CheckerContext &
C,
266 CheckerKind CheckKind)
const;
267 void DestroyLockAux(
const CallEvent &
Call, CheckerContext &
C,
268 const Expr *MtxExpr, SVal MtxVal,
269 LockingSemantics Semantics, CheckerKind CheckKind)
const;
272 void checkPostCall(
const CallEvent &
Call, CheckerContext &
C)
const;
273 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &
C)
const;
276 ArrayRef<const MemRegion *> ExplicitRegions,
277 ArrayRef<const MemRegion *> Regions,
const StackFrame *SF,
278 const CallEvent *
Call)
const;
279 void printState(raw_ostream &Out,
ProgramStateRef State,
const char *NL,
280 const char *Sep)
const override;
283 mutable std::unique_ptr<BugType> BT_doublelock[CK_NumCheckKinds];
284 mutable std::unique_ptr<BugType> BT_doubleunlock[CK_NumCheckKinds];
285 mutable std::unique_ptr<BugType> BT_destroylock[CK_NumCheckKinds];
286 mutable std::unique_ptr<BugType> BT_initlock[CK_NumCheckKinds];
287 mutable std::unique_ptr<BugType> BT_lor[CK_NumCheckKinds];
289 void initBugType(CheckerKind CheckKind)
const {
290 if (BT_doublelock[CheckKind])
292 BT_doublelock[CheckKind].reset(
new BugType{
294 BT_doubleunlock[CheckKind].reset(
new BugType{
296 BT_destroylock[CheckKind].reset(
new BugType{
298 BT_initlock[CheckKind].reset(
new BugType{
300 BT_lor[CheckKind].reset(
new BugType{
322 if (
const FnCheck *Callback = PThreadCallbacks.lookup(
Call))
323 (this->**Callback)(
Call,
C, CK_PthreadLockChecker);
324 else if (
const FnCheck *Callback = FuchsiaCallbacks.
lookup(
Call))
325 (this->**Callback)(
Call,
C, CK_FuchsiaLockChecker);
326 else if (
const FnCheck *Callback = C11Callbacks.
lookup(
Call))
327 (this->**Callback)(
Call,
C, CK_C11LockChecker);
342 const LockState *lstate = state->get<LockMap>(lockR);
347 assert(lstate->isUntouchedAndPossiblyDestroyed() ||
348 lstate->isUnlockedAndPossiblyDestroyed());
350 ConstraintManager &CMgr = state->getConstraintManager();
351 ConditionTruthVal retZero = CMgr.
isNull(state, *sym);
353 if (lstate->isUntouchedAndPossiblyDestroyed())
354 state = state->remove<LockMap>(lockR);
355 else if (lstate->isUnlockedAndPossiblyDestroyed())
356 state = state->set<LockMap>(lockR, LockState::getUnlocked());
358 state = state->set<LockMap>(lockR, LockState::getDestroyed());
362 state = state->remove<DestroyRetVal>(lockR);
366void PthreadLockChecker::printState(raw_ostream &Out,
ProgramStateRef State,
367 const char *NL,
const char *Sep)
const {
368 LockMapTy LM = State->get<LockMap>();
370 Out << Sep <<
"Mutex states:" << NL;
372 I.first->dumpToStream(Out);
373 if (I.second.isLocked())
375 else if (I.second.isUnlocked())
377 else if (I.second.isDestroyed())
378 Out <<
": destroyed";
379 else if (I.second.isUntouchedAndPossiblyDestroyed())
380 Out <<
": not tracked, possibly destroyed";
381 else if (I.second.isUnlockedAndPossiblyDestroyed())
382 Out <<
": unlocked, possibly destroyed";
387 LockSetTy LS = State->get<LockSet>();
389 Out << Sep <<
"Mutex lock order:" << NL;
391 I->dumpToStream(Out);
396 DestroyRetValTy DRV = State->get<DestroyRetVal>();
397 if (!DRV.isEmpty()) {
398 Out << Sep <<
"Mutexes in unresolved possibly destroyed state:" << NL;
400 I.first->dumpToStream(Out);
402 I.second->dumpToStream(Out);
408void PthreadLockChecker::AcquirePthreadLock(
const CallEvent &
Call,
410 CheckerKind CheckKind)
const {
411 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
false,
412 PthreadSemantics, CheckKind);
415void PthreadLockChecker::AcquireXNULock(
const CallEvent &
Call,
417 CheckerKind CheckKind)
const {
418 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
false,
419 XNUSemantics, CheckKind);
422void PthreadLockChecker::TryPthreadLock(
const CallEvent &
Call,
424 CheckerKind CheckKind)
const {
425 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
true,
426 PthreadSemantics, CheckKind);
429void PthreadLockChecker::TryXNULock(
const CallEvent &
Call, CheckerContext &
C,
430 CheckerKind CheckKind)
const {
431 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
true,
432 PthreadSemantics, CheckKind);
435void PthreadLockChecker::TryFuchsiaLock(
const CallEvent &
Call,
437 CheckerKind CheckKind)
const {
438 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
true,
439 PthreadSemantics, CheckKind);
442void PthreadLockChecker::TryC11Lock(
const CallEvent &
Call, CheckerContext &
C,
443 CheckerKind CheckKind)
const {
444 AcquireLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
true,
445 PthreadSemantics, CheckKind);
448void PthreadLockChecker::AcquireLockAux(
const CallEvent &
Call,
449 CheckerContext &
C,
const Expr *MtxExpr,
450 SVal MtxVal,
bool IsTryLock,
451 enum LockingSemantics Semantics,
452 CheckerKind CheckKind)
const {
453 if (!ChecksEnabled[CheckKind])
461 const SymbolRef *sym = state->get<DestroyRetVal>(lockR);
463 state = resolvePossiblyDestroyedMutex(state, lockR, sym);
465 if (
const LockState *LState = state->get<LockMap>(lockR)) {
466 if (LState->isLocked()) {
467 reportBug(
C, BT_doublelock, MtxExpr, lockR, CheckKind,
468 "This lock has already been acquired");
470 }
else if (LState->isDestroyed()) {
471 reportBug(
C, BT_destroylock, MtxExpr, lockR, CheckKind,
472 "This lock has already been destroyed");
480 SVal RetVal =
Call.getReturnValue();
481 if (
auto DefinedRetVal = RetVal.
getAs<DefinedSVal>()) {
484 case PthreadSemantics:
485 std::tie(lockFail, lockSucc) = state->assume(*DefinedRetVal);
488 std::tie(lockSucc, lockFail) = state->assume(*DefinedRetVal);
491 llvm_unreachable(
"Unknown tryLock locking semantics");
493 assert(lockFail && lockSucc);
494 C.addTransition(lockFail);
498 }
else if (Semantics == PthreadSemantics) {
500 SVal RetVal =
Call.getReturnValue();
501 if (
auto DefinedRetVal = RetVal.
getAs<DefinedSVal>()) {
504 lockSucc = state->assume(*DefinedRetVal,
false);
511 assert((Semantics == XNUSemantics) &&
"Unknown locking semantics");
516 lockSucc = lockSucc->add<LockSet>(lockR);
517 lockSucc = lockSucc->set<LockMap>(lockR, LockState::getLocked());
518 C.addTransition(lockSucc,
522void PthreadLockChecker::ReleaseAnyLock(
const CallEvent &
Call,
524 CheckerKind CheckKind)
const {
525 ReleaseLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0), CheckKind);
528void PthreadLockChecker::ReleaseLockAux(
const CallEvent &
Call,
529 CheckerContext &
C,
const Expr *MtxExpr,
531 CheckerKind CheckKind)
const {
532 if (!ChecksEnabled[CheckKind])
540 const SymbolRef *sym = state->get<DestroyRetVal>(lockR);
542 state = resolvePossiblyDestroyedMutex(state, lockR, sym);
544 if (
const LockState *LState = state->get<LockMap>(lockR)) {
545 if (LState->isUnlocked()) {
546 reportBug(
C, BT_doubleunlock, MtxExpr, lockR, CheckKind,
547 "This lock has already been unlocked");
549 }
else if (LState->isDestroyed()) {
550 reportBug(
C, BT_destroylock, MtxExpr, lockR, CheckKind,
551 "This lock has already been destroyed");
556 LockSetTy LS = state->get<LockSet>();
559 const MemRegion *firstLockR = LS.getHead();
560 if (firstLockR != lockR) {
561 ExplodedNode *N =
C.generateErrorNode();
564 initBugType(CheckKind);
565 auto Report = std::make_unique<PathSensitiveBugReport>(
567 "This was not the most recently acquired lock. Possible lock "
571 Report->markInteresting(lockR);
572 Report->markInteresting(firstLockR);
573 C.emitReport(std::move(
Report));
577 state = state->set<LockSet>(LS.getTail());
580 state = state->set<LockMap>(lockR, LockState::getUnlocked());
585void PthreadLockChecker::DestroyPthreadLock(
const CallEvent &
Call,
587 CheckerKind CheckKind)
const {
588 DestroyLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0),
589 PthreadSemantics, CheckKind);
592void PthreadLockChecker::DestroyXNULock(
const CallEvent &
Call,
594 CheckerKind CheckKind)
const {
595 DestroyLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0), XNUSemantics,
599void PthreadLockChecker::DestroyLockAux(
const CallEvent &
Call,
600 CheckerContext &
C,
const Expr *MtxExpr,
602 enum LockingSemantics Semantics,
603 CheckerKind CheckKind)
const {
604 if (!ChecksEnabled[CheckKind])
613 const SymbolRef *sym = State->get<DestroyRetVal>(LockR);
615 State = resolvePossiblyDestroyedMutex(State, LockR, sym);
617 const LockState *LState = State->get<LockMap>(LockR);
620 if (Semantics == PthreadSemantics) {
621 if (!LState || LState->isUnlocked()) {
624 State = State->remove<LockMap>(LockR);
626 "Mutex destroyed here"));
629 State = State->set<DestroyRetVal>(LockR, sym);
630 if (LState && LState->isUnlocked())
631 State = State->set<LockMap>(
632 LockR, LockState::getUnlockedAndPossiblyDestroyed());
634 State = State->set<LockMap>(
635 LockR, LockState::getUntouchedAndPossiblyDestroyed());
637 "Mutex destroyed here"));
641 if (!LState || LState->isUnlocked()) {
642 State = State->set<LockMap>(LockR, LockState::getDestroyed());
644 "Mutex destroyed here"));
649 StringRef
Message = LState->isLocked()
650 ?
"This lock is still locked"
651 :
"This lock has already been destroyed";
653 reportBug(
C, BT_destroylock, MtxExpr, LockR, CheckKind, Message);
656void PthreadLockChecker::InitAnyLock(
const CallEvent &
Call, CheckerContext &
C,
657 CheckerKind CheckKind)
const {
658 InitLockAux(
Call,
C,
Call.getArgExpr(0),
Call.getArgSVal(0), CheckKind);
661void PthreadLockChecker::InitLockAux(
const CallEvent &
Call, CheckerContext &
C,
662 const Expr *MtxExpr, SVal MtxVal,
663 CheckerKind CheckKind)
const {
664 if (!ChecksEnabled[CheckKind])
673 const SymbolRef *sym = State->get<DestroyRetVal>(LockR);
675 State = resolvePossiblyDestroyedMutex(State, LockR, sym);
677 const struct LockState *LState = State->get<LockMap>(LockR);
678 if (!LState || LState->isDestroyed()) {
679 State = State->set<LockMap>(LockR, LockState::getUnlocked());
681 "Mutex initialized here"));
685 StringRef
Message = LState->isLocked()
686 ?
"This lock is still being held"
687 :
"This lock has already been initialized";
689 reportBug(
C, BT_initlock, MtxExpr, LockR, CheckKind, Message);
692void PthreadLockChecker::reportBug(
693 CheckerContext &
C, std::unique_ptr<BugType> BT[],
const Expr *MtxExpr,
694 const MemRegion *MtxRegion, CheckerKind CheckKind, StringRef Desc)
const {
695 ExplodedNode *N =
C.generateErrorNode();
698 initBugType(CheckKind);
700 std::make_unique<PathSensitiveBugReport>(*BT[CheckKind], Desc, N);
703 Report->markInteresting(MtxRegion);
704 C.emitReport(std::move(
Report));
707void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper,
708 CheckerContext &
C)
const {
711 for (
auto I : State->get<DestroyRetVal>()) {
715 if (SymReaper.
isDead(I.second))
716 State = resolvePossiblyDestroyedMutex(State, I.first, &I.second);
719 for (
auto I : State->get<LockMap>()) {
722 State = State->remove<LockMap>(I.first);
723 State = State->remove<DestroyRetVal>(I.first);
731 C.addTransition(State);
736 ArrayRef<const MemRegion *> ExplicitRegions,
737 ArrayRef<const MemRegion *> Regions,
const StackFrame *SF,
738 const CallEvent *
Call)
const {
740 bool IsLibraryFunction =
false;
741 if (
Call &&
Call->isGlobalCFunction()) {
743 if (PThreadCallbacks.lookup(*
Call) || FuchsiaCallbacks.
lookup(*
Call) ||
747 if (
Call->isInSystemHeader())
748 IsLibraryFunction =
true;
751 for (
auto R : Regions) {
755 if (IsLibraryFunction && !llvm::is_contained(ExplicitRegions, R))
758 State = State->remove<LockMap>(
R);
759 State = State->remove<DestroyRetVal>(
R);
769void ento::registerPthreadLockBase(CheckerManager &mgr) {
773bool ento::shouldRegisterPthreadLockBase(
const CheckerManager &mgr) {
return true; }
775#define REGISTER_CHECKER(name) \
776 void ento::register##name(CheckerManager &mgr) { \
777 PthreadLockChecker *checker = mgr.getChecker<PthreadLockChecker>(); \
778 checker->ChecksEnabled[PthreadLockChecker::CK_##name] = true; \
779 checker->CheckNames[PthreadLockChecker::CK_##name] = \
780 mgr.getCurrentCheckerName(); \
783 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
789#undef REGISTER_CHECKER
#define REGISTER_CHECKER(name)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable list type NameTy, suitable for placement into the ProgramState.
static bool isLockRelevant(const MemRegion *R, const PathSensitiveBugReport &BR)
static const NoteTag * createMutexNote(CheckerContext &C, const MemRegion *R, StringRef MsgForNamed, StringRef MsgForUnnamed)
constexpr llvm::StringRef LOCK_CHECKER_CATEGORY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const BugType & getBugType() const
StringRef getCategory() const
const T * lookup(const CallEvent &Call) const
Represents an abstract call to a function or method along a particular path.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
MemRegion - The root abstract class for all memory regions.
The tag upon which the TagVisitor reacts.
bool isInteresting(SymbolRef sym) const
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
bool isLiveRegion(const MemRegion *region)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)