1 //===-- NullabilityChecker.cpp - Nullability checker ----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This checker tries to find nullability violations. There are several kinds of
10 // possible violations:
11 // * Null pointer is passed to a pointer which has a _Nonnull type.
12 // * Null pointer is returned from a function which has a _Nonnull return type.
13 // * Nullable pointer is passed to a pointer which has a _Nonnull type.
14 // * Nullable pointer is returned from a function which has a _Nonnull return
16 // * Nullable pointer is dereferenced.
18 // This checker propagates the nullability information of the pointers and looks
19 // for the patterns that are described above. Explicit casts are trusted and are
20 // considered a way to suppress false positives for this checker. The other way
21 // to suppress warnings would be to add asserts or guarding if statements to the
22 // code. In addition to the nullability propagation this checker also uses some
23 // heuristics to suppress potential false positives.
25 //===----------------------------------------------------------------------===//
27 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
29 #include "clang/Analysis/AnyCall.h"
30 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
31 #include "clang/StaticAnalyzer/Core/Checker.h"
32 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
33 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
34 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
35 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
37 #include "llvm/ADT/STLExtras.h"
38 #include "llvm/ADT/StringExtras.h"
39 #include "llvm/Support/Path.h"
41 using namespace clang
;
46 /// Returns the most nullable nullability. This is used for message expressions
47 /// like [receiver method], where the nullability of this expression is either
48 /// the nullability of the receiver or the nullability of the return type of the
49 /// method, depending on which is more nullable. Contradicted is considered to
50 /// be the most nullable, to avoid false positive results.
51 Nullability
getMostNullable(Nullability Lhs
, Nullability Rhs
) {
52 return static_cast<Nullability
>(
53 std::min(static_cast<char>(Lhs
), static_cast<char>(Rhs
)));
56 const 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.");
71 // These enums are used as an index to ErrorMessages array.
72 enum class ErrorKind
: int {
76 NullableAssignedToNonnull
,
77 NullableReturnedToNonnull
,
79 NullablePassedToNonnull
82 class NullabilityChecker
83 : public Checker
<check::Bind
, check::PreCall
, check::PreStmt
<ReturnStmt
>,
84 check::PostCall
, check::PostStmt
<ExplicitCastExpr
>,
85 check::PostObjCMessage
, check::DeadSymbols
, eval::Assume
,
86 check::Location
, check::Event
<ImplicitNullDerefEvent
>,
87 check::BeginFunction
> {
90 // If true, the checker will not diagnose nullabilility issues for calls
91 // to system headers. This option is motivated by the observation that large
92 // projects may have many nullability warnings. These projects may
93 // find warnings about nullability annotations that they have explicitly
94 // added themselves higher priority to fix than warnings on calls to system
96 bool NoDiagnoseCallsToSystemHeaders
= false;
98 void checkBind(SVal L
, SVal V
, const Stmt
*S
, CheckerContext
&C
) const;
99 void checkPostStmt(const ExplicitCastExpr
*CE
, CheckerContext
&C
) const;
100 void checkPreStmt(const ReturnStmt
*S
, CheckerContext
&C
) const;
101 void checkPostObjCMessage(const ObjCMethodCall
&M
, CheckerContext
&C
) const;
102 void checkPostCall(const CallEvent
&Call
, CheckerContext
&C
) const;
103 void checkPreCall(const CallEvent
&Call
, CheckerContext
&C
) const;
104 void checkDeadSymbols(SymbolReaper
&SR
, CheckerContext
&C
) const;
105 void checkEvent(ImplicitNullDerefEvent Event
) const;
106 void checkLocation(SVal Location
, bool IsLoad
, const Stmt
*S
,
107 CheckerContext
&C
) const;
108 void checkBeginFunction(CheckerContext
&Ctx
) const;
109 ProgramStateRef
evalAssume(ProgramStateRef State
, SVal Cond
,
110 bool Assumption
) const;
112 void printState(raw_ostream
&Out
, ProgramStateRef State
, const char *NL
,
113 const char *Sep
) const override
;
116 CK_NullPassedToNonnull
,
117 CK_NullReturnedFromNonnull
,
118 CK_NullableDereferenced
,
119 CK_NullablePassedToNonnull
,
120 CK_NullableReturnedFromNonnull
,
124 bool ChecksEnabled
[CK_NumCheckKinds
] = {false};
125 CheckerNameRef CheckNames
[CK_NumCheckKinds
];
126 mutable std::unique_ptr
<BugType
> BTs
[CK_NumCheckKinds
];
128 const std::unique_ptr
<BugType
> &getBugType(CheckKind Kind
) const {
130 BTs
[Kind
].reset(new BugType(CheckNames
[Kind
], "Nullability",
131 categories::MemoryError
));
135 // When set to false no nullability information will be tracked in
136 // NullabilityMap. It is possible to catch errors like passing a null pointer
137 // to a callee that expects nonnull argument without the information that is
138 // stored in the NullabilityMap. This is an optimization.
139 bool NeedTracking
= false;
142 class NullabilityBugVisitor
: public BugReporterVisitor
{
144 NullabilityBugVisitor(const MemRegion
*M
) : Region(M
) {}
146 void Profile(llvm::FoldingSetNodeID
&ID
) const override
{
149 ID
.AddPointer(Region
);
152 PathDiagnosticPieceRef
VisitNode(const ExplodedNode
*N
,
153 BugReporterContext
&BRC
,
154 PathSensitiveBugReport
&BR
) override
;
157 // The tracked region.
158 const MemRegion
*Region
;
161 /// When any of the nonnull arguments of the analyzed function is null, do not
162 /// report anything and turn off the check.
164 /// When \p SuppressPath is set to true, no more bugs will be reported on this
165 /// path by this checker.
166 void reportBugIfInvariantHolds(StringRef Msg
, ErrorKind Error
, CheckKind CK
,
167 ExplodedNode
*N
, const MemRegion
*Region
,
169 const Stmt
*ValueExpr
= nullptr,
170 bool SuppressPath
= false) const;
172 void reportBug(StringRef Msg
, ErrorKind Error
, CheckKind CK
, ExplodedNode
*N
,
173 const MemRegion
*Region
, BugReporter
&BR
,
174 const Stmt
*ValueExpr
= nullptr) const {
175 const std::unique_ptr
<BugType
> &BT
= getBugType(CK
);
176 auto R
= std::make_unique
<PathSensitiveBugReport
>(*BT
, Msg
, N
);
178 R
->markInteresting(Region
);
179 R
->addVisitor
<NullabilityBugVisitor
>(Region
);
182 R
->addRange(ValueExpr
->getSourceRange());
183 if (Error
== ErrorKind::NilAssignedToNonnull
||
184 Error
== ErrorKind::NilPassedToNonnull
||
185 Error
== ErrorKind::NilReturnedToNonnull
)
186 if (const auto *Ex
= dyn_cast
<Expr
>(ValueExpr
))
187 bugreporter::trackExpressionValue(N
, Ex
, *R
);
189 BR
.emitReport(std::move(R
));
192 /// If an SVal wraps a region that should be tracked, it will return a pointer
193 /// to the wrapped region. Otherwise it will return a nullptr.
194 const SymbolicRegion
*getTrackRegion(SVal Val
,
195 bool CheckSuperRegion
= false) const;
197 /// Returns true if the call is diagnosable in the current analyzer
199 bool isDiagnosableCall(const CallEvent
&Call
) const {
200 if (NoDiagnoseCallsToSystemHeaders
&& Call
.isInSystemHeader())
207 class NullabilityState
{
209 NullabilityState(Nullability Nullab
, const Stmt
*Source
= nullptr)
210 : Nullab(Nullab
), Source(Source
) {}
212 const Stmt
*getNullabilitySource() const { return Source
; }
214 Nullability
getValue() const { return Nullab
; }
216 void Profile(llvm::FoldingSetNodeID
&ID
) const {
217 ID
.AddInteger(static_cast<char>(Nullab
));
218 ID
.AddPointer(Source
);
221 void print(raw_ostream
&Out
) const {
222 Out
<< getNullabilityString(Nullab
) << "\n";
227 // Source is the expression which determined the nullability. For example in a
228 // message like [nullable nonnull_returning] has nullable nullability, because
229 // the receiver is nullable. Here the receiver will be the source of the
230 // nullability. This is useful information when the diagnostics are generated.
234 bool operator==(NullabilityState Lhs
, NullabilityState Rhs
) {
235 return Lhs
.getValue() == Rhs
.getValue() &&
236 Lhs
.getNullabilitySource() == Rhs
.getNullabilitySource();
239 // For the purpose of tracking historical property accesses, the key for lookup
240 // is an object pointer (could be an instance or a class) paired with the unique
241 // identifier for the property being invoked on that object.
242 using ObjectPropPair
= std::pair
<const MemRegion
*, const IdentifierInfo
*>;
244 // Metadata associated with the return value from a recorded property access.
245 struct ConstrainedPropertyVal
{
246 // This will reference the conjured return SVal for some call
247 // of the form [object property]
248 DefinedOrUnknownSVal Value
;
250 // If the SVal has been determined to be nonnull, that is recorded here
251 bool isConstrainedNonnull
;
253 ConstrainedPropertyVal(DefinedOrUnknownSVal SV
)
254 : Value(SV
), isConstrainedNonnull(false) {}
256 void Profile(llvm::FoldingSetNodeID
&ID
) const {
258 ID
.AddInteger(isConstrainedNonnull
? 1 : 0);
262 bool operator==(const ConstrainedPropertyVal
&Lhs
,
263 const ConstrainedPropertyVal
&Rhs
) {
264 return Lhs
.Value
== Rhs
.Value
&&
265 Lhs
.isConstrainedNonnull
== Rhs
.isConstrainedNonnull
;
268 } // end anonymous namespace
270 REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap
, const MemRegion
*,
272 REGISTER_MAP_WITH_PROGRAMSTATE(PropertyAccessesMap
, ObjectPropPair
,
273 ConstrainedPropertyVal
)
275 // We say "the nullability type invariant is violated" when a location with a
276 // non-null type contains NULL or a function with a non-null return type returns
277 // NULL. Violations of the nullability type invariant can be detected either
278 // directly (for example, when NULL is passed as an argument to a nonnull
279 // parameter) or indirectly (for example, when, inside a function, the
280 // programmer defensively checks whether a nonnull parameter contains NULL and
281 // finds that it does).
283 // As a matter of policy, the nullability checker typically warns on direct
284 // violations of the nullability invariant (although it uses various
285 // heuristics to suppress warnings in some cases) but will not warn if the
286 // invariant has already been violated along the path (either directly or
287 // indirectly). As a practical matter, this prevents the analyzer from
288 // (1) warning on defensive code paths where a nullability precondition is
289 // determined to have been violated, (2) warning additional times after an
290 // initial direct violation has been discovered, and (3) warning after a direct
291 // violation that has been implicitly or explicitly suppressed (for
292 // example, with a cast of NULL to _Nonnull). In essence, once an invariant
293 // violation is detected on a path, this checker will be essentially turned off
294 // for the rest of the analysis
296 // The analyzer takes this approach (rather than generating a sink node) to
297 // ensure coverage of defensive paths, which may be important for backwards
298 // compatibility in codebases that were developed without nullability in mind.
299 REGISTER_TRAIT_WITH_PROGRAMSTATE(InvariantViolated
, bool)
301 enum class NullConstraint
{ IsNull
, IsNotNull
, Unknown
};
303 static NullConstraint
getNullConstraint(DefinedOrUnknownSVal Val
,
304 ProgramStateRef State
) {
305 ConditionTruthVal Nullness
= State
->isNull(Val
);
306 if (Nullness
.isConstrainedFalse())
307 return NullConstraint::IsNotNull
;
308 if (Nullness
.isConstrainedTrue())
309 return NullConstraint::IsNull
;
310 return NullConstraint::Unknown
;
313 static bool isValidPointerType(QualType T
) {
314 return T
->isAnyPointerType() || T
->isBlockPointerType();
317 const SymbolicRegion
*
318 NullabilityChecker::getTrackRegion(SVal Val
, bool CheckSuperRegion
) const {
322 auto RegionSVal
= Val
.getAs
<loc::MemRegionVal
>();
326 const MemRegion
*Region
= RegionSVal
->getRegion();
328 if (CheckSuperRegion
) {
329 if (const SubRegion
*FieldReg
= Region
->getAs
<FieldRegion
>()) {
330 if (const auto *ER
= dyn_cast
<ElementRegion
>(FieldReg
->getSuperRegion()))
332 return dyn_cast
<SymbolicRegion
>(FieldReg
->getSuperRegion());
334 if (auto ElementReg
= Region
->getAs
<ElementRegion
>())
335 return dyn_cast
<SymbolicRegion
>(ElementReg
->getSuperRegion());
338 return dyn_cast
<SymbolicRegion
>(Region
);
341 PathDiagnosticPieceRef
NullabilityChecker::NullabilityBugVisitor::VisitNode(
342 const ExplodedNode
*N
, BugReporterContext
&BRC
,
343 PathSensitiveBugReport
&BR
) {
344 ProgramStateRef State
= N
->getState();
345 ProgramStateRef StatePrev
= N
->getFirstPred()->getState();
347 const NullabilityState
*TrackedNullab
= State
->get
<NullabilityMap
>(Region
);
348 const NullabilityState
*TrackedNullabPrev
=
349 StatePrev
->get
<NullabilityMap
>(Region
);
353 if (TrackedNullabPrev
&&
354 TrackedNullabPrev
->getValue() == TrackedNullab
->getValue())
357 // Retrieve the associated statement.
358 const Stmt
*S
= TrackedNullab
->getNullabilitySource();
359 if (!S
|| S
->getBeginLoc().isInvalid()) {
360 S
= N
->getStmtForDiagnostics();
366 std::string InfoText
=
367 (llvm::Twine("Nullability '") +
368 getNullabilityString(TrackedNullab
->getValue()) + "' is inferred")
371 // Generate the extra diagnostic.
372 PathDiagnosticLocation
Pos(S
, BRC
.getSourceManager(),
373 N
->getLocationContext());
374 return std::make_shared
<PathDiagnosticEventPiece
>(Pos
, InfoText
, true);
377 /// Returns true when the value stored at the given location has been
378 /// constrained to null after being passed through an object of nonnnull type.
379 static bool checkValueAtLValForInvariantViolation(ProgramStateRef State
,
380 SVal LV
, QualType T
) {
381 if (getNullabilityAnnotation(T
) != Nullability::Nonnull
)
384 auto RegionVal
= LV
.getAs
<loc::MemRegionVal
>();
388 // If the value was constrained to null *after* it was passed through that
389 // location, it could not have been a concrete pointer *when* it was passed.
390 // In that case we would have handled the situation when the value was
391 // bound to that location, by emitting (or not emitting) a report.
392 // Therefore we are only interested in symbolic regions that can be either
393 // null or non-null depending on the value of their respective symbol.
394 auto StoredVal
= State
->getSVal(*RegionVal
).getAs
<loc::MemRegionVal
>();
395 if (!StoredVal
|| !isa
<SymbolicRegion
>(StoredVal
->getRegion()))
398 if (getNullConstraint(*StoredVal
, State
) == NullConstraint::IsNull
)
405 checkParamsForPreconditionViolation(ArrayRef
<ParmVarDecl
*> Params
,
406 ProgramStateRef State
,
407 const LocationContext
*LocCtxt
) {
408 for (const auto *ParamDecl
: Params
) {
409 if (ParamDecl
->isParameterPack())
412 SVal LV
= State
->getLValue(ParamDecl
, LocCtxt
);
413 if (checkValueAtLValForInvariantViolation(State
, LV
,
414 ParamDecl
->getType())) {
422 checkSelfIvarsForInvariantViolation(ProgramStateRef State
,
423 const LocationContext
*LocCtxt
) {
424 auto *MD
= dyn_cast
<ObjCMethodDecl
>(LocCtxt
->getDecl());
425 if (!MD
|| !MD
->isInstanceMethod())
428 const ImplicitParamDecl
*SelfDecl
= LocCtxt
->getSelfDecl();
432 SVal SelfVal
= State
->getSVal(State
->getRegion(SelfDecl
, LocCtxt
));
434 const ObjCObjectPointerType
*SelfType
=
435 dyn_cast
<ObjCObjectPointerType
>(SelfDecl
->getType());
439 const ObjCInterfaceDecl
*ID
= SelfType
->getInterfaceDecl();
443 for (const auto *IvarDecl
: ID
->ivars()) {
444 SVal LV
= State
->getLValue(IvarDecl
, SelfVal
);
445 if (checkValueAtLValForInvariantViolation(State
, LV
, IvarDecl
->getType())) {
452 static bool checkInvariantViolation(ProgramStateRef State
, ExplodedNode
*N
,
454 if (State
->get
<InvariantViolated
>())
457 const LocationContext
*LocCtxt
= C
.getLocationContext();
458 const Decl
*D
= LocCtxt
->getDecl();
462 ArrayRef
<ParmVarDecl
*> Params
;
463 if (const auto *BD
= dyn_cast
<BlockDecl
>(D
))
464 Params
= BD
->parameters();
465 else if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
))
466 Params
= FD
->parameters();
467 else if (const auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
))
468 Params
= MD
->parameters();
472 if (checkParamsForPreconditionViolation(Params
, State
, LocCtxt
) ||
473 checkSelfIvarsForInvariantViolation(State
, LocCtxt
)) {
475 C
.addTransition(State
->set
<InvariantViolated
>(true), N
);
481 void NullabilityChecker::reportBugIfInvariantHolds(
482 StringRef Msg
, ErrorKind Error
, CheckKind CK
, ExplodedNode
*N
,
483 const MemRegion
*Region
, CheckerContext
&C
, const Stmt
*ValueExpr
,
484 bool SuppressPath
) const {
485 ProgramStateRef OriginalState
= N
->getState();
487 if (checkInvariantViolation(OriginalState
, N
, C
))
490 OriginalState
= OriginalState
->set
<InvariantViolated
>(true);
491 N
= C
.addTransition(OriginalState
, N
);
494 reportBug(Msg
, Error
, CK
, N
, Region
, C
.getBugReporter(), ValueExpr
);
497 /// Cleaning up the program state.
498 void NullabilityChecker::checkDeadSymbols(SymbolReaper
&SR
,
499 CheckerContext
&C
) const {
500 ProgramStateRef State
= C
.getState();
501 NullabilityMapTy Nullabilities
= State
->get
<NullabilityMap
>();
502 for (const MemRegion
*Reg
: llvm::make_first_range(Nullabilities
)) {
503 const auto *Region
= Reg
->getAs
<SymbolicRegion
>();
504 assert(Region
&& "Non-symbolic region is tracked.");
505 if (SR
.isDead(Region
->getSymbol())) {
506 State
= State
->remove
<NullabilityMap
>(Reg
);
510 // When an object goes out of scope, we can free the history associated
511 // with any property accesses on that object
512 PropertyAccessesMapTy PropertyAccesses
= State
->get
<PropertyAccessesMap
>();
513 for (ObjectPropPair PropKey
: llvm::make_first_range(PropertyAccesses
)) {
514 const MemRegion
*ReceiverRegion
= PropKey
.first
;
515 if (!SR
.isLiveRegion(ReceiverRegion
)) {
516 State
= State
->remove
<PropertyAccessesMap
>(PropKey
);
520 // When one of the nonnull arguments are constrained to be null, nullability
521 // preconditions are violated. It is not enough to check this only when we
522 // actually report an error, because at that time interesting symbols might be
524 if (checkInvariantViolation(State
, C
.getPredecessor(), C
))
526 C
.addTransition(State
);
529 /// This callback triggers when a pointer is dereferenced and the analyzer does
530 /// not know anything about the value of that pointer. When that pointer is
531 /// nullable, this code emits a warning.
532 void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event
) const {
533 if (Event
.SinkNode
->getState()->get
<InvariantViolated
>())
536 const MemRegion
*Region
=
537 getTrackRegion(Event
.Location
, /*CheckSuperRegion=*/true);
541 ProgramStateRef State
= Event
.SinkNode
->getState();
542 const NullabilityState
*TrackedNullability
=
543 State
->get
<NullabilityMap
>(Region
);
545 if (!TrackedNullability
)
548 if (ChecksEnabled
[CK_NullableDereferenced
] &&
549 TrackedNullability
->getValue() == Nullability::Nullable
) {
550 BugReporter
&BR
= *Event
.BR
;
551 // Do not suppress errors on defensive code paths, because dereferencing
552 // a nullable pointer is always an error.
553 if (Event
.IsDirectDereference
)
554 reportBug("Nullable pointer is dereferenced",
555 ErrorKind::NullableDereferenced
, CK_NullableDereferenced
,
556 Event
.SinkNode
, Region
, BR
);
558 reportBug("Nullable pointer is passed to a callee that requires a "
560 ErrorKind::NullablePassedToNonnull
, CK_NullableDereferenced
,
561 Event
.SinkNode
, Region
, BR
);
566 void NullabilityChecker::checkBeginFunction(CheckerContext
&C
) const {
570 const LocationContext
*LCtx
= C
.getLocationContext();
571 auto AbstractCall
= AnyCall::forDecl(LCtx
->getDecl());
572 if (!AbstractCall
|| AbstractCall
->parameters().empty())
575 ProgramStateRef State
= C
.getState();
576 for (const ParmVarDecl
*Param
: AbstractCall
->parameters()) {
577 if (!isValidPointerType(Param
->getType()))
580 Nullability RequiredNullability
=
581 getNullabilityAnnotation(Param
->getType());
582 if (RequiredNullability
!= Nullability::Nullable
)
585 const VarRegion
*ParamRegion
= State
->getRegion(Param
, LCtx
);
586 const MemRegion
*ParamPointeeRegion
=
587 State
->getSVal(ParamRegion
).getAsRegion();
588 if (!ParamPointeeRegion
)
591 State
= State
->set
<NullabilityMap
>(ParamPointeeRegion
,
592 NullabilityState(RequiredNullability
));
594 C
.addTransition(State
);
597 // Whenever we see a load from a typed memory region that's been annotated as
598 // 'nonnull', we want to trust the user on that and assume that it is is indeed
601 // We do so even if the value is known to have been assigned to null.
602 // The user should be warned on assigning the null value to a non-null pointer
603 // as opposed to warning on the later dereference of this pointer.
606 // int * _Nonnull var = 0; // we want to warn the user here...
608 // *var = 42; // ...and not here
610 void NullabilityChecker::checkLocation(SVal Location
, bool IsLoad
,
612 CheckerContext
&Context
) const {
613 // We should care only about loads.
614 // The main idea is to add a constraint whenever we're loading a value from
615 // an annotated pointer type.
619 // Annotations that we want to consider make sense only for types.
621 dyn_cast_or_null
<TypedValueRegion
>(Location
.getAsRegion());
625 ProgramStateRef State
= Context
.getState();
627 auto StoredVal
= State
->getSVal(Region
).getAs
<loc::MemRegionVal
>();
631 Nullability NullabilityOfTheLoadedValue
=
632 getNullabilityAnnotation(Region
->getValueType());
634 if (NullabilityOfTheLoadedValue
== Nullability::Nonnull
) {
635 // It doesn't matter what we think about this particular pointer, it should
636 // be considered non-null as annotated by the developer.
637 if (ProgramStateRef NewState
= State
->assume(*StoredVal
, true)) {
638 Context
.addTransition(NewState
);
643 /// Find the outermost subexpression of E that is not an implicit cast.
644 /// This looks through the implicit casts to _Nonnull that ARC adds to
645 /// return expressions of ObjC types when the return type of the function or
646 /// method is non-null but the express is not.
647 static const Expr
*lookThroughImplicitCasts(const Expr
*E
) {
648 return E
->IgnoreImpCasts();
651 /// This method check when nullable pointer or null value is returned from a
652 /// function that has nonnull return type.
653 void NullabilityChecker::checkPreStmt(const ReturnStmt
*S
,
654 CheckerContext
&C
) const {
655 auto RetExpr
= S
->getRetValue();
659 if (!isValidPointerType(RetExpr
->getType()))
662 ProgramStateRef State
= C
.getState();
663 if (State
->get
<InvariantViolated
>())
666 auto RetSVal
= C
.getSVal(S
).getAs
<DefinedOrUnknownSVal
>();
670 bool InSuppressedMethodFamily
= false;
672 QualType RequiredRetType
;
673 AnalysisDeclContext
*DeclCtxt
=
674 C
.getLocationContext()->getAnalysisDeclContext();
675 const Decl
*D
= DeclCtxt
->getDecl();
676 if (auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
677 // HACK: This is a big hammer to avoid warning when there are defensive
678 // nil checks in -init and -copy methods. We should add more sophisticated
679 // logic here to suppress on common defensive idioms but still
680 // warn when there is a likely problem.
681 ObjCMethodFamily Family
= MD
->getMethodFamily();
682 if (OMF_init
== Family
|| OMF_copy
== Family
|| OMF_mutableCopy
== Family
)
683 InSuppressedMethodFamily
= true;
685 RequiredRetType
= MD
->getReturnType();
686 } else if (auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
687 RequiredRetType
= FD
->getReturnType();
692 NullConstraint Nullness
= getNullConstraint(*RetSVal
, State
);
694 Nullability RequiredNullability
= getNullabilityAnnotation(RequiredRetType
);
696 // If the returned value is null but the type of the expression
697 // generating it is nonnull then we will suppress the diagnostic.
698 // This enables explicit suppression when returning a nil literal in a
699 // function with a _Nonnull return type:
700 // return (NSString * _Nonnull)0;
701 Nullability RetExprTypeLevelNullability
=
702 getNullabilityAnnotation(lookThroughImplicitCasts(RetExpr
)->getType());
704 bool NullReturnedFromNonNull
= (RequiredNullability
== Nullability::Nonnull
&&
705 Nullness
== NullConstraint::IsNull
);
706 if (ChecksEnabled
[CK_NullReturnedFromNonnull
] && NullReturnedFromNonNull
&&
707 RetExprTypeLevelNullability
!= Nullability::Nonnull
&&
708 !InSuppressedMethodFamily
&& C
.getLocationContext()->inTopFrame()) {
709 static CheckerProgramPointTag
Tag(this, "NullReturnedFromNonnull");
710 ExplodedNode
*N
= C
.generateErrorNode(State
, &Tag
);
714 SmallString
<256> SBuf
;
715 llvm::raw_svector_ostream
OS(SBuf
);
716 OS
<< (RetExpr
->getType()->isObjCObjectPointerType() ? "nil" : "Null");
717 OS
<< " returned from a " << C
.getDeclDescription(D
) <<
718 " that is expected to return a non-null value";
719 reportBugIfInvariantHolds(OS
.str(), ErrorKind::NilReturnedToNonnull
,
720 CK_NullReturnedFromNonnull
, N
, nullptr, C
,
725 // If null was returned from a non-null function, mark the nullability
726 // invariant as violated even if the diagnostic was suppressed.
727 if (NullReturnedFromNonNull
) {
728 State
= State
->set
<InvariantViolated
>(true);
729 C
.addTransition(State
);
733 const MemRegion
*Region
= getTrackRegion(*RetSVal
);
737 const NullabilityState
*TrackedNullability
=
738 State
->get
<NullabilityMap
>(Region
);
739 if (TrackedNullability
) {
740 Nullability TrackedNullabValue
= TrackedNullability
->getValue();
741 if (ChecksEnabled
[CK_NullableReturnedFromNonnull
] &&
742 Nullness
!= NullConstraint::IsNotNull
&&
743 TrackedNullabValue
== Nullability::Nullable
&&
744 RequiredNullability
== Nullability::Nonnull
) {
745 static CheckerProgramPointTag
Tag(this, "NullableReturnedFromNonnull");
746 ExplodedNode
*N
= C
.addTransition(State
, C
.getPredecessor(), &Tag
);
748 SmallString
<256> SBuf
;
749 llvm::raw_svector_ostream
OS(SBuf
);
750 OS
<< "Nullable pointer is returned from a " << C
.getDeclDescription(D
) <<
751 " that is expected to return a non-null value";
753 reportBugIfInvariantHolds(OS
.str(), ErrorKind::NullableReturnedToNonnull
,
754 CK_NullableReturnedFromNonnull
, N
, Region
, C
);
758 if (RequiredNullability
== Nullability::Nullable
) {
759 State
= State
->set
<NullabilityMap
>(Region
,
760 NullabilityState(RequiredNullability
,
762 C
.addTransition(State
);
766 /// This callback warns when a nullable pointer or a null value is passed to a
767 /// function that expects its argument to be nonnull.
768 void NullabilityChecker::checkPreCall(const CallEvent
&Call
,
769 CheckerContext
&C
) const {
773 ProgramStateRef State
= C
.getState();
774 if (State
->get
<InvariantViolated
>())
777 ProgramStateRef OrigState
= State
;
780 for (const ParmVarDecl
*Param
: Call
.parameters()) {
781 if (Param
->isParameterPack())
784 if (Idx
>= Call
.getNumArgs())
787 const Expr
*ArgExpr
= Call
.getArgExpr(Idx
);
788 auto ArgSVal
= Call
.getArgSVal(Idx
++).getAs
<DefinedOrUnknownSVal
>();
792 if (!isValidPointerType(Param
->getType()) &&
793 !Param
->getType()->isReferenceType())
796 NullConstraint Nullness
= getNullConstraint(*ArgSVal
, State
);
798 Nullability RequiredNullability
=
799 getNullabilityAnnotation(Param
->getType());
800 Nullability ArgExprTypeLevelNullability
=
801 getNullabilityAnnotation(lookThroughImplicitCasts(ArgExpr
)->getType());
803 unsigned ParamIdx
= Param
->getFunctionScopeIndex() + 1;
805 if (ChecksEnabled
[CK_NullPassedToNonnull
] &&
806 Nullness
== NullConstraint::IsNull
&&
807 ArgExprTypeLevelNullability
!= Nullability::Nonnull
&&
808 RequiredNullability
== Nullability::Nonnull
&&
809 isDiagnosableCall(Call
)) {
810 ExplodedNode
*N
= C
.generateErrorNode(State
);
814 SmallString
<256> SBuf
;
815 llvm::raw_svector_ostream
OS(SBuf
);
816 OS
<< (Param
->getType()->isObjCObjectPointerType() ? "nil" : "Null");
817 OS
<< " passed to a callee that requires a non-null " << ParamIdx
818 << llvm::getOrdinalSuffix(ParamIdx
) << " parameter";
819 reportBugIfInvariantHolds(OS
.str(), ErrorKind::NilPassedToNonnull
,
820 CK_NullPassedToNonnull
, N
, nullptr, C
, ArgExpr
,
821 /*SuppressPath=*/false);
825 const MemRegion
*Region
= getTrackRegion(*ArgSVal
);
829 const NullabilityState
*TrackedNullability
=
830 State
->get
<NullabilityMap
>(Region
);
832 if (TrackedNullability
) {
833 if (Nullness
== NullConstraint::IsNotNull
||
834 TrackedNullability
->getValue() != Nullability::Nullable
)
837 if (ChecksEnabled
[CK_NullablePassedToNonnull
] &&
838 RequiredNullability
== Nullability::Nonnull
&&
839 isDiagnosableCall(Call
)) {
840 ExplodedNode
*N
= C
.addTransition(State
);
841 SmallString
<256> SBuf
;
842 llvm::raw_svector_ostream
OS(SBuf
);
843 OS
<< "Nullable pointer is passed to a callee that requires a non-null "
844 << ParamIdx
<< llvm::getOrdinalSuffix(ParamIdx
) << " parameter";
845 reportBugIfInvariantHolds(OS
.str(), ErrorKind::NullablePassedToNonnull
,
846 CK_NullablePassedToNonnull
, N
, Region
, C
,
847 ArgExpr
, /*SuppressPath=*/true);
850 if (ChecksEnabled
[CK_NullableDereferenced
] &&
851 Param
->getType()->isReferenceType()) {
852 ExplodedNode
*N
= C
.addTransition(State
);
853 reportBugIfInvariantHolds("Nullable pointer is dereferenced",
854 ErrorKind::NullableDereferenced
,
855 CK_NullableDereferenced
, N
, Region
, C
,
856 ArgExpr
, /*SuppressPath=*/true);
862 if (State
!= OrigState
)
863 C
.addTransition(State
);
866 /// Suppress the nullability warnings for some functions.
867 void NullabilityChecker::checkPostCall(const CallEvent
&Call
,
868 CheckerContext
&C
) const {
869 auto Decl
= Call
.getDecl();
872 // ObjC Messages handles in a different callback.
873 if (Call
.getKind() == CE_ObjCMessage
)
875 const FunctionType
*FuncType
= Decl
->getFunctionType();
878 QualType ReturnType
= FuncType
->getReturnType();
879 if (!isValidPointerType(ReturnType
))
881 ProgramStateRef State
= C
.getState();
882 if (State
->get
<InvariantViolated
>())
885 const MemRegion
*Region
= getTrackRegion(Call
.getReturnValue());
889 // CG headers are misannotated. Do not warn for symbols that are the results
891 const SourceManager
&SM
= C
.getSourceManager();
892 StringRef FilePath
= SM
.getFilename(SM
.getSpellingLoc(Decl
->getBeginLoc()));
893 if (llvm::sys::path::filename(FilePath
).startswith("CG")) {
894 State
= State
->set
<NullabilityMap
>(Region
, Nullability::Contradicted
);
895 C
.addTransition(State
);
899 const NullabilityState
*TrackedNullability
=
900 State
->get
<NullabilityMap
>(Region
);
902 // ObjCMessageExpr gets the actual type through
903 // Sema::getMessageSendResultType, instead of using the return type of
904 // MethodDecl directly. The final type is generated by considering the
905 // nullability of receiver and MethodDecl together. Thus, The type of
906 // ObjCMessageExpr is prefer.
907 if (const Expr
*E
= Call
.getOriginExpr())
908 ReturnType
= E
->getType();
910 if (!TrackedNullability
&&
911 getNullabilityAnnotation(ReturnType
) == Nullability::Nullable
) {
912 State
= State
->set
<NullabilityMap
>(Region
, Nullability::Nullable
);
913 C
.addTransition(State
);
917 static Nullability
getReceiverNullability(const ObjCMethodCall
&M
,
918 ProgramStateRef State
) {
919 if (M
.isReceiverSelfOrSuper()) {
920 // For super and super class receivers we assume that the receiver is
922 return Nullability::Nonnull
;
924 // Otherwise look up nullability in the state.
925 SVal Receiver
= M
.getReceiverSVal();
926 if (auto DefOrUnknown
= Receiver
.getAs
<DefinedOrUnknownSVal
>()) {
927 // If the receiver is constrained to be nonnull, assume that it is nonnull
928 // regardless of its type.
929 NullConstraint Nullness
= getNullConstraint(*DefOrUnknown
, State
);
930 if (Nullness
== NullConstraint::IsNotNull
)
931 return Nullability::Nonnull
;
933 auto ValueRegionSVal
= Receiver
.getAs
<loc::MemRegionVal
>();
934 if (ValueRegionSVal
) {
935 const MemRegion
*SelfRegion
= ValueRegionSVal
->getRegion();
938 const NullabilityState
*TrackedSelfNullability
=
939 State
->get
<NullabilityMap
>(SelfRegion
);
940 if (TrackedSelfNullability
)
941 return TrackedSelfNullability
->getValue();
943 return Nullability::Unspecified
;
946 // The return value of a property access is typically a temporary value which
947 // will not be tracked in a persistent manner by the analyzer. We use
948 // evalAssume() in order to immediately record constraints on those temporaries
949 // at the time they are imposed (e.g. by a nil-check conditional).
950 ProgramStateRef
NullabilityChecker::evalAssume(ProgramStateRef State
, SVal Cond
,
951 bool Assumption
) const {
952 PropertyAccessesMapTy PropertyAccesses
= State
->get
<PropertyAccessesMap
>();
953 for (auto [PropKey
, PropVal
] : PropertyAccesses
) {
954 if (!PropVal
.isConstrainedNonnull
) {
955 ConditionTruthVal IsNonNull
= State
->isNonNull(PropVal
.Value
);
956 if (IsNonNull
.isConstrainedTrue()) {
957 ConstrainedPropertyVal Replacement
= PropVal
;
958 Replacement
.isConstrainedNonnull
= true;
959 State
= State
->set
<PropertyAccessesMap
>(PropKey
, Replacement
);
960 } else if (IsNonNull
.isConstrainedFalse()) {
961 // Space optimization: no point in tracking constrained-null cases
962 State
= State
->remove
<PropertyAccessesMap
>(PropKey
);
970 /// Calculate the nullability of the result of a message expr based on the
971 /// nullability of the receiver, the nullability of the return value, and the
973 void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall
&M
,
974 CheckerContext
&C
) const {
975 auto Decl
= M
.getDecl();
978 QualType RetType
= Decl
->getReturnType();
979 if (!isValidPointerType(RetType
))
982 ProgramStateRef State
= C
.getState();
983 if (State
->get
<InvariantViolated
>())
986 const MemRegion
*ReturnRegion
= getTrackRegion(M
.getReturnValue());
990 auto Interface
= Decl
->getClassInterface();
991 auto Name
= Interface
? Interface
->getName() : "";
992 // In order to reduce the noise in the diagnostics generated by this checker,
993 // some framework and programming style based heuristics are used. These
994 // heuristics are for Cocoa APIs which have NS prefix.
995 if (Name
.startswith("NS")) {
996 // Developers rely on dynamic invariants such as an item should be available
997 // in a collection, or a collection is not empty often. Those invariants can
998 // not be inferred by any static analysis tool. To not to bother the users
999 // with too many false positives, every item retrieval function should be
1000 // ignored for collections. The instance methods of dictionaries in Cocoa
1001 // are either item retrieval related or not interesting nullability wise.
1002 // Using this fact, to keep the code easier to read just ignore the return
1003 // value of every instance method of dictionaries.
1004 if (M
.isInstanceMessage() && Name
.contains("Dictionary")) {
1006 State
->set
<NullabilityMap
>(ReturnRegion
, Nullability::Contradicted
);
1007 C
.addTransition(State
);
1010 // For similar reasons ignore some methods of Cocoa arrays.
1011 StringRef FirstSelectorSlot
= M
.getSelector().getNameForSlot(0);
1012 if (Name
.contains("Array") &&
1013 (FirstSelectorSlot
== "firstObject" ||
1014 FirstSelectorSlot
== "lastObject")) {
1016 State
->set
<NullabilityMap
>(ReturnRegion
, Nullability::Contradicted
);
1017 C
.addTransition(State
);
1021 // Encoding related methods of string should not fail when lossless
1022 // encodings are used. Using lossless encodings is so frequent that ignoring
1023 // this class of methods reduced the emitted diagnostics by about 30% on
1024 // some projects (and all of that was false positives).
1025 if (Name
.contains("String")) {
1026 for (auto *Param
: M
.parameters()) {
1027 if (Param
->getName() == "encoding") {
1028 State
= State
->set
<NullabilityMap
>(ReturnRegion
,
1029 Nullability::Contradicted
);
1030 C
.addTransition(State
);
1037 const ObjCMessageExpr
*Message
= M
.getOriginExpr();
1038 Nullability SelfNullability
= getReceiverNullability(M
, State
);
1040 const NullabilityState
*NullabilityOfReturn
=
1041 State
->get
<NullabilityMap
>(ReturnRegion
);
1043 if (NullabilityOfReturn
) {
1044 // When we have a nullability tracked for the return value, the nullability
1045 // of the expression will be the most nullable of the receiver and the
1047 Nullability RetValTracked
= NullabilityOfReturn
->getValue();
1048 Nullability ComputedNullab
=
1049 getMostNullable(RetValTracked
, SelfNullability
);
1050 if (ComputedNullab
!= RetValTracked
&&
1051 ComputedNullab
!= Nullability::Unspecified
) {
1052 const Stmt
*NullabilitySource
=
1053 ComputedNullab
== RetValTracked
1054 ? NullabilityOfReturn
->getNullabilitySource()
1055 : Message
->getInstanceReceiver();
1056 State
= State
->set
<NullabilityMap
>(
1057 ReturnRegion
, NullabilityState(ComputedNullab
, NullabilitySource
));
1058 C
.addTransition(State
);
1063 // No tracked information. Use static type information for return value.
1064 Nullability RetNullability
= getNullabilityAnnotation(Message
->getType());
1066 // Properties might be computed, which means the property value could
1067 // theoretically change between calls even in commonly-observed cases like
1070 // if (foo.prop) { // ok, it's nonnull here...
1071 // [bar doStuffWithNonnullVal:foo.prop]; // ...but what about
1075 // If the property is nullable-annotated, a naive analysis would lead to many
1076 // false positives despite the presence of probably-correct nil-checks. To
1077 // reduce the false positive rate, we maintain a history of the most recently
1078 // observed property value. For each property access, if the prior value has
1079 // been constrained to be not nil then we will conservatively assume that the
1080 // next access can be inferred as nonnull.
1081 if (RetNullability
!= Nullability::Nonnull
&&
1082 M
.getMessageKind() == OCM_PropertyAccess
&& !C
.wasInlined
) {
1083 bool LookupResolved
= false;
1084 if (const MemRegion
*ReceiverRegion
= getTrackRegion(M
.getReceiverSVal())) {
1085 if (IdentifierInfo
*Ident
= M
.getSelector().getIdentifierInfoForSlot(0)) {
1086 LookupResolved
= true;
1087 ObjectPropPair Key
= std::make_pair(ReceiverRegion
, Ident
);
1088 const ConstrainedPropertyVal
*PrevPropVal
=
1089 State
->get
<PropertyAccessesMap
>(Key
);
1090 if (PrevPropVal
&& PrevPropVal
->isConstrainedNonnull
) {
1091 RetNullability
= Nullability::Nonnull
;
1093 // If a previous property access was constrained as nonnull, we hold
1094 // on to that constraint (effectively inferring that all subsequent
1095 // accesses on that code path can be inferred as nonnull). If the
1096 // previous property access was *not* constrained as nonnull, then
1097 // let's throw it away in favor of keeping the SVal associated with
1098 // this more recent access.
1099 if (auto ReturnSVal
=
1100 M
.getReturnValue().getAs
<DefinedOrUnknownSVal
>()) {
1101 State
= State
->set
<PropertyAccessesMap
>(
1102 Key
, ConstrainedPropertyVal(*ReturnSVal
));
1108 if (!LookupResolved
) {
1109 // Fallback: err on the side of suppressing the false positive.
1110 RetNullability
= Nullability::Nonnull
;
1114 Nullability ComputedNullab
= getMostNullable(RetNullability
, SelfNullability
);
1115 if (ComputedNullab
== Nullability::Nullable
) {
1116 const Stmt
*NullabilitySource
= ComputedNullab
== RetNullability
1118 : Message
->getInstanceReceiver();
1119 State
= State
->set
<NullabilityMap
>(
1120 ReturnRegion
, NullabilityState(ComputedNullab
, NullabilitySource
));
1121 C
.addTransition(State
);
1125 /// Explicit casts are trusted. If there is a disagreement in the nullability
1126 /// annotations in the destination and the source or '0' is casted to nonnull
1127 /// track the value as having contraditory nullability. This will allow users to
1128 /// suppress warnings.
1129 void NullabilityChecker::checkPostStmt(const ExplicitCastExpr
*CE
,
1130 CheckerContext
&C
) const {
1131 QualType OriginType
= CE
->getSubExpr()->getType();
1132 QualType DestType
= CE
->getType();
1133 if (!isValidPointerType(OriginType
))
1135 if (!isValidPointerType(DestType
))
1138 ProgramStateRef State
= C
.getState();
1139 if (State
->get
<InvariantViolated
>())
1142 Nullability DestNullability
= getNullabilityAnnotation(DestType
);
1144 // No explicit nullability in the destination type, so this cast does not
1145 // change the nullability.
1146 if (DestNullability
== Nullability::Unspecified
)
1149 auto RegionSVal
= C
.getSVal(CE
).getAs
<DefinedOrUnknownSVal
>();
1150 const MemRegion
*Region
= getTrackRegion(*RegionSVal
);
1154 // When 0 is converted to nonnull mark it as contradicted.
1155 if (DestNullability
== Nullability::Nonnull
) {
1156 NullConstraint Nullness
= getNullConstraint(*RegionSVal
, State
);
1157 if (Nullness
== NullConstraint::IsNull
) {
1158 State
= State
->set
<NullabilityMap
>(Region
, Nullability::Contradicted
);
1159 C
.addTransition(State
);
1164 const NullabilityState
*TrackedNullability
=
1165 State
->get
<NullabilityMap
>(Region
);
1167 if (!TrackedNullability
) {
1168 if (DestNullability
!= Nullability::Nullable
)
1170 State
= State
->set
<NullabilityMap
>(Region
,
1171 NullabilityState(DestNullability
, CE
));
1172 C
.addTransition(State
);
1176 if (TrackedNullability
->getValue() != DestNullability
&&
1177 TrackedNullability
->getValue() != Nullability::Contradicted
) {
1178 State
= State
->set
<NullabilityMap
>(Region
, Nullability::Contradicted
);
1179 C
.addTransition(State
);
1183 /// For a given statement performing a bind, attempt to syntactically
1184 /// match the expression resulting in the bound value.
1185 static const Expr
* matchValueExprForBind(const Stmt
*S
) {
1186 // For `x = e` the value expression is the right-hand side.
1187 if (auto *BinOp
= dyn_cast
<BinaryOperator
>(S
)) {
1188 if (BinOp
->getOpcode() == BO_Assign
)
1189 return BinOp
->getRHS();
1192 // For `int x = e` the value expression is the initializer.
1193 if (auto *DS
= dyn_cast
<DeclStmt
>(S
)) {
1194 if (DS
->isSingleDecl()) {
1195 auto *VD
= dyn_cast
<VarDecl
>(DS
->getSingleDecl());
1199 if (const Expr
*Init
= VD
->getInit())
1207 /// Returns true if \param S is a DeclStmt for a local variable that
1208 /// ObjC automated reference counting initialized with zero.
1209 static bool isARCNilInitializedLocal(CheckerContext
&C
, const Stmt
*S
) {
1210 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1211 // prevents false positives when a _Nonnull local variable cannot be
1212 // initialized with an initialization expression:
1213 // NSString * _Nonnull s; // no-warning
1214 // @autoreleasepool {
1218 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1219 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1220 // the zero-initialized definition will unexpectedly yield nil.
1222 // Locals are only zero-initialized when automated reference counting
1224 if (!C
.getASTContext().getLangOpts().ObjCAutoRefCount
)
1227 auto *DS
= dyn_cast
<DeclStmt
>(S
);
1228 if (!DS
|| !DS
->isSingleDecl())
1231 auto *VD
= dyn_cast
<VarDecl
>(DS
->getSingleDecl());
1235 // Sema only zero-initializes locals with ObjCLifetimes.
1236 if(!VD
->getType().getQualifiers().hasObjCLifetime())
1239 const Expr
*Init
= VD
->getInit();
1240 assert(Init
&& "ObjC local under ARC without initializer");
1242 // Return false if the local is explicitly initialized (e.g., with '= nil').
1243 if (!isa
<ImplicitValueInitExpr
>(Init
))
1249 /// Propagate the nullability information through binds and warn when nullable
1250 /// pointer or null symbol is assigned to a pointer with a nonnull type.
1251 void NullabilityChecker::checkBind(SVal L
, SVal V
, const Stmt
*S
,
1252 CheckerContext
&C
) const {
1253 const TypedValueRegion
*TVR
=
1254 dyn_cast_or_null
<TypedValueRegion
>(L
.getAsRegion());
1258 QualType LocType
= TVR
->getValueType();
1259 if (!isValidPointerType(LocType
))
1262 ProgramStateRef State
= C
.getState();
1263 if (State
->get
<InvariantViolated
>())
1266 auto ValDefOrUnknown
= V
.getAs
<DefinedOrUnknownSVal
>();
1267 if (!ValDefOrUnknown
)
1270 NullConstraint RhsNullness
= getNullConstraint(*ValDefOrUnknown
, State
);
1272 Nullability ValNullability
= Nullability::Unspecified
;
1273 if (SymbolRef Sym
= ValDefOrUnknown
->getAsSymbol())
1274 ValNullability
= getNullabilityAnnotation(Sym
->getType());
1276 Nullability LocNullability
= getNullabilityAnnotation(LocType
);
1278 // If the type of the RHS expression is nonnull, don't warn. This
1279 // enables explicit suppression with a cast to nonnull.
1280 Nullability ValueExprTypeLevelNullability
= Nullability::Unspecified
;
1281 const Expr
*ValueExpr
= matchValueExprForBind(S
);
1283 ValueExprTypeLevelNullability
=
1284 getNullabilityAnnotation(lookThroughImplicitCasts(ValueExpr
)->getType());
1287 bool NullAssignedToNonNull
= (LocNullability
== Nullability::Nonnull
&&
1288 RhsNullness
== NullConstraint::IsNull
);
1289 if (ChecksEnabled
[CK_NullPassedToNonnull
] && NullAssignedToNonNull
&&
1290 ValNullability
!= Nullability::Nonnull
&&
1291 ValueExprTypeLevelNullability
!= Nullability::Nonnull
&&
1292 !isARCNilInitializedLocal(C
, S
)) {
1293 static CheckerProgramPointTag
Tag(this, "NullPassedToNonnull");
1294 ExplodedNode
*N
= C
.generateErrorNode(State
, &Tag
);
1299 const Stmt
*ValueStmt
= S
;
1301 ValueStmt
= ValueExpr
;
1303 SmallString
<256> SBuf
;
1304 llvm::raw_svector_ostream
OS(SBuf
);
1305 OS
<< (LocType
->isObjCObjectPointerType() ? "nil" : "Null");
1306 OS
<< " assigned to a pointer which is expected to have non-null value";
1307 reportBugIfInvariantHolds(OS
.str(), ErrorKind::NilAssignedToNonnull
,
1308 CK_NullPassedToNonnull
, N
, nullptr, C
, ValueStmt
);
1312 // If null was returned from a non-null function, mark the nullability
1313 // invariant as violated even if the diagnostic was suppressed.
1314 if (NullAssignedToNonNull
) {
1315 State
= State
->set
<InvariantViolated
>(true);
1316 C
.addTransition(State
);
1320 // Intentionally missing case: '0' is bound to a reference. It is handled by
1321 // the DereferenceChecker.
1323 const MemRegion
*ValueRegion
= getTrackRegion(*ValDefOrUnknown
);
1327 const NullabilityState
*TrackedNullability
=
1328 State
->get
<NullabilityMap
>(ValueRegion
);
1330 if (TrackedNullability
) {
1331 if (RhsNullness
== NullConstraint::IsNotNull
||
1332 TrackedNullability
->getValue() != Nullability::Nullable
)
1334 if (ChecksEnabled
[CK_NullablePassedToNonnull
] &&
1335 LocNullability
== Nullability::Nonnull
) {
1336 static CheckerProgramPointTag
Tag(this, "NullablePassedToNonnull");
1337 ExplodedNode
*N
= C
.addTransition(State
, C
.getPredecessor(), &Tag
);
1338 reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1339 "which is expected to have non-null value",
1340 ErrorKind::NullableAssignedToNonnull
,
1341 CK_NullablePassedToNonnull
, N
, ValueRegion
, C
);
1346 const auto *BinOp
= dyn_cast
<BinaryOperator
>(S
);
1348 if (ValNullability
== Nullability::Nullable
) {
1349 // Trust the static information of the value more than the static
1350 // information on the location.
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
);
1366 void 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
<< " : ";
1388 void ento::registerNullabilityBase(CheckerManager
&mgr
) {
1389 mgr
.registerChecker
<NullabilityChecker
>();
1392 bool ento::shouldRegisterNullabilityBase(const CheckerManager
&mgr
) {
1396 #define REGISTER_CHECKER(name, trackingRequired) \
1397 void ento::register##name##Checker(CheckerManager &mgr) { \
1398 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1399 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1400 checker->CheckNames[NullabilityChecker::CK_##name] = \
1401 mgr.getCurrentCheckerName(); \
1402 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1403 checker->NoDiagnoseCallsToSystemHeaders = \
1404 checker->NoDiagnoseCallsToSystemHeaders || \
1405 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1406 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1409 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
1413 // The checks are likely to be turned on by default and it is possible to do
1414 // them without tracking any nullability related information. As an optimization
1415 // no nullability information will be tracked when only these two checks are
1417 REGISTER_CHECKER(NullPassedToNonnull
, false)
1418 REGISTER_CHECKER(NullReturnedFromNonnull
, false)
1420 REGISTER_CHECKER(NullableDereferenced
, true)
1421 REGISTER_CHECKER(NullablePassedToNonnull
, true)
1422 REGISTER_CHECKER(NullableReturnedFromNonnull
, true)