Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / nullability.mm
blobd69116d03df74653366e803512adfc10e0099d23
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)takesNonnullBlock:(void (^ _Nonnull)(void))block;
50 - (void)takesNullable:(int *_Nullable)p;
51 - (void)takesUnspecified:(int *)p;
52 @property(readonly, strong) NSString *stuff;
53 @property(readonly, nonnull) int *propReturnsNonnull;
54 @property(readonly, nonnull) void (^propReturnsNonnullBlock)(void);
55 @property(readonly, nullable) void (^propReturnsNullableBlock)(void);
56 @property(readonly, nullable) int *propReturnsNullable;
57 @property(readonly) int *propReturnsUnspecified;
58 + (nullable TestObject *)getNullableObject;
59 @end
61 TestObject * getUnspecifiedTestObject();
62 TestObject *_Nonnull getNonnullTestObject();
63 TestObject *_Nullable getNullableTestObject();
65 int getRandom();
67 typedef struct Dummy { int val; } Dummy;
69 void takesNullable(Dummy *_Nullable);
70 void takesNonnull(Dummy *_Nonnull);
71 void takesUnspecified(Dummy *);
72 void takesNonnullBlock(void (^ _Nonnull)(void));
73 void takesNonnullObject(NSObject *_Nonnull);
75 Dummy *_Nullable returnsNullable();
76 Dummy *_Nonnull returnsNonnull();
77 Dummy *returnsUnspecified();
78 int *_Nullable returnsNullableInt();
80 template <typename T> T *eraseNullab(T *p) { return p; }
82 void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
84 void testBasicRules() {
85   Dummy *p = returnsNullable();
86   int *ptr = returnsNullableInt();
87   // Make every dereference a different path to avoid sinks after errors.
88   switch (getRandom()) {
89   case 0: {
90     Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}}
91   } break;
92   case 1: {
93     int b = p->val; // expected-warning {{Nullable pointer is dereferenced}}
94   } break;
95   case 2: {
96     int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}}
97   } break;
98   case 3:
99     takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
100     break;
101   case 4: {
102     Dummy d;
103     takesNullable(&d);
104     Dummy dd(d);
105     break;
106   }
107   case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
108   default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
109   }
110   if (p) {
111     takesNonnull(p);
112     if (getRandom()) {
113       Dummy &r = *p;
114     } else {
115       int b = p->val;
116     }
117   }
118   Dummy *q = 0;
119   if (getRandom()) {
120     takesNullable(q);
121     takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
122   }
123   Dummy a;
124   Dummy *_Nonnull nonnull = &a;
125   nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}}
126   q = &a;
127   takesNullable(q);
128   takesNonnull(q);
131 void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
132                             Dummy *_Nonnull c);
134 void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
135   Dummy *p = nullable;
136   Dummy *q = nonnull;
137   switch(getRandom()) {
138   case 1: nonnull = p; break; // expected-warning {{Nullable pointer is assigned to a pointer which is expected to have non-null value}}
139   case 2: p = 0; break;
140   case 3: q = p; break;
141   case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;
142   case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;
143   case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}
144   case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
145   case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
146   case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
147   }
150 void testArgumentTrackingDirectly(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
151   switch(getRandom()) {
152   case 1: testMultiParamChecking(nonnull, nullable, nonnull); break;
153   case 2: testMultiParamChecking(nonnull, nonnull, nonnull); break;
154   case 3: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}
155   case 4: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
156   case 5: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
157   case 6: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
158   }
161 Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
162   Dummy *p = a;
163   return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}
166 Dummy *_Nonnull testNullReturn() {
167   Dummy *p = 0;
168   return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
171 void testObjCMessageResultNullability() {
172   // The expected result: the most nullable of self and method return type.
173   TestObject *o = getUnspecifiedTestObject();
174   int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];
175   switch (getRandom()) {
176   case 0:
177     // The core analyzer assumes that the receiver is non-null after a message
178     // send. This is to avoid some false positives, and increase performance
179     // but it also reduces the coverage and makes this checker unable to reason
180     // about the nullness of the receiver. 
181     [o takesNonnull:shouldBeNullable]; // No warning expected.
182     break;
183   case 1:
184     shouldBeNullable =
185         [eraseNullab(getNullableTestObject()) returnsUnspecified];
186     [o takesNonnull:shouldBeNullable]; // No warning expected.
187     break;
188   case 3:
189     shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
190     [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
191     break;
192   case 4:
193     shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];
194     [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
195     break;
196   case 5:
197     shouldBeNullable =
198         [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
199     [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
200     break;
201   case 6:
202     shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
203     [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
204     break;
205   case 7: {
206     int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
207     [o takesNonnull:shouldBeNonnull];
208   } break;
209   }
212 void testObjCPropertyReadNullability() {
213   TestObject *o = getNonnullTestObject();
214   switch (getRandom()) {
215   case 0:
216     [o takesNonnull:o.propReturnsNonnull]; // no-warning
217     [o takesNonnullBlock:o.propReturnsNonnullBlock]; // no-warning
218     break;
219   case 1:
220     [o takesNonnull:o.propReturnsUnspecified]; // no-warning
221     break;
222   case 2:
223     [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
224     break;
225   case 3:
226     // If a property is constrained nonnull, assume it remains nonnull
227     if (o.propReturnsNullable) {
228       [o takesNonnull:o.propReturnsNullable]; // no-warning
229       [o takesNonnull:o.propReturnsNullable]; // no-warning
230     }
231     break;
232   case 4:
233     if (!o.propReturnsNullable) {
234       [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
235     }
236     break;
237   case 5:
238     if (!o.propReturnsNullable) {
239       if (o.propReturnsNullable) {
240         // Nonnull constraint from the more recent call wins
241         [o takesNonnull:o.propReturnsNullable]; // no-warning
242       }
243     }
244     break;
245   case 6:
246     // Constraints on property return values are receiver-qualified
247     if (o.propReturnsNullable) {
248       [o takesNonnull:o.propReturnsNullable];                      // no-warning
249       [o takesNonnull:getNonnullTestObject().propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
250     }
251     break;
252   case 7:
253     // Assertions must be effective at suppressing warnings
254     assert(o.propReturnsNullable);
255     [o takesNonnull:o.propReturnsNullable]; // no-warning
256     break;
257   case 8:
258     [o takesNonnullBlock:o.propReturnsNullableBlock]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
259     break;
260   case 9:
261     [o takesNonnull:getNullableTestObject().propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
262     break;
263   case 10:
264     [o takesNonnull:[TestObject getNullableObject].propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
265     break;
266   }
269 Dummy * _Nonnull testDirectCastNullableToNonnull() {
270   Dummy *p = returnsNullable();
271   takesNonnull((Dummy * _Nonnull)p);  // no-warning
272   return (Dummy * _Nonnull)p;         // no-warning
275 Dummy * _Nonnull testIndirectCastNullableToNonnull() {
276   Dummy *p = (Dummy * _Nonnull)returnsNullable();
277   takesNonnull(p);  // no-warning
278   return p;         // no-warning
281 Dummy * _Nonnull testDirectCastNilToNonnull() {
282   takesNonnull((Dummy * _Nonnull)0);  // no-warning
283   return (Dummy * _Nonnull)0;         // no-warning
286 void testImplicitCastNilToNonnull() {
287   id obj = nil;
288   takesNonnullObject(obj); // expected-warning {{nil passed to a callee that requires a non-null 1st parameter}}
291 void testImplicitCastNullableArgToNonnull(TestObject *_Nullable obj) {
292   if (!obj) {
293     takesNonnullObject(obj); // expected-warning {{nil passed to a callee that requires a non-null 1st parameter}}
294   }
297 void testIndirectCastNilToNonnullAndPass() {
298   Dummy *p = (Dummy * _Nonnull)0;
299   // FIXME: Ideally the cast above would suppress this warning.
300   takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
303 void testDirectCastNilToNonnullAndAssignToLocalInInitializer() {
304   Dummy * _Nonnull nonnullLocalWithAssignmentInInitializer = (Dummy * _Nonnull)0; // no-warning
305   (void)nonnullLocalWithAssignmentInInitializer;
307   // Since we've already had an invariant violation along this path,
308   // we shouldn't warn here.
309   nonnullLocalWithAssignmentInInitializer = 0;
310   (void)nonnullLocalWithAssignmentInInitializer;
314 void testDirectCastNilToNonnullAndAssignToLocal(Dummy * _Nonnull p) {
315   Dummy * _Nonnull nonnullLocalWithAssignment = p;
316   nonnullLocalWithAssignment = (Dummy * _Nonnull)0; // no-warning
317   (void)nonnullLocalWithAssignment;
319   // Since we've already had an invariant violation along this path,
320   // we shouldn't warn here.
321   nonnullLocalWithAssignment = 0;
322   (void)nonnullLocalWithAssignment;
325 void testDirectCastNilToNonnullAndAssignToParam(Dummy * _Nonnull p) {
326   p = (Dummy * _Nonnull)0; // no-warning
329 @interface ClassWithNonnullIvar : NSObject {
330   Dummy *_nonnullIvar;
332 @end
334 @implementation ClassWithNonnullIvar
335 -(void)testDirectCastNilToNonnullAndAssignToIvar {
336   _nonnullIvar = (Dummy * _Nonnull)0; // no-warning;
338   // Since we've already had an invariant violation along this path,
339   // we shouldn't warn here.
340   _nonnullIvar = 0;
342 @end
344 void testIndirectNilPassToNonnull() {
345   Dummy *p = 0;
346   takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
349 void testBlockIndirectNilPassToNonnull() {
350   void (^p)(void) = nil;
351   takesNonnullBlock(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
354 void testConditionalNilPassToNonnull(Dummy *p) {
355   if (!p) {
356     takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
357   }
360 Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
361   Dummy *p = (Dummy * _Nonnull)0;
362   // FIXME: Ideally the cast above would suppress this warning.
363   return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
366 void testInvalidPropagation() {
367   Dummy *p = returnsUnspecified();
368   takesNullable(p);
369   takesNonnull(p);
372 void onlyReportFirstPreconditionViolationOnPath() {
373   Dummy *p = returnsNullable();
374   takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
375   takesNonnull(p); // No warning.
376   // The first warning was not a sink. The analysis expected to continue.
377   int i = 0;
378   i = 5 / i; // expected-warning {{Division by zero}}
379   (void)i;
382 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
383     Dummy *_Nonnull p) {
384   if (!p) {
385     Dummy *ret =
386         0; // avoid compiler warning (which is not generated by the analyzer)
387     if (getRandom())
388       return ret; // no warning
389     else
390       return p; // no warning
391   } else {
392     return p;
393   }
396 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
397   if (!p) {
398     Dummy *ret =
399         0; // avoid compiler warning (which is not generated by the analyzer)
400     if (getRandom())
401       return ret; // no warning
402     else
403       return p; // no warning
404   } else {
405     return p;
406   }
409 void testPreconditionViolationInInlinedFunction(Dummy *p) {
410   doNotWarnWhenPreconditionIsViolated(p);
413 @interface TestInlinedPreconditionViolationClass : NSObject
414 @end
416 @implementation TestInlinedPreconditionViolationClass
417 -(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
418   Dummy *x = 0;
419   if (!p2) // p2 binding becomes dead at this point.
420     return x; // no-warning
421   else
422    return p2;
425 -(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
426   return [self calleeWithParam:p1];
429 @end
431 int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
432   int *x = 0;
433   if (!p2) // p2 binding becomes dead at this point.
434     return x; // no-warning
435   else
436    return p2;
439 int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
440   int *result = 0;
441   return result; // no-warning; but this is an over suppression
444 int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {
445   return InlinedReturnNullOverSuppressionCallee(p1);
448 void inlinedNullable(Dummy *_Nullable p) {
449   if (p) return;
451 void inlinedNonnull(Dummy *_Nonnull p) {
452   if (p) return;
454 void inlinedUnspecified(Dummy *p) {
455   if (p) return;
458 void testNilReturnWithBlock(Dummy *p) {
459   p = 0;
460   Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) {
461     return p; // TODO: We should warn in blocks.
462   };
463   myblock();
466 Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
467   switch (getRandom()) {
468   case 1: inlinedNullable(p); break;
469   case 2: inlinedNonnull(p); break;
470   case 3: inlinedUnspecified(p); break;
471   }
472   if (getRandom())
473     takesNonnull(p);  // no-warning
475   if (getRandom()) {
476     Dummy *_Nonnull varWithInitializer = p; // no-warning
478      Dummy *_Nonnull var1WithInitializer = p,  // no-warning
479            *_Nonnull var2WithInitializer = p;  // no-warning
480   }
482   if (getRandom()) {
483     Dummy *_Nonnull varWithoutInitializer;
484     varWithoutInitializer = p; // no-warning
485   }
487   return p;
491 @interface SomeClass : NSObject {
492   int instanceVar;
494 @end
496 @implementation SomeClass (MethodReturn)
497 - (id)initWithSomething:(int)i {
498   if (self = [super init]) {
499     instanceVar = i;
500   }
502   return self;
505 - (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {
506   TestObject *local = getNullableTestObject();
507   return local; // expected-warning {{Nullable pointer is returned from a method that is expected to return a non-null value}}
510 - (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {
511   TestObject *local = getNullableTestObject();
512   return (TestObject * _Nonnull)local; // no-warning
515 - (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {
516   TestObject *local = getNullableTestObject();
517   if (!p) // Pre-condition violated here.
518     return local; // no-warning
519   else
520     return p; // no-warning
522 @end
524 @interface ClassWithInitializers : NSObject
525 @end
527 @implementation ClassWithInitializers
528 - (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {
529   // This defensive check is a common-enough idiom that we filter don't want
530   // to issue a diagnostic for it,
531   if (self = [super init]) {
532   }
534   return self; // no-warning
537 - (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
538   self = [super init];
539   // This leaks, but we're not checking for that here.
541   ClassWithInitializers *other = nil;
542   // False negative. Once we have more subtle suppression of defensive checks in
543   // initializers we should warn here.
544   return other;
546 @end
548 @interface SubClassWithInitializers : ClassWithInitializers
549 @end
551 @implementation SubClassWithInitializers
552 // Note: Because this is overriding
553 // -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],
554 // the return type of this method becomes implicitly id _Nonnull.
555 - (id)initWithNonnullReturnAndSelfCheckingIdiom {
556   if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) {
557   }
559   return self; // no-warning
562 - (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; {
563   // Another common return-checking idiom
564   self = [super initWithNonnullReturnAndSelfCheckingIdiom];
565   if (!self) {
566     return nil; // no-warning
567   }
569   return self;
571 @end
573 @interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> {
574   id i;
577 @end
579 @implementation ClassWithCopyWithZone
580 -(id)copyWithZone:(NSZone *)zone {
581   ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
582   if (!newInstance)
583     return nil;
585   newInstance->i = i;
586   return newInstance;
589 -(id)mutableCopyWithZone:(NSZone *)zone {
590   ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
591   if (newInstance) {
592     newInstance->i = i;
593   }
595   return newInstance;
597 @end
599 NSString * _Nullable returnsNullableString();
601 void callFunctionInSystemHeader() {
602   NSString *s = returnsNullableString();
604   NSSystemFunctionTakingNonnull(s);
605   #if !NOSYSTEMHEADERS
606   // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
607   #endif
610 void callMethodInSystemHeader() {
611   NSString *s = returnsNullableString();
613   NSSystemClass *sc = [[NSSystemClass alloc] init];
614   [sc takesNonnull:s];
615   #if !NOSYSTEMHEADERS
616   // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
617   #endif
620 // Test to make sure the analyzer doesn't warn when an a nullability invariant
621 // has already been found to be violated on an instance variable.
623 @class MyInternalClass;
624 @interface MyClass : NSObject {
625   MyInternalClass * _Nonnull _internal;
627 @end
629 @interface MyInternalClass : NSObject {
630   @public
631   id _someIvar;
633 -(id _Nonnull)methodWithInternalImplementation;
634 @end
636 @interface MyClass () {
637   MyInternalClass * _Nonnull _nilledOutInternal;
639 @end
641 @implementation MyClass
642 -(id _Nonnull)methodWithInternalImplementation {
643   if (!_internal)
644     return nil; // no-warning
646   return [_internal methodWithInternalImplementation];
649 - (id _Nonnull)methodReturningIvarInImplementation; {
650   return _internal == 0 ? nil : _internal->_someIvar; // no-warning
653 -(id _Nonnull)methodWithNilledOutInternal {
654   _nilledOutInternal = (id _Nonnull)nil;
656   return nil; // no-warning
658 @end