r256603 - [analyzer] Suppress nullability warning for _Nonnull locals zero-initialized by ObjC ARC.
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 29 15:44:20 PST 2015
Author: dcoughlin
Date: Tue Dec 29 17:44:19 2015
New Revision: 256603
URL: http://llvm.org/viewvc/llvm-project?rev=256603&view=rev
Log:
[analyzer] Suppress nullability warning for _Nonnull locals zero-initialized by ObjC ARC.
Prevent the analyzer from warning when a _Nonnnull local variable is implicitly
zero-initialized because of Objective-C automated reference counting. This avoids false
positives in cases where a _Nonnull local variable cannot be initialized with an
initialization expression, such as:
NSString * _Nonnull s; // no-warning
@autoreleasepool {
s = ...;
}
The nullability checker will still warn when a _Nonnull local variable is explicitly
initialized with nil.
This suppression introduces the potential for false negatives if the local variable
is used before it is assigned a _Nonnull value. Based on a discussion with Anna Zaks,
Jordan Rose, and John McCall, I've added a FIXME to treat implicitly zero-initialized
_Nonnull locals as uninitialized in Sema's UninitializedValues analysis to avoid these
false negatives.
rdar://problem/23522311
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
cfe/trunk/test/Analysis/nullability.mm
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=256603&r1=256602&r2=256603&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Tue Dec 29 17:44:19 2015
@@ -897,6 +897,48 @@ static const Expr * matchValueExprForBin
return nullptr;
}
+/// Returns true if \param S is a DeclStmt for a local variable that
+/// ObjC automated reference counting initialized with zero.
+static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
+ // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
+ // prevents false positives when a _Nonnull local variable cannot be
+ // initialized with an initialization expression:
+ // NSString * _Nonnull s; // no-warning
+ // @autoreleasepool {
+ // s = ...
+ // }
+ //
+ // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
+ // uninitialized in Sema's UninitializedValues analysis to warn when a use of
+ // the zero-initialized definition will unexpectedly yield nil.
+
+ // Locals are only zero-initialized when automated reference counting
+ // is turned on.
+ if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
+ return false;
+
+ auto *DS = dyn_cast<DeclStmt>(S);
+ if (!DS || !DS->isSingleDecl())
+ return false;
+
+ auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!VD)
+ return false;
+
+ // Sema only zero-initializes locals with ObjCLifetimes.
+ if(!VD->getType().getQualifiers().hasObjCLifetime())
+ return false;
+
+ const Expr *Init = VD->getInit();
+ assert(Init && "ObjC local under ARC without initializer");
+
+ // Return false if the local is explicitly initialized (e.g., with '= nil').
+ if (!isa<ImplicitValueInitExpr>(Init))
+ return false;
+
+ return true;
+}
+
/// Propagate the nullability information through binds and warn when nullable
/// pointer or null symbol is assigned to a pointer with a nonnull type.
void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
@@ -928,7 +970,8 @@ void NullabilityChecker::checkBind(SVal
if (Filter.CheckNullPassedToNonnull &&
RhsNullness == NullConstraint::IsNull &&
ValNullability != Nullability::Nonnull &&
- LocNullability == Nullability::Nonnull) {
+ LocNullability == Nullability::Nonnull &&
+ !isARCNilInitializedLocal(C, S)) {
static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
ExplodedNode *N = C.generateErrorNode(State, &Tag);
if (!N)
Modified: cfe/trunk/test/Analysis/nullability.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullability.mm?rev=256603&r1=256602&r2=256603&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nullability.mm (original)
+++ cfe/trunk/test/Analysis/nullability.mm Tue Dec 29 17:44:19 2015
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,nullability -verify %s
+// RUN: %clang_cc1 -fobjc-arc -analyze -analyzer-checker=core,nullability -verify %s
#define nil 0
#define BOOL int
@@ -278,3 +278,12 @@ Dummy *_Nonnull testDefensiveInlineCheck
return p;
}
+
+void testObjCARCImplicitZeroInitialization() {
+ TestObject * _Nonnull implicitlyZeroInitialized; // no-warning
+ implicitlyZeroInitialized = getNonnullTestObject();
+}
+
+void testObjCARCExplicitZeroInitialization() {
+ TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
+}
More information about the cfe-commits
mailing list