From: Anna Zaks Date: Thu, 15 Dec 2016 22:55:15 +0000 (+0000) Subject: [analyzer] Refine the diagnostics in the nullability checker to differentiate between... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f328169726f0096e3762d93938dc2048efc59ea;p=clang [analyzer] Refine the diagnostics in the nullability checker to differentiate between nil and null This is a big deal for ObjC, where nullability annotations are extensively used. I've also changed "Null" -> "null" and removed "is" as this is the pattern that Sema is using. Differential Revision: https://reviews.llvm.org/D27600 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289885 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index 4e2aace389..d96017a1f5 100644 --- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -610,9 +610,9 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S, SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); - OS << "Null is returned from a " << C.getDeclDescription(D) << + OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null"); + OS << " returned from a " << C.getDeclDescription(D) << " that is expected to return a non-null value"; - reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull, N, nullptr, C, RetExpr); @@ -707,9 +707,11 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call, ExplodedNode *N = C.generateErrorNode(State); if (!N) return; + SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); - OS << "Null passed to a callee that requires a non-null " << ParamIdx + OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null"); + OS << " passed to a callee that requires a non-null " << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter"; reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull, N, nullptr, C, @@ -1128,8 +1130,11 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S, if (ValueExpr) ValueStmt = ValueExpr; - reportBugIfInvariantHolds("Null is assigned to a pointer which is " - "expected to have non-null value", + SmallString<256> SBuf; + llvm::raw_svector_ostream OS(SBuf); + OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null"); + OS << " assigned to a pointer which is expected to have non-null value"; + reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull, N, nullptr, C, ValueStmt); return; diff --git a/test/Analysis/nullability-no-arc.mm b/test/Analysis/nullability-no-arc.mm index 37d29b7457..e872266d27 100644 --- a/test/Analysis/nullability-no-arc.mm +++ b/test/Analysis/nullability-no-arc.mm @@ -17,20 +17,20 @@ NSObject @interface TestObject : NSObject @end -TestObject * _Nonnull returnsNilObjCInstanceIndirectly() { - TestObject *local = 0; - return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} +TestObject *_Nonnull returnsNilObjCInstanceIndirectly() { + TestObject *local = nil; + return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}} } TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() { - TestObject *local = 0; + TestObject *local = nil; return (TestObject * _Nonnull)local; // no-warning } TestObject * _Nonnull returnsNilObjCInstanceDirectly() { // The first warning is from Sema. The second is from the static analyzer. return nil; // expected-warning {{null returned from function that requires a non-null return value}} - // expected-warning@-1 {{Null is returned from a function that is expected to return a non-null value}} + // expected-warning@-1 {{nil returned from a function that is expected to return a non-null value}} } TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() { @@ -43,7 +43,7 @@ void testObjCNonARCNoInitialization(TestObject * _Nonnull p) { } void testObjCNonARCExplicitZeroInitialization() { - TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}} + TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{nil assigned to a pointer which is expected to have non-null value}} } @interface ClassWithInitializers : NSObject diff --git a/test/Analysis/nullability.mm b/test/Analysis/nullability.mm index ac2a839f40..e4f13c6162 100644 --- a/test/Analysis/nullability.mm +++ b/test/Analysis/nullability.mm @@ -75,7 +75,7 @@ void testBasicRules() { } Dummy a; Dummy *_Nonnull nonnull = &a; - nonnull = q; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}} + nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}} q = &a; takesNullable(q); takesNonnull(q); @@ -107,7 +107,7 @@ Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) { Dummy *_Nonnull testNullReturn() { Dummy *p = 0; - return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} + return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}} } void testObjCMessageResultNullability() { @@ -229,7 +229,7 @@ void testConditionalNilPassToNonnull(Dummy *p) { Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() { Dummy *p = (Dummy * _Nonnull)0; // FIXME: Ideally the cast above would suppress this warning. - return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} + return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}} } void testInvalidPropagation() { diff --git a/test/Analysis/nullability_nullonly.mm b/test/Analysis/nullability_nullonly.mm index 9671877719..359841d97a 100644 --- a/test/Analysis/nullability_nullonly.mm +++ b/test/Analysis/nullability_nullonly.mm @@ -24,7 +24,7 @@ void testBasicRules() { Dummy *_Nonnull testNullReturn() { Dummy *p = 0; - return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} + return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}} } void onlyReportFirstPreconditionViolationOnPath() { @@ -100,24 +100,24 @@ void testObjCARCImplicitZeroInitialization() { } void testObjCARCExplicitZeroInitialization() { - TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}} + TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{nil assigned to a pointer which is expected to have non-null value}} } // Under ARC, returned expressions of ObjC objects types are are implicitly // cast to _Nonnull when the functions return type is _Nonnull, so make // sure this doesn't implicit cast doesn't suppress a legitimate warning. TestObject * _Nonnull returnsNilObjCInstanceIndirectly() { - TestObject *local = 0; - return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} + TestObject *local = nil; + return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}} } TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() { - TestObject *local = 0; + TestObject *local = nil; return (TestObject * _Nonnull)local; // no-warning } TestObject * _Nonnull returnsNilObjCInstanceDirectly() { - return nil; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} + return nil; // expected-warning {{nil returned from a function that is expected to return a non-null value}} } TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() { @@ -130,7 +130,7 @@ TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() { @implementation SomeClass (MethodReturn) - (SomeClass * _Nonnull)testReturnsNilInNonnull { SomeClass *local = nil; - return local; // expected-warning {{Null is returned from a method that is expected to return a non-null value}} + return local; // expected-warning {{nil returned from a method that is expected to return a non-null value}} } - (SomeClass * _Nonnull)testReturnsCastSuppressedNilInNonnull { @@ -154,7 +154,7 @@ void callFunctionInSystemHeader() { NSSystemFunctionTakingNonnull(s); #if !NOSYSTEMHEADERS - // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}} + // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}} #endif } @@ -165,6 +165,6 @@ void callMethodInSystemHeader() { NSSystemClass *sc = [[NSSystemClass alloc] init]; [sc takesNonnull:s]; #if !NOSYSTEMHEADERS - // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}} + // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}} #endif }