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).startswith(
"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())
908 ReturnType = E->getType();
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.startswith(
"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;
1086 LookupResolved =
true;
1088 const ConstrainedPropertyVal *PrevPropVal =
1089 State->get<PropertyAccessesMap>(Key);
1090 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1091 RetNullability = Nullability::Nonnull;
1099 if (
auto ReturnSVal =
1101 State = State->set<PropertyAccessesMap>(
1102 Key, ConstrainedPropertyVal(*ReturnSVal));
1108 if (!LookupResolved) {
1110 RetNullability = Nullability::Nonnull;
1114 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1115 if (ComputedNullab == Nullability::Nullable) {
1116 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1118 : Message->getInstanceReceiver();
1119 State = State->set<NullabilityMap>(
1120 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1121 C.addTransition(State);
1139 if (State->get<InvariantViolated>())
1146 if (DestNullability == Nullability::Unspecified)
1150 const MemRegion *Region = getTrackRegion(*RegionSVal);
1155 if (DestNullability == Nullability::Nonnull) {
1158 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1159 C.addTransition(State);
1164 const NullabilityState *TrackedNullability =
1165 State->get<NullabilityMap>(Region);
1167 if (!TrackedNullability) {
1168 if (DestNullability != Nullability::Nullable)
1170 State = State->set<NullabilityMap>(Region,
1171 NullabilityState(DestNullability, CE));
1172 C.addTransition(State);
1176 if (TrackedNullability->getValue() != DestNullability &&
1177 TrackedNullability->getValue() != Nullability::Contradicted) {
1178 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1179 C.addTransition(State);
1187 if (
auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1188 if (BinOp->getOpcode() == BO_Assign)
1189 return BinOp->getRHS();
1193 if (
auto *DS = dyn_cast<DeclStmt>(S)) {
1194 if (DS->isSingleDecl()) {
1195 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1199 if (
const Expr *
Init = VD->getInit())
1224 if (!
C.getASTContext().getLangOpts().ObjCAutoRefCount)
1227 auto *DS = dyn_cast<DeclStmt>(S);
1228 if (!DS || !DS->isSingleDecl())
1231 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1236 if(!VD->getType().getQualifiers().hasObjCLifetime())
1240 assert(
Init &&
"ObjC local under ARC without initializer");
1243 if (!isa<ImplicitValueInitExpr>(
Init))
1251void NullabilityChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
1254 dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
1263 if (State->get<InvariantViolated>())
1267 if (!ValDefOrUnknown)
1272 Nullability ValNullability = Nullability::Unspecified;
1273 if (
SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1280 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1283 ValueExprTypeLevelNullability =
1287 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1289 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1290 ValNullability != Nullability::Nonnull &&
1291 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1304 llvm::raw_svector_ostream OS(SBuf);
1306 OS <<
" assigned to a pointer which is expected to have non-null value";
1307 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1308 CK_NullPassedToNonnull, N,
nullptr,
C,
ValueStmt);
1314 if (NullAssignedToNonNull) {
1315 State = State->set<InvariantViolated>(
true);
1316 C.addTransition(State);
1323 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1327 const NullabilityState *TrackedNullability =
1328 State->get<NullabilityMap>(ValueRegion);
1330 if (TrackedNullability) {
1332 TrackedNullability->getValue() != Nullability::Nullable)
1334 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1335 LocNullability == Nullability::Nonnull) {
1337 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
1338 reportBugIfInvariantHolds(
"Nullable pointer is assigned to a pointer "
1339 "which is expected to have non-null value",
1340 ErrorKind::NullableAssignedToNonnull,
1341 CK_NullablePassedToNonnull, N, ValueRegion,
C);
1346 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1348 if (ValNullability == Nullability::Nullable) {
1351 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1352 State = State->set<NullabilityMap>(
1353 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1354 C.addTransition(State);
1358 if (LocNullability == Nullability::Nullable) {
1359 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1360 State = State->set<NullabilityMap>(
1361 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1362 C.addTransition(State);
1366void NullabilityChecker::printState(raw_ostream &Out,
ProgramStateRef State,
1367 const char *NL,
const char *Sep)
const {
1369 NullabilityMapTy B = State->get<NullabilityMap>();
1371 if (State->get<InvariantViolated>())
1373 <<
"Nullability invariant was violated, warnings suppressed." << NL;
1378 if (!State->get<InvariantViolated>())
1381 for (
auto [Region, State] : B) {
1382 Out << Region <<
" : ";
1392bool ento::shouldRegisterNullabilityBase(
const CheckerManager &mgr) {
1396#define REGISTER_CHECKER(name, trackingRequired) \
1397 void ento::register##name##Checker(CheckerManager &mgr) { \
1398 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1399 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1400 checker->CheckNames[NullabilityChecker::CK_##name] = \
1401 mgr.getCurrentCheckerName(); \
1402 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1403 checker->NoDiagnoseCallsToSystemHeaders = \
1404 checker->NoDiagnoseCallsToSystemHeaders || \
1405 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1406 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1409 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType)
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.
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
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
ObjCMethodFamily
A family of Objective-C methods.
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
We dereferenced a location that may be null.