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();
695 if (
const auto *FunDecl =
C.getLocationContext()->getDecl();
696 FunDecl && FunDecl->getAttr<ReturnsNonNullAttr>() &&
697 (RequiredNullability == Nullability::Unspecified ||
698 RequiredNullability == Nullability::Nullable)) {
701 RequiredNullability = Nullability::Nonnull;
712 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
714 if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
715 RetExprTypeLevelNullability != Nullability::Nonnull &&
716 !InSuppressedMethodFamily) {
723 llvm::raw_svector_ostream OS(SBuf);
724 OS << (RetExpr->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
725 OS <<
" returned from a " <<
C.getDeclDescription(
D) <<
726 " that is expected to return a non-null value";
727 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
728 CK_NullReturnedFromNonnull, N,
nullptr,
C,
735 if (NullReturnedFromNonNull) {
736 State = State->set<InvariantViolated>(
true);
737 C.addTransition(State);
741 const MemRegion *Region = getTrackRegion(*RetSVal);
745 const NullabilityState *TrackedNullability =
746 State->get<NullabilityMap>(Region);
747 if (TrackedNullability) {
748 Nullability TrackedNullabValue = TrackedNullability->getValue();
749 if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
751 TrackedNullabValue == Nullability::Nullable &&
752 RequiredNullability == Nullability::Nonnull) {
754 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
757 llvm::raw_svector_ostream OS(SBuf);
758 OS <<
"Nullable pointer is returned from a " <<
C.getDeclDescription(
D) <<
759 " that is expected to return a non-null value";
761 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
762 CK_NullableReturnedFromNonnull, N, Region,
C);
766 if (RequiredNullability == Nullability::Nullable) {
767 State = State->set<NullabilityMap>(Region,
768 NullabilityState(RequiredNullability,
770 C.addTransition(State);
782 if (State->get<InvariantViolated>())
789 if (Param->isParameterPack())
792 if (Idx >=
Call.getNumArgs())
795 const Expr *ArgExpr =
Call.getArgExpr(Idx);
801 !Param->getType()->isReferenceType())
811 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
813 if (ChecksEnabled[CK_NullPassedToNonnull] &&
815 ArgExprTypeLevelNullability != Nullability::Nonnull &&
816 RequiredNullability == Nullability::Nonnull &&
817 isDiagnosableCall(
Call)) {
823 llvm::raw_svector_ostream OS(SBuf);
824 OS << (Param->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
825 OS <<
" passed to a callee that requires a non-null " <<
ParamIdx
826 << llvm::getOrdinalSuffix(
ParamIdx) <<
" parameter";
827 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
828 CK_NullPassedToNonnull, N,
nullptr,
C, ArgExpr,
833 const MemRegion *Region = getTrackRegion(*ArgSVal);
837 const NullabilityState *TrackedNullability =
838 State->get<NullabilityMap>(Region);
840 if (TrackedNullability) {
842 TrackedNullability->getValue() != Nullability::Nullable)
845 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
846 RequiredNullability == Nullability::Nonnull &&
847 isDiagnosableCall(
Call)) {
850 llvm::raw_svector_ostream OS(SBuf);
851 OS <<
"Nullable pointer is passed to a callee that requires a non-null "
853 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
854 CK_NullablePassedToNonnull, N, Region,
C,
858 if (ChecksEnabled[CK_NullableDereferenced] &&
859 Param->getType()->isReferenceType()) {
861 reportBugIfInvariantHolds(
"Nullable pointer is dereferenced",
862 ErrorKind::NullableDereferenced,
863 CK_NullableDereferenced, N, Region,
C,
870 if (State != OrigState)
871 C.addTransition(State);
890 if (State->get<InvariantViolated>())
893 const MemRegion *Region = getTrackRegion(
Call.getReturnValue());
901 if (llvm::sys::path::filename(FilePath).starts_with(
"CG")) {
902 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
903 C.addTransition(State);
907 const NullabilityState *TrackedNullability =
908 State->get<NullabilityMap>(Region);
915 if (
const Expr *
E =
Call.getOriginExpr())
918 if (!TrackedNullability &&
920 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
921 C.addTransition(State);
930 return Nullability::Nonnull;
939 return Nullability::Nonnull;
942 if (ValueRegionSVal) {
943 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
946 const NullabilityState *TrackedSelfNullability =
947 State->get<NullabilityMap>(SelfRegion);
948 if (TrackedSelfNullability)
949 return TrackedSelfNullability->getValue();
951 return Nullability::Unspecified;
959 bool Assumption)
const {
960 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
961 for (
auto [PropKey, PropVal] : PropertyAccesses) {
962 if (!PropVal.isConstrainedNonnull) {
965 ConstrainedPropertyVal Replacement = PropVal;
966 Replacement.isConstrainedNonnull =
true;
967 State = State->set<PropertyAccessesMap>(PropKey, Replacement);
968 }
else if (
IsNonNull.isConstrainedFalse()) {
970 State = State->remove<PropertyAccessesMap>(PropKey);
981void NullabilityChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
991 if (State->get<InvariantViolated>())
1003 if (Name.starts_with(
"NS")) {
1014 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1015 C.addTransition(State);
1020 if (Name.contains(
"Array") &&
1021 (FirstSelectorSlot ==
"firstObject" ||
1022 FirstSelectorSlot ==
"lastObject")) {
1024 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1025 C.addTransition(State);
1033 if (Name.contains(
"String")) {
1035 if (Param->getName() ==
"encoding") {
1036 State = State->set<NullabilityMap>(ReturnRegion,
1037 Nullability::Contradicted);
1038 C.addTransition(State);
1048 const NullabilityState *NullabilityOfReturn =
1049 State->get<NullabilityMap>(ReturnRegion);
1051 if (NullabilityOfReturn) {
1055 Nullability RetValTracked = NullabilityOfReturn->getValue();
1057 getMostNullable(RetValTracked, SelfNullability);
1058 if (ComputedNullab != RetValTracked &&
1059 ComputedNullab != Nullability::Unspecified) {
1060 const Stmt *NullabilitySource =
1061 ComputedNullab == RetValTracked
1062 ? NullabilityOfReturn->getNullabilitySource()
1063 : Message->getInstanceReceiver();
1064 State = State->set<NullabilityMap>(
1065 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1066 C.addTransition(State);
1089 if (RetNullability != Nullability::Nonnull &&
1091 bool LookupResolved =
false;
1095 LookupResolved =
true;
1097 const ConstrainedPropertyVal *PrevPropVal =
1098 State->get<PropertyAccessesMap>(Key);
1099 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1100 RetNullability = Nullability::Nonnull;
1108 if (
auto ReturnSVal =
1110 State = State->set<PropertyAccessesMap>(
1111 Key, ConstrainedPropertyVal(*ReturnSVal));
1117 if (!LookupResolved) {
1119 RetNullability = Nullability::Nonnull;
1123 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1124 if (ComputedNullab == Nullability::Nullable) {
1125 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1127 : Message->getInstanceReceiver();
1128 State = State->set<NullabilityMap>(
1129 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1130 C.addTransition(State);
1148 if (State->get<InvariantViolated>())
1155 if (DestNullability == Nullability::Unspecified)
1159 const MemRegion *Region = getTrackRegion(*RegionSVal);
1164 if (DestNullability == Nullability::Nonnull) {
1167 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1168 C.addTransition(State);
1173 const NullabilityState *TrackedNullability =
1174 State->get<NullabilityMap>(Region);
1176 if (!TrackedNullability) {
1177 if (DestNullability != Nullability::Nullable)
1179 State = State->set<NullabilityMap>(Region,
1180 NullabilityState(DestNullability, CE));
1181 C.addTransition(State);
1185 if (TrackedNullability->getValue() != DestNullability &&
1186 TrackedNullability->getValue() != Nullability::Contradicted) {
1187 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1188 C.addTransition(State);
1196 if (
auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1197 if (BinOp->getOpcode() == BO_Assign)
1198 return BinOp->getRHS();
1202 if (
auto *DS = dyn_cast<DeclStmt>(S)) {
1203 if (DS->isSingleDecl()) {
1204 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1208 if (
const Expr *
Init = VD->getInit())
1233 if (!
C.getASTContext().getLangOpts().ObjCAutoRefCount)
1236 auto *DS = dyn_cast<DeclStmt>(S);
1237 if (!DS || !DS->isSingleDecl())
1240 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1245 if(!VD->getType().getQualifiers().hasObjCLifetime())
1249 assert(
Init &&
"ObjC local under ARC without initializer");
1252 if (!isa<ImplicitValueInitExpr>(
Init))
1260void NullabilityChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
1263 dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
1272 if (State->get<InvariantViolated>())
1276 if (!ValDefOrUnknown)
1281 Nullability ValNullability = Nullability::Unspecified;
1282 if (
SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1289 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1292 ValueExprTypeLevelNullability =
1296 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1298 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1299 ValNullability != Nullability::Nonnull &&
1300 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1313 llvm::raw_svector_ostream OS(SBuf);
1315 OS <<
" assigned to a pointer which is expected to have non-null value";
1316 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1317 CK_NullPassedToNonnull, N,
nullptr,
C,
ValueStmt);
1323 if (NullAssignedToNonNull) {
1324 State = State->set<InvariantViolated>(
true);
1325 C.addTransition(State);
1332 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1336 const NullabilityState *TrackedNullability =
1337 State->get<NullabilityMap>(ValueRegion);
1339 if (TrackedNullability) {
1341 TrackedNullability->getValue() != Nullability::Nullable)
1343 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1344 LocNullability == Nullability::Nonnull) {
1346 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
1347 reportBugIfInvariantHolds(
"Nullable pointer is assigned to a pointer "
1348 "which is expected to have non-null value",
1349 ErrorKind::NullableAssignedToNonnull,
1350 CK_NullablePassedToNonnull, N, ValueRegion,
C);
1355 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1357 if (ValNullability == Nullability::Nullable) {
1360 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1361 State = State->set<NullabilityMap>(
1362 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1363 C.addTransition(State);
1367 if (LocNullability == Nullability::Nullable) {
1368 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1369 State = State->set<NullabilityMap>(
1370 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1371 C.addTransition(State);
1375void NullabilityChecker::printState(raw_ostream &Out,
ProgramStateRef State,
1376 const char *NL,
const char *Sep)
const {
1378 NullabilityMapTy B = State->get<NullabilityMap>();
1380 if (State->get<InvariantViolated>())
1382 <<
"Nullability invariant was violated, warnings suppressed." << NL;
1387 if (!State->get<InvariantViolated>())
1390 for (
auto [Region, State] : B) {
1391 Out << Region <<
" : ";
1401bool ento::shouldRegisterNullabilityBase(
const CheckerManager &mgr) {
1405#define REGISTER_CHECKER(name, trackingRequired) \
1406 void ento::register##name##Checker(CheckerManager &mgr) { \
1407 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1408 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1409 checker->CheckNames[NullabilityChecker::CK_##name] = \
1410 mgr.getCurrentCheckerName(); \
1411 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1412 checker->NoDiagnoseCallsToSystemHeaders = \
1413 checker->NoDiagnoseCallsToSystemHeaders || \
1414 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1415 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1418 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
bool IsNonNull(InterpState &S, CodePtr OpPC)
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.