[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / nullability.mm
blobf9b3fc60c5a0269ef53408ab1f5b2501be979e3d
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;
55 @end
57 TestObject * getUnspecifiedTestObject();
58 TestObject *_Nonnull getNonnullTestObject();
59 TestObject *_Nullable getNullableTestObject();
61 int getRandom();
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()) {
83   case 0: {
84     Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}}
85   } break;
86   case 1: {
87     int b = p->val; // expected-warning {{Nullable pointer is dereferenced}}
88   } break;
89   case 2: {
90     int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}}
91   } break;
92   case 3:
93     takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
94     break;
95   case 4: {
96     Dummy d;
97     takesNullable(&d);
98     Dummy dd(d);
99     break;
100   }
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}}
103   }
104   if (p) {
105     takesNonnull(p);
106     if (getRandom()) {
107       Dummy &r = *p;
108     } else {
109       int b = p->val;
110     }
111   }
112   Dummy *q = 0;
113   if (getRandom()) {
114     takesNullable(q);
115     takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
116   }
117   Dummy a;
118   Dummy *_Nonnull nonnull = &a;
119   nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}}
120   q = &a;
121   takesNullable(q);
122   takesNonnull(q);
125 void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
126                             Dummy *_Nonnull c);
128 void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
129   Dummy *p = nullable;
130   Dummy *q = nonnull;
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;
141   }
144 Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
145   Dummy *p = 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() {
150   Dummy *p = 0;
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()) {
159   case 0:
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.
165     break;
166   case 1:
167     shouldBeNullable =
168         [eraseNullab(getNullableTestObject()) returnsUnspecified];
169     [o takesNonnull:shouldBeNullable]; // No warning expected.
170     break;
171   case 3:
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}}
174     break;
175   case 4:
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}}
178     break;
179   case 5:
180     shouldBeNullable =
181         [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
182     [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
183     break;
184   case 6:
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}}
187     break;
188   case 7: {
189     int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
190     [o takesNonnull:shouldBeNonnull];
191   } break;
192   }
195 void testObjCPropertyReadNullability() {
196   TestObject *o = getNonnullTestObject();
197   switch (getRandom()) {
198   case 0:
199     [o takesNonnull:o.propReturnsNonnull]; // no-warning
200     break;
201   case 1:
202     [o takesNonnull:o.propReturnsUnspecified]; // no-warning
203     break;
204   case 2:
205     [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
206     break;
207   case 3:
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
212     }
213     break;
214   case 4:
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}}
217     }
218     break;
219   case 5:
220     if (!o.propReturnsNullable) {
221       if (o.propReturnsNullable) {
222         // Nonnull constraint from the more recent call wins
223         [o takesNonnull:o.propReturnsNullable]; // no-warning
224       }
225     }
226     break;
227   case 6:
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}}
232     }
233     break;
234   case 7:
235     // Assertions must be effective at suppressing warnings
236     assert(o.propReturnsNullable);
237     [o takesNonnull:o.propReturnsNullable]; // no-warning
238     break;
239   }
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 {
292   Dummy *_nonnullIvar;
294 @end
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.
302   _nonnullIvar = 0;
304 @end
306 void testIndirectNilPassToNonnull() {
307   Dummy *p = 0;
308   takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
311 void testConditionalNilPassToNonnull(Dummy *p) {
312   if (!p) {
313     takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
314   }
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();
325   takesNullable(p);
326   takesNonnull(p);
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.
334   int i = 0;
335   i = 5 / i; // expected-warning {{Division by zero}}
336   (void)i;
339 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
340     Dummy *_Nonnull p) {
341   if (!p) {
342     Dummy *ret =
343         0; // avoid compiler warning (which is not generated by the analyzer)
344     if (getRandom())
345       return ret; // no warning
346     else
347       return p; // no warning
348   } else {
349     return p;
350   }
353 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
354   if (!p) {
355     Dummy *ret =
356         0; // avoid compiler warning (which is not generated by the analyzer)
357     if (getRandom())
358       return ret; // no warning
359     else
360       return p; // no warning
361   } else {
362     return p;
363   }
366 void testPreconditionViolationInInlinedFunction(Dummy *p) {
367   doNotWarnWhenPreconditionIsViolated(p);
370 @interface TestInlinedPreconditionViolationClass : NSObject
371 @end
373 @implementation TestInlinedPreconditionViolationClass
374 -(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
375   Dummy *x = 0;
376   if (!p2) // p2 binding becomes dead at this point.
377     return x; // no-warning
378   else
379    return p2;
382 -(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
383   return [self calleeWithParam:p1];
386 @end
388 int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
389   int *x = 0;
390   if (!p2) // p2 binding becomes dead at this point.
391     return x; // no-warning
392   else
393    return p2;
396 int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
397   int *result = 0;
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) {
406   if (p) return;
408 void inlinedNonnull(Dummy *_Nonnull p) {
409   if (p) return;
411 void inlinedUnspecified(Dummy *p) {
412   if (p) return;
415 void testNilReturnWithBlock(Dummy *p) {
416   p = 0;
417   Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) {
418     return p; // TODO: We should warn in blocks.
419   };
420   myblock();
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;
428   }
429   if (getRandom())
430     takesNonnull(p);  // no-warning
432   if (getRandom()) {
433     Dummy *_Nonnull varWithInitializer = p; // no-warning
435      Dummy *_Nonnull var1WithInitializer = p,  // no-warning
436            *_Nonnull var2WithInitializer = p;  // no-warning
437   }
439   if (getRandom()) {
440     Dummy *_Nonnull varWithoutInitializer;
441     varWithoutInitializer = p; // no-warning
442   }
444   return p;
448 @interface SomeClass : NSObject {
449   int instanceVar;
451 @end
453 @implementation SomeClass (MethodReturn)
454 - (id)initWithSomething:(int)i {
455   if (self = [super init]) {
456     instanceVar = i;
457   }
459   return self;
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
476   else
477     return p; // no-warning
479 @end
481 @interface ClassWithInitializers : NSObject
482 @end
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]) {
489   }
491   return self; // no-warning
494 - (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
495   self = [super init];
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.
501   return other;
503 @end
505 @interface SubClassWithInitializers : ClassWithInitializers
506 @end
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]) {
514   }
516   return self; // no-warning
519 - (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; {
520   // Another common return-checking idiom
521   self = [super initWithNonnullReturnAndSelfCheckingIdiom];
522   if (!self) {
523     return nil; // no-warning
524   }
526   return self;
528 @end
530 @interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> {
531   id i;
534 @end
536 @implementation ClassWithCopyWithZone
537 -(id)copyWithZone:(NSZone *)zone {
538   ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
539   if (!newInstance)
540     return nil;
542   newInstance->i = i;
543   return newInstance;
546 -(id)mutableCopyWithZone:(NSZone *)zone {
547   ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
548   if (newInstance) {
549     newInstance->i = i;
550   }
552   return newInstance;
554 @end
556 NSString * _Nullable returnsNullableString();
558 void callFunctionInSystemHeader() {
559   NSString *s = returnsNullableString();
561   NSSystemFunctionTakingNonnull(s);
562   #if !NOSYSTEMHEADERS
563   // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
564   #endif
567 void callMethodInSystemHeader() {
568   NSString *s = returnsNullableString();
570   NSSystemClass *sc = [[NSSystemClass alloc] init];
571   [sc takesNonnull:s];
572   #if !NOSYSTEMHEADERS
573   // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
574   #endif
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;
584 @end
586 @interface MyInternalClass : NSObject {
587   @public
588   id _someIvar;
590 -(id _Nonnull)methodWithInternalImplementation;
591 @end
593 @interface MyClass () {
594   MyInternalClass * _Nonnull _nilledOutInternal;
596 @end
598 @implementation MyClass
599 -(id _Nonnull)methodWithInternalImplementation {
600   if (!_internal)
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
615 @end