37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/StringExtras.h"
39#include "llvm/Support/Path.h"
53 std::min(
static_cast<char>(Lhs),
static_cast<char>(Rhs)));
56const char *getNullabilityString(
Nullability Nullab) {
58 case Nullability::Contradicted:
59 return "contradicted";
60 case Nullability::Nullable:
62 case Nullability::Unspecified:
64 case Nullability::Nonnull:
67 llvm_unreachable(
"Unexpected enumeration.");
72enum class ErrorKind :
int {
76 NullableAssignedToNonnull,
77 NullableReturnedToNonnull,
79 NullablePassedToNonnull
82class NullabilityChecker
83 :
public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
84 check::PostCall, check::PostStmt<ExplicitCastExpr>,
85 check::PostObjCMessage, check::DeadSymbols, eval::Assume,
86 check::Location, check::Event<ImplicitNullDerefEvent>,
87 check::BeginFunction> {
96 bool NoDiagnoseCallsToSystemHeaders =
false;
106 void checkLocation(
SVal Location,
bool IsLoad,
const Stmt *S,
110 bool Assumption)
const;
113 const char *Sep)
const override;
116 CK_NullPassedToNonnull,
117 CK_NullReturnedFromNonnull,
118 CK_NullableDereferenced,
119 CK_NullablePassedToNonnull,
120 CK_NullableReturnedFromNonnull,
124 bool ChecksEnabled[CK_NumCheckKinds] = {
false};
126 mutable std::unique_ptr<BugType> BTs[CK_NumCheckKinds];
128 const std::unique_ptr<BugType> &getBugType(CheckKind Kind)
const {
130 BTs[
Kind].reset(
new BugType(CheckNames[Kind],
"Nullability",
139 bool NeedTracking =
false;
144 NullabilityBugVisitor(
const MemRegion *M) : Region(M) {}
146 void Profile(llvm::FoldingSetNodeID &ID)
const override {
149 ID.AddPointer(Region);
166 void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error, CheckKind CK,
169 const Stmt *ValueExpr =
nullptr,
170 bool SuppressPath =
false)
const;
172 void reportBug(StringRef Msg, ErrorKind Error, CheckKind CK,
ExplodedNode *N,
174 const Stmt *ValueExpr =
nullptr)
const {
175 const std::unique_ptr<BugType> &BT = getBugType(CK);
176 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
178 R->markInteresting(Region);
179 R->addVisitor<NullabilityBugVisitor>(Region);
182 R->addRange(ValueExpr->getSourceRange());
183 if (Error == ErrorKind::NilAssignedToNonnull ||
184 Error == ErrorKind::NilPassedToNonnull ||
185 Error == ErrorKind::NilReturnedToNonnull)
186 if (
const auto *Ex = dyn_cast<Expr>(ValueExpr))
195 bool CheckSuperRegion =
false)
const;
200 if (NoDiagnoseCallsToSystemHeaders &&
Call.isInSystemHeader())
207class NullabilityState {
210 : Nullab(Nullab), Source(Source) {}
212 const Stmt *getNullabilitySource()
const {
return Source; }
216 void Profile(llvm::FoldingSetNodeID &ID)
const {
217 ID.AddInteger(
static_cast<char>(Nullab));
218 ID.AddPointer(Source);
221 void print(raw_ostream &Out)
const {
222 Out << getNullabilityString(Nullab) <<
"\n";
234bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
235 return Lhs.getValue() == Rhs.getValue() &&
236 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
242using ObjectPropPair = std::pair<const MemRegion *, const IdentifierInfo *>;
245struct ConstrainedPropertyVal {
251 bool isConstrainedNonnull;
256 void Profile(llvm::FoldingSetNodeID &ID)
const {
258 ID.AddInteger(isConstrainedNonnull ? 1 : 0);
262bool operator==(
const ConstrainedPropertyVal &Lhs,
263 const ConstrainedPropertyVal &Rhs) {
264 return Lhs.Value == Rhs.Value &&
265 Lhs.isConstrainedNonnull == Rhs.isConstrainedNonnull;
273 ConstrainedPropertyVal)
318NullabilityChecker::getTrackRegion(
SVal Val,
bool CheckSuperRegion)
const {
326 const MemRegion *Region = RegionSVal->getRegion();
328 if (CheckSuperRegion) {
330 if (
const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
332 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
335 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
338 return dyn_cast<SymbolicRegion>(Region);
347 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
348 const NullabilityState *TrackedNullabPrev =
349 StatePrev->get<NullabilityMap>(Region);
353 if (TrackedNullabPrev &&
354 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
358 const Stmt *S = TrackedNullab->getNullabilitySource();
359 if (!S || S->getBeginLoc().isInvalid()) {
366 std::string InfoText =
367 (llvm::Twine(
"Nullability '") +
368 getNullabilityString(TrackedNullab->getValue()) +
"' is inferred")
374 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText,
true);
395 if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
408 for (
const auto *ParamDecl : Params) {
409 if (ParamDecl->isParameterPack())
412 SVal LV = State->getLValue(ParamDecl, LocCtxt);
424 auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->
getDecl());
425 if (!MD || !MD->isInstanceMethod())
432 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
435 dyn_cast<ObjCObjectPointerType>(SelfDecl->
getType());
443 for (
const auto *IvarDecl : ID->ivars()) {
444 SVal LV = State->getLValue(IvarDecl, SelfVal);
454 if (State->get<InvariantViolated>())
463 if (
const auto *BD = dyn_cast<BlockDecl>(
D))
464 Params = BD->parameters();
465 else if (
const auto *FD = dyn_cast<FunctionDecl>(
D))
466 Params = FD->parameters();
467 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(
D))
468 Params = MD->parameters();
475 C.addTransition(State->set<InvariantViolated>(
true), N);
481void NullabilityChecker::reportBugIfInvariantHolds(
482 StringRef Msg, ErrorKind Error, CheckKind CK,
ExplodedNode *N,
484 bool SuppressPath)
const {
490 OriginalState = OriginalState->set<InvariantViolated>(
true);
491 N =
C.addTransition(OriginalState, N);
494 reportBug(Msg, Error, CK, N, Region,
C.getBugReporter(), ValueExpr);
498void NullabilityChecker::checkDeadSymbols(
SymbolReaper &SR,
501 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
502 for (
const MemRegion *Reg : llvm::make_first_range(Nullabilities)) {
504 assert(Region &&
"Non-symbolic region is tracked.");
505 if (SR.
isDead(Region->getSymbol())) {
506 State = State->remove<NullabilityMap>(Reg);
512 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
513 for (
ObjectPropPair PropKey : llvm::make_first_range(PropertyAccesses)) {
514 const MemRegion *ReceiverRegion = PropKey.first;
516 State = State->remove<PropertyAccessesMap>(PropKey);
526 C.addTransition(State);
537 getTrackRegion(Event.
Location,
true);
542 const NullabilityState *TrackedNullability =
543 State->get<NullabilityMap>(Region);
545 if (!TrackedNullability)
548 if (ChecksEnabled[CK_NullableDereferenced] &&
549 TrackedNullability->getValue() == Nullability::Nullable) {
554 reportBug(
"Nullable pointer is dereferenced",
555 ErrorKind::NullableDereferenced, CK_NullableDereferenced,
558 reportBug(
"Nullable pointer is passed to a callee that requires a "
560 ErrorKind::NullablePassedToNonnull, CK_NullableDereferenced,
572 if (!AbstractCall || AbstractCall->parameters().empty())
576 for (
const ParmVarDecl *Param : AbstractCall->parameters()) {
582 if (RequiredNullability != Nullability::Nullable)
585 const VarRegion *ParamRegion = State->getRegion(Param, LCtx);
587 State->getSVal(ParamRegion).getAsRegion();
588 if (!ParamPointeeRegion)
591 State = State->set<NullabilityMap>(ParamPointeeRegion,
592 NullabilityState(RequiredNullability));
594 C.addTransition(State);
610void NullabilityChecker::checkLocation(
SVal Location,
bool IsLoad,
621 dyn_cast_or_null<TypedValueRegion>(Location.
getAsRegion());
634 if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
638 Context.addTransition(NewState);
653void NullabilityChecker::checkPreStmt(
const ReturnStmt *S,
655 auto RetExpr = S->getRetValue();
663 if (State->get<InvariantViolated>())
670 bool InSuppressedMethodFamily =
false;
674 C.getLocationContext()->getAnalysisDeclContext();
676 if (
auto *MD = dyn_cast<ObjCMethodDecl>(
D)) {
683 InSuppressedMethodFamily =
true;
685 RequiredRetType = MD->getReturnType();
686 }
else if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
687 RequiredRetType = FD->getReturnType();
704 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
706 if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
707 RetExprTypeLevelNullability != Nullability::Nonnull &&
708 !InSuppressedMethodFamily &&
C.getLocationContext()->inTopFrame()) {
715 llvm::raw_svector_ostream OS(SBuf);
716 OS << (RetExpr->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
717 OS <<
" returned from a " <<
C.getDeclDescription(
D) <<
718 " that is expected to return a non-null value";
719 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
720 CK_NullReturnedFromNonnull, N,
nullptr,
C,
727 if (NullReturnedFromNonNull) {
728 State = State->set<InvariantViolated>(
true);
729 C.addTransition(State);
733 const MemRegion *Region = getTrackRegion(*RetSVal);
737 const NullabilityState *TrackedNullability =
738 State->get<NullabilityMap>(Region);
739 if (TrackedNullability) {
740 Nullability TrackedNullabValue = TrackedNullability->getValue();
741 if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
743 TrackedNullabValue == Nullability::Nullable &&
744 RequiredNullability == Nullability::Nonnull) {
746 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
749 llvm::raw_svector_ostream OS(SBuf);
750 OS <<
"Nullable pointer is returned from a " <<
C.getDeclDescription(
D) <<
751 " that is expected to return a non-null value";
753 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
754 CK_NullableReturnedFromNonnull, N, Region,
C);
758 if (RequiredNullability == Nullability::Nullable) {
759 State = State->set<NullabilityMap>(Region,
760 NullabilityState(RequiredNullability,
762 C.addTransition(State);
774 if (State->get<InvariantViolated>())
781 if (Param->isParameterPack())
784 if (Idx >=
Call.getNumArgs())
787 const Expr *ArgExpr =
Call.getArgExpr(Idx);
793 !Param->getType()->isReferenceType())
803 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
805 if (ChecksEnabled[CK_NullPassedToNonnull] &&
807 ArgExprTypeLevelNullability != Nullability::Nonnull &&
808 RequiredNullability == Nullability::Nonnull &&
809 isDiagnosableCall(
Call)) {
815 llvm::raw_svector_ostream OS(SBuf);
816 OS << (Param->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
817 OS <<
" passed to a callee that requires a non-null " <<
ParamIdx
818 << llvm::getOrdinalSuffix(
ParamIdx) <<
" parameter";
819 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
820 CK_NullPassedToNonnull, N,
nullptr,
C, ArgExpr,
825 const MemRegion *Region = getTrackRegion(*ArgSVal);
829 const NullabilityState *TrackedNullability =
830 State->get<NullabilityMap>(Region);
832 if (TrackedNullability) {
834 TrackedNullability->getValue() != Nullability::Nullable)
837 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
838 RequiredNullability == Nullability::Nonnull &&
839 isDiagnosableCall(
Call)) {
842 llvm::raw_svector_ostream OS(SBuf);
843 OS <<
"Nullable pointer is passed to a callee that requires a non-null "
845 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
846 CK_NullablePassedToNonnull, N, Region,
C,
850 if (ChecksEnabled[CK_NullableDereferenced] &&
851 Param->getType()->isReferenceType()) {
853 reportBugIfInvariantHolds(
"Nullable pointer is dereferenced",
854 ErrorKind::NullableDereferenced,
855 CK_NullableDereferenced, N, Region,
C,
862 if (State != OrigState)
863 C.addTransition(State);
882 if (State->get<InvariantViolated>())
885 const MemRegion *Region = getTrackRegion(
Call.getReturnValue());
893 if (llvm::sys::path::filename(FilePath).starts_with(
"CG")) {
894 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
895 C.addTransition(State);
899 const NullabilityState *TrackedNullability =
900 State->get<NullabilityMap>(Region);
907 if (
const Expr *
E =
Call.getOriginExpr())
910 if (!TrackedNullability &&
912 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
913 C.addTransition(State);
922 return Nullability::Nonnull;
931 return Nullability::Nonnull;
934 if (ValueRegionSVal) {
935 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
938 const NullabilityState *TrackedSelfNullability =
939 State->get<NullabilityMap>(SelfRegion);
940 if (TrackedSelfNullability)
941 return TrackedSelfNullability->getValue();
943 return Nullability::Unspecified;
951 bool Assumption)
const {
952 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
953 for (
auto [PropKey, PropVal] : PropertyAccesses) {
954 if (!PropVal.isConstrainedNonnull) {
957 ConstrainedPropertyVal Replacement = PropVal;
958 Replacement.isConstrainedNonnull =
true;
959 State = State->set<PropertyAccessesMap>(PropKey, Replacement);
962 State = State->remove<PropertyAccessesMap>(PropKey);
973void NullabilityChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
983 if (State->get<InvariantViolated>())
995 if (Name.starts_with(
"NS")) {
1006 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1007 C.addTransition(State);
1012 if (Name.contains(
"Array") &&
1013 (FirstSelectorSlot ==
"firstObject" ||
1014 FirstSelectorSlot ==
"lastObject")) {
1016 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1017 C.addTransition(State);
1025 if (Name.contains(
"String")) {
1027 if (Param->getName() ==
"encoding") {
1028 State = State->set<NullabilityMap>(ReturnRegion,
1029 Nullability::Contradicted);
1030 C.addTransition(State);
1040 const NullabilityState *NullabilityOfReturn =
1041 State->get<NullabilityMap>(ReturnRegion);
1043 if (NullabilityOfReturn) {
1047 Nullability RetValTracked = NullabilityOfReturn->getValue();
1049 getMostNullable(RetValTracked, SelfNullability);
1050 if (ComputedNullab != RetValTracked &&
1051 ComputedNullab != Nullability::Unspecified) {
1052 const Stmt *NullabilitySource =
1053 ComputedNullab == RetValTracked
1054 ? NullabilityOfReturn->getNullabilitySource()
1055 : Message->getInstanceReceiver();
1056 State = State->set<NullabilityMap>(
1057 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1058 C.addTransition(State);
1081 if (RetNullability != Nullability::Nonnull &&
1083 bool LookupResolved =
false;
1087 LookupResolved =
true;
1089 const ConstrainedPropertyVal *PrevPropVal =
1090 State->get<PropertyAccessesMap>(Key);
1091 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1092 RetNullability = Nullability::Nonnull;
1100 if (
auto ReturnSVal =
1102 State = State->set<PropertyAccessesMap>(
1103 Key, ConstrainedPropertyVal(*ReturnSVal));
1109 if (!LookupResolved) {
1111 RetNullability = Nullability::Nonnull;
1115 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1116 if (ComputedNullab == Nullability::Nullable) {
1117 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1119 : Message->getInstanceReceiver();
1120 State = State->set<NullabilityMap>(
1121 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1122 C.addTransition(State);
1140 if (State->get<InvariantViolated>())
1147 if (DestNullability == Nullability::Unspecified)
1151 const MemRegion *Region = getTrackRegion(*RegionSVal);
1156 if (DestNullability == Nullability::Nonnull) {
1159 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1160 C.addTransition(State);
1165 const NullabilityState *TrackedNullability =
1166 State->get<NullabilityMap>(Region);
1168 if (!TrackedNullability) {
1169 if (DestNullability != Nullability::Nullable)
1171 State = State->set<NullabilityMap>(Region,
1172 NullabilityState(DestNullability, CE));
1173 C.addTransition(State);
1177 if (TrackedNullability->getValue() != DestNullability &&
1178 TrackedNullability->getValue() != Nullability::Contradicted) {
1179 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1180 C.addTransition(State);
1188 if (
auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1189 if (BinOp->getOpcode() == BO_Assign)
1190 return BinOp->getRHS();
1194 if (
auto *DS = dyn_cast<DeclStmt>(S)) {
1195 if (DS->isSingleDecl()) {
1196 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1200 if (
const Expr *
Init = VD->getInit())
1225 if (!
C.getASTContext().getLangOpts().ObjCAutoRefCount)
1228 auto *DS = dyn_cast<DeclStmt>(S);
1229 if (!DS || !DS->isSingleDecl())
1232 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1237 if(!VD->getType().getQualifiers().hasObjCLifetime())
1241 assert(
Init &&
"ObjC local under ARC without initializer");
1244 if (!isa<ImplicitValueInitExpr>(
Init))
1252void NullabilityChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
1255 dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
1264 if (State->get<InvariantViolated>())
1268 if (!ValDefOrUnknown)
1273 Nullability ValNullability = Nullability::Unspecified;
1274 if (
SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1281 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1284 ValueExprTypeLevelNullability =
1288 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1290 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1291 ValNullability != Nullability::Nonnull &&
1292 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1305 llvm::raw_svector_ostream OS(SBuf);
1307 OS <<
" assigned to a pointer which is expected to have non-null value";
1308 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1309 CK_NullPassedToNonnull, N,
nullptr,
C,
ValueStmt);
1315 if (NullAssignedToNonNull) {
1316 State = State->set<InvariantViolated>(
true);
1317 C.addTransition(State);
1324 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1328 const NullabilityState *TrackedNullability =
1329 State->get<NullabilityMap>(ValueRegion);
1331 if (TrackedNullability) {
1333 TrackedNullability->getValue() != Nullability::Nullable)
1335 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1336 LocNullability == Nullability::Nonnull) {
1338 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
1339 reportBugIfInvariantHolds(
"Nullable pointer is assigned to a pointer "
1340 "which is expected to have non-null value",
1341 ErrorKind::NullableAssignedToNonnull,
1342 CK_NullablePassedToNonnull, N, ValueRegion,
C);
1347 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1349 if (ValNullability == Nullability::Nullable) {
1352 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1353 State = State->set<NullabilityMap>(
1354 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1355 C.addTransition(State);
1359 if (LocNullability == Nullability::Nullable) {
1360 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1361 State = State->set<NullabilityMap>(
1362 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1363 C.addTransition(State);
1367void NullabilityChecker::printState(raw_ostream &Out,
ProgramStateRef State,
1368 const char *NL,
const char *Sep)
const {
1370 NullabilityMapTy B = State->get<NullabilityMap>();
1372 if (State->get<InvariantViolated>())
1374 <<
"Nullability invariant was violated, warnings suppressed." << NL;
1379 if (!State->get<InvariantViolated>())
1382 for (
auto [Region, State] : B) {
1383 Out << Region <<
" : ";
1393bool ento::shouldRegisterNullabilityBase(
const CheckerManager &mgr) {
1397#define REGISTER_CHECKER(name, trackingRequired) \
1398 void ento::register##name##Checker(CheckerManager &mgr) { \
1399 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1400 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1401 checker->CheckNames[NullabilityChecker::CK_##name] = \
1402 mgr.getCurrentCheckerName(); \
1403 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1404 checker->NoDiagnoseCallsToSystemHeaders = \
1405 checker->NoDiagnoseCallsToSystemHeaders || \
1406 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1407 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1410 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
static bool isValidPointerType(QualType T)
static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val, ProgramStateRef State)
#define REGISTER_CHECKER(name, trackingRequired)
static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S)
Returns true if.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State, SVal LV, QualType T)
Returns true when the value stored at the given location has been constrained to null after being pas...
static const Expr * matchValueExprForBind(const Stmt *S)
For a given statement performing a bind, attempt to syntactically match the expression resulting in t...
static bool checkSelfIvarsForInvariantViolation(ProgramStateRef State, const LocationContext *LocCtxt)
static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N, CheckerContext &C)
static const Expr * lookThroughImplicitCasts(const Expr *E)
Find the outermost subexpression of E that is not an implicit cast.
static bool checkParamsForPreconditionViolation(ArrayRef< ParmVarDecl * > Params, ProgramStateRef State, const LocationContext *LocCtxt)
static Nullability getReceiverNullability(const ObjCMethodCall &M, ProgramStateRef State)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
static std::optional< AnyCall > forDecl(const Decl *D)
If D is a callable (Objective-C method or a function), return a constructed AnyCall object.
Decl - This represents one declaration (or definition), e.g.
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
SourceLocation getBeginLoc() const LLVM_READONLY
ExplicitCastExpr - An explicit cast written in the source code.
This represents one expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
One of these records is kept for each identifier that is lexed.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
const ImplicitParamDecl * getSelfDecl() const
Represents an ObjC class declaration.
An expression that sends a message to the given Objective-C object or class.
Represents a pointer to an Objective C object.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Represents a parameter to a function.
A (possibly-)qualified type.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
bool isBlockPointerType() const
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
Represents a statement that could possibly have a value and type.
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
BugReporter is a utility class for generating PathDiagnostics for analysis.
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
Represents an abstract call to a function or method along a particular path.
SVal getReturnValue() const
Returns the return value of the call.
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
ElementRegion is used to represent both array elements and casts.
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
MemRegion - The root abstract class for all memory regions.
const RegionTy * getAs() const
Represents any expression that calls an Objective-C method.
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
bool isInstanceMessage() const
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
ArrayRef< ParmVarDecl * > parameters() const override
Return call's formal parameters.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Selector getSelector() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
const MemRegion * getAsRegion() const
SubRegion - A region that subsets another larger region.
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
bool isLiveRegion(const MemRegion *region)
SymbolicRegion - A special, "non-concrete" region.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const MemoryError
Nullability getNullabilityAnnotation(QualType Type)
Get nullability annotation for a given type.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
ObjCMethodFamily
A family of Objective-C methods.
const FunctionProtoType * T
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
We dereferenced a location that may be null.