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.");
73enum class ErrorKind :
int {
77 NullableAssignedToNonnull,
78 NullableReturnedToNonnull,
80 NullablePassedToNonnull
83class NullabilityChecker
85 check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
86 check::PostCall, check::PostStmt<ExplicitCastExpr>,
87 check::PostObjCMessage, check::DeadSymbols, eval::Assume,
88 check::Location, check::Event<ImplicitNullDerefEvent>,
89 check::BeginFunction> {
98 bool NoDiagnoseCallsToSystemHeaders =
false;
100 void checkBind(
SVal L,
SVal V,
const Stmt *S,
bool AtDeclInit,
109 void checkLocation(
SVal Location,
bool IsLoad,
const Stmt *S,
113 bool Assumption)
const;
116 const char *Sep)
const override;
118 StringRef
getDebugTag()
const override {
return "NullabilityChecker"; }
138 bool NeedTracking =
false;
143 NullabilityBugVisitor(
const MemRegion *M) : Region(M) {}
145 void Profile(llvm::FoldingSetNodeID &ID)
const override {
148 ID.AddPointer(Region);
165 void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error,
168 const Stmt *ValueExpr =
nullptr,
169 bool SuppressPath =
false)
const;
171 void reportBug(StringRef Msg, ErrorKind Error,
const BugType &BT,
173 const Stmt *ValueExpr =
nullptr)
const {
174 auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
176 R->markInteresting(Region);
177 R->addVisitor<NullabilityBugVisitor>(Region);
180 R->addRange(ValueExpr->getSourceRange());
181 if (Error == ErrorKind::NilAssignedToNonnull ||
182 Error == ErrorKind::NilPassedToNonnull ||
183 Error == ErrorKind::NilReturnedToNonnull)
184 if (
const auto *Ex = dyn_cast<Expr>(ValueExpr))
193 bool CheckSuperRegion =
false)
const;
198 if (NoDiagnoseCallsToSystemHeaders &&
Call.isInSystemHeader())
205class NullabilityState {
208 : Nullab(Nullab), Source(Source) {}
210 const Stmt *getNullabilitySource()
const {
return Source; }
214 void Profile(llvm::FoldingSetNodeID &ID)
const {
215 ID.AddInteger(
static_cast<char>(Nullab));
216 ID.AddPointer(Source);
219 void print(raw_ostream &Out)
const {
220 Out << getNullabilityString(Nullab) <<
"\n";
232bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
233 return Lhs.getValue() == Rhs.getValue() &&
234 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
240using ObjectPropPair = std::pair<const MemRegion *, const IdentifierInfo *>;
243struct ConstrainedPropertyVal {
249 bool isConstrainedNonnull;
254 void Profile(llvm::FoldingSetNodeID &ID)
const {
256 ID.AddInteger(isConstrainedNonnull ? 1 : 0);
260bool operator==(
const ConstrainedPropertyVal &Lhs,
261 const ConstrainedPropertyVal &Rhs) {
262 return Lhs.Value == Rhs.Value &&
263 Lhs.isConstrainedNonnull == Rhs.isConstrainedNonnull;
271 ConstrainedPropertyVal)
316NullabilityChecker::getTrackRegion(
SVal Val,
bool CheckSuperRegion)
const {
324 const MemRegion *Region = RegionSVal->getRegion();
326 if (CheckSuperRegion) {
328 if (
const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
330 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
333 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
336 return dyn_cast<SymbolicRegion>(Region);
345 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
346 const NullabilityState *TrackedNullabPrev =
347 StatePrev->get<NullabilityMap>(Region);
351 if (TrackedNullabPrev &&
352 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
356 const Stmt *S = TrackedNullab->getNullabilitySource();
357 if (!S || S->getBeginLoc().isInvalid()) {
364 std::string InfoText =
365 (llvm::Twine(
"Nullability '") +
366 getNullabilityString(TrackedNullab->getValue()) +
"' is inferred")
372 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText,
true);
393 if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
406 for (
const auto *ParamDecl : Params) {
407 if (ParamDecl->isParameterPack())
410 SVal LV = State->getLValue(ParamDecl, LocCtxt);
422 auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->
getDecl());
423 if (!MD || !MD->isInstanceMethod())
430 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
433 dyn_cast<ObjCObjectPointerType>(SelfDecl->
getType());
441 for (
const auto *IvarDecl : ID->ivars()) {
442 SVal LV = State->getLValue(IvarDecl, SelfVal);
452 if (State->get<InvariantViolated>())
461 if (
const auto *BD = dyn_cast<BlockDecl>(
D))
462 Params = BD->parameters();
463 else if (
const auto *FD = dyn_cast<FunctionDecl>(
D))
464 Params = FD->parameters();
465 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(
D))
466 Params = MD->parameters();
473 C.addTransition(State->set<InvariantViolated>(
true), N);
479void NullabilityChecker::reportBugIfInvariantHolds(
482 bool SuppressPath)
const {
488 OriginalState = OriginalState->set<InvariantViolated>(
true);
489 N =
C.addTransition(OriginalState, N);
492 reportBug(Msg, Error, BT, N, Region,
C.getBugReporter(), ValueExpr);
496void NullabilityChecker::checkDeadSymbols(
SymbolReaper &SR,
499 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
500 for (
const MemRegion *Reg : llvm::make_first_range(Nullabilities)) {
502 assert(Region &&
"Non-symbolic region is tracked.");
503 if (SR.
isDead(Region->getSymbol())) {
504 State = State->remove<NullabilityMap>(Reg);
510 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
511 for (
ObjectPropPair PropKey : llvm::make_first_range(PropertyAccesses)) {
512 const MemRegion *ReceiverRegion = PropKey.first;
514 State = State->remove<PropertyAccessesMap>(PropKey);
524 C.addTransition(State);
535 getTrackRegion(Event.
Location,
true);
540 const NullabilityState *TrackedNullability =
541 State->get<NullabilityMap>(Region);
543 if (!TrackedNullability)
546 if (NullableDereferenced.isEnabled() &&
547 TrackedNullability->getValue() == Nullability::Nullable) {
552 reportBug(
"Nullable pointer is dereferenced",
553 ErrorKind::NullableDereferenced, NullableDereferenced,
556 reportBug(
"Nullable pointer is passed to a callee that requires a "
558 ErrorKind::NullablePassedToNonnull, NullableDereferenced,
570 if (!AbstractCall || AbstractCall->parameters().empty())
574 for (
const ParmVarDecl *Param : AbstractCall->parameters()) {
580 if (RequiredNullability != Nullability::Nullable)
583 const VarRegion *ParamRegion = State->getRegion(Param, LCtx);
585 State->getSVal(ParamRegion).getAsRegion();
586 if (!ParamPointeeRegion)
589 State = State->set<NullabilityMap>(ParamPointeeRegion,
590 NullabilityState(RequiredNullability));
592 C.addTransition(State);
608void NullabilityChecker::checkLocation(
SVal Location,
bool IsLoad,
619 dyn_cast_or_null<TypedValueRegion>(Location.
getAsRegion());
632 if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
636 Context.addTransition(NewState);
651void NullabilityChecker::checkPreStmt(
const ReturnStmt *S,
653 auto RetExpr = S->getRetValue();
661 if (State->get<InvariantViolated>())
668 bool InSuppressedMethodFamily =
false;
672 C.getLocationContext()->getAnalysisDeclContext();
674 if (
auto *MD = dyn_cast<ObjCMethodDecl>(
D)) {
681 InSuppressedMethodFamily =
true;
683 RequiredRetType = MD->getReturnType();
684 }
else if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
685 RequiredRetType = FD->getReturnType();
693 if (
const auto *FunDecl =
C.getLocationContext()->getDecl();
694 FunDecl && FunDecl->getAttr<ReturnsNonNullAttr>() &&
695 (RequiredNullability == Nullability::Unspecified ||
696 RequiredNullability == Nullability::Nullable)) {
699 RequiredNullability = Nullability::Nonnull;
710 if (RequiredNullability == Nullability::Nonnull &&
712 if (NullReturnedFromNonnull.isEnabled() &&
713 RetExprTypeLevelNullability != Nullability::Nonnull &&
714 !InSuppressedMethodFamily) {
720 llvm::raw_svector_ostream OS(SBuf);
721 OS << (RetExpr->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
722 OS <<
" returned from a " <<
C.getDeclDescription(
D)
723 <<
" that is expected to return a non-null value";
724 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
725 NullReturnedFromNonnull, N,
nullptr,
C,
732 State = State->set<InvariantViolated>(
true);
733 C.addTransition(State);
737 const MemRegion *Region = getTrackRegion(*RetSVal);
741 const NullabilityState *TrackedNullability =
742 State->get<NullabilityMap>(Region);
743 if (TrackedNullability) {
744 Nullability TrackedNullabValue = TrackedNullability->getValue();
745 if (NullableReturnedFromNonnull.isEnabled() &&
747 TrackedNullabValue == Nullability::Nullable &&
748 RequiredNullability == Nullability::Nonnull) {
752 llvm::raw_svector_ostream OS(SBuf);
753 OS <<
"Nullable pointer is returned from a " <<
C.getDeclDescription(
D) <<
754 " that is expected to return a non-null value";
756 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
757 NullableReturnedFromNonnull, N, Region,
C);
761 if (RequiredNullability == Nullability::Nullable) {
762 State = State->set<NullabilityMap>(Region,
763 NullabilityState(RequiredNullability,
765 C.addTransition(State);
777 if (State->get<InvariantViolated>())
784 if (Param->isParameterPack())
787 if (Idx >=
Call.getNumArgs())
790 const Expr *ArgExpr =
Call.getArgExpr(Idx);
796 !Param->getType()->isReferenceType())
806 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
809 ArgExprTypeLevelNullability != Nullability::Nonnull &&
810 RequiredNullability == Nullability::Nonnull &&
811 isDiagnosableCall(
Call)) {
817 llvm::raw_svector_ostream OS(SBuf);
818 OS << (Param->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
819 OS <<
" passed to a callee that requires a non-null " <<
ParamIdx
820 << llvm::getOrdinalSuffix(
ParamIdx) <<
" parameter";
821 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
822 NullPassedToNonnull, N,
nullptr,
C, ArgExpr,
827 const MemRegion *Region = getTrackRegion(*ArgSVal);
831 const NullabilityState *TrackedNullability =
832 State->get<NullabilityMap>(Region);
834 if (TrackedNullability) {
836 TrackedNullability->getValue() != Nullability::Nullable)
839 if (NullablePassedToNonnull.isEnabled() &&
840 RequiredNullability == Nullability::Nonnull &&
841 isDiagnosableCall(
Call)) {
844 llvm::raw_svector_ostream OS(SBuf);
845 OS <<
"Nullable pointer is passed to a callee that requires a non-null "
847 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
848 NullablePassedToNonnull, N, Region,
C,
852 if (NullableDereferenced.isEnabled() &&
853 Param->getType()->isReferenceType()) {
855 reportBugIfInvariantHolds(
856 "Nullable pointer is dereferenced", ErrorKind::NullableDereferenced,
857 NullableDereferenced, N, Region,
C, ArgExpr,
true);
863 if (State != OrigState)
864 C.addTransition(State);
883 if (State->get<InvariantViolated>())
886 const MemRegion *Region = getTrackRegion(
Call.getReturnValue());
894 if (llvm::sys::path::filename(FilePath).starts_with(
"CG")) {
895 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
896 C.addTransition(State);
900 const NullabilityState *TrackedNullability =
901 State->get<NullabilityMap>(Region);
908 if (
const Expr *
E =
Call.getOriginExpr())
911 if (!TrackedNullability &&
913 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
914 C.addTransition(State);
923 return Nullability::Nonnull;
932 return Nullability::Nonnull;
935 if (ValueRegionSVal) {
936 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
939 const NullabilityState *TrackedSelfNullability =
940 State->get<NullabilityMap>(SelfRegion);
941 if (TrackedSelfNullability)
942 return TrackedSelfNullability->getValue();
944 return Nullability::Unspecified;
952 bool Assumption)
const {
953 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
954 for (
auto [PropKey, PropVal] : PropertyAccesses) {
955 if (!PropVal.isConstrainedNonnull) {
958 ConstrainedPropertyVal Replacement = PropVal;
959 Replacement.isConstrainedNonnull =
true;
960 State = State->set<PropertyAccessesMap>(PropKey, Replacement);
961 }
else if (
IsNonNull.isConstrainedFalse()) {
963 State = State->remove<PropertyAccessesMap>(PropKey);
974void NullabilityChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
984 if (State->get<InvariantViolated>())
996 if (Name.starts_with(
"NS")) {
1007 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1008 C.addTransition(State);
1013 if (Name.contains(
"Array") &&
1014 (FirstSelectorSlot ==
"firstObject" ||
1015 FirstSelectorSlot ==
"lastObject")) {
1017 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1018 C.addTransition(State);
1026 if (Name.contains(
"String")) {
1028 if (Param->getName() ==
"encoding") {
1029 State = State->set<NullabilityMap>(ReturnRegion,
1030 Nullability::Contradicted);
1031 C.addTransition(State);
1041 const NullabilityState *NullabilityOfReturn =
1042 State->get<NullabilityMap>(ReturnRegion);
1044 if (NullabilityOfReturn) {
1048 Nullability RetValTracked = NullabilityOfReturn->getValue();
1050 getMostNullable(RetValTracked, SelfNullability);
1051 if (ComputedNullab != RetValTracked &&
1052 ComputedNullab != Nullability::Unspecified) {
1053 const Stmt *NullabilitySource =
1054 ComputedNullab == RetValTracked
1055 ? NullabilityOfReturn->getNullabilitySource()
1056 : Message->getInstanceReceiver();
1057 State = State->set<NullabilityMap>(
1058 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1059 C.addTransition(State);
1082 if (RetNullability != Nullability::Nonnull &&
1084 bool LookupResolved =
false;
1088 LookupResolved =
true;
1090 const ConstrainedPropertyVal *PrevPropVal =
1091 State->get<PropertyAccessesMap>(Key);
1092 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1093 RetNullability = Nullability::Nonnull;
1101 if (
auto ReturnSVal =
1103 State = State->set<PropertyAccessesMap>(
1104 Key, ConstrainedPropertyVal(*ReturnSVal));
1110 if (!LookupResolved) {
1112 RetNullability = Nullability::Nonnull;
1116 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1117 if (ComputedNullab == Nullability::Nullable) {
1118 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1120 : Message->getInstanceReceiver();
1121 State = State->set<NullabilityMap>(
1122 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1123 C.addTransition(State);
1141 if (State->get<InvariantViolated>())
1148 if (DestNullability == Nullability::Unspecified)
1152 const MemRegion *Region = getTrackRegion(*RegionSVal);
1157 if (DestNullability == Nullability::Nonnull) {
1160 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1161 C.addTransition(State);
1166 const NullabilityState *TrackedNullability =
1167 State->get<NullabilityMap>(Region);
1169 if (!TrackedNullability) {
1170 if (DestNullability != Nullability::Nullable)
1172 State = State->set<NullabilityMap>(Region,
1173 NullabilityState(DestNullability, CE));
1174 C.addTransition(State);
1178 if (TrackedNullability->getValue() != DestNullability &&
1179 TrackedNullability->getValue() != Nullability::Contradicted) {
1180 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1181 C.addTransition(State);
1189 if (
auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1190 if (BinOp->getOpcode() == BO_Assign)
1191 return BinOp->getRHS();
1195 if (
auto *DS = dyn_cast<DeclStmt>(S)) {
1196 if (DS->isSingleDecl()) {
1197 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1201 if (
const Expr *
Init = VD->getInit())
1226 if (!
C.getASTContext().getLangOpts().ObjCAutoRefCount)
1229 auto *DS = dyn_cast<DeclStmt>(S);
1230 if (!DS || !DS->isSingleDecl())
1233 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1238 if(!VD->getType().getQualifiers().hasObjCLifetime())
1242 assert(
Init &&
"ObjC local under ARC without initializer");
1245 if (!isa<ImplicitValueInitExpr>(
Init))
1253void NullabilityChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
1256 dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
1265 if (State->get<InvariantViolated>())
1269 if (!ValDefOrUnknown)
1274 Nullability ValNullability = Nullability::Unspecified;
1275 if (
SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1282 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1285 ValueExprTypeLevelNullability =
1289 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1291 if (NullPassedToNonnull.isEnabled() && NullAssignedToNonNull &&
1292 ValNullability != Nullability::Nonnull &&
1293 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 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 (NullablePassedToNonnull.isEnabled() &&
1336 LocNullability == Nullability::Nonnull) {
1338 reportBugIfInvariantHolds(
"Nullable pointer is assigned to a pointer "
1339 "which is expected to have non-null value",
1340 ErrorKind::NullableAssignedToNonnull,
1341 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 <<
" : ";
1395constexpr llvm::StringLiteral
GroupOptName =
"NoDiagnoseCallsToSystemHeaders";
1397#define REGISTER_CHECKER(NAME, TRACKING_REQUIRED) \
1398 void ento::register##NAME##Checker(CheckerManager &Mgr) { \
1399 NullabilityChecker *Chk = Mgr.getChecker<NullabilityChecker>(); \
1400 Chk->NAME.enable(Mgr); \
1401 Chk->NeedTracking = Chk->NeedTracking || TRACKING_REQUIRED; \
1402 Chk->NoDiagnoseCallsToSystemHeaders = \
1403 Mgr.getAnalyzerOptions().getCheckerBooleanOption(GroupName, \
1404 GroupOptName, true); \
1407 bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
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)
static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S)
Returns true if.
constexpr llvm::StringLiteral GroupOptName
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)
constexpr llvm::StringLiteral GroupName
static const Expr * lookThroughImplicitCasts(const Expr *E)
Find the outermost subexpression of E that is not an implicit cast.
#define REGISTER_CHECKER(NAME, TRACKING_REQUIRED)
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.
virtual StringRef getDebugTag() const =0
The description of this program point which will be dumped for debugging purposes.
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
Debug state dump callback, see CheckerManager::runCheckersForPrintState.
Checker families (where a single backend class implements multiple related frontends) should derive f...
Trivial convenience class for the common case when a certain checker frontend always uses the same bu...
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.