36#include "llvm/ADT/StringExtras.h"
37#include "llvm/Support/Path.h"
51 std::min(
static_cast<char>(Lhs),
static_cast<char>(Rhs)));
54const char *getNullabilityString(
Nullability Nullab) {
56 case Nullability::Contradicted:
57 return "contradicted";
58 case Nullability::Nullable:
60 case Nullability::Unspecified:
62 case Nullability::Nonnull:
65 llvm_unreachable(
"Unexpected enumeration.");
70enum class ErrorKind :
int {
74 NullableAssignedToNonnull,
75 NullableReturnedToNonnull,
77 NullablePassedToNonnull
80class NullabilityChecker
81 :
public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
82 check::PostCall, check::PostStmt<ExplicitCastExpr>,
83 check::PostObjCMessage, check::DeadSymbols, eval::Assume,
84 check::Location, check::Event<ImplicitNullDerefEvent>> {
93 bool NoDiagnoseCallsToSystemHeaders =
false;
103 void checkLocation(
SVal Location,
bool IsLoad,
const Stmt *S,
106 bool Assumption)
const;
109 const char *Sep)
const override;
112 CK_NullPassedToNonnull,
113 CK_NullReturnedFromNonnull,
114 CK_NullableDereferenced,
115 CK_NullablePassedToNonnull,
116 CK_NullableReturnedFromNonnull,
120 bool ChecksEnabled[CK_NumCheckKinds] = {
false};
122 mutable std::unique_ptr<BugType> BTs[CK_NumCheckKinds];
124 const std::unique_ptr<BugType> &getBugType(CheckKind Kind)
const {
126 BTs[
Kind].reset(
new BugType(CheckNames[Kind],
"Nullability",
135 bool NeedTracking =
false;
140 NullabilityBugVisitor(
const MemRegion *M) : Region(M) {}
142 void Profile(llvm::FoldingSetNodeID &ID)
const override {
145 ID.AddPointer(Region);
162 void reportBugIfInvariantHolds(StringRef Msg, ErrorKind
Error, CheckKind CK,
165 const Stmt *ValueExpr =
nullptr,
166 bool SuppressPath =
false)
const;
170 const Stmt *ValueExpr =
nullptr)
const {
171 const std::unique_ptr<BugType> &BT = getBugType(CK);
172 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
174 R->markInteresting(Region);
175 R->addVisitor<NullabilityBugVisitor>(Region);
178 R->addRange(ValueExpr->getSourceRange());
179 if (
Error == ErrorKind::NilAssignedToNonnull ||
180 Error == ErrorKind::NilPassedToNonnull ||
181 Error == ErrorKind::NilReturnedToNonnull)
182 if (
const auto *Ex = dyn_cast<Expr>(ValueExpr))
191 bool CheckSuperRegion =
false)
const;
195 bool isDiagnosableCall(
const CallEvent &Call)
const {
196 if (NoDiagnoseCallsToSystemHeaders &&
Call.isInSystemHeader())
203class NullabilityState {
206 : Nullab(Nullab), Source(Source) {}
208 const Stmt *getNullabilitySource()
const {
return Source; }
212 void Profile(llvm::FoldingSetNodeID &ID)
const {
213 ID.AddInteger(
static_cast<char>(Nullab));
214 ID.AddPointer(Source);
217 void print(raw_ostream &Out)
const {
218 Out << getNullabilityString(Nullab) <<
"\n";
230bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
231 return Lhs.getValue() == Rhs.getValue() &&
232 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
238using ObjectPropPair = std::pair<const MemRegion *, const IdentifierInfo *>;
241struct ConstrainedPropertyVal {
247 bool isConstrainedNonnull;
252 void Profile(llvm::FoldingSetNodeID &ID)
const {
254 ID.AddInteger(isConstrainedNonnull ? 1 : 0);
258bool operator==(
const ConstrainedPropertyVal &Lhs,
259 const ConstrainedPropertyVal &Rhs) {
260 return Lhs.Value == Rhs.Value &&
261 Lhs.isConstrainedNonnull == Rhs.isConstrainedNonnull;
269 ConstrainedPropertyVal)
310NullabilityChecker::getTrackRegion(
SVal Val,
bool CheckSuperRegion)
const {
318 const MemRegion *Region = RegionSVal->getRegion();
320 if (CheckSuperRegion) {
322 if (
const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
324 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
327 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
330 return dyn_cast<SymbolicRegion>(Region);
339 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
340 const NullabilityState *TrackedNullabPrev =
341 StatePrev->get<NullabilityMap>(Region);
345 if (TrackedNullabPrev &&
346 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
350 const Stmt *S = TrackedNullab->getNullabilitySource();
351 if (!S || S->getBeginLoc().isInvalid()) {
358 std::string InfoText =
359 (llvm::Twine(
"Nullability '") +
360 getNullabilityString(TrackedNullab->getValue()) +
"' is inferred")
366 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText,
true);
387 if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
400 for (
const auto *ParamDecl : Params) {
401 if (ParamDecl->isParameterPack())
404 SVal LV = State->getLValue(ParamDecl, LocCtxt);
416 auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->
getDecl());
417 if (!MD || !MD->isInstanceMethod())
424 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
427 dyn_cast<ObjCObjectPointerType>(SelfDecl->
getType());
435 for (
const auto *IvarDecl : ID->ivars()) {
436 SVal LV = State->getLValue(IvarDecl, SelfVal);
446 if (State->get<InvariantViolated>())
455 if (
const auto *BD = dyn_cast<BlockDecl>(D))
456 Params = BD->parameters();
457 else if (
const auto *FD = dyn_cast<FunctionDecl>(D))
458 Params = FD->parameters();
459 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
460 Params = MD->parameters();
467 C.addTransition(State->set<InvariantViolated>(
true), N);
473void NullabilityChecker::reportBugIfInvariantHolds(
476 bool SuppressPath)
const {
482 OriginalState = OriginalState->set<InvariantViolated>(
true);
483 N =
C.addTransition(OriginalState, N);
486 reportBug(Msg,
Error, CK, N, Region,
C.getBugReporter(), ValueExpr);
490void NullabilityChecker::checkDeadSymbols(
SymbolReaper &SR,
493 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
494 for (NullabilityMapTy::iterator I = Nullabilities.begin(),
495 E = Nullabilities.end();
498 assert(Region &&
"Non-symbolic region is tracked.");
499 if (SR.
isDead(Region->getSymbol())) {
500 State = State->remove<NullabilityMap>(I->first);
506 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
507 for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
508 E = PropertyAccesses.end();
510 const MemRegion *ReceiverRegion = I->first.first;
512 State = State->remove<PropertyAccessesMap>(I->first);
522 C.addTransition(State);
533 getTrackRegion(Event.
Location,
true);
538 const NullabilityState *TrackedNullability =
539 State->get<NullabilityMap>(Region);
541 if (!TrackedNullability)
544 if (ChecksEnabled[CK_NullableDereferenced] &&
545 TrackedNullability->getValue() == Nullability::Nullable) {
550 reportBug(
"Nullable pointer is dereferenced",
551 ErrorKind::NullableDereferenced, CK_NullableDereferenced,
554 reportBug(
"Nullable pointer is passed to a callee that requires a "
556 ErrorKind::NullablePassedToNonnull, CK_NullableDereferenced,
575void NullabilityChecker::checkLocation(
SVal Location,
bool IsLoad,
586 dyn_cast_or_null<TypedValueRegion>(Location.
getAsRegion());
599 if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
603 Context.addTransition(NewState);
618void NullabilityChecker::checkPreStmt(
const ReturnStmt *S,
620 auto RetExpr = S->getRetValue();
624 if (!RetExpr->getType()->isAnyPointerType())
628 if (State->get<InvariantViolated>())
635 bool InSuppressedMethodFamily =
false;
639 C.getLocationContext()->getAnalysisDeclContext();
641 if (
auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
648 InSuppressedMethodFamily =
true;
650 RequiredRetType = MD->getReturnType();
651 }
else if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
652 RequiredRetType = FD->getReturnType();
669 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
671 if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
672 RetExprTypeLevelNullability != Nullability::Nonnull &&
673 !InSuppressedMethodFamily &&
C.getLocationContext()->inTopFrame()) {
680 llvm::raw_svector_ostream
OS(SBuf);
681 OS << (RetExpr->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
682 OS <<
" returned from a " <<
C.getDeclDescription(D) <<
683 " that is expected to return a non-null value";
684 reportBugIfInvariantHolds(
OS.str(), ErrorKind::NilReturnedToNonnull,
685 CK_NullReturnedFromNonnull, N,
nullptr,
C,
692 if (NullReturnedFromNonNull) {
693 State = State->set<InvariantViolated>(
true);
694 C.addTransition(State);
698 const MemRegion *Region = getTrackRegion(*RetSVal);
702 const NullabilityState *TrackedNullability =
703 State->get<NullabilityMap>(Region);
704 if (TrackedNullability) {
705 Nullability TrackedNullabValue = TrackedNullability->getValue();
706 if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
708 TrackedNullabValue == Nullability::Nullable &&
709 RequiredNullability == Nullability::Nonnull) {
711 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
714 llvm::raw_svector_ostream
OS(SBuf);
715 OS <<
"Nullable pointer is returned from a " <<
C.getDeclDescription(D) <<
716 " that is expected to return a non-null value";
718 reportBugIfInvariantHolds(
OS.str(), ErrorKind::NullableReturnedToNonnull,
719 CK_NullableReturnedFromNonnull, N, Region,
C);
723 if (RequiredNullability == Nullability::Nullable) {
724 State = State->set<NullabilityMap>(Region,
725 NullabilityState(RequiredNullability,
727 C.addTransition(State);
733void NullabilityChecker::checkPreCall(
const CallEvent &Call,
739 if (State->get<InvariantViolated>())
746 if (Param->isParameterPack())
749 if (Idx >=
Call.getNumArgs())
752 const Expr *ArgExpr =
Call.getArgExpr(Idx);
757 if (!Param->getType()->isAnyPointerType() &&
758 !Param->getType()->isReferenceType())
768 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
770 if (ChecksEnabled[CK_NullPassedToNonnull] &&
772 ArgExprTypeLevelNullability != Nullability::Nonnull &&
773 RequiredNullability == Nullability::Nonnull &&
774 isDiagnosableCall(Call)) {
780 llvm::raw_svector_ostream
OS(SBuf);
781 OS << (Param->getType()->isObjCObjectPointerType() ?
"nil" :
"Null");
782 OS <<
" passed to a callee that requires a non-null " <<
ParamIdx
783 << llvm::getOrdinalSuffix(
ParamIdx) <<
" parameter";
784 reportBugIfInvariantHolds(
OS.str(), ErrorKind::NilPassedToNonnull,
785 CK_NullPassedToNonnull, N,
nullptr,
C, ArgExpr,
790 const MemRegion *Region = getTrackRegion(*ArgSVal);
794 const NullabilityState *TrackedNullability =
795 State->get<NullabilityMap>(Region);
797 if (TrackedNullability) {
799 TrackedNullability->getValue() != Nullability::Nullable)
802 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
803 RequiredNullability == Nullability::Nonnull &&
804 isDiagnosableCall(Call)) {
807 llvm::raw_svector_ostream
OS(SBuf);
808 OS <<
"Nullable pointer is passed to a callee that requires a non-null "
810 reportBugIfInvariantHolds(
OS.str(), ErrorKind::NullablePassedToNonnull,
811 CK_NullablePassedToNonnull, N, Region,
C,
815 if (ChecksEnabled[CK_NullableDereferenced] &&
816 Param->getType()->isReferenceType()) {
818 reportBugIfInvariantHolds(
"Nullable pointer is dereferenced",
819 ErrorKind::NullableDereferenced,
820 CK_NullableDereferenced, N, Region,
C,
827 if (State != OrigState)
828 C.addTransition(State);
832void NullabilityChecker::checkPostCall(
const CallEvent &Call,
847 if (State->get<InvariantViolated>())
850 const MemRegion *Region = getTrackRegion(
Call.getReturnValue());
858 if (llvm::sys::path::filename(FilePath).startswith(
"CG")) {
859 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
860 C.addTransition(State);
864 const NullabilityState *TrackedNullability =
865 State->get<NullabilityMap>(Region);
867 if (!TrackedNullability &&
869 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
870 C.addTransition(State);
879 return Nullability::Nonnull;
888 return Nullability::Nonnull;
891 if (ValueRegionSVal) {
892 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
895 const NullabilityState *TrackedSelfNullability =
896 State->get<NullabilityMap>(SelfRegion);
897 if (TrackedSelfNullability)
898 return TrackedSelfNullability->getValue();
900 return Nullability::Unspecified;
908 bool Assumption)
const {
909 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
910 for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
911 E = PropertyAccesses.end();
913 if (!I->second.isConstrainedNonnull) {
916 ConstrainedPropertyVal Replacement = I->second;
917 Replacement.isConstrainedNonnull =
true;
918 State = State->set<PropertyAccessesMap>(I->first, Replacement);
921 State = State->remove<PropertyAccessesMap>(I->first);
932void NullabilityChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
942 if (State->get<InvariantViolated>())
949 auto Interface =
Decl->getClassInterface();
950 auto Name = Interface ? Interface->getName() :
"";
954 if (Name.startswith(
"NS")) {
965 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
966 C.addTransition(State);
971 if (Name.contains(
"Array") &&
972 (FirstSelectorSlot ==
"firstObject" ||
973 FirstSelectorSlot ==
"lastObject")) {
975 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
976 C.addTransition(State);
984 if (Name.contains(
"String")) {
986 if (Param->getName() ==
"encoding") {
987 State = State->set<NullabilityMap>(ReturnRegion,
988 Nullability::Contradicted);
989 C.addTransition(State);
999 const NullabilityState *NullabilityOfReturn =
1000 State->get<NullabilityMap>(ReturnRegion);
1002 if (NullabilityOfReturn) {
1006 Nullability RetValTracked = NullabilityOfReturn->getValue();
1008 getMostNullable(RetValTracked, SelfNullability);
1009 if (ComputedNullab != RetValTracked &&
1010 ComputedNullab != Nullability::Unspecified) {
1011 const Stmt *NullabilitySource =
1012 ComputedNullab == RetValTracked
1013 ? NullabilityOfReturn->getNullabilitySource()
1014 :
Message->getInstanceReceiver();
1015 State = State->set<NullabilityMap>(
1016 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1017 C.addTransition(State);
1040 if (RetNullability != Nullability::Nonnull &&
1042 bool LookupResolved =
false;
1045 LookupResolved =
true;
1047 const ConstrainedPropertyVal *PrevPropVal =
1048 State->get<PropertyAccessesMap>(Key);
1049 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1050 RetNullability = Nullability::Nonnull;
1058 if (
auto ReturnSVal =
1060 State = State->set<PropertyAccessesMap>(
1061 Key, ConstrainedPropertyVal(*ReturnSVal));
1067 if (!LookupResolved) {
1069 RetNullability = Nullability::Nonnull;
1073 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1074 if (ComputedNullab == Nullability::Nullable) {
1075 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1077 :
Message->getInstanceReceiver();
1078 State = State->set<NullabilityMap>(
1079 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1080 C.addTransition(State);
1098 if (State->get<InvariantViolated>())
1105 if (DestNullability == Nullability::Unspecified)
1109 const MemRegion *Region = getTrackRegion(*RegionSVal);
1114 if (DestNullability == Nullability::Nonnull) {
1117 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1118 C.addTransition(State);
1123 const NullabilityState *TrackedNullability =
1124 State->get<NullabilityMap>(Region);
1126 if (!TrackedNullability) {
1127 if (DestNullability != Nullability::Nullable)
1129 State = State->set<NullabilityMap>(Region,
1130 NullabilityState(DestNullability, CE));
1131 C.addTransition(State);
1135 if (TrackedNullability->getValue() != DestNullability &&
1136 TrackedNullability->getValue() != Nullability::Contradicted) {
1137 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1138 C.addTransition(State);
1146 if (
auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1147 if (BinOp->getOpcode() == BO_Assign)
1148 return BinOp->getRHS();
1152 if (
auto *DS = dyn_cast<DeclStmt>(S)) {
1153 if (DS->isSingleDecl()) {
1154 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1158 if (
const Expr *Init = VD->getInit())
1183 if (!
C.getASTContext().getLangOpts().ObjCAutoRefCount)
1186 auto *DS = dyn_cast<DeclStmt>(S);
1187 if (!DS || !DS->isSingleDecl())
1190 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1195 if(!VD->getType().getQualifiers().hasObjCLifetime())
1198 const Expr *Init = VD->getInit();
1199 assert(Init &&
"ObjC local under ARC without initializer");
1202 if (!isa<ImplicitValueInitExpr>(Init))
1210void NullabilityChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
1213 dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
1222 if (State->get<InvariantViolated>())
1226 if (!ValDefOrUnknown)
1231 Nullability ValNullability = Nullability::Unspecified;
1232 if (
SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1239 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1242 ValueExprTypeLevelNullability =
1246 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1248 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1249 ValNullability != Nullability::Nonnull &&
1250 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1263 llvm::raw_svector_ostream
OS(SBuf);
1265 OS <<
" assigned to a pointer which is expected to have non-null value";
1266 reportBugIfInvariantHolds(
OS.str(), ErrorKind::NilAssignedToNonnull,
1267 CK_NullPassedToNonnull, N,
nullptr,
C,
ValueStmt);
1273 if (NullAssignedToNonNull) {
1274 State = State->set<InvariantViolated>(
true);
1275 C.addTransition(State);
1282 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1286 const NullabilityState *TrackedNullability =
1287 State->get<NullabilityMap>(ValueRegion);
1289 if (TrackedNullability) {
1291 TrackedNullability->getValue() != Nullability::Nullable)
1293 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1294 LocNullability == Nullability::Nonnull) {
1296 ExplodedNode *N =
C.addTransition(State,
C.getPredecessor(), &Tag);
1297 reportBugIfInvariantHolds(
"Nullable pointer is assigned to a pointer "
1298 "which is expected to have non-null value",
1299 ErrorKind::NullableAssignedToNonnull,
1300 CK_NullablePassedToNonnull, N, ValueRegion,
C);
1305 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1307 if (ValNullability == Nullability::Nullable) {
1310 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1311 State = State->set<NullabilityMap>(
1312 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1313 C.addTransition(State);
1317 if (LocNullability == Nullability::Nullable) {
1318 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1319 State = State->set<NullabilityMap>(
1320 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1321 C.addTransition(State);
1325void NullabilityChecker::printState(raw_ostream &Out,
ProgramStateRef State,
1326 const char *NL,
const char *Sep)
const {
1328 NullabilityMapTy B = State->get<NullabilityMap>();
1330 if (State->get<InvariantViolated>())
1332 <<
"Nullability invariant was violated, warnings suppressed." << NL;
1337 if (!State->get<InvariantViolated>())
1340 for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1341 Out << I->first <<
" : ";
1342 I->second.print(Out);
1351bool ento::shouldRegisterNullabilityBase(
const CheckerManager &mgr) {
1355#define REGISTER_CHECKER(name, trackingRequired) \
1356 void ento::register##name##Checker(CheckerManager &mgr) { \
1357 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1358 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1359 checker->CheckNames[NullabilityChecker::CK_##name] = \
1360 mgr.getCurrentCheckerName(); \
1361 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1362 checker->NoDiagnoseCallsToSystemHeaders = \
1363 checker->NoDiagnoseCallsToSystemHeaders || \
1364 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1365 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1368 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
static SVal getValue(SVal val, SValBuilder &svalBuilder)
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType)
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
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 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 Call(InterpState &S, CodePtr &PC, const Function *Func)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
ObjCMethodFamily
A family of Objective-C methods.
@ C
Languages that the frontend can parse and compile.
We dereferenced a location that may be null.