blob: 18225391ee8728776dbc1113714508b33193b484 [file] [log] [blame]
// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull -DNOSYSTEMHEADERS=0 -verify %s
// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
#include "Inputs/system-header-simulator-for-nullability.h"
int getRandom();
typedef struct Dummy { int val; } Dummy;
void takesNullable(Dummy *_Nullable);
void takesNonnull(Dummy *_Nonnull);
Dummy *_Nullable returnsNullable();
void testBasicRules() {
// The tracking of nullable values is turned off.
Dummy *p = returnsNullable();
takesNonnull(p); // no warning
Dummy *q = 0;
if (getRandom()) {
takesNullable(q);
takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
}
}
Dummy *_Nonnull testNullReturn() {
Dummy *p = 0;
return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
}
void onlyReportFirstPreconditionViolationOnPath() {
Dummy *p = 0;
takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
takesNonnull(p); // No warning.
// Passing null to nonnull is a sink. Stop the analysis.
int i = 0;
i = 5 / i; // no warning
(void)i;
}
Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
Dummy *_Nonnull p) {
if (!p) {
Dummy *ret =
0; // avoid compiler warning (which is not generated by the analyzer)
if (getRandom())
return ret; // no warning
else
return p; // no warning
} else {
return p;
}
}
Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
if (!p) {
Dummy *ret =
0; // avoid compiler warning (which is not generated by the analyzer)
if (getRandom())
return ret; // no warning
else
return p; // no warning
} else {
return p;
}
}
void testPreconditionViolationInInlinedFunction(Dummy *p) {
doNotWarnWhenPreconditionIsViolated(p);
}
void inlinedNullable(Dummy *_Nullable p) {
if (p) return;
}
void inlinedNonnull(Dummy *_Nonnull p) {
if (p) return;
}
void inlinedUnspecified(Dummy *p) {
if (p) return;
}
Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
switch (getRandom()) {
case 1: inlinedNullable(p); break;
case 2: inlinedNonnull(p); break;
case 3: inlinedUnspecified(p); break;
}
if (getRandom())
takesNonnull(p);
return p;
}
@interface TestObject : NSObject
@end
TestObject *_Nonnull getNonnullTestObject();
void testObjCARCImplicitZeroInitialization() {
TestObject * _Nonnull implicitlyZeroInitialized; // no-warning
implicitlyZeroInitialized = getNonnullTestObject();
}
void testObjCARCExplicitZeroInitialization() {
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 = nil;
return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
TestObject *local = nil;
return (TestObject * _Nonnull)local; // no-warning
}
TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
return nil; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
return (TestObject * _Nonnull)nil; // no-warning
}
@interface SomeClass : NSObject
@end
@implementation SomeClass (MethodReturn)
- (SomeClass * _Nonnull)testReturnsNilInNonnull {
SomeClass *local = nil;
return local; // expected-warning {{nil returned from a method that is expected to return a non-null value}}
}
- (SomeClass * _Nonnull)testReturnsCastSuppressedNilInNonnull {
SomeClass *local = nil;
return (SomeClass * _Nonnull)local; // no-warning
}
- (SomeClass * _Nonnull)testReturnsNilInNonnullWhenPreconditionViolated:(SomeClass * _Nonnull) p {
SomeClass *local = nil;
if (!p) // Pre-condition violated here.
return local; // no-warning
else
return p; // no-warning
}
@end
void callFunctionInSystemHeader() {
NSString *s;
s = nil;
NSSystemFunctionTakingNonnull(s);
#if !NOSYSTEMHEADERS
// expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
#endif
}
void callMethodInSystemHeader() {
NSString *s;
s = nil;
NSSystemClass *sc = [[NSSystemClass alloc] init];
[sc takesNonnull:s];
#if !NOSYSTEMHEADERS
// expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
#endif
}