1e5dd7070Spatrick //===-- NullabilityChecker.cpp - Nullability checker ----------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This checker tries to find nullability violations. There are several kinds of
10e5dd7070Spatrick // possible violations:
11e5dd7070Spatrick // * Null pointer is passed to a pointer which has a _Nonnull type.
12e5dd7070Spatrick // * Null pointer is returned from a function which has a _Nonnull return type.
13e5dd7070Spatrick // * Nullable pointer is passed to a pointer which has a _Nonnull type.
14e5dd7070Spatrick // * Nullable pointer is returned from a function which has a _Nonnull return
15e5dd7070Spatrick //   type.
16e5dd7070Spatrick // * Nullable pointer is dereferenced.
17e5dd7070Spatrick //
18e5dd7070Spatrick // This checker propagates the nullability information of the pointers and looks
19e5dd7070Spatrick // for the patterns that are described above. Explicit casts are trusted and are
20e5dd7070Spatrick // considered a way to suppress false positives for this checker. The other way
21e5dd7070Spatrick // to suppress warnings would be to add asserts or guarding if statements to the
22e5dd7070Spatrick // code. In addition to the nullability propagation this checker also uses some
23e5dd7070Spatrick // heuristics to suppress potential false positives.
24e5dd7070Spatrick //
25e5dd7070Spatrick //===----------------------------------------------------------------------===//
26e5dd7070Spatrick 
27e5dd7070Spatrick #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
28e5dd7070Spatrick 
29e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
30e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/Checker.h"
31e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/CheckerManager.h"
32e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
33e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
34e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
35e5dd7070Spatrick 
36e5dd7070Spatrick #include "llvm/ADT/StringExtras.h"
37e5dd7070Spatrick #include "llvm/Support/Path.h"
38e5dd7070Spatrick 
39e5dd7070Spatrick using namespace clang;
40e5dd7070Spatrick using namespace ento;
41e5dd7070Spatrick 
42e5dd7070Spatrick namespace {
43e5dd7070Spatrick 
44e5dd7070Spatrick /// Returns the most nullable nullability. This is used for message expressions
45e5dd7070Spatrick /// like [receiver method], where the nullability of this expression is either
46e5dd7070Spatrick /// the nullability of the receiver or the nullability of the return type of the
47e5dd7070Spatrick /// method, depending on which is more nullable. Contradicted is considered to
48e5dd7070Spatrick /// be the most nullable, to avoid false positive results.
getMostNullable(Nullability Lhs,Nullability Rhs)49e5dd7070Spatrick Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
50e5dd7070Spatrick   return static_cast<Nullability>(
51e5dd7070Spatrick       std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
52e5dd7070Spatrick }
53e5dd7070Spatrick 
getNullabilityString(Nullability Nullab)54e5dd7070Spatrick const char *getNullabilityString(Nullability Nullab) {
55e5dd7070Spatrick   switch (Nullab) {
56e5dd7070Spatrick   case Nullability::Contradicted:
57e5dd7070Spatrick     return "contradicted";
58e5dd7070Spatrick   case Nullability::Nullable:
59e5dd7070Spatrick     return "nullable";
60e5dd7070Spatrick   case Nullability::Unspecified:
61e5dd7070Spatrick     return "unspecified";
62e5dd7070Spatrick   case Nullability::Nonnull:
63e5dd7070Spatrick     return "nonnull";
64e5dd7070Spatrick   }
65e5dd7070Spatrick   llvm_unreachable("Unexpected enumeration.");
66e5dd7070Spatrick   return "";
67e5dd7070Spatrick }
68e5dd7070Spatrick 
69e5dd7070Spatrick // These enums are used as an index to ErrorMessages array.
70e5dd7070Spatrick enum class ErrorKind : int {
71e5dd7070Spatrick   NilAssignedToNonnull,
72e5dd7070Spatrick   NilPassedToNonnull,
73e5dd7070Spatrick   NilReturnedToNonnull,
74e5dd7070Spatrick   NullableAssignedToNonnull,
75e5dd7070Spatrick   NullableReturnedToNonnull,
76e5dd7070Spatrick   NullableDereferenced,
77e5dd7070Spatrick   NullablePassedToNonnull
78e5dd7070Spatrick };
79e5dd7070Spatrick 
80e5dd7070Spatrick class NullabilityChecker
81e5dd7070Spatrick     : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
82e5dd7070Spatrick                      check::PostCall, check::PostStmt<ExplicitCastExpr>,
83*12c85518Srobert                      check::PostObjCMessage, check::DeadSymbols, eval::Assume,
84ec727ea7Spatrick                      check::Location, check::Event<ImplicitNullDerefEvent>> {
85e5dd7070Spatrick 
86e5dd7070Spatrick public:
87e5dd7070Spatrick   // If true, the checker will not diagnose nullabilility issues for calls
88e5dd7070Spatrick   // to system headers. This option is motivated by the observation that large
89e5dd7070Spatrick   // projects may have many nullability warnings. These projects may
90e5dd7070Spatrick   // find warnings about nullability annotations that they have explicitly
91e5dd7070Spatrick   // added themselves higher priority to fix than warnings on calls to system
92e5dd7070Spatrick   // libraries.
93*12c85518Srobert   bool NoDiagnoseCallsToSystemHeaders = false;
94e5dd7070Spatrick 
95e5dd7070Spatrick   void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
96e5dd7070Spatrick   void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
97e5dd7070Spatrick   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
98e5dd7070Spatrick   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
99e5dd7070Spatrick   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
100e5dd7070Spatrick   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
101e5dd7070Spatrick   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
102e5dd7070Spatrick   void checkEvent(ImplicitNullDerefEvent Event) const;
103ec727ea7Spatrick   void checkLocation(SVal Location, bool IsLoad, const Stmt *S,
104ec727ea7Spatrick                      CheckerContext &C) const;
105*12c85518Srobert   ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
106*12c85518Srobert                              bool Assumption) const;
107e5dd7070Spatrick 
108e5dd7070Spatrick   void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
109e5dd7070Spatrick                   const char *Sep) const override;
110e5dd7070Spatrick 
111ec727ea7Spatrick   enum CheckKind {
112ec727ea7Spatrick     CK_NullPassedToNonnull,
113ec727ea7Spatrick     CK_NullReturnedFromNonnull,
114ec727ea7Spatrick     CK_NullableDereferenced,
115ec727ea7Spatrick     CK_NullablePassedToNonnull,
116ec727ea7Spatrick     CK_NullableReturnedFromNonnull,
117ec727ea7Spatrick     CK_NumCheckKinds
118e5dd7070Spatrick   };
119e5dd7070Spatrick 
120*12c85518Srobert   bool ChecksEnabled[CK_NumCheckKinds] = {false};
121ec727ea7Spatrick   CheckerNameRef CheckNames[CK_NumCheckKinds];
122ec727ea7Spatrick   mutable std::unique_ptr<BugType> BTs[CK_NumCheckKinds];
123ec727ea7Spatrick 
getBugType(CheckKind Kind) const124ec727ea7Spatrick   const std::unique_ptr<BugType> &getBugType(CheckKind Kind) const {
125ec727ea7Spatrick     if (!BTs[Kind])
126ec727ea7Spatrick       BTs[Kind].reset(new BugType(CheckNames[Kind], "Nullability",
127ec727ea7Spatrick                                   categories::MemoryError));
128ec727ea7Spatrick     return BTs[Kind];
129ec727ea7Spatrick   }
130ec727ea7Spatrick 
131e5dd7070Spatrick   // When set to false no nullability information will be tracked in
132e5dd7070Spatrick   // NullabilityMap. It is possible to catch errors like passing a null pointer
133e5dd7070Spatrick   // to a callee that expects nonnull argument without the information that is
134*12c85518Srobert   // stored in the NullabilityMap. This is an optimization.
135*12c85518Srobert   bool NeedTracking = false;
136e5dd7070Spatrick 
137e5dd7070Spatrick private:
138e5dd7070Spatrick   class NullabilityBugVisitor : public BugReporterVisitor {
139e5dd7070Spatrick   public:
NullabilityBugVisitor(const MemRegion * M)140e5dd7070Spatrick     NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
141e5dd7070Spatrick 
Profile(llvm::FoldingSetNodeID & ID) const142e5dd7070Spatrick     void Profile(llvm::FoldingSetNodeID &ID) const override {
143e5dd7070Spatrick       static int X = 0;
144e5dd7070Spatrick       ID.AddPointer(&X);
145e5dd7070Spatrick       ID.AddPointer(Region);
146e5dd7070Spatrick     }
147e5dd7070Spatrick 
148e5dd7070Spatrick     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
149e5dd7070Spatrick                                      BugReporterContext &BRC,
150e5dd7070Spatrick                                      PathSensitiveBugReport &BR) override;
151e5dd7070Spatrick 
152e5dd7070Spatrick   private:
153e5dd7070Spatrick     // The tracked region.
154e5dd7070Spatrick     const MemRegion *Region;
155e5dd7070Spatrick   };
156e5dd7070Spatrick 
157e5dd7070Spatrick   /// When any of the nonnull arguments of the analyzed function is null, do not
158e5dd7070Spatrick   /// report anything and turn off the check.
159e5dd7070Spatrick   ///
160e5dd7070Spatrick   /// When \p SuppressPath is set to true, no more bugs will be reported on this
161e5dd7070Spatrick   /// path by this checker.
162ec727ea7Spatrick   void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error, CheckKind CK,
163e5dd7070Spatrick                                  ExplodedNode *N, const MemRegion *Region,
164e5dd7070Spatrick                                  CheckerContext &C,
165e5dd7070Spatrick                                  const Stmt *ValueExpr = nullptr,
166e5dd7070Spatrick                                  bool SuppressPath = false) const;
167e5dd7070Spatrick 
reportBug(StringRef Msg,ErrorKind Error,CheckKind CK,ExplodedNode * N,const MemRegion * Region,BugReporter & BR,const Stmt * ValueExpr=nullptr) const168ec727ea7Spatrick   void reportBug(StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
169e5dd7070Spatrick                  const MemRegion *Region, BugReporter &BR,
170e5dd7070Spatrick                  const Stmt *ValueExpr = nullptr) const {
171ec727ea7Spatrick     const std::unique_ptr<BugType> &BT = getBugType(CK);
172e5dd7070Spatrick     auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
173e5dd7070Spatrick     if (Region) {
174e5dd7070Spatrick       R->markInteresting(Region);
175a9ac8606Spatrick       R->addVisitor<NullabilityBugVisitor>(Region);
176e5dd7070Spatrick     }
177e5dd7070Spatrick     if (ValueExpr) {
178e5dd7070Spatrick       R->addRange(ValueExpr->getSourceRange());
179e5dd7070Spatrick       if (Error == ErrorKind::NilAssignedToNonnull ||
180e5dd7070Spatrick           Error == ErrorKind::NilPassedToNonnull ||
181e5dd7070Spatrick           Error == ErrorKind::NilReturnedToNonnull)
182e5dd7070Spatrick         if (const auto *Ex = dyn_cast<Expr>(ValueExpr))
183e5dd7070Spatrick           bugreporter::trackExpressionValue(N, Ex, *R);
184e5dd7070Spatrick     }
185e5dd7070Spatrick     BR.emitReport(std::move(R));
186e5dd7070Spatrick   }
187e5dd7070Spatrick 
188e5dd7070Spatrick   /// If an SVal wraps a region that should be tracked, it will return a pointer
189e5dd7070Spatrick   /// to the wrapped region. Otherwise it will return a nullptr.
190e5dd7070Spatrick   const SymbolicRegion *getTrackRegion(SVal Val,
191e5dd7070Spatrick                                        bool CheckSuperRegion = false) const;
192e5dd7070Spatrick 
193e5dd7070Spatrick   /// Returns true if the call is diagnosable in the current analyzer
194e5dd7070Spatrick   /// configuration.
isDiagnosableCall(const CallEvent & Call) const195e5dd7070Spatrick   bool isDiagnosableCall(const CallEvent &Call) const {
196e5dd7070Spatrick     if (NoDiagnoseCallsToSystemHeaders && Call.isInSystemHeader())
197e5dd7070Spatrick       return false;
198e5dd7070Spatrick 
199e5dd7070Spatrick     return true;
200e5dd7070Spatrick   }
201e5dd7070Spatrick };
202e5dd7070Spatrick 
203e5dd7070Spatrick class NullabilityState {
204e5dd7070Spatrick public:
NullabilityState(Nullability Nullab,const Stmt * Source=nullptr)205e5dd7070Spatrick   NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
206e5dd7070Spatrick       : Nullab(Nullab), Source(Source) {}
207e5dd7070Spatrick 
getNullabilitySource() const208e5dd7070Spatrick   const Stmt *getNullabilitySource() const { return Source; }
209e5dd7070Spatrick 
getValue() const210e5dd7070Spatrick   Nullability getValue() const { return Nullab; }
211e5dd7070Spatrick 
Profile(llvm::FoldingSetNodeID & ID) const212e5dd7070Spatrick   void Profile(llvm::FoldingSetNodeID &ID) const {
213e5dd7070Spatrick     ID.AddInteger(static_cast<char>(Nullab));
214e5dd7070Spatrick     ID.AddPointer(Source);
215e5dd7070Spatrick   }
216e5dd7070Spatrick 
print(raw_ostream & Out) const217e5dd7070Spatrick   void print(raw_ostream &Out) const {
218e5dd7070Spatrick     Out << getNullabilityString(Nullab) << "\n";
219e5dd7070Spatrick   }
220e5dd7070Spatrick 
221e5dd7070Spatrick private:
222e5dd7070Spatrick   Nullability Nullab;
223e5dd7070Spatrick   // Source is the expression which determined the nullability. For example in a
224e5dd7070Spatrick   // message like [nullable nonnull_returning] has nullable nullability, because
225e5dd7070Spatrick   // the receiver is nullable. Here the receiver will be the source of the
226e5dd7070Spatrick   // nullability. This is useful information when the diagnostics are generated.
227e5dd7070Spatrick   const Stmt *Source;
228e5dd7070Spatrick };
229e5dd7070Spatrick 
operator ==(NullabilityState Lhs,NullabilityState Rhs)230e5dd7070Spatrick bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
231e5dd7070Spatrick   return Lhs.getValue() == Rhs.getValue() &&
232e5dd7070Spatrick          Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
233e5dd7070Spatrick }
234e5dd7070Spatrick 
235*12c85518Srobert // For the purpose of tracking historical property accesses, the key for lookup
236*12c85518Srobert // is an object pointer (could be an instance or a class) paired with the unique
237*12c85518Srobert // identifier for the property being invoked on that object.
238*12c85518Srobert using ObjectPropPair = std::pair<const MemRegion *, const IdentifierInfo *>;
239*12c85518Srobert 
240*12c85518Srobert // Metadata associated with the return value from a recorded property access.
241*12c85518Srobert struct ConstrainedPropertyVal {
242*12c85518Srobert   // This will reference the conjured return SVal for some call
243*12c85518Srobert   // of the form [object property]
244*12c85518Srobert   DefinedOrUnknownSVal Value;
245*12c85518Srobert 
246*12c85518Srobert   // If the SVal has been determined to be nonnull, that is recorded here
247*12c85518Srobert   bool isConstrainedNonnull;
248*12c85518Srobert 
ConstrainedPropertyVal__anonae5e82590111::ConstrainedPropertyVal249*12c85518Srobert   ConstrainedPropertyVal(DefinedOrUnknownSVal SV)
250*12c85518Srobert       : Value(SV), isConstrainedNonnull(false) {}
251*12c85518Srobert 
Profile__anonae5e82590111::ConstrainedPropertyVal252*12c85518Srobert   void Profile(llvm::FoldingSetNodeID &ID) const {
253*12c85518Srobert     Value.Profile(ID);
254*12c85518Srobert     ID.AddInteger(isConstrainedNonnull ? 1 : 0);
255*12c85518Srobert   }
256*12c85518Srobert };
257*12c85518Srobert 
operator ==(const ConstrainedPropertyVal & Lhs,const ConstrainedPropertyVal & Rhs)258*12c85518Srobert bool operator==(const ConstrainedPropertyVal &Lhs,
259*12c85518Srobert                 const ConstrainedPropertyVal &Rhs) {
260*12c85518Srobert   return Lhs.Value == Rhs.Value &&
261*12c85518Srobert          Lhs.isConstrainedNonnull == Rhs.isConstrainedNonnull;
262*12c85518Srobert }
263*12c85518Srobert 
264e5dd7070Spatrick } // end anonymous namespace
265e5dd7070Spatrick 
266e5dd7070Spatrick REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
267e5dd7070Spatrick                                NullabilityState)
268*12c85518Srobert REGISTER_MAP_WITH_PROGRAMSTATE(PropertyAccessesMap, ObjectPropPair,
269*12c85518Srobert                                ConstrainedPropertyVal)
270e5dd7070Spatrick 
271e5dd7070Spatrick // We say "the nullability type invariant is violated" when a location with a
272e5dd7070Spatrick // non-null type contains NULL or a function with a non-null return type returns
273e5dd7070Spatrick // NULL. Violations of the nullability type invariant can be detected either
274e5dd7070Spatrick // directly (for example, when NULL is passed as an argument to a nonnull
275e5dd7070Spatrick // parameter) or indirectly (for example, when, inside a function, the
276e5dd7070Spatrick // programmer defensively checks whether a nonnull parameter contains NULL and
277e5dd7070Spatrick // finds that it does).
278e5dd7070Spatrick //
279e5dd7070Spatrick // As a matter of policy, the nullability checker typically warns on direct
280e5dd7070Spatrick // violations of the nullability invariant (although it uses various
281e5dd7070Spatrick // heuristics to suppress warnings in some cases) but will not warn if the
282e5dd7070Spatrick // invariant has already been violated along the path (either directly or
283e5dd7070Spatrick // indirectly). As a practical matter, this prevents the analyzer from
284e5dd7070Spatrick // (1) warning on defensive code paths where a nullability precondition is
285e5dd7070Spatrick // determined to have been violated, (2) warning additional times after an
286e5dd7070Spatrick // initial direct violation has been discovered, and (3) warning after a direct
287e5dd7070Spatrick // violation that has been implicitly or explicitly suppressed (for
288e5dd7070Spatrick // example, with a cast of NULL to _Nonnull). In essence, once an invariant
289e5dd7070Spatrick // violation is detected on a path, this checker will be essentially turned off
290e5dd7070Spatrick // for the rest of the analysis
291e5dd7070Spatrick //
292e5dd7070Spatrick // The analyzer takes this approach (rather than generating a sink node) to
293e5dd7070Spatrick // ensure coverage of defensive paths, which may be important for backwards
294e5dd7070Spatrick // compatibility in codebases that were developed without nullability in mind.
295e5dd7070Spatrick REGISTER_TRAIT_WITH_PROGRAMSTATE(InvariantViolated, bool)
296e5dd7070Spatrick 
297e5dd7070Spatrick enum class NullConstraint { IsNull, IsNotNull, Unknown };
298e5dd7070Spatrick 
getNullConstraint(DefinedOrUnknownSVal Val,ProgramStateRef State)299e5dd7070Spatrick static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
300e5dd7070Spatrick                                         ProgramStateRef State) {
301e5dd7070Spatrick   ConditionTruthVal Nullness = State->isNull(Val);
302e5dd7070Spatrick   if (Nullness.isConstrainedFalse())
303e5dd7070Spatrick     return NullConstraint::IsNotNull;
304e5dd7070Spatrick   if (Nullness.isConstrainedTrue())
305e5dd7070Spatrick     return NullConstraint::IsNull;
306e5dd7070Spatrick   return NullConstraint::Unknown;
307e5dd7070Spatrick }
308e5dd7070Spatrick 
309e5dd7070Spatrick const SymbolicRegion *
getTrackRegion(SVal Val,bool CheckSuperRegion) const310e5dd7070Spatrick NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
311e5dd7070Spatrick   if (!NeedTracking)
312e5dd7070Spatrick     return nullptr;
313e5dd7070Spatrick 
314e5dd7070Spatrick   auto RegionSVal = Val.getAs<loc::MemRegionVal>();
315e5dd7070Spatrick   if (!RegionSVal)
316e5dd7070Spatrick     return nullptr;
317e5dd7070Spatrick 
318e5dd7070Spatrick   const MemRegion *Region = RegionSVal->getRegion();
319e5dd7070Spatrick 
320e5dd7070Spatrick   if (CheckSuperRegion) {
321*12c85518Srobert     if (const SubRegion *FieldReg = Region->getAs<FieldRegion>()) {
322*12c85518Srobert       if (const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
323*12c85518Srobert         FieldReg = ER;
324e5dd7070Spatrick       return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
325*12c85518Srobert     }
326e5dd7070Spatrick     if (auto ElementReg = Region->getAs<ElementRegion>())
327e5dd7070Spatrick       return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
328e5dd7070Spatrick   }
329e5dd7070Spatrick 
330e5dd7070Spatrick   return dyn_cast<SymbolicRegion>(Region);
331e5dd7070Spatrick }
332e5dd7070Spatrick 
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)333e5dd7070Spatrick PathDiagnosticPieceRef NullabilityChecker::NullabilityBugVisitor::VisitNode(
334e5dd7070Spatrick     const ExplodedNode *N, BugReporterContext &BRC,
335e5dd7070Spatrick     PathSensitiveBugReport &BR) {
336e5dd7070Spatrick   ProgramStateRef State = N->getState();
337e5dd7070Spatrick   ProgramStateRef StatePrev = N->getFirstPred()->getState();
338e5dd7070Spatrick 
339e5dd7070Spatrick   const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
340e5dd7070Spatrick   const NullabilityState *TrackedNullabPrev =
341e5dd7070Spatrick       StatePrev->get<NullabilityMap>(Region);
342e5dd7070Spatrick   if (!TrackedNullab)
343e5dd7070Spatrick     return nullptr;
344e5dd7070Spatrick 
345e5dd7070Spatrick   if (TrackedNullabPrev &&
346e5dd7070Spatrick       TrackedNullabPrev->getValue() == TrackedNullab->getValue())
347e5dd7070Spatrick     return nullptr;
348e5dd7070Spatrick 
349e5dd7070Spatrick   // Retrieve the associated statement.
350e5dd7070Spatrick   const Stmt *S = TrackedNullab->getNullabilitySource();
351e5dd7070Spatrick   if (!S || S->getBeginLoc().isInvalid()) {
352e5dd7070Spatrick     S = N->getStmtForDiagnostics();
353e5dd7070Spatrick   }
354e5dd7070Spatrick 
355e5dd7070Spatrick   if (!S)
356e5dd7070Spatrick     return nullptr;
357e5dd7070Spatrick 
358e5dd7070Spatrick   std::string InfoText =
359e5dd7070Spatrick       (llvm::Twine("Nullability '") +
360e5dd7070Spatrick        getNullabilityString(TrackedNullab->getValue()) + "' is inferred")
361e5dd7070Spatrick           .str();
362e5dd7070Spatrick 
363e5dd7070Spatrick   // Generate the extra diagnostic.
364e5dd7070Spatrick   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
365e5dd7070Spatrick                              N->getLocationContext());
366e5dd7070Spatrick   return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
367e5dd7070Spatrick }
368e5dd7070Spatrick 
369e5dd7070Spatrick /// Returns true when the value stored at the given location has been
370e5dd7070Spatrick /// constrained to null after being passed through an object of nonnnull type.
checkValueAtLValForInvariantViolation(ProgramStateRef State,SVal LV,QualType T)371e5dd7070Spatrick static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
372e5dd7070Spatrick                                                   SVal LV, QualType T) {
373e5dd7070Spatrick   if (getNullabilityAnnotation(T) != Nullability::Nonnull)
374e5dd7070Spatrick     return false;
375e5dd7070Spatrick 
376e5dd7070Spatrick   auto RegionVal = LV.getAs<loc::MemRegionVal>();
377e5dd7070Spatrick   if (!RegionVal)
378e5dd7070Spatrick     return false;
379e5dd7070Spatrick 
380e5dd7070Spatrick   // If the value was constrained to null *after* it was passed through that
381e5dd7070Spatrick   // location, it could not have been a concrete pointer *when* it was passed.
382e5dd7070Spatrick   // In that case we would have handled the situation when the value was
383e5dd7070Spatrick   // bound to that location, by emitting (or not emitting) a report.
384e5dd7070Spatrick   // Therefore we are only interested in symbolic regions that can be either
385e5dd7070Spatrick   // null or non-null depending on the value of their respective symbol.
386e5dd7070Spatrick   auto StoredVal = State->getSVal(*RegionVal).getAs<loc::MemRegionVal>();
387e5dd7070Spatrick   if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
388e5dd7070Spatrick     return false;
389e5dd7070Spatrick 
390e5dd7070Spatrick   if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
391e5dd7070Spatrick     return true;
392e5dd7070Spatrick 
393e5dd7070Spatrick   return false;
394e5dd7070Spatrick }
395e5dd7070Spatrick 
396e5dd7070Spatrick static bool
checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl * > Params,ProgramStateRef State,const LocationContext * LocCtxt)397e5dd7070Spatrick checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl *> Params,
398e5dd7070Spatrick                                     ProgramStateRef State,
399e5dd7070Spatrick                                     const LocationContext *LocCtxt) {
400e5dd7070Spatrick   for (const auto *ParamDecl : Params) {
401e5dd7070Spatrick     if (ParamDecl->isParameterPack())
402e5dd7070Spatrick       break;
403e5dd7070Spatrick 
404e5dd7070Spatrick     SVal LV = State->getLValue(ParamDecl, LocCtxt);
405e5dd7070Spatrick     if (checkValueAtLValForInvariantViolation(State, LV,
406e5dd7070Spatrick                                               ParamDecl->getType())) {
407e5dd7070Spatrick       return true;
408e5dd7070Spatrick     }
409e5dd7070Spatrick   }
410e5dd7070Spatrick   return false;
411e5dd7070Spatrick }
412e5dd7070Spatrick 
413e5dd7070Spatrick static bool
checkSelfIvarsForInvariantViolation(ProgramStateRef State,const LocationContext * LocCtxt)414e5dd7070Spatrick checkSelfIvarsForInvariantViolation(ProgramStateRef State,
415e5dd7070Spatrick                                     const LocationContext *LocCtxt) {
416e5dd7070Spatrick   auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->getDecl());
417e5dd7070Spatrick   if (!MD || !MD->isInstanceMethod())
418e5dd7070Spatrick     return false;
419e5dd7070Spatrick 
420e5dd7070Spatrick   const ImplicitParamDecl *SelfDecl = LocCtxt->getSelfDecl();
421e5dd7070Spatrick   if (!SelfDecl)
422e5dd7070Spatrick     return false;
423e5dd7070Spatrick 
424e5dd7070Spatrick   SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
425e5dd7070Spatrick 
426e5dd7070Spatrick   const ObjCObjectPointerType *SelfType =
427e5dd7070Spatrick       dyn_cast<ObjCObjectPointerType>(SelfDecl->getType());
428e5dd7070Spatrick   if (!SelfType)
429e5dd7070Spatrick     return false;
430e5dd7070Spatrick 
431e5dd7070Spatrick   const ObjCInterfaceDecl *ID = SelfType->getInterfaceDecl();
432e5dd7070Spatrick   if (!ID)
433e5dd7070Spatrick     return false;
434e5dd7070Spatrick 
435e5dd7070Spatrick   for (const auto *IvarDecl : ID->ivars()) {
436e5dd7070Spatrick     SVal LV = State->getLValue(IvarDecl, SelfVal);
437e5dd7070Spatrick     if (checkValueAtLValForInvariantViolation(State, LV, IvarDecl->getType())) {
438e5dd7070Spatrick       return true;
439e5dd7070Spatrick     }
440e5dd7070Spatrick   }
441e5dd7070Spatrick   return false;
442e5dd7070Spatrick }
443e5dd7070Spatrick 
checkInvariantViolation(ProgramStateRef State,ExplodedNode * N,CheckerContext & C)444e5dd7070Spatrick static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
445e5dd7070Spatrick                                     CheckerContext &C) {
446e5dd7070Spatrick   if (State->get<InvariantViolated>())
447e5dd7070Spatrick     return true;
448e5dd7070Spatrick 
449e5dd7070Spatrick   const LocationContext *LocCtxt = C.getLocationContext();
450e5dd7070Spatrick   const Decl *D = LocCtxt->getDecl();
451e5dd7070Spatrick   if (!D)
452e5dd7070Spatrick     return false;
453e5dd7070Spatrick 
454e5dd7070Spatrick   ArrayRef<ParmVarDecl*> Params;
455e5dd7070Spatrick   if (const auto *BD = dyn_cast<BlockDecl>(D))
456e5dd7070Spatrick     Params = BD->parameters();
457e5dd7070Spatrick   else if (const auto *FD = dyn_cast<FunctionDecl>(D))
458e5dd7070Spatrick     Params = FD->parameters();
459e5dd7070Spatrick   else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
460e5dd7070Spatrick     Params = MD->parameters();
461e5dd7070Spatrick   else
462e5dd7070Spatrick     return false;
463e5dd7070Spatrick 
464e5dd7070Spatrick   if (checkParamsForPreconditionViolation(Params, State, LocCtxt) ||
465e5dd7070Spatrick       checkSelfIvarsForInvariantViolation(State, LocCtxt)) {
466e5dd7070Spatrick     if (!N->isSink())
467e5dd7070Spatrick       C.addTransition(State->set<InvariantViolated>(true), N);
468e5dd7070Spatrick     return true;
469e5dd7070Spatrick   }
470e5dd7070Spatrick   return false;
471e5dd7070Spatrick }
472e5dd7070Spatrick 
reportBugIfInvariantHolds(StringRef Msg,ErrorKind Error,CheckKind CK,ExplodedNode * N,const MemRegion * Region,CheckerContext & C,const Stmt * ValueExpr,bool SuppressPath) const473ec727ea7Spatrick void NullabilityChecker::reportBugIfInvariantHolds(
474ec727ea7Spatrick     StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
475ec727ea7Spatrick     const MemRegion *Region, CheckerContext &C, const Stmt *ValueExpr,
476ec727ea7Spatrick     bool SuppressPath) const {
477e5dd7070Spatrick   ProgramStateRef OriginalState = N->getState();
478e5dd7070Spatrick 
479e5dd7070Spatrick   if (checkInvariantViolation(OriginalState, N, C))
480e5dd7070Spatrick     return;
481e5dd7070Spatrick   if (SuppressPath) {
482e5dd7070Spatrick     OriginalState = OriginalState->set<InvariantViolated>(true);
483e5dd7070Spatrick     N = C.addTransition(OriginalState, N);
484e5dd7070Spatrick   }
485e5dd7070Spatrick 
486ec727ea7Spatrick   reportBug(Msg, Error, CK, N, Region, C.getBugReporter(), ValueExpr);
487e5dd7070Spatrick }
488e5dd7070Spatrick 
489e5dd7070Spatrick /// Cleaning up the program state.
checkDeadSymbols(SymbolReaper & SR,CheckerContext & C) const490e5dd7070Spatrick void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
491e5dd7070Spatrick                                           CheckerContext &C) const {
492e5dd7070Spatrick   ProgramStateRef State = C.getState();
493e5dd7070Spatrick   NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
494e5dd7070Spatrick   for (NullabilityMapTy::iterator I = Nullabilities.begin(),
495e5dd7070Spatrick                                   E = Nullabilities.end();
496e5dd7070Spatrick        I != E; ++I) {
497e5dd7070Spatrick     const auto *Region = I->first->getAs<SymbolicRegion>();
498e5dd7070Spatrick     assert(Region && "Non-symbolic region is tracked.");
499e5dd7070Spatrick     if (SR.isDead(Region->getSymbol())) {
500e5dd7070Spatrick       State = State->remove<NullabilityMap>(I->first);
501e5dd7070Spatrick     }
502e5dd7070Spatrick   }
503*12c85518Srobert 
504*12c85518Srobert   // When an object goes out of scope, we can free the history associated
505*12c85518Srobert   // with any property accesses on that object
506*12c85518Srobert   PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
507*12c85518Srobert   for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
508*12c85518Srobert                                        E = PropertyAccesses.end();
509*12c85518Srobert        I != E; ++I) {
510*12c85518Srobert     const MemRegion *ReceiverRegion = I->first.first;
511*12c85518Srobert     if (!SR.isLiveRegion(ReceiverRegion)) {
512*12c85518Srobert       State = State->remove<PropertyAccessesMap>(I->first);
513*12c85518Srobert     }
514*12c85518Srobert   }
515*12c85518Srobert 
516e5dd7070Spatrick   // When one of the nonnull arguments are constrained to be null, nullability
517e5dd7070Spatrick   // preconditions are violated. It is not enough to check this only when we
518e5dd7070Spatrick   // actually report an error, because at that time interesting symbols might be
519e5dd7070Spatrick   // reaped.
520e5dd7070Spatrick   if (checkInvariantViolation(State, C.getPredecessor(), C))
521e5dd7070Spatrick     return;
522e5dd7070Spatrick   C.addTransition(State);
523e5dd7070Spatrick }
524e5dd7070Spatrick 
525e5dd7070Spatrick /// This callback triggers when a pointer is dereferenced and the analyzer does
526e5dd7070Spatrick /// not know anything about the value of that pointer. When that pointer is
527e5dd7070Spatrick /// nullable, this code emits a warning.
checkEvent(ImplicitNullDerefEvent Event) const528e5dd7070Spatrick void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
529e5dd7070Spatrick   if (Event.SinkNode->getState()->get<InvariantViolated>())
530e5dd7070Spatrick     return;
531e5dd7070Spatrick 
532e5dd7070Spatrick   const MemRegion *Region =
533e5dd7070Spatrick       getTrackRegion(Event.Location, /*CheckSuperRegion=*/true);
534e5dd7070Spatrick   if (!Region)
535e5dd7070Spatrick     return;
536e5dd7070Spatrick 
537e5dd7070Spatrick   ProgramStateRef State = Event.SinkNode->getState();
538e5dd7070Spatrick   const NullabilityState *TrackedNullability =
539e5dd7070Spatrick       State->get<NullabilityMap>(Region);
540e5dd7070Spatrick 
541e5dd7070Spatrick   if (!TrackedNullability)
542e5dd7070Spatrick     return;
543e5dd7070Spatrick 
544ec727ea7Spatrick   if (ChecksEnabled[CK_NullableDereferenced] &&
545e5dd7070Spatrick       TrackedNullability->getValue() == Nullability::Nullable) {
546e5dd7070Spatrick     BugReporter &BR = *Event.BR;
547e5dd7070Spatrick     // Do not suppress errors on defensive code paths, because dereferencing
548e5dd7070Spatrick     // a nullable pointer is always an error.
549e5dd7070Spatrick     if (Event.IsDirectDereference)
550e5dd7070Spatrick       reportBug("Nullable pointer is dereferenced",
551ec727ea7Spatrick                 ErrorKind::NullableDereferenced, CK_NullableDereferenced,
552ec727ea7Spatrick                 Event.SinkNode, Region, BR);
553e5dd7070Spatrick     else {
554e5dd7070Spatrick       reportBug("Nullable pointer is passed to a callee that requires a "
555ec727ea7Spatrick                 "non-null",
556ec727ea7Spatrick                 ErrorKind::NullablePassedToNonnull, CK_NullableDereferenced,
557e5dd7070Spatrick                 Event.SinkNode, Region, BR);
558e5dd7070Spatrick     }
559e5dd7070Spatrick   }
560e5dd7070Spatrick }
561e5dd7070Spatrick 
562ec727ea7Spatrick // Whenever we see a load from a typed memory region that's been annotated as
563ec727ea7Spatrick // 'nonnull', we want to trust the user on that and assume that it is is indeed
564ec727ea7Spatrick // non-null.
565ec727ea7Spatrick //
566ec727ea7Spatrick // We do so even if the value is known to have been assigned to null.
567ec727ea7Spatrick // The user should be warned on assigning the null value to a non-null pointer
568ec727ea7Spatrick // as opposed to warning on the later dereference of this pointer.
569ec727ea7Spatrick //
570ec727ea7Spatrick // \code
571ec727ea7Spatrick //   int * _Nonnull var = 0; // we want to warn the user here...
572ec727ea7Spatrick //   // . . .
573ec727ea7Spatrick //   *var = 42;              // ...and not here
574ec727ea7Spatrick // \endcode
checkLocation(SVal Location,bool IsLoad,const Stmt * S,CheckerContext & Context) const575ec727ea7Spatrick void NullabilityChecker::checkLocation(SVal Location, bool IsLoad,
576ec727ea7Spatrick                                        const Stmt *S,
577ec727ea7Spatrick                                        CheckerContext &Context) const {
578ec727ea7Spatrick   // We should care only about loads.
579ec727ea7Spatrick   // The main idea is to add a constraint whenever we're loading a value from
580ec727ea7Spatrick   // an annotated pointer type.
581ec727ea7Spatrick   if (!IsLoad)
582ec727ea7Spatrick     return;
583ec727ea7Spatrick 
584ec727ea7Spatrick   // Annotations that we want to consider make sense only for types.
585ec727ea7Spatrick   const auto *Region =
586ec727ea7Spatrick       dyn_cast_or_null<TypedValueRegion>(Location.getAsRegion());
587ec727ea7Spatrick   if (!Region)
588ec727ea7Spatrick     return;
589ec727ea7Spatrick 
590ec727ea7Spatrick   ProgramStateRef State = Context.getState();
591ec727ea7Spatrick 
592ec727ea7Spatrick   auto StoredVal = State->getSVal(Region).getAs<loc::MemRegionVal>();
593ec727ea7Spatrick   if (!StoredVal)
594ec727ea7Spatrick     return;
595ec727ea7Spatrick 
596ec727ea7Spatrick   Nullability NullabilityOfTheLoadedValue =
597ec727ea7Spatrick       getNullabilityAnnotation(Region->getValueType());
598ec727ea7Spatrick 
599ec727ea7Spatrick   if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
600ec727ea7Spatrick     // It doesn't matter what we think about this particular pointer, it should
601ec727ea7Spatrick     // be considered non-null as annotated by the developer.
602ec727ea7Spatrick     if (ProgramStateRef NewState = State->assume(*StoredVal, true)) {
603ec727ea7Spatrick       Context.addTransition(NewState);
604ec727ea7Spatrick     }
605ec727ea7Spatrick   }
606ec727ea7Spatrick }
607ec727ea7Spatrick 
608e5dd7070Spatrick /// Find the outermost subexpression of E that is not an implicit cast.
609e5dd7070Spatrick /// This looks through the implicit casts to _Nonnull that ARC adds to
610e5dd7070Spatrick /// return expressions of ObjC types when the return type of the function or
611e5dd7070Spatrick /// method is non-null but the express is not.
lookThroughImplicitCasts(const Expr * E)612e5dd7070Spatrick static const Expr *lookThroughImplicitCasts(const Expr *E) {
613ec727ea7Spatrick   return E->IgnoreImpCasts();
614e5dd7070Spatrick }
615e5dd7070Spatrick 
616e5dd7070Spatrick /// This method check when nullable pointer or null value is returned from a
617e5dd7070Spatrick /// function that has nonnull return type.
checkPreStmt(const ReturnStmt * S,CheckerContext & C) const618e5dd7070Spatrick void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
619e5dd7070Spatrick                                       CheckerContext &C) const {
620e5dd7070Spatrick   auto RetExpr = S->getRetValue();
621e5dd7070Spatrick   if (!RetExpr)
622e5dd7070Spatrick     return;
623e5dd7070Spatrick 
624e5dd7070Spatrick   if (!RetExpr->getType()->isAnyPointerType())
625e5dd7070Spatrick     return;
626e5dd7070Spatrick 
627e5dd7070Spatrick   ProgramStateRef State = C.getState();
628e5dd7070Spatrick   if (State->get<InvariantViolated>())
629e5dd7070Spatrick     return;
630e5dd7070Spatrick 
631e5dd7070Spatrick   auto RetSVal = C.getSVal(S).getAs<DefinedOrUnknownSVal>();
632e5dd7070Spatrick   if (!RetSVal)
633e5dd7070Spatrick     return;
634e5dd7070Spatrick 
635e5dd7070Spatrick   bool InSuppressedMethodFamily = false;
636e5dd7070Spatrick 
637e5dd7070Spatrick   QualType RequiredRetType;
638e5dd7070Spatrick   AnalysisDeclContext *DeclCtxt =
639e5dd7070Spatrick       C.getLocationContext()->getAnalysisDeclContext();
640e5dd7070Spatrick   const Decl *D = DeclCtxt->getDecl();
641e5dd7070Spatrick   if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
642e5dd7070Spatrick     // HACK: This is a big hammer to avoid warning when there are defensive
643e5dd7070Spatrick     // nil checks in -init and -copy methods. We should add more sophisticated
644e5dd7070Spatrick     // logic here to suppress on common defensive idioms but still
645e5dd7070Spatrick     // warn when there is a likely problem.
646e5dd7070Spatrick     ObjCMethodFamily Family = MD->getMethodFamily();
647e5dd7070Spatrick     if (OMF_init == Family || OMF_copy == Family || OMF_mutableCopy == Family)
648e5dd7070Spatrick       InSuppressedMethodFamily = true;
649e5dd7070Spatrick 
650e5dd7070Spatrick     RequiredRetType = MD->getReturnType();
651e5dd7070Spatrick   } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
652e5dd7070Spatrick     RequiredRetType = FD->getReturnType();
653e5dd7070Spatrick   } else {
654e5dd7070Spatrick     return;
655e5dd7070Spatrick   }
656e5dd7070Spatrick 
657e5dd7070Spatrick   NullConstraint Nullness = getNullConstraint(*RetSVal, State);
658e5dd7070Spatrick 
659e5dd7070Spatrick   Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
660e5dd7070Spatrick 
661e5dd7070Spatrick   // If the returned value is null but the type of the expression
662e5dd7070Spatrick   // generating it is nonnull then we will suppress the diagnostic.
663e5dd7070Spatrick   // This enables explicit suppression when returning a nil literal in a
664e5dd7070Spatrick   // function with a _Nonnull return type:
665e5dd7070Spatrick   //    return (NSString * _Nonnull)0;
666e5dd7070Spatrick   Nullability RetExprTypeLevelNullability =
667e5dd7070Spatrick         getNullabilityAnnotation(lookThroughImplicitCasts(RetExpr)->getType());
668e5dd7070Spatrick 
669e5dd7070Spatrick   bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
670e5dd7070Spatrick                                   Nullness == NullConstraint::IsNull);
671ec727ea7Spatrick   if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
672e5dd7070Spatrick       RetExprTypeLevelNullability != Nullability::Nonnull &&
673ec727ea7Spatrick       !InSuppressedMethodFamily && C.getLocationContext()->inTopFrame()) {
674e5dd7070Spatrick     static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
675e5dd7070Spatrick     ExplodedNode *N = C.generateErrorNode(State, &Tag);
676e5dd7070Spatrick     if (!N)
677e5dd7070Spatrick       return;
678e5dd7070Spatrick 
679e5dd7070Spatrick     SmallString<256> SBuf;
680e5dd7070Spatrick     llvm::raw_svector_ostream OS(SBuf);
681e5dd7070Spatrick     OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
682e5dd7070Spatrick     OS << " returned from a " << C.getDeclDescription(D) <<
683e5dd7070Spatrick           " that is expected to return a non-null value";
684ec727ea7Spatrick     reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
685ec727ea7Spatrick                               CK_NullReturnedFromNonnull, N, nullptr, C,
686e5dd7070Spatrick                               RetExpr);
687e5dd7070Spatrick     return;
688e5dd7070Spatrick   }
689e5dd7070Spatrick 
690e5dd7070Spatrick   // If null was returned from a non-null function, mark the nullability
691e5dd7070Spatrick   // invariant as violated even if the diagnostic was suppressed.
692e5dd7070Spatrick   if (NullReturnedFromNonNull) {
693e5dd7070Spatrick     State = State->set<InvariantViolated>(true);
694e5dd7070Spatrick     C.addTransition(State);
695e5dd7070Spatrick     return;
696e5dd7070Spatrick   }
697e5dd7070Spatrick 
698e5dd7070Spatrick   const MemRegion *Region = getTrackRegion(*RetSVal);
699e5dd7070Spatrick   if (!Region)
700e5dd7070Spatrick     return;
701e5dd7070Spatrick 
702e5dd7070Spatrick   const NullabilityState *TrackedNullability =
703e5dd7070Spatrick       State->get<NullabilityMap>(Region);
704e5dd7070Spatrick   if (TrackedNullability) {
705e5dd7070Spatrick     Nullability TrackedNullabValue = TrackedNullability->getValue();
706ec727ea7Spatrick     if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
707e5dd7070Spatrick         Nullness != NullConstraint::IsNotNull &&
708e5dd7070Spatrick         TrackedNullabValue == Nullability::Nullable &&
709e5dd7070Spatrick         RequiredNullability == Nullability::Nonnull) {
710e5dd7070Spatrick       static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
711e5dd7070Spatrick       ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
712e5dd7070Spatrick 
713e5dd7070Spatrick       SmallString<256> SBuf;
714e5dd7070Spatrick       llvm::raw_svector_ostream OS(SBuf);
715e5dd7070Spatrick       OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
716e5dd7070Spatrick             " that is expected to return a non-null value";
717e5dd7070Spatrick 
718ec727ea7Spatrick       reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
719ec727ea7Spatrick                                 CK_NullableReturnedFromNonnull, N, Region, C);
720e5dd7070Spatrick     }
721e5dd7070Spatrick     return;
722e5dd7070Spatrick   }
723e5dd7070Spatrick   if (RequiredNullability == Nullability::Nullable) {
724e5dd7070Spatrick     State = State->set<NullabilityMap>(Region,
725e5dd7070Spatrick                                        NullabilityState(RequiredNullability,
726e5dd7070Spatrick                                                         S));
727e5dd7070Spatrick     C.addTransition(State);
728e5dd7070Spatrick   }
729e5dd7070Spatrick }
730e5dd7070Spatrick 
731e5dd7070Spatrick /// This callback warns when a nullable pointer or a null value is passed to a
732e5dd7070Spatrick /// function that expects its argument to be nonnull.
checkPreCall(const CallEvent & Call,CheckerContext & C) const733e5dd7070Spatrick void NullabilityChecker::checkPreCall(const CallEvent &Call,
734e5dd7070Spatrick                                       CheckerContext &C) const {
735e5dd7070Spatrick   if (!Call.getDecl())
736e5dd7070Spatrick     return;
737e5dd7070Spatrick 
738e5dd7070Spatrick   ProgramStateRef State = C.getState();
739e5dd7070Spatrick   if (State->get<InvariantViolated>())
740e5dd7070Spatrick     return;
741e5dd7070Spatrick 
742e5dd7070Spatrick   ProgramStateRef OrigState = State;
743e5dd7070Spatrick 
744e5dd7070Spatrick   unsigned Idx = 0;
745e5dd7070Spatrick   for (const ParmVarDecl *Param : Call.parameters()) {
746e5dd7070Spatrick     if (Param->isParameterPack())
747e5dd7070Spatrick       break;
748e5dd7070Spatrick 
749e5dd7070Spatrick     if (Idx >= Call.getNumArgs())
750e5dd7070Spatrick       break;
751e5dd7070Spatrick 
752e5dd7070Spatrick     const Expr *ArgExpr = Call.getArgExpr(Idx);
753e5dd7070Spatrick     auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
754e5dd7070Spatrick     if (!ArgSVal)
755e5dd7070Spatrick       continue;
756e5dd7070Spatrick 
757e5dd7070Spatrick     if (!Param->getType()->isAnyPointerType() &&
758e5dd7070Spatrick         !Param->getType()->isReferenceType())
759e5dd7070Spatrick       continue;
760e5dd7070Spatrick 
761e5dd7070Spatrick     NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
762e5dd7070Spatrick 
763e5dd7070Spatrick     Nullability RequiredNullability =
764e5dd7070Spatrick         getNullabilityAnnotation(Param->getType());
765e5dd7070Spatrick     Nullability ArgExprTypeLevelNullability =
766e5dd7070Spatrick         getNullabilityAnnotation(ArgExpr->getType());
767e5dd7070Spatrick 
768e5dd7070Spatrick     unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
769e5dd7070Spatrick 
770ec727ea7Spatrick     if (ChecksEnabled[CK_NullPassedToNonnull] &&
771ec727ea7Spatrick         Nullness == NullConstraint::IsNull &&
772e5dd7070Spatrick         ArgExprTypeLevelNullability != Nullability::Nonnull &&
773e5dd7070Spatrick         RequiredNullability == Nullability::Nonnull &&
774e5dd7070Spatrick         isDiagnosableCall(Call)) {
775e5dd7070Spatrick       ExplodedNode *N = C.generateErrorNode(State);
776e5dd7070Spatrick       if (!N)
777e5dd7070Spatrick         return;
778e5dd7070Spatrick 
779e5dd7070Spatrick       SmallString<256> SBuf;
780e5dd7070Spatrick       llvm::raw_svector_ostream OS(SBuf);
781e5dd7070Spatrick       OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
782e5dd7070Spatrick       OS << " passed to a callee that requires a non-null " << ParamIdx
783e5dd7070Spatrick          << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
784ec727ea7Spatrick       reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
785ec727ea7Spatrick                                 CK_NullPassedToNonnull, N, nullptr, C, ArgExpr,
786ec727ea7Spatrick                                 /*SuppressPath=*/false);
787e5dd7070Spatrick       return;
788e5dd7070Spatrick     }
789e5dd7070Spatrick 
790e5dd7070Spatrick     const MemRegion *Region = getTrackRegion(*ArgSVal);
791e5dd7070Spatrick     if (!Region)
792e5dd7070Spatrick       continue;
793e5dd7070Spatrick 
794e5dd7070Spatrick     const NullabilityState *TrackedNullability =
795e5dd7070Spatrick         State->get<NullabilityMap>(Region);
796e5dd7070Spatrick 
797e5dd7070Spatrick     if (TrackedNullability) {
798e5dd7070Spatrick       if (Nullness == NullConstraint::IsNotNull ||
799e5dd7070Spatrick           TrackedNullability->getValue() != Nullability::Nullable)
800e5dd7070Spatrick         continue;
801e5dd7070Spatrick 
802ec727ea7Spatrick       if (ChecksEnabled[CK_NullablePassedToNonnull] &&
803e5dd7070Spatrick           RequiredNullability == Nullability::Nonnull &&
804e5dd7070Spatrick           isDiagnosableCall(Call)) {
805e5dd7070Spatrick         ExplodedNode *N = C.addTransition(State);
806e5dd7070Spatrick         SmallString<256> SBuf;
807e5dd7070Spatrick         llvm::raw_svector_ostream OS(SBuf);
808e5dd7070Spatrick         OS << "Nullable pointer is passed to a callee that requires a non-null "
809e5dd7070Spatrick            << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
810ec727ea7Spatrick         reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
811ec727ea7Spatrick                                   CK_NullablePassedToNonnull, N, Region, C,
812ec727ea7Spatrick                                   ArgExpr, /*SuppressPath=*/true);
813e5dd7070Spatrick         return;
814e5dd7070Spatrick       }
815ec727ea7Spatrick       if (ChecksEnabled[CK_NullableDereferenced] &&
816e5dd7070Spatrick           Param->getType()->isReferenceType()) {
817e5dd7070Spatrick         ExplodedNode *N = C.addTransition(State);
818e5dd7070Spatrick         reportBugIfInvariantHolds("Nullable pointer is dereferenced",
819ec727ea7Spatrick                                   ErrorKind::NullableDereferenced,
820ec727ea7Spatrick                                   CK_NullableDereferenced, N, Region, C,
821ec727ea7Spatrick                                   ArgExpr, /*SuppressPath=*/true);
822e5dd7070Spatrick         return;
823e5dd7070Spatrick       }
824e5dd7070Spatrick       continue;
825e5dd7070Spatrick     }
826e5dd7070Spatrick   }
827e5dd7070Spatrick   if (State != OrigState)
828e5dd7070Spatrick     C.addTransition(State);
829e5dd7070Spatrick }
830e5dd7070Spatrick 
831e5dd7070Spatrick /// Suppress the nullability warnings for some functions.
checkPostCall(const CallEvent & Call,CheckerContext & C) const832e5dd7070Spatrick void NullabilityChecker::checkPostCall(const CallEvent &Call,
833e5dd7070Spatrick                                        CheckerContext &C) const {
834e5dd7070Spatrick   auto Decl = Call.getDecl();
835e5dd7070Spatrick   if (!Decl)
836e5dd7070Spatrick     return;
837e5dd7070Spatrick   // ObjC Messages handles in a different callback.
838e5dd7070Spatrick   if (Call.getKind() == CE_ObjCMessage)
839e5dd7070Spatrick     return;
840e5dd7070Spatrick   const FunctionType *FuncType = Decl->getFunctionType();
841e5dd7070Spatrick   if (!FuncType)
842e5dd7070Spatrick     return;
843e5dd7070Spatrick   QualType ReturnType = FuncType->getReturnType();
844e5dd7070Spatrick   if (!ReturnType->isAnyPointerType())
845e5dd7070Spatrick     return;
846e5dd7070Spatrick   ProgramStateRef State = C.getState();
847e5dd7070Spatrick   if (State->get<InvariantViolated>())
848e5dd7070Spatrick     return;
849e5dd7070Spatrick 
850e5dd7070Spatrick   const MemRegion *Region = getTrackRegion(Call.getReturnValue());
851e5dd7070Spatrick   if (!Region)
852e5dd7070Spatrick     return;
853e5dd7070Spatrick 
854e5dd7070Spatrick   // CG headers are misannotated. Do not warn for symbols that are the results
855e5dd7070Spatrick   // of CG calls.
856e5dd7070Spatrick   const SourceManager &SM = C.getSourceManager();
857e5dd7070Spatrick   StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
858e5dd7070Spatrick   if (llvm::sys::path::filename(FilePath).startswith("CG")) {
859e5dd7070Spatrick     State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
860e5dd7070Spatrick     C.addTransition(State);
861e5dd7070Spatrick     return;
862e5dd7070Spatrick   }
863e5dd7070Spatrick 
864e5dd7070Spatrick   const NullabilityState *TrackedNullability =
865e5dd7070Spatrick       State->get<NullabilityMap>(Region);
866e5dd7070Spatrick 
867e5dd7070Spatrick   if (!TrackedNullability &&
868e5dd7070Spatrick       getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
869e5dd7070Spatrick     State = State->set<NullabilityMap>(Region, Nullability::Nullable);
870e5dd7070Spatrick     C.addTransition(State);
871e5dd7070Spatrick   }
872e5dd7070Spatrick }
873e5dd7070Spatrick 
getReceiverNullability(const ObjCMethodCall & M,ProgramStateRef State)874e5dd7070Spatrick static Nullability getReceiverNullability(const ObjCMethodCall &M,
875e5dd7070Spatrick                                           ProgramStateRef State) {
876e5dd7070Spatrick   if (M.isReceiverSelfOrSuper()) {
877e5dd7070Spatrick     // For super and super class receivers we assume that the receiver is
878e5dd7070Spatrick     // nonnull.
879e5dd7070Spatrick     return Nullability::Nonnull;
880e5dd7070Spatrick   }
881e5dd7070Spatrick   // Otherwise look up nullability in the state.
882e5dd7070Spatrick   SVal Receiver = M.getReceiverSVal();
883e5dd7070Spatrick   if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
884e5dd7070Spatrick     // If the receiver is constrained to be nonnull, assume that it is nonnull
885e5dd7070Spatrick     // regardless of its type.
886e5dd7070Spatrick     NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
887e5dd7070Spatrick     if (Nullness == NullConstraint::IsNotNull)
888e5dd7070Spatrick       return Nullability::Nonnull;
889e5dd7070Spatrick   }
890e5dd7070Spatrick   auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
891e5dd7070Spatrick   if (ValueRegionSVal) {
892e5dd7070Spatrick     const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
893e5dd7070Spatrick     assert(SelfRegion);
894e5dd7070Spatrick 
895e5dd7070Spatrick     const NullabilityState *TrackedSelfNullability =
896e5dd7070Spatrick         State->get<NullabilityMap>(SelfRegion);
897e5dd7070Spatrick     if (TrackedSelfNullability)
898e5dd7070Spatrick       return TrackedSelfNullability->getValue();
899e5dd7070Spatrick   }
900e5dd7070Spatrick   return Nullability::Unspecified;
901e5dd7070Spatrick }
902e5dd7070Spatrick 
903*12c85518Srobert // The return value of a property access is typically a temporary value which
904*12c85518Srobert // will not be tracked in a persistent manner by the analyzer.  We use
905*12c85518Srobert // evalAssume() in order to immediately record constraints on those temporaries
906*12c85518Srobert // at the time they are imposed (e.g. by a nil-check conditional).
evalAssume(ProgramStateRef State,SVal Cond,bool Assumption) const907*12c85518Srobert ProgramStateRef NullabilityChecker::evalAssume(ProgramStateRef State, SVal Cond,
908*12c85518Srobert                                                bool Assumption) const {
909*12c85518Srobert   PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
910*12c85518Srobert   for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
911*12c85518Srobert                                        E = PropertyAccesses.end();
912*12c85518Srobert        I != E; ++I) {
913*12c85518Srobert     if (!I->second.isConstrainedNonnull) {
914*12c85518Srobert       ConditionTruthVal IsNonNull = State->isNonNull(I->second.Value);
915*12c85518Srobert       if (IsNonNull.isConstrainedTrue()) {
916*12c85518Srobert         ConstrainedPropertyVal Replacement = I->second;
917*12c85518Srobert         Replacement.isConstrainedNonnull = true;
918*12c85518Srobert         State = State->set<PropertyAccessesMap>(I->first, Replacement);
919*12c85518Srobert       } else if (IsNonNull.isConstrainedFalse()) {
920*12c85518Srobert         // Space optimization: no point in tracking constrained-null cases
921*12c85518Srobert         State = State->remove<PropertyAccessesMap>(I->first);
922*12c85518Srobert       }
923*12c85518Srobert     }
924*12c85518Srobert   }
925*12c85518Srobert 
926*12c85518Srobert   return State;
927*12c85518Srobert }
928*12c85518Srobert 
929e5dd7070Spatrick /// Calculate the nullability of the result of a message expr based on the
930e5dd7070Spatrick /// nullability of the receiver, the nullability of the return value, and the
931e5dd7070Spatrick /// constraints.
checkPostObjCMessage(const ObjCMethodCall & M,CheckerContext & C) const932e5dd7070Spatrick void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
933e5dd7070Spatrick                                               CheckerContext &C) const {
934e5dd7070Spatrick   auto Decl = M.getDecl();
935e5dd7070Spatrick   if (!Decl)
936e5dd7070Spatrick     return;
937e5dd7070Spatrick   QualType RetType = Decl->getReturnType();
938e5dd7070Spatrick   if (!RetType->isAnyPointerType())
939e5dd7070Spatrick     return;
940e5dd7070Spatrick 
941e5dd7070Spatrick   ProgramStateRef State = C.getState();
942e5dd7070Spatrick   if (State->get<InvariantViolated>())
943e5dd7070Spatrick     return;
944e5dd7070Spatrick 
945e5dd7070Spatrick   const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
946e5dd7070Spatrick   if (!ReturnRegion)
947e5dd7070Spatrick     return;
948e5dd7070Spatrick 
949e5dd7070Spatrick   auto Interface = Decl->getClassInterface();
950e5dd7070Spatrick   auto Name = Interface ? Interface->getName() : "";
951e5dd7070Spatrick   // In order to reduce the noise in the diagnostics generated by this checker,
952e5dd7070Spatrick   // some framework and programming style based heuristics are used. These
953e5dd7070Spatrick   // heuristics are for Cocoa APIs which have NS prefix.
954e5dd7070Spatrick   if (Name.startswith("NS")) {
955e5dd7070Spatrick     // Developers rely on dynamic invariants such as an item should be available
956e5dd7070Spatrick     // in a collection, or a collection is not empty often. Those invariants can
957e5dd7070Spatrick     // not be inferred by any static analysis tool. To not to bother the users
958e5dd7070Spatrick     // with too many false positives, every item retrieval function should be
959e5dd7070Spatrick     // ignored for collections. The instance methods of dictionaries in Cocoa
960e5dd7070Spatrick     // are either item retrieval related or not interesting nullability wise.
961e5dd7070Spatrick     // Using this fact, to keep the code easier to read just ignore the return
962e5dd7070Spatrick     // value of every instance method of dictionaries.
963e5dd7070Spatrick     if (M.isInstanceMessage() && Name.contains("Dictionary")) {
964e5dd7070Spatrick       State =
965e5dd7070Spatrick           State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
966e5dd7070Spatrick       C.addTransition(State);
967e5dd7070Spatrick       return;
968e5dd7070Spatrick     }
969e5dd7070Spatrick     // For similar reasons ignore some methods of Cocoa arrays.
970e5dd7070Spatrick     StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
971e5dd7070Spatrick     if (Name.contains("Array") &&
972e5dd7070Spatrick         (FirstSelectorSlot == "firstObject" ||
973e5dd7070Spatrick          FirstSelectorSlot == "lastObject")) {
974e5dd7070Spatrick       State =
975e5dd7070Spatrick           State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
976e5dd7070Spatrick       C.addTransition(State);
977e5dd7070Spatrick       return;
978e5dd7070Spatrick     }
979e5dd7070Spatrick 
980e5dd7070Spatrick     // Encoding related methods of string should not fail when lossless
981e5dd7070Spatrick     // encodings are used. Using lossless encodings is so frequent that ignoring
982e5dd7070Spatrick     // this class of methods reduced the emitted diagnostics by about 30% on
983e5dd7070Spatrick     // some projects (and all of that was false positives).
984e5dd7070Spatrick     if (Name.contains("String")) {
985*12c85518Srobert       for (auto *Param : M.parameters()) {
986e5dd7070Spatrick         if (Param->getName() == "encoding") {
987e5dd7070Spatrick           State = State->set<NullabilityMap>(ReturnRegion,
988e5dd7070Spatrick                                              Nullability::Contradicted);
989e5dd7070Spatrick           C.addTransition(State);
990e5dd7070Spatrick           return;
991e5dd7070Spatrick         }
992e5dd7070Spatrick       }
993e5dd7070Spatrick     }
994e5dd7070Spatrick   }
995e5dd7070Spatrick 
996e5dd7070Spatrick   const ObjCMessageExpr *Message = M.getOriginExpr();
997e5dd7070Spatrick   Nullability SelfNullability = getReceiverNullability(M, State);
998e5dd7070Spatrick 
999e5dd7070Spatrick   const NullabilityState *NullabilityOfReturn =
1000e5dd7070Spatrick       State->get<NullabilityMap>(ReturnRegion);
1001e5dd7070Spatrick 
1002e5dd7070Spatrick   if (NullabilityOfReturn) {
1003e5dd7070Spatrick     // When we have a nullability tracked for the return value, the nullability
1004e5dd7070Spatrick     // of the expression will be the most nullable of the receiver and the
1005e5dd7070Spatrick     // return value.
1006e5dd7070Spatrick     Nullability RetValTracked = NullabilityOfReturn->getValue();
1007e5dd7070Spatrick     Nullability ComputedNullab =
1008e5dd7070Spatrick         getMostNullable(RetValTracked, SelfNullability);
1009e5dd7070Spatrick     if (ComputedNullab != RetValTracked &&
1010e5dd7070Spatrick         ComputedNullab != Nullability::Unspecified) {
1011e5dd7070Spatrick       const Stmt *NullabilitySource =
1012e5dd7070Spatrick           ComputedNullab == RetValTracked
1013e5dd7070Spatrick               ? NullabilityOfReturn->getNullabilitySource()
1014e5dd7070Spatrick               : Message->getInstanceReceiver();
1015e5dd7070Spatrick       State = State->set<NullabilityMap>(
1016e5dd7070Spatrick           ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1017e5dd7070Spatrick       C.addTransition(State);
1018e5dd7070Spatrick     }
1019e5dd7070Spatrick     return;
1020e5dd7070Spatrick   }
1021e5dd7070Spatrick 
1022e5dd7070Spatrick   // No tracked information. Use static type information for return value.
1023e5dd7070Spatrick   Nullability RetNullability = getNullabilityAnnotation(RetType);
1024e5dd7070Spatrick 
1025*12c85518Srobert   // Properties might be computed, which means the property value could
1026*12c85518Srobert   // theoretically change between calls even in commonly-observed cases like
1027*12c85518Srobert   // this:
1028*12c85518Srobert   //
1029*12c85518Srobert   //     if (foo.prop) {    // ok, it's nonnull here...
1030*12c85518Srobert   //         [bar doStuffWithNonnullVal:foo.prop];     // ...but what about
1031*12c85518Srobert   //         here?
1032*12c85518Srobert   //     }
1033*12c85518Srobert   //
1034*12c85518Srobert   // If the property is nullable-annotated, a naive analysis would lead to many
1035*12c85518Srobert   // false positives despite the presence of probably-correct nil-checks.  To
1036*12c85518Srobert   // reduce the false positive rate, we maintain a history of the most recently
1037*12c85518Srobert   // observed property value.  For each property access, if the prior value has
1038*12c85518Srobert   // been constrained to be not nil then we will conservatively assume that the
1039*12c85518Srobert   // next access can be inferred as nonnull.
1040*12c85518Srobert   if (RetNullability != Nullability::Nonnull &&
1041*12c85518Srobert       M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined) {
1042*12c85518Srobert     bool LookupResolved = false;
1043*12c85518Srobert     if (const MemRegion *ReceiverRegion = getTrackRegion(M.getReceiverSVal())) {
1044*12c85518Srobert       if (IdentifierInfo *Ident = M.getSelector().getIdentifierInfoForSlot(0)) {
1045*12c85518Srobert         LookupResolved = true;
1046*12c85518Srobert         ObjectPropPair Key = std::make_pair(ReceiverRegion, Ident);
1047*12c85518Srobert         const ConstrainedPropertyVal *PrevPropVal =
1048*12c85518Srobert             State->get<PropertyAccessesMap>(Key);
1049*12c85518Srobert         if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1050e5dd7070Spatrick           RetNullability = Nullability::Nonnull;
1051*12c85518Srobert         } else {
1052*12c85518Srobert           // If a previous property access was constrained as nonnull, we hold
1053*12c85518Srobert           // on to that constraint (effectively inferring that all subsequent
1054*12c85518Srobert           // accesses on that code path can be inferred as nonnull).  If the
1055*12c85518Srobert           // previous property access was *not* constrained as nonnull, then
1056*12c85518Srobert           // let's throw it away in favor of keeping the SVal associated with
1057*12c85518Srobert           // this more recent access.
1058*12c85518Srobert           if (auto ReturnSVal =
1059*12c85518Srobert                   M.getReturnValue().getAs<DefinedOrUnknownSVal>()) {
1060*12c85518Srobert             State = State->set<PropertyAccessesMap>(
1061*12c85518Srobert                 Key, ConstrainedPropertyVal(*ReturnSVal));
1062*12c85518Srobert           }
1063*12c85518Srobert         }
1064*12c85518Srobert       }
1065*12c85518Srobert     }
1066*12c85518Srobert 
1067*12c85518Srobert     if (!LookupResolved) {
1068*12c85518Srobert       // Fallback: err on the side of suppressing the false positive.
1069*12c85518Srobert       RetNullability = Nullability::Nonnull;
1070*12c85518Srobert     }
1071*12c85518Srobert   }
1072e5dd7070Spatrick 
1073e5dd7070Spatrick   Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1074e5dd7070Spatrick   if (ComputedNullab == Nullability::Nullable) {
1075e5dd7070Spatrick     const Stmt *NullabilitySource = ComputedNullab == RetNullability
1076e5dd7070Spatrick                                         ? Message
1077e5dd7070Spatrick                                         : Message->getInstanceReceiver();
1078e5dd7070Spatrick     State = State->set<NullabilityMap>(
1079e5dd7070Spatrick         ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1080e5dd7070Spatrick     C.addTransition(State);
1081e5dd7070Spatrick   }
1082e5dd7070Spatrick }
1083e5dd7070Spatrick 
1084e5dd7070Spatrick /// Explicit casts are trusted. If there is a disagreement in the nullability
1085e5dd7070Spatrick /// annotations in the destination and the source or '0' is casted to nonnull
1086e5dd7070Spatrick /// track the value as having contraditory nullability. This will allow users to
1087e5dd7070Spatrick /// suppress warnings.
checkPostStmt(const ExplicitCastExpr * CE,CheckerContext & C) const1088e5dd7070Spatrick void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
1089e5dd7070Spatrick                                        CheckerContext &C) const {
1090e5dd7070Spatrick   QualType OriginType = CE->getSubExpr()->getType();
1091e5dd7070Spatrick   QualType DestType = CE->getType();
1092e5dd7070Spatrick   if (!OriginType->isAnyPointerType())
1093e5dd7070Spatrick     return;
1094e5dd7070Spatrick   if (!DestType->isAnyPointerType())
1095e5dd7070Spatrick     return;
1096e5dd7070Spatrick 
1097e5dd7070Spatrick   ProgramStateRef State = C.getState();
1098e5dd7070Spatrick   if (State->get<InvariantViolated>())
1099e5dd7070Spatrick     return;
1100e5dd7070Spatrick 
1101e5dd7070Spatrick   Nullability DestNullability = getNullabilityAnnotation(DestType);
1102e5dd7070Spatrick 
1103e5dd7070Spatrick   // No explicit nullability in the destination type, so this cast does not
1104e5dd7070Spatrick   // change the nullability.
1105e5dd7070Spatrick   if (DestNullability == Nullability::Unspecified)
1106e5dd7070Spatrick     return;
1107e5dd7070Spatrick 
1108e5dd7070Spatrick   auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
1109e5dd7070Spatrick   const MemRegion *Region = getTrackRegion(*RegionSVal);
1110e5dd7070Spatrick   if (!Region)
1111e5dd7070Spatrick     return;
1112e5dd7070Spatrick 
1113e5dd7070Spatrick   // When 0 is converted to nonnull mark it as contradicted.
1114e5dd7070Spatrick   if (DestNullability == Nullability::Nonnull) {
1115e5dd7070Spatrick     NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
1116e5dd7070Spatrick     if (Nullness == NullConstraint::IsNull) {
1117e5dd7070Spatrick       State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1118e5dd7070Spatrick       C.addTransition(State);
1119e5dd7070Spatrick       return;
1120e5dd7070Spatrick     }
1121e5dd7070Spatrick   }
1122e5dd7070Spatrick 
1123e5dd7070Spatrick   const NullabilityState *TrackedNullability =
1124e5dd7070Spatrick       State->get<NullabilityMap>(Region);
1125e5dd7070Spatrick 
1126e5dd7070Spatrick   if (!TrackedNullability) {
1127e5dd7070Spatrick     if (DestNullability != Nullability::Nullable)
1128e5dd7070Spatrick       return;
1129e5dd7070Spatrick     State = State->set<NullabilityMap>(Region,
1130e5dd7070Spatrick                                        NullabilityState(DestNullability, CE));
1131e5dd7070Spatrick     C.addTransition(State);
1132e5dd7070Spatrick     return;
1133e5dd7070Spatrick   }
1134e5dd7070Spatrick 
1135e5dd7070Spatrick   if (TrackedNullability->getValue() != DestNullability &&
1136e5dd7070Spatrick       TrackedNullability->getValue() != Nullability::Contradicted) {
1137e5dd7070Spatrick     State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1138e5dd7070Spatrick     C.addTransition(State);
1139e5dd7070Spatrick   }
1140e5dd7070Spatrick }
1141e5dd7070Spatrick 
1142e5dd7070Spatrick /// For a given statement performing a bind, attempt to syntactically
1143e5dd7070Spatrick /// match the expression resulting in the bound value.
matchValueExprForBind(const Stmt * S)1144e5dd7070Spatrick static const Expr * matchValueExprForBind(const Stmt *S) {
1145e5dd7070Spatrick   // For `x = e` the value expression is the right-hand side.
1146e5dd7070Spatrick   if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1147e5dd7070Spatrick     if (BinOp->getOpcode() == BO_Assign)
1148e5dd7070Spatrick       return BinOp->getRHS();
1149e5dd7070Spatrick   }
1150e5dd7070Spatrick 
1151e5dd7070Spatrick   // For `int x = e` the value expression is the initializer.
1152e5dd7070Spatrick   if (auto *DS = dyn_cast<DeclStmt>(S))  {
1153e5dd7070Spatrick     if (DS->isSingleDecl()) {
1154e5dd7070Spatrick       auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1155e5dd7070Spatrick       if (!VD)
1156e5dd7070Spatrick         return nullptr;
1157e5dd7070Spatrick 
1158e5dd7070Spatrick       if (const Expr *Init = VD->getInit())
1159e5dd7070Spatrick         return Init;
1160e5dd7070Spatrick     }
1161e5dd7070Spatrick   }
1162e5dd7070Spatrick 
1163e5dd7070Spatrick   return nullptr;
1164e5dd7070Spatrick }
1165e5dd7070Spatrick 
1166e5dd7070Spatrick /// Returns true if \param S is a DeclStmt for a local variable that
1167e5dd7070Spatrick /// ObjC automated reference counting initialized with zero.
isARCNilInitializedLocal(CheckerContext & C,const Stmt * S)1168e5dd7070Spatrick static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
1169e5dd7070Spatrick   // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1170e5dd7070Spatrick   // prevents false positives when a _Nonnull local variable cannot be
1171e5dd7070Spatrick   // initialized with an initialization expression:
1172e5dd7070Spatrick   //    NSString * _Nonnull s; // no-warning
1173e5dd7070Spatrick   //    @autoreleasepool {
1174e5dd7070Spatrick   //      s = ...
1175e5dd7070Spatrick   //    }
1176e5dd7070Spatrick   //
1177e5dd7070Spatrick   // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1178e5dd7070Spatrick   // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1179e5dd7070Spatrick   // the zero-initialized definition will unexpectedly yield nil.
1180e5dd7070Spatrick 
1181e5dd7070Spatrick   // Locals are only zero-initialized when automated reference counting
1182e5dd7070Spatrick   // is turned on.
1183e5dd7070Spatrick   if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
1184e5dd7070Spatrick     return false;
1185e5dd7070Spatrick 
1186e5dd7070Spatrick   auto *DS = dyn_cast<DeclStmt>(S);
1187e5dd7070Spatrick   if (!DS || !DS->isSingleDecl())
1188e5dd7070Spatrick     return false;
1189e5dd7070Spatrick 
1190e5dd7070Spatrick   auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1191e5dd7070Spatrick   if (!VD)
1192e5dd7070Spatrick     return false;
1193e5dd7070Spatrick 
1194e5dd7070Spatrick   // Sema only zero-initializes locals with ObjCLifetimes.
1195e5dd7070Spatrick   if(!VD->getType().getQualifiers().hasObjCLifetime())
1196e5dd7070Spatrick     return false;
1197e5dd7070Spatrick 
1198e5dd7070Spatrick   const Expr *Init = VD->getInit();
1199e5dd7070Spatrick   assert(Init && "ObjC local under ARC without initializer");
1200e5dd7070Spatrick 
1201e5dd7070Spatrick   // Return false if the local is explicitly initialized (e.g., with '= nil').
1202e5dd7070Spatrick   if (!isa<ImplicitValueInitExpr>(Init))
1203e5dd7070Spatrick     return false;
1204e5dd7070Spatrick 
1205e5dd7070Spatrick   return true;
1206e5dd7070Spatrick }
1207e5dd7070Spatrick 
1208e5dd7070Spatrick /// Propagate the nullability information through binds and warn when nullable
1209e5dd7070Spatrick /// pointer or null symbol is assigned to a pointer with a nonnull type.
checkBind(SVal L,SVal V,const Stmt * S,CheckerContext & C) const1210e5dd7070Spatrick void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
1211e5dd7070Spatrick                                    CheckerContext &C) const {
1212e5dd7070Spatrick   const TypedValueRegion *TVR =
1213e5dd7070Spatrick       dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
1214e5dd7070Spatrick   if (!TVR)
1215e5dd7070Spatrick     return;
1216e5dd7070Spatrick 
1217e5dd7070Spatrick   QualType LocType = TVR->getValueType();
1218e5dd7070Spatrick   if (!LocType->isAnyPointerType())
1219e5dd7070Spatrick     return;
1220e5dd7070Spatrick 
1221e5dd7070Spatrick   ProgramStateRef State = C.getState();
1222e5dd7070Spatrick   if (State->get<InvariantViolated>())
1223e5dd7070Spatrick     return;
1224e5dd7070Spatrick 
1225e5dd7070Spatrick   auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1226e5dd7070Spatrick   if (!ValDefOrUnknown)
1227e5dd7070Spatrick     return;
1228e5dd7070Spatrick 
1229e5dd7070Spatrick   NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1230e5dd7070Spatrick 
1231e5dd7070Spatrick   Nullability ValNullability = Nullability::Unspecified;
1232e5dd7070Spatrick   if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1233e5dd7070Spatrick     ValNullability = getNullabilityAnnotation(Sym->getType());
1234e5dd7070Spatrick 
1235e5dd7070Spatrick   Nullability LocNullability = getNullabilityAnnotation(LocType);
1236e5dd7070Spatrick 
1237e5dd7070Spatrick   // If the type of the RHS expression is nonnull, don't warn. This
1238e5dd7070Spatrick   // enables explicit suppression with a cast to nonnull.
1239e5dd7070Spatrick   Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1240e5dd7070Spatrick   const Expr *ValueExpr = matchValueExprForBind(S);
1241e5dd7070Spatrick   if (ValueExpr) {
1242e5dd7070Spatrick     ValueExprTypeLevelNullability =
1243e5dd7070Spatrick       getNullabilityAnnotation(lookThroughImplicitCasts(ValueExpr)->getType());
1244e5dd7070Spatrick   }
1245e5dd7070Spatrick 
1246e5dd7070Spatrick   bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1247e5dd7070Spatrick                                 RhsNullness == NullConstraint::IsNull);
1248ec727ea7Spatrick   if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1249e5dd7070Spatrick       ValNullability != Nullability::Nonnull &&
1250e5dd7070Spatrick       ValueExprTypeLevelNullability != Nullability::Nonnull &&
1251e5dd7070Spatrick       !isARCNilInitializedLocal(C, S)) {
1252e5dd7070Spatrick     static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
1253e5dd7070Spatrick     ExplodedNode *N = C.generateErrorNode(State, &Tag);
1254e5dd7070Spatrick     if (!N)
1255e5dd7070Spatrick       return;
1256e5dd7070Spatrick 
1257e5dd7070Spatrick 
1258e5dd7070Spatrick     const Stmt *ValueStmt = S;
1259e5dd7070Spatrick     if (ValueExpr)
1260e5dd7070Spatrick       ValueStmt = ValueExpr;
1261e5dd7070Spatrick 
1262e5dd7070Spatrick     SmallString<256> SBuf;
1263e5dd7070Spatrick     llvm::raw_svector_ostream OS(SBuf);
1264e5dd7070Spatrick     OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
1265e5dd7070Spatrick     OS << " assigned to a pointer which is expected to have non-null value";
1266ec727ea7Spatrick     reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1267ec727ea7Spatrick                               CK_NullPassedToNonnull, N, nullptr, C, ValueStmt);
1268e5dd7070Spatrick     return;
1269e5dd7070Spatrick   }
1270e5dd7070Spatrick 
1271e5dd7070Spatrick   // If null was returned from a non-null function, mark the nullability
1272e5dd7070Spatrick   // invariant as violated even if the diagnostic was suppressed.
1273e5dd7070Spatrick   if (NullAssignedToNonNull) {
1274e5dd7070Spatrick     State = State->set<InvariantViolated>(true);
1275e5dd7070Spatrick     C.addTransition(State);
1276e5dd7070Spatrick     return;
1277e5dd7070Spatrick   }
1278e5dd7070Spatrick 
1279e5dd7070Spatrick   // Intentionally missing case: '0' is bound to a reference. It is handled by
1280e5dd7070Spatrick   // the DereferenceChecker.
1281e5dd7070Spatrick 
1282e5dd7070Spatrick   const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1283e5dd7070Spatrick   if (!ValueRegion)
1284e5dd7070Spatrick     return;
1285e5dd7070Spatrick 
1286e5dd7070Spatrick   const NullabilityState *TrackedNullability =
1287e5dd7070Spatrick       State->get<NullabilityMap>(ValueRegion);
1288e5dd7070Spatrick 
1289e5dd7070Spatrick   if (TrackedNullability) {
1290e5dd7070Spatrick     if (RhsNullness == NullConstraint::IsNotNull ||
1291e5dd7070Spatrick         TrackedNullability->getValue() != Nullability::Nullable)
1292e5dd7070Spatrick       return;
1293ec727ea7Spatrick     if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1294e5dd7070Spatrick         LocNullability == Nullability::Nonnull) {
1295e5dd7070Spatrick       static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1296e5dd7070Spatrick       ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
1297e5dd7070Spatrick       reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1298e5dd7070Spatrick                                 "which is expected to have non-null value",
1299ec727ea7Spatrick                                 ErrorKind::NullableAssignedToNonnull,
1300ec727ea7Spatrick                                 CK_NullablePassedToNonnull, N, ValueRegion, C);
1301e5dd7070Spatrick     }
1302e5dd7070Spatrick     return;
1303e5dd7070Spatrick   }
1304e5dd7070Spatrick 
1305e5dd7070Spatrick   const auto *BinOp = dyn_cast<BinaryOperator>(S);
1306e5dd7070Spatrick 
1307e5dd7070Spatrick   if (ValNullability == Nullability::Nullable) {
1308e5dd7070Spatrick     // Trust the static information of the value more than the static
1309e5dd7070Spatrick     // information on the location.
1310e5dd7070Spatrick     const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1311e5dd7070Spatrick     State = State->set<NullabilityMap>(
1312e5dd7070Spatrick         ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1313e5dd7070Spatrick     C.addTransition(State);
1314e5dd7070Spatrick     return;
1315e5dd7070Spatrick   }
1316e5dd7070Spatrick 
1317e5dd7070Spatrick   if (LocNullability == Nullability::Nullable) {
1318e5dd7070Spatrick     const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1319e5dd7070Spatrick     State = State->set<NullabilityMap>(
1320e5dd7070Spatrick         ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1321e5dd7070Spatrick     C.addTransition(State);
1322e5dd7070Spatrick   }
1323e5dd7070Spatrick }
1324e5dd7070Spatrick 
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep) const1325e5dd7070Spatrick void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1326e5dd7070Spatrick                                     const char *NL, const char *Sep) const {
1327e5dd7070Spatrick 
1328e5dd7070Spatrick   NullabilityMapTy B = State->get<NullabilityMap>();
1329e5dd7070Spatrick 
1330e5dd7070Spatrick   if (State->get<InvariantViolated>())
1331e5dd7070Spatrick     Out << Sep << NL
1332e5dd7070Spatrick         << "Nullability invariant was violated, warnings suppressed." << NL;
1333e5dd7070Spatrick 
1334e5dd7070Spatrick   if (B.isEmpty())
1335e5dd7070Spatrick     return;
1336e5dd7070Spatrick 
1337e5dd7070Spatrick   if (!State->get<InvariantViolated>())
1338e5dd7070Spatrick     Out << Sep << NL;
1339e5dd7070Spatrick 
1340e5dd7070Spatrick   for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1341e5dd7070Spatrick     Out << I->first << " : ";
1342e5dd7070Spatrick     I->second.print(Out);
1343e5dd7070Spatrick     Out << NL;
1344e5dd7070Spatrick   }
1345e5dd7070Spatrick }
1346e5dd7070Spatrick 
registerNullabilityBase(CheckerManager & mgr)1347e5dd7070Spatrick void ento::registerNullabilityBase(CheckerManager &mgr) {
1348e5dd7070Spatrick   mgr.registerChecker<NullabilityChecker>();
1349e5dd7070Spatrick }
1350e5dd7070Spatrick 
shouldRegisterNullabilityBase(const CheckerManager & mgr)1351ec727ea7Spatrick bool ento::shouldRegisterNullabilityBase(const CheckerManager &mgr) {
1352e5dd7070Spatrick   return true;
1353e5dd7070Spatrick }
1354e5dd7070Spatrick 
1355e5dd7070Spatrick #define REGISTER_CHECKER(name, trackingRequired)                               \
1356e5dd7070Spatrick   void ento::register##name##Checker(CheckerManager &mgr) {                    \
1357e5dd7070Spatrick     NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>();        \
1358ec727ea7Spatrick     checker->ChecksEnabled[NullabilityChecker::CK_##name] = true;              \
1359ec727ea7Spatrick     checker->CheckNames[NullabilityChecker::CK_##name] =                       \
1360ec727ea7Spatrick         mgr.getCurrentCheckerName();                                           \
1361e5dd7070Spatrick     checker->NeedTracking = checker->NeedTracking || trackingRequired;         \
1362e5dd7070Spatrick     checker->NoDiagnoseCallsToSystemHeaders =                                  \
1363e5dd7070Spatrick         checker->NoDiagnoseCallsToSystemHeaders ||                             \
1364e5dd7070Spatrick         mgr.getAnalyzerOptions().getCheckerBooleanOption(                      \
1365e5dd7070Spatrick             checker, "NoDiagnoseCallsToSystemHeaders", true);                  \
1366e5dd7070Spatrick   }                                                                            \
1367e5dd7070Spatrick                                                                                \
1368ec727ea7Spatrick   bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) {        \
1369e5dd7070Spatrick     return true;                                                               \
1370e5dd7070Spatrick   }
1371e5dd7070Spatrick 
1372e5dd7070Spatrick // The checks are likely to be turned on by default and it is possible to do
1373e5dd7070Spatrick // them without tracking any nullability related information. As an optimization
1374e5dd7070Spatrick // no nullability information will be tracked when only these two checks are
1375e5dd7070Spatrick // enables.
1376e5dd7070Spatrick REGISTER_CHECKER(NullPassedToNonnull, false)
1377e5dd7070Spatrick REGISTER_CHECKER(NullReturnedFromNonnull, false)
1378e5dd7070Spatrick 
1379e5dd7070Spatrick REGISTER_CHECKER(NullableDereferenced, true)
1380e5dd7070Spatrick REGISTER_CHECKER(NullablePassedToNonnull, true)
1381e5dd7070Spatrick REGISTER_CHECKER(NullableReturnedFromNonnull, true)
1382