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,
 
  101                 CheckerContext &
C) 
const;
 
  102  void checkPostStmt(
const ExplicitCastExpr *CE, CheckerContext &
C) 
const;
 
  103  void checkPreStmt(
const ReturnStmt *S, CheckerContext &
C) 
const;
 
  104  void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C) 
const;
 
  105  void checkPostCall(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
  106  void checkPreCall(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
  107  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &
C) 
const;
 
  108  void checkEvent(ImplicitNullDerefEvent Event) 
const;
 
  109  void checkLocation(SVal Location, 
bool IsLoad, 
const Stmt *S,
 
  110                     CheckerContext &
C) 
const;
 
  111  void checkBeginFunction(CheckerContext &Ctx) 
const;
 
  113                             bool Assumption) 
const;
 
  115  void printState(raw_ostream &Out, 
ProgramStateRef State, 
const char *NL,
 
  116                  const char *Sep) 
const override;
 
  118  StringRef getDebugTag()
 const override { 
return "NullabilityChecker"; }
 
  123  CheckerFrontendWithBugType NullPassedToNonnull{
"Nullability",
 
  125  CheckerFrontendWithBugType NullReturnedFromNonnull{
"Nullability",
 
  127  CheckerFrontendWithBugType NullableDereferenced{
"Nullability",
 
  129  CheckerFrontendWithBugType NullablePassedToNonnull{
"Nullability",
 
  131  CheckerFrontendWithBugType NullableReturnedFromNonnull{
 
  138  bool NeedTracking = 
false;
 
  141  class NullabilityBugVisitor : 
public BugReporterVisitor {
 
  143    NullabilityBugVisitor(
const MemRegion *M) : Region(M) {}
 
  145    void Profile(llvm::FoldingSetNodeID &ID)
 const override {
 
  148      ID.AddPointer(Region);
 
  152                                     BugReporterContext &BRC,
 
  153                                     PathSensitiveBugReport &BR) 
override;
 
  157    const MemRegion *Region;
 
  165  void reportBugIfInvariantHolds(StringRef Msg, ErrorKind 
Error,
 
  166                                 const BugType &BT, ExplodedNode *N,
 
  167                                 const MemRegion *Region, CheckerContext &
C,
 
  168                                 const Stmt *ValueExpr = 
nullptr,
 
  169                                 bool SuppressPath = 
false) 
const;
 
  171  void reportBug(StringRef Msg, ErrorKind 
Error, 
const BugType &BT,
 
  172                 ExplodedNode *N, 
const MemRegion *Region, BugReporter &BR,
 
  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))
 
  192  const SymbolicRegion *getTrackRegion(SVal Val,
 
  193                                       bool CheckSuperRegion = 
false) 
const;
 
  197  bool isDiagnosableCall(
const CallEvent &
Call)
 const {
 
  198    if (NoDiagnoseCallsToSystemHeaders && 
Call.isInSystemHeader())
 
  205class NullabilityState {
 
  207  NullabilityState(
Nullability Nullab, 
const Stmt *Source = 
nullptr)
 
  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 {
 
  246  DefinedOrUnknownSVal Value;
 
  249  bool isConstrainedNonnull;
 
  251  ConstrainedPropertyVal(DefinedOrUnknownSVal SV)
 
  252      : Value(SV), isConstrainedNonnull(
false) {}
 
  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)
 
  312  return T->isAnyPointerType() || 
T->isBlockPointerType();
 
 
  316NullabilityChecker::getTrackRegion(
SVal Val, 
bool CheckSuperRegion)
 const {
 
  320  auto RegionSVal = Val.
getAs<loc::MemRegionVal>();
 
  324  const MemRegion *Region = RegionSVal->getRegion();
 
  326  if (CheckSuperRegion) {
 
  327    if (
const SubRegion *FieldReg = Region->
getAs<FieldRegion>()) {
 
  328      if (
const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
 
  330      return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
 
  332    if (
auto ElementReg = Region->
getAs<ElementRegion>())
 
  333      return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
 
  336  return dyn_cast<SymbolicRegion>(Region);
 
  340    const ExplodedNode *N, BugReporterContext &BRC,
 
  341    PathSensitiveBugReport &BR) {
 
  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();
 
  364  std::string InfoText =
 
  365      (llvm::Twine(
"Nullability '") +
 
  366       getNullabilityString(TrackedNullab->getValue()) + 
"' is inferred")
 
  372  return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, 
true);
 
  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(
 
  480    StringRef Msg, ErrorKind 
Error, 
const BugType &BT, ExplodedNode *N,
 
  481    const MemRegion *Region, CheckerContext &
C, 
const Stmt *ValueExpr,
 
  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,
 
  497                                          CheckerContext &
C)
 const {
 
  499  NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
 
  500  for (
const MemRegion *Reg : llvm::make_first_range(Nullabilities)) {
 
  501    const auto *Region = Reg->
getAs<SymbolicRegion>();
 
  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);
 
  530void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event)
 const {
 
  534  const MemRegion *Region =
 
  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) {
 
  548    BugReporter &BR = *Event.
BR;
 
  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,
 
  564void NullabilityChecker::checkBeginFunction(CheckerContext &
C)
 const {
 
  568  const LocationContext *LCtx = 
C.getLocationContext();
 
  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);
 
  584    const MemRegion *ParamPointeeRegion =
 
  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,
 
  610                                       CheckerContext &Context)
 const {
 
  619      dyn_cast_or_null<TypedValueRegion>(Location.
getAsRegion());
 
  625  auto StoredVal = State->getSVal(Region).getAs<loc::MemRegionVal>();
 
  632  if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
 
  636      Context.addTransition(NewState);
 
  651void NullabilityChecker::checkPreStmt(
const ReturnStmt *S,
 
  652                                      CheckerContext &
C)
 const {
 
  661  if (State->get<InvariantViolated>())
 
  664  auto RetSVal = 
C.getSVal(S).getAs<DefinedOrUnknownSVal>();
 
  668  bool InSuppressedMethodFamily = 
false;
 
  670  QualType RequiredRetType;
 
  671  AnalysisDeclContext *DeclCtxt =
 
  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) {
 
  715      ExplodedNode *N = 
C.generateErrorNode(State);
 
  719      SmallString<256> SBuf;
 
  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) {
 
  749      ExplodedNode *N = 
C.addTransition(State, 
C.getPredecessor());
 
  751      SmallString<256> SBuf;
 
  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);
 
  771void NullabilityChecker::checkPreCall(
const CallEvent &
Call,
 
  772                                      CheckerContext &
C)
 const {
 
  777  if (State->get<InvariantViolated>())
 
  783  for (
const ParmVarDecl *Param : 
Call.parameters()) {
 
  784    if (Param->isParameterPack())
 
  787    if (Idx >= 
Call.getNumArgs())
 
  790    const Expr *ArgExpr = 
Call.getArgExpr(Idx);
 
  791    auto ArgSVal = 
Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
 
  796        !Param->getType()->isReferenceType())
 
  806    unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
 
  809        ArgExprTypeLevelNullability != Nullability::Nonnull &&
 
  810        RequiredNullability == Nullability::Nonnull &&
 
  811        isDiagnosableCall(
Call)) {
 
  812      ExplodedNode *N = 
C.generateErrorNode(State);
 
  816      SmallString<256> SBuf;
 
  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)) {
 
  842        ExplodedNode *N = 
C.addTransition(State);
 
  843        SmallString<256> SBuf;
 
  844        llvm::raw_svector_ostream 
OS(SBuf);
 
  845        OS << 
"Nullable pointer is passed to a callee that requires a non-null " 
  846           << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << 
" parameter";
 
  847        reportBugIfInvariantHolds(
OS.str(), ErrorKind::NullablePassedToNonnull,
 
  848                                  NullablePassedToNonnull, N, Region, 
C,
 
  852      if (NullableDereferenced.isEnabled() &&
 
  853          Param->getType()->isReferenceType()) {
 
  854        ExplodedNode *N = 
C.addTransition(State);
 
  855        reportBugIfInvariantHolds(
 
  856            "Nullable pointer is dereferenced", ErrorKind::NullableDereferenced,
 
  857            NullableDereferenced, N, Region, 
C, ArgExpr, 
true);
 
  863  if (State != OrigState)
 
  864    C.addTransition(State);
 
  868void NullabilityChecker::checkPostCall(
const CallEvent &
Call,
 
  869                                       CheckerContext &
C)
 const {
 
  876  const FunctionType *FuncType = 
Decl->getFunctionType();
 
  883  if (State->get<InvariantViolated>())
 
  886  const MemRegion *Region = getTrackRegion(
Call.getReturnValue());
 
  892  const SourceManager &
SM = 
C.getSourceManager();
 
  893  StringRef FilePath = 
SM.getFilename(
SM.getSpellingLoc(
Decl->getBeginLoc()));
 
  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())
 
  909    ReturnType = E->getType();
 
  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) {
 
  956      ConditionTruthVal 
IsNonNull = State->isNonNull(PropVal.Value);
 
  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,
 
  975                                              CheckerContext &
C)
 const {
 
  979  QualType RetType = 
Decl->getReturnType();
 
  984  if (State->get<InvariantViolated>())
 
  987  const MemRegion *ReturnRegion = getTrackRegion(M.
getReturnValue());
 
  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;
 
 1085    if (
const MemRegion *ReceiverRegion = getTrackRegion(M.
getReceiverSVal())) {
 
 1086      if (
const IdentifierInfo *Ident =
 
 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);
 
 1131void NullabilityChecker::checkPostStmt(
const ExplicitCastExpr *CE,
 
 1132                                       CheckerContext &
C)
 const {
 
 1134  QualType DestType = CE->
getType();
 
 1141  if (State->get<InvariantViolated>())
 
 1148  if (DestNullability == Nullability::Unspecified)
 
 1151  auto RegionSVal = 
C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
 
 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");
 
 
 1253void NullabilityChecker::checkBind(SVal L, SVal 
V, 
const Stmt *S,
 
 1254                                   bool AtDeclInit, CheckerContext &
C)
 const {
 
 1255  const TypedValueRegion *TVR =
 
 1256      dyn_cast_or_null<TypedValueRegion>(L.
getAsRegion());
 
 1265  if (State->get<InvariantViolated>())
 
 1268  auto ValDefOrUnknown = 
V.getAs<DefinedOrUnknownSVal>();
 
 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 &&
 
 1295    ExplodedNode *N = 
C.generateErrorNode(State);
 
 1300    const Stmt *ValueStmt = S;
 
 1302      ValueStmt = ValueExpr;
 
 1304    SmallString<256> SBuf;
 
 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) {
 
 1337      ExplodedNode *N = 
C.addTransition(State, 
C.getPredecessor());
 
 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 &) {           \ 
 
#define REGISTER_CHECKER(name)
 
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.
 
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.
 
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.
 
This represents one expression.
 
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
 
QualType getReturnType() const
 
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.
 
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 (possibly-)qualified type.
 
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.
 
Stmt - This represents one statement.
 
SourceLocation getBeginLoc() const LLVM_READONLY
 
bool isObjCObjectPointerType() const
 
const SourceManager & getSourceManager() const
 
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
 
SVal getReturnValue() const
Returns the return value of the call.
 
Checker families (where a single backend class implements multiple related frontends) should derive f...
 
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'.
 
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
 
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.
 
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.
 
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
 
const SymExpr * SymbolRef
 
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
 
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
 
bool IsNonNull(InterpState &S, CodePtr OpPC)
 
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
 
The JSON file list parser is used to communicate input to InstallAPI.
 
bool isa(CodeGen::Address addr)
 
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.