1 // RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \
2 // RUN: -analyzer-checker=nullability.NullPassedToNonnull \
3 // RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \
4 // RUN: -analyzer-checker=nullability.NullablePassedToNonnull \
5 // RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \
6 // RUN: -analyzer-checker=nullability.NullableDereferenced \
7 // RUN: -DNOSYSTEMHEADERS=0
9 // RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \
10 // RUN: -analyzer-checker=nullability.NullPassedToNonnull \
11 // RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \
12 // RUN: -analyzer-checker=nullability.NullablePassedToNonnull \
13 // RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \
14 // RUN: -analyzer-checker=nullability.NullableDereferenced \
15 // RUN: -DNOSYSTEMHEADERS=1 \
16 // RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true
18 // RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\
19 // RUN: -analyzer-checker=nullability.NullPassedToNonnull\
20 // RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\
21 // RUN: -analyzer-checker=nullability.NullablePassedToNonnull\
22 // RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\
23 // RUN: -analyzer-checker=nullability.NullableDereferenced\
24 // RUN: -DNOSYSTEMHEADERS=0 -fobjc-arc
26 // RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\
27 // RUN: -analyzer-checker=nullability.NullPassedToNonnull\
28 // RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\
29 // RUN: -analyzer-checker=nullability.NullablePassedToNonnull\
30 // RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\
31 // RUN: -analyzer-checker=nullability.NullableDereferenced\
32 // RUN: -DNOSYSTEMHEADERS=1 -fobjc-arc\
33 // RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true
35 #include "Inputs/system-header-simulator-for-nullability.h"
37 extern void __assert_fail(__const char *__assertion, __const char *__file,
38 unsigned int __line, __const char *__function)
39 __attribute__((__noreturn__));
41 #define assert(expr) \
42 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
44 @interface TestObject : NSObject
45 - (int *_Nonnull)returnsNonnull;
46 - (int *_Nullable)returnsNullable;
47 - (int *)returnsUnspecified;
48 - (void)takesNonnull:(int *_Nonnull)p;
49 - (void)takesNullable:(int *_Nullable)p;
50 - (void)takesUnspecified:(int *)p;
51 @property(readonly, strong) NSString *stuff;
52 @property(readonly, nonnull) int *propReturnsNonnull;
53 @property(readonly, nullable) int *propReturnsNullable;
54 @property(readonly) int *propReturnsUnspecified;
57 TestObject * getUnspecifiedTestObject();
58 TestObject *_Nonnull getNonnullTestObject();
59 TestObject *_Nullable getNullableTestObject();
63 typedef struct Dummy { int val; } Dummy;
65 void takesNullable(Dummy *_Nullable);
66 void takesNonnull(Dummy *_Nonnull);
67 void takesUnspecified(Dummy *);
69 Dummy *_Nullable returnsNullable();
70 Dummy *_Nonnull returnsNonnull();
71 Dummy *returnsUnspecified();
72 int *_Nullable returnsNullableInt();
74 template <typename T> T *eraseNullab(T *p) { return p; }
76 void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
78 void testBasicRules() {
79 Dummy *p = returnsNullable();
80 int *ptr = returnsNullableInt();
81 // Make every dereference a different path to avoid sinks after errors.
82 switch (getRandom()) {
84 Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}}
87 int b = p->val; // expected-warning {{Nullable pointer is dereferenced}}
90 int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}}
93 takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
101 case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
102 default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
115 takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
118 Dummy *_Nonnull nonnull = &a;
119 nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}}
125 void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
128 void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
131 switch(getRandom()) {
132 case 1: nonnull = p; break; // expected-warning {{Nullable pointer is assigned to a pointer which is expected to have non-null value}}
133 case 2: p = 0; break;
134 case 3: q = p; break;
135 case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;
136 case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;
137 case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}
138 case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
139 case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
140 case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
144 Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
146 return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}
149 Dummy *_Nonnull testNullReturn() {
151 return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
154 void testObjCMessageResultNullability() {
155 // The expected result: the most nullable of self and method return type.
156 TestObject *o = getUnspecifiedTestObject();
157 int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];
158 switch (getRandom()) {
160 // The core analyzer assumes that the receiver is non-null after a message
161 // send. This is to avoid some false positives, and increase performance
162 // but it also reduces the coverage and makes this checker unable to reason
163 // about the nullness of the receiver.
164 [o takesNonnull:shouldBeNullable]; // No warning expected.
168 [eraseNullab(getNullableTestObject()) returnsUnspecified];
169 [o takesNonnull:shouldBeNullable]; // No warning expected.
172 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
173 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
176 shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];
177 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
181 [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
182 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
185 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
186 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
189 int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
190 [o takesNonnull:shouldBeNonnull];
195 void testObjCPropertyReadNullability() {
196 TestObject *o = getNonnullTestObject();
197 switch (getRandom()) {
199 [o takesNonnull:o.propReturnsNonnull]; // no-warning
202 [o takesNonnull:o.propReturnsUnspecified]; // no-warning
205 [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
208 // If a property is constrained nonnull, assume it remains nonnull
209 if (o.propReturnsNullable) {
210 [o takesNonnull:o.propReturnsNullable]; // no-warning
211 [o takesNonnull:o.propReturnsNullable]; // no-warning
215 if (!o.propReturnsNullable) {
216 [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
220 if (!o.propReturnsNullable) {
221 if (o.propReturnsNullable) {
222 // Nonnull constraint from the more recent call wins
223 [o takesNonnull:o.propReturnsNullable]; // no-warning
228 // Constraints on property return values are receiver-qualified
229 if (o.propReturnsNullable) {
230 [o takesNonnull:o.propReturnsNullable]; // no-warning
231 [o takesNonnull:getNonnullTestObject().propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
235 // Assertions must be effective at suppressing warnings
236 assert(o.propReturnsNullable);
237 [o takesNonnull:o.propReturnsNullable]; // no-warning
242 Dummy * _Nonnull testDirectCastNullableToNonnull() {
243 Dummy *p = returnsNullable();
244 takesNonnull((Dummy * _Nonnull)p); // no-warning
245 return (Dummy * _Nonnull)p; // no-warning
248 Dummy * _Nonnull testIndirectCastNullableToNonnull() {
249 Dummy *p = (Dummy * _Nonnull)returnsNullable();
250 takesNonnull(p); // no-warning
251 return p; // no-warning
254 Dummy * _Nonnull testDirectCastNilToNonnull() {
255 takesNonnull((Dummy * _Nonnull)0); // no-warning
256 return (Dummy * _Nonnull)0; // no-warning
259 void testIndirectCastNilToNonnullAndPass() {
260 Dummy *p = (Dummy * _Nonnull)0;
261 // FIXME: Ideally the cast above would suppress this warning.
262 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
265 void testDirectCastNilToNonnullAndAssignToLocalInInitializer() {
266 Dummy * _Nonnull nonnullLocalWithAssignmentInInitializer = (Dummy * _Nonnull)0; // no-warning
267 (void)nonnullLocalWithAssignmentInInitializer;
269 // Since we've already had an invariant violation along this path,
270 // we shouldn't warn here.
271 nonnullLocalWithAssignmentInInitializer = 0;
272 (void)nonnullLocalWithAssignmentInInitializer;
276 void testDirectCastNilToNonnullAndAssignToLocal(Dummy * _Nonnull p) {
277 Dummy * _Nonnull nonnullLocalWithAssignment = p;
278 nonnullLocalWithAssignment = (Dummy * _Nonnull)0; // no-warning
279 (void)nonnullLocalWithAssignment;
281 // Since we've already had an invariant violation along this path,
282 // we shouldn't warn here.
283 nonnullLocalWithAssignment = 0;
284 (void)nonnullLocalWithAssignment;
287 void testDirectCastNilToNonnullAndAssignToParam(Dummy * _Nonnull p) {
288 p = (Dummy * _Nonnull)0; // no-warning
291 @interface ClassWithNonnullIvar : NSObject {
296 @implementation ClassWithNonnullIvar
297 -(void)testDirectCastNilToNonnullAndAssignToIvar {
298 _nonnullIvar = (Dummy * _Nonnull)0; // no-warning;
300 // Since we've already had an invariant violation along this path,
301 // we shouldn't warn here.
306 void testIndirectNilPassToNonnull() {
308 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
311 void testConditionalNilPassToNonnull(Dummy *p) {
313 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
317 Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
318 Dummy *p = (Dummy * _Nonnull)0;
319 // FIXME: Ideally the cast above would suppress this warning.
320 return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
323 void testInvalidPropagation() {
324 Dummy *p = returnsUnspecified();
329 void onlyReportFirstPreconditionViolationOnPath() {
330 Dummy *p = returnsNullable();
331 takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
332 takesNonnull(p); // No warning.
333 // The first warning was not a sink. The analysis expected to continue.
335 i = 5 / i; // expected-warning {{Division by zero}}
339 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
343 0; // avoid compiler warning (which is not generated by the analyzer)
345 return ret; // no warning
347 return p; // no warning
353 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
356 0; // avoid compiler warning (which is not generated by the analyzer)
358 return ret; // no warning
360 return p; // no warning
366 void testPreconditionViolationInInlinedFunction(Dummy *p) {
367 doNotWarnWhenPreconditionIsViolated(p);
370 @interface TestInlinedPreconditionViolationClass : NSObject
373 @implementation TestInlinedPreconditionViolationClass
374 -(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
376 if (!p2) // p2 binding becomes dead at this point.
377 return x; // no-warning
382 -(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
383 return [self calleeWithParam:p1];
388 int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
390 if (!p2) // p2 binding becomes dead at this point.
391 return x; // no-warning
396 int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
398 return result; // no-warning; but this is an over suppression
401 int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {
402 return InlinedReturnNullOverSuppressionCallee(p1);
405 void inlinedNullable(Dummy *_Nullable p) {
408 void inlinedNonnull(Dummy *_Nonnull p) {
411 void inlinedUnspecified(Dummy *p) {
415 void testNilReturnWithBlock(Dummy *p) {
417 Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) {
418 return p; // TODO: We should warn in blocks.
423 Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
424 switch (getRandom()) {
425 case 1: inlinedNullable(p); break;
426 case 2: inlinedNonnull(p); break;
427 case 3: inlinedUnspecified(p); break;
430 takesNonnull(p); // no-warning
433 Dummy *_Nonnull varWithInitializer = p; // no-warning
435 Dummy *_Nonnull var1WithInitializer = p, // no-warning
436 *_Nonnull var2WithInitializer = p; // no-warning
440 Dummy *_Nonnull varWithoutInitializer;
441 varWithoutInitializer = p; // no-warning
448 @interface SomeClass : NSObject {
453 @implementation SomeClass (MethodReturn)
454 - (id)initWithSomething:(int)i {
455 if (self = [super init]) {
462 - (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {
463 TestObject *local = getNullableTestObject();
464 return local; // expected-warning {{Nullable pointer is returned from a method that is expected to return a non-null value}}
467 - (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {
468 TestObject *local = getNullableTestObject();
469 return (TestObject * _Nonnull)local; // no-warning
472 - (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {
473 TestObject *local = getNullableTestObject();
474 if (!p) // Pre-condition violated here.
475 return local; // no-warning
477 return p; // no-warning
481 @interface ClassWithInitializers : NSObject
484 @implementation ClassWithInitializers
485 - (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {
486 // This defensive check is a common-enough idiom that we filter don't want
487 // to issue a diagnostic for it,
488 if (self = [super init]) {
491 return self; // no-warning
494 - (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
496 // This leaks, but we're not checking for that here.
498 ClassWithInitializers *other = nil;
499 // False negative. Once we have more subtle suppression of defensive checks in
500 // initializers we should warn here.
505 @interface SubClassWithInitializers : ClassWithInitializers
508 @implementation SubClassWithInitializers
509 // Note: Because this is overriding
510 // -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],
511 // the return type of this method becomes implicitly id _Nonnull.
512 - (id)initWithNonnullReturnAndSelfCheckingIdiom {
513 if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) {
516 return self; // no-warning
519 - (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; {
520 // Another common return-checking idiom
521 self = [super initWithNonnullReturnAndSelfCheckingIdiom];
523 return nil; // no-warning
530 @interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> {
536 @implementation ClassWithCopyWithZone
537 -(id)copyWithZone:(NSZone *)zone {
538 ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
546 -(id)mutableCopyWithZone:(NSZone *)zone {
547 ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
556 NSString * _Nullable returnsNullableString();
558 void callFunctionInSystemHeader() {
559 NSString *s = returnsNullableString();
561 NSSystemFunctionTakingNonnull(s);
563 // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
567 void callMethodInSystemHeader() {
568 NSString *s = returnsNullableString();
570 NSSystemClass *sc = [[NSSystemClass alloc] init];
573 // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
577 // Test to make sure the analyzer doesn't warn when an a nullability invariant
578 // has already been found to be violated on an instance variable.
580 @class MyInternalClass;
581 @interface MyClass : NSObject {
582 MyInternalClass * _Nonnull _internal;
586 @interface MyInternalClass : NSObject {
590 -(id _Nonnull)methodWithInternalImplementation;
593 @interface MyClass () {
594 MyInternalClass * _Nonnull _nilledOutInternal;
598 @implementation MyClass
599 -(id _Nonnull)methodWithInternalImplementation {
601 return nil; // no-warning
603 return [_internal methodWithInternalImplementation];
606 - (id _Nonnull)methodReturningIvarInImplementation; {
607 return _internal == 0 ? nil : _internal->_someIvar; // no-warning
610 -(id _Nonnull)methodWithNilledOutInternal {
611 _nilledOutInternal = (id _Nonnull)nil;
613 return nil; // no-warning