xref: /aosp_15_r20/external/clang/test/Analysis/nullability.mm (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -DNOSYSTEMHEADERS=0 -verify %s
2*67e74705SXin Li// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
3*67e74705SXin Li
4*67e74705SXin Li#include "Inputs/system-header-simulator-for-nullability.h"
5*67e74705SXin Li
6*67e74705SXin Li@interface TestObject : NSObject
7*67e74705SXin Li- (int *_Nonnull)returnsNonnull;
8*67e74705SXin Li- (int *_Nullable)returnsNullable;
9*67e74705SXin Li- (int *)returnsUnspecified;
10*67e74705SXin Li- (void)takesNonnull:(int *_Nonnull)p;
11*67e74705SXin Li- (void)takesNullable:(int *_Nullable)p;
12*67e74705SXin Li- (void)takesUnspecified:(int *)p;
13*67e74705SXin Li@property(readonly, strong) NSString *stuff;
14*67e74705SXin Li@end
15*67e74705SXin Li
16*67e74705SXin LiTestObject * getUnspecifiedTestObject();
17*67e74705SXin LiTestObject *_Nonnull getNonnullTestObject();
18*67e74705SXin LiTestObject *_Nullable getNullableTestObject();
19*67e74705SXin Li
20*67e74705SXin Liint getRandom();
21*67e74705SXin Li
22*67e74705SXin Litypedef struct Dummy { int val; } Dummy;
23*67e74705SXin Li
24*67e74705SXin Livoid takesNullable(Dummy *_Nullable);
25*67e74705SXin Livoid takesNonnull(Dummy *_Nonnull);
26*67e74705SXin Livoid takesUnspecified(Dummy *);
27*67e74705SXin Li
28*67e74705SXin LiDummy *_Nullable returnsNullable();
29*67e74705SXin LiDummy *_Nonnull returnsNonnull();
30*67e74705SXin LiDummy *returnsUnspecified();
31*67e74705SXin Liint *_Nullable returnsNullableInt();
32*67e74705SXin Li
33*67e74705SXin Litemplate <typename T> T *eraseNullab(T *p) { return p; }
34*67e74705SXin Li
35*67e74705SXin Livoid takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
36*67e74705SXin Li
37*67e74705SXin Livoid testBasicRules() {
38*67e74705SXin Li  Dummy *p = returnsNullable();
39*67e74705SXin Li  int *ptr = returnsNullableInt();
40*67e74705SXin Li  // Make every dereference a different path to avoid sinks after errors.
41*67e74705SXin Li  switch (getRandom()) {
42*67e74705SXin Li  case 0: {
43*67e74705SXin Li    Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}}
44*67e74705SXin Li  } break;
45*67e74705SXin Li  case 1: {
46*67e74705SXin Li    int b = p->val; // expected-warning {{Nullable pointer is dereferenced}}
47*67e74705SXin Li  } break;
48*67e74705SXin Li  case 2: {
49*67e74705SXin Li    int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}}
50*67e74705SXin Li  } break;
51*67e74705SXin Li  case 3:
52*67e74705SXin Li    takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
53*67e74705SXin Li    break;
54*67e74705SXin Li  case 4: {
55*67e74705SXin Li    Dummy d;
56*67e74705SXin Li    takesNullable(&d);
57*67e74705SXin Li    Dummy dd(d);
58*67e74705SXin Li    break;
59*67e74705SXin Li  }
60*67e74705SXin Li  case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
61*67e74705SXin Li  default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
62*67e74705SXin Li  }
63*67e74705SXin Li  if (p) {
64*67e74705SXin Li    takesNonnull(p);
65*67e74705SXin Li    if (getRandom()) {
66*67e74705SXin Li      Dummy &r = *p;
67*67e74705SXin Li    } else {
68*67e74705SXin Li      int b = p->val;
69*67e74705SXin Li    }
70*67e74705SXin Li  }
71*67e74705SXin Li  Dummy *q = 0;
72*67e74705SXin Li  if (getRandom()) {
73*67e74705SXin Li    takesNullable(q);
74*67e74705SXin Li    takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
75*67e74705SXin Li  }
76*67e74705SXin Li  Dummy a;
77*67e74705SXin Li  Dummy *_Nonnull nonnull = &a;
78*67e74705SXin Li  nonnull = q; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
79*67e74705SXin Li  q = &a;
80*67e74705SXin Li  takesNullable(q);
81*67e74705SXin Li  takesNonnull(q);
82*67e74705SXin Li}
83*67e74705SXin Li
84*67e74705SXin Livoid testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
85*67e74705SXin Li                            Dummy *_Nonnull c);
86*67e74705SXin Li
87*67e74705SXin Livoid testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
88*67e74705SXin Li  Dummy *p = nullable;
89*67e74705SXin Li  Dummy *q = nonnull;
90*67e74705SXin Li  switch(getRandom()) {
91*67e74705SXin Li  case 1: nonnull = p; break; // expected-warning {{Nullable pointer is assigned to a pointer which is expected to have non-null value}}
92*67e74705SXin Li  case 2: p = 0; break;
93*67e74705SXin Li  case 3: q = p; break;
94*67e74705SXin Li  case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;
95*67e74705SXin Li  case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;
96*67e74705SXin Li  case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}
97*67e74705SXin Li  case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
98*67e74705SXin Li  case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
99*67e74705SXin Li  case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
100*67e74705SXin Li  }
101*67e74705SXin Li}
102*67e74705SXin Li
103*67e74705SXin LiDummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
104*67e74705SXin Li  Dummy *p = a;
105*67e74705SXin Li  return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}
106*67e74705SXin Li}
107*67e74705SXin Li
108*67e74705SXin LiDummy *_Nonnull testNullReturn() {
109*67e74705SXin Li  Dummy *p = 0;
110*67e74705SXin Li  return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
111*67e74705SXin Li}
112*67e74705SXin Li
113*67e74705SXin Livoid testObjCMessageResultNullability() {
114*67e74705SXin Li  // The expected result: the most nullable of self and method return type.
115*67e74705SXin Li  TestObject *o = getUnspecifiedTestObject();
116*67e74705SXin Li  int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];
117*67e74705SXin Li  switch (getRandom()) {
118*67e74705SXin Li  case 0:
119*67e74705SXin Li    // The core analyzer assumes that the receiver is non-null after a message
120*67e74705SXin Li    // send. This is to avoid some false positives, and increase performance
121*67e74705SXin Li    // but it also reduces the coverage and makes this checker unable to reason
122*67e74705SXin Li    // about the nullness of the receiver.
123*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // No warning expected.
124*67e74705SXin Li    break;
125*67e74705SXin Li  case 1:
126*67e74705SXin Li    shouldBeNullable =
127*67e74705SXin Li        [eraseNullab(getNullableTestObject()) returnsUnspecified];
128*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // No warning expected.
129*67e74705SXin Li    break;
130*67e74705SXin Li  case 3:
131*67e74705SXin Li    shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
132*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
133*67e74705SXin Li    break;
134*67e74705SXin Li  case 4:
135*67e74705SXin Li    shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];
136*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
137*67e74705SXin Li    break;
138*67e74705SXin Li  case 5:
139*67e74705SXin Li    shouldBeNullable =
140*67e74705SXin Li        [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
141*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
142*67e74705SXin Li    break;
143*67e74705SXin Li  case 6:
144*67e74705SXin Li    shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
145*67e74705SXin Li    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
146*67e74705SXin Li    break;
147*67e74705SXin Li  case 7: {
148*67e74705SXin Li    int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
149*67e74705SXin Li    [o takesNonnull:shouldBeNonnull];
150*67e74705SXin Li  } break;
151*67e74705SXin Li  }
152*67e74705SXin Li}
153*67e74705SXin Li
154*67e74705SXin LiDummy * _Nonnull testDirectCastNullableToNonnull() {
155*67e74705SXin Li  Dummy *p = returnsNullable();
156*67e74705SXin Li  takesNonnull((Dummy * _Nonnull)p);  // no-warning
157*67e74705SXin Li  return (Dummy * _Nonnull)p;         // no-warning
158*67e74705SXin Li}
159*67e74705SXin Li
160*67e74705SXin LiDummy * _Nonnull testIndirectCastNullableToNonnull() {
161*67e74705SXin Li  Dummy *p = (Dummy * _Nonnull)returnsNullable();
162*67e74705SXin Li  takesNonnull(p);  // no-warning
163*67e74705SXin Li  return p;         // no-warning
164*67e74705SXin Li}
165*67e74705SXin Li
166*67e74705SXin LiDummy * _Nonnull testDirectCastNilToNonnull() {
167*67e74705SXin Li  takesNonnull((Dummy * _Nonnull)0);  // no-warning
168*67e74705SXin Li  return (Dummy * _Nonnull)0;         // no-warning
169*67e74705SXin Li}
170*67e74705SXin Li
171*67e74705SXin Livoid testIndirectCastNilToNonnullAndPass() {
172*67e74705SXin Li  Dummy *p = (Dummy * _Nonnull)0;
173*67e74705SXin Li  // FIXME: Ideally the cast above would suppress this warning.
174*67e74705SXin Li  takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
175*67e74705SXin Li}
176*67e74705SXin Li
177*67e74705SXin Livoid testDirectCastNilToNonnullAndAssignToLocalInInitializer() {
178*67e74705SXin Li  Dummy * _Nonnull nonnullLocalWithAssignmentInInitializer = (Dummy * _Nonnull)0; // no-warning
179*67e74705SXin Li  (void)nonnullLocalWithAssignmentInInitializer;
180*67e74705SXin Li
181*67e74705SXin Li  // Since we've already had an invariant violation along this path,
182*67e74705SXin Li  // we shouldn't warn here.
183*67e74705SXin Li  nonnullLocalWithAssignmentInInitializer = 0;
184*67e74705SXin Li  (void)nonnullLocalWithAssignmentInInitializer;
185*67e74705SXin Li
186*67e74705SXin Li}
187*67e74705SXin Li
188*67e74705SXin Livoid testDirectCastNilToNonnullAndAssignToLocal(Dummy * _Nonnull p) {
189*67e74705SXin Li  Dummy * _Nonnull nonnullLocalWithAssignment = p;
190*67e74705SXin Li  nonnullLocalWithAssignment = (Dummy * _Nonnull)0; // no-warning
191*67e74705SXin Li  (void)nonnullLocalWithAssignment;
192*67e74705SXin Li
193*67e74705SXin Li  // Since we've already had an invariant violation along this path,
194*67e74705SXin Li  // we shouldn't warn here.
195*67e74705SXin Li  nonnullLocalWithAssignment = 0;
196*67e74705SXin Li  (void)nonnullLocalWithAssignment;
197*67e74705SXin Li}
198*67e74705SXin Li
199*67e74705SXin Livoid testDirectCastNilToNonnullAndAssignToParam(Dummy * _Nonnull p) {
200*67e74705SXin Li  p = (Dummy * _Nonnull)0; // no-warning
201*67e74705SXin Li}
202*67e74705SXin Li
203*67e74705SXin Li@interface ClassWithNonnullIvar : NSObject {
204*67e74705SXin Li  Dummy *_nonnullIvar;
205*67e74705SXin Li}
206*67e74705SXin Li@end
207*67e74705SXin Li
208*67e74705SXin Li@implementation ClassWithNonnullIvar
209*67e74705SXin Li-(void)testDirectCastNilToNonnullAndAssignToIvar {
210*67e74705SXin Li  _nonnullIvar = (Dummy * _Nonnull)0; // no-warning;
211*67e74705SXin Li
212*67e74705SXin Li  // Since we've already had an invariant violation along this path,
213*67e74705SXin Li  // we shouldn't warn here.
214*67e74705SXin Li  _nonnullIvar = 0;
215*67e74705SXin Li}
216*67e74705SXin Li@end
217*67e74705SXin Li
218*67e74705SXin Livoid testIndirectNilPassToNonnull() {
219*67e74705SXin Li  Dummy *p = 0;
220*67e74705SXin Li  takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
221*67e74705SXin Li}
222*67e74705SXin Li
223*67e74705SXin Livoid testConditionalNilPassToNonnull(Dummy *p) {
224*67e74705SXin Li  if (!p) {
225*67e74705SXin Li    takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
226*67e74705SXin Li  }
227*67e74705SXin Li}
228*67e74705SXin Li
229*67e74705SXin LiDummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
230*67e74705SXin Li  Dummy *p = (Dummy * _Nonnull)0;
231*67e74705SXin Li  // FIXME: Ideally the cast above would suppress this warning.
232*67e74705SXin Li  return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
233*67e74705SXin Li}
234*67e74705SXin Li
235*67e74705SXin Livoid testInvalidPropagation() {
236*67e74705SXin Li  Dummy *p = returnsUnspecified();
237*67e74705SXin Li  takesNullable(p);
238*67e74705SXin Li  takesNonnull(p);
239*67e74705SXin Li}
240*67e74705SXin Li
241*67e74705SXin Livoid onlyReportFirstPreconditionViolationOnPath() {
242*67e74705SXin Li  Dummy *p = returnsNullable();
243*67e74705SXin Li  takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
244*67e74705SXin Li  takesNonnull(p); // No warning.
245*67e74705SXin Li  // The first warning was not a sink. The analysis expected to continue.
246*67e74705SXin Li  int i = 0;
247*67e74705SXin Li  i = 5 / i; // expected-warning {{Division by zero}}
248*67e74705SXin Li  (void)i;
249*67e74705SXin Li}
250*67e74705SXin Li
251*67e74705SXin LiDummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
252*67e74705SXin Li    Dummy *_Nonnull p) {
253*67e74705SXin Li  if (!p) {
254*67e74705SXin Li    Dummy *ret =
255*67e74705SXin Li        0; // avoid compiler warning (which is not generated by the analyzer)
256*67e74705SXin Li    if (getRandom())
257*67e74705SXin Li      return ret; // no warning
258*67e74705SXin Li    else
259*67e74705SXin Li      return p; // no warning
260*67e74705SXin Li  } else {
261*67e74705SXin Li    return p;
262*67e74705SXin Li  }
263*67e74705SXin Li}
264*67e74705SXin Li
265*67e74705SXin LiDummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
266*67e74705SXin Li  if (!p) {
267*67e74705SXin Li    Dummy *ret =
268*67e74705SXin Li        0; // avoid compiler warning (which is not generated by the analyzer)
269*67e74705SXin Li    if (getRandom())
270*67e74705SXin Li      return ret; // no warning
271*67e74705SXin Li    else
272*67e74705SXin Li      return p; // no warning
273*67e74705SXin Li  } else {
274*67e74705SXin Li    return p;
275*67e74705SXin Li  }
276*67e74705SXin Li}
277*67e74705SXin Li
278*67e74705SXin Livoid testPreconditionViolationInInlinedFunction(Dummy *p) {
279*67e74705SXin Li  doNotWarnWhenPreconditionIsViolated(p);
280*67e74705SXin Li}
281*67e74705SXin Li
282*67e74705SXin Li@interface TestInlinedPreconditionViolationClass : NSObject
283*67e74705SXin Li@end
284*67e74705SXin Li
285*67e74705SXin Li@implementation TestInlinedPreconditionViolationClass
286*67e74705SXin Li-(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
287*67e74705SXin Li  Dummy *x = 0;
288*67e74705SXin Li  if (!p2) // p2 binding becomes dead at this point.
289*67e74705SXin Li    return x; // no-warning
290*67e74705SXin Li  else
291*67e74705SXin Li   return p2;
292*67e74705SXin Li}
293*67e74705SXin Li
294*67e74705SXin Li-(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
295*67e74705SXin Li  return [self calleeWithParam:p1];
296*67e74705SXin Li}
297*67e74705SXin Li
298*67e74705SXin Li@end
299*67e74705SXin Li
300*67e74705SXin Liint * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
301*67e74705SXin Li  int *x = 0;
302*67e74705SXin Li  if (!p2) // p2 binding becomes dead at this point.
303*67e74705SXin Li    return x; // no-warning
304*67e74705SXin Li  else
305*67e74705SXin Li   return p2;
306*67e74705SXin Li}
307*67e74705SXin Li
308*67e74705SXin Liint * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
309*67e74705SXin Li  int *result = 0;
310*67e74705SXin Li  return result; // no-warning; but this is an over suppression
311*67e74705SXin Li}
312*67e74705SXin Li
313*67e74705SXin Liint *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {
314*67e74705SXin Li  return InlinedReturnNullOverSuppressionCallee(p1);
315*67e74705SXin Li}
316*67e74705SXin Li
317*67e74705SXin Livoid inlinedNullable(Dummy *_Nullable p) {
318*67e74705SXin Li  if (p) return;
319*67e74705SXin Li}
320*67e74705SXin Livoid inlinedNonnull(Dummy *_Nonnull p) {
321*67e74705SXin Li  if (p) return;
322*67e74705SXin Li}
323*67e74705SXin Livoid inlinedUnspecified(Dummy *p) {
324*67e74705SXin Li  if (p) return;
325*67e74705SXin Li}
326*67e74705SXin Li
327*67e74705SXin Livoid testNilReturnWithBlock(Dummy *p) {
328*67e74705SXin Li  p = 0;
329*67e74705SXin Li  Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) {
330*67e74705SXin Li    return p; // TODO: We should warn in blocks.
331*67e74705SXin Li  };
332*67e74705SXin Li  myblock();
333*67e74705SXin Li}
334*67e74705SXin Li
335*67e74705SXin LiDummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
336*67e74705SXin Li  switch (getRandom()) {
337*67e74705SXin Li  case 1: inlinedNullable(p); break;
338*67e74705SXin Li  case 2: inlinedNonnull(p); break;
339*67e74705SXin Li  case 3: inlinedUnspecified(p); break;
340*67e74705SXin Li  }
341*67e74705SXin Li  if (getRandom())
342*67e74705SXin Li    takesNonnull(p);  // no-warning
343*67e74705SXin Li
344*67e74705SXin Li  if (getRandom()) {
345*67e74705SXin Li    Dummy *_Nonnull varWithInitializer = p; // no-warning
346*67e74705SXin Li
347*67e74705SXin Li     Dummy *_Nonnull var1WithInitializer = p,  // no-warning
348*67e74705SXin Li           *_Nonnull var2WithInitializer = p;  // no-warning
349*67e74705SXin Li  }
350*67e74705SXin Li
351*67e74705SXin Li  if (getRandom()) {
352*67e74705SXin Li    Dummy *_Nonnull varWithoutInitializer;
353*67e74705SXin Li    varWithoutInitializer = p; // no-warning
354*67e74705SXin Li  }
355*67e74705SXin Li
356*67e74705SXin Li  return p;
357*67e74705SXin Li}
358*67e74705SXin Li
359*67e74705SXin Li
360*67e74705SXin Li@interface SomeClass : NSObject {
361*67e74705SXin Li  int instanceVar;
362*67e74705SXin Li}
363*67e74705SXin Li@end
364*67e74705SXin Li
365*67e74705SXin Li@implementation SomeClass (MethodReturn)
366*67e74705SXin Li- (id)initWithSomething:(int)i {
367*67e74705SXin Li  if (self = [super init]) {
368*67e74705SXin Li    instanceVar = i;
369*67e74705SXin Li  }
370*67e74705SXin Li
371*67e74705SXin Li  return self;
372*67e74705SXin Li}
373*67e74705SXin Li
374*67e74705SXin Li- (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {
375*67e74705SXin Li  TestObject *local = getNullableTestObject();
376*67e74705SXin Li  return local; // expected-warning {{Nullable pointer is returned from a method that is expected to return a non-null value}}
377*67e74705SXin Li}
378*67e74705SXin Li
379*67e74705SXin Li- (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {
380*67e74705SXin Li  TestObject *local = getNullableTestObject();
381*67e74705SXin Li  return (TestObject * _Nonnull)local; // no-warning
382*67e74705SXin Li}
383*67e74705SXin Li
384*67e74705SXin Li- (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {
385*67e74705SXin Li  TestObject *local = getNullableTestObject();
386*67e74705SXin Li  if (!p) // Pre-condition violated here.
387*67e74705SXin Li    return local; // no-warning
388*67e74705SXin Li  else
389*67e74705SXin Li    return p; // no-warning
390*67e74705SXin Li}
391*67e74705SXin Li@end
392*67e74705SXin Li
393*67e74705SXin Li@interface ClassWithInitializers : NSObject
394*67e74705SXin Li@end
395*67e74705SXin Li
396*67e74705SXin Li@implementation ClassWithInitializers
397*67e74705SXin Li- (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {
398*67e74705SXin Li  // This defensive check is a common-enough idiom that we filter don't want
399*67e74705SXin Li  // to issue a diagnostic for it,
400*67e74705SXin Li  if (self = [super init]) {
401*67e74705SXin Li  }
402*67e74705SXin Li
403*67e74705SXin Li  return self; // no-warning
404*67e74705SXin Li}
405*67e74705SXin Li
406*67e74705SXin Li- (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
407*67e74705SXin Li  self = [super init];
408*67e74705SXin Li  // This leaks, but we're not checking for that here.
409*67e74705SXin Li
410*67e74705SXin Li  ClassWithInitializers *other = nil;
411*67e74705SXin Li  // False negative. Once we have more subtle suppression of defensive checks in
412*67e74705SXin Li  // initializers we should warn here.
413*67e74705SXin Li  return other;
414*67e74705SXin Li}
415*67e74705SXin Li@end
416*67e74705SXin Li
417*67e74705SXin Li@interface SubClassWithInitializers : ClassWithInitializers
418*67e74705SXin Li@end
419*67e74705SXin Li
420*67e74705SXin Li@implementation SubClassWithInitializers
421*67e74705SXin Li// Note: Because this is overridding
422*67e74705SXin Li// -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],
423*67e74705SXin Li// the return type of this method becomes implicitly id _Nonnull.
424*67e74705SXin Li- (id)initWithNonnullReturnAndSelfCheckingIdiom {
425*67e74705SXin Li  if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) {
426*67e74705SXin Li  }
427*67e74705SXin Li
428*67e74705SXin Li  return self; // no-warning
429*67e74705SXin Li}
430*67e74705SXin Li
431*67e74705SXin Li- (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; {
432*67e74705SXin Li  // Another common return-checking idiom
433*67e74705SXin Li  self = [super initWithNonnullReturnAndSelfCheckingIdiom];
434*67e74705SXin Li  if (!self) {
435*67e74705SXin Li    return nil; // no-warning
436*67e74705SXin Li  }
437*67e74705SXin Li
438*67e74705SXin Li  return self;
439*67e74705SXin Li}
440*67e74705SXin Li@end
441*67e74705SXin Li
442*67e74705SXin Li@interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> {
443*67e74705SXin Li  id i;
444*67e74705SXin Li}
445*67e74705SXin Li
446*67e74705SXin Li@end
447*67e74705SXin Li
448*67e74705SXin Li@implementation ClassWithCopyWithZone
449*67e74705SXin Li-(id)copyWithZone:(NSZone *)zone {
450*67e74705SXin Li  ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
451*67e74705SXin Li  if (!newInstance)
452*67e74705SXin Li    return nil;
453*67e74705SXin Li
454*67e74705SXin Li  newInstance->i = i;
455*67e74705SXin Li  return newInstance;
456*67e74705SXin Li}
457*67e74705SXin Li
458*67e74705SXin Li-(id)mutableCopyWithZone:(NSZone *)zone {
459*67e74705SXin Li  ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];
460*67e74705SXin Li  if (newInstance) {
461*67e74705SXin Li    newInstance->i = i;
462*67e74705SXin Li  }
463*67e74705SXin Li
464*67e74705SXin Li  return newInstance;
465*67e74705SXin Li}
466*67e74705SXin Li@end
467*67e74705SXin Li
468*67e74705SXin LiNSString * _Nullable returnsNullableString();
469*67e74705SXin Li
470*67e74705SXin Livoid callFunctionInSystemHeader() {
471*67e74705SXin Li  NSString *s = returnsNullableString();
472*67e74705SXin Li
473*67e74705SXin Li  NSSystemFunctionTakingNonnull(s);
474*67e74705SXin Li  #if !NOSYSTEMHEADERS
475*67e74705SXin Li  // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
476*67e74705SXin Li  #endif
477*67e74705SXin Li}
478*67e74705SXin Li
479*67e74705SXin Livoid callMethodInSystemHeader() {
480*67e74705SXin Li  NSString *s = returnsNullableString();
481*67e74705SXin Li
482*67e74705SXin Li  NSSystemClass *sc = [[NSSystemClass alloc] init];
483*67e74705SXin Li  [sc takesNonnull:s];
484*67e74705SXin Li  #if !NOSYSTEMHEADERS
485*67e74705SXin Li  // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
486*67e74705SXin Li  #endif
487*67e74705SXin Li}
488*67e74705SXin Li
489*67e74705SXin Li// Test to make sure the analyzer doesn't warn when an a nullability invariant
490*67e74705SXin Li// has already been found to be violated on an instance variable.
491*67e74705SXin Li
492*67e74705SXin Li@class MyInternalClass;
493*67e74705SXin Li@interface MyClass : NSObject {
494*67e74705SXin Li  MyInternalClass * _Nonnull _internal;
495*67e74705SXin Li}
496*67e74705SXin Li@end
497*67e74705SXin Li
498*67e74705SXin Li@interface MyInternalClass : NSObject {
499*67e74705SXin Li  @public
500*67e74705SXin Li  id _someIvar;
501*67e74705SXin Li}
502*67e74705SXin Li-(id _Nonnull)methodWithInternalImplementation;
503*67e74705SXin Li@end
504*67e74705SXin Li
505*67e74705SXin Li@interface MyClass () {
506*67e74705SXin Li  MyInternalClass * _Nonnull _nilledOutInternal;
507*67e74705SXin Li}
508*67e74705SXin Li@end
509*67e74705SXin Li
510*67e74705SXin Li@implementation MyClass
511*67e74705SXin Li-(id _Nonnull)methodWithInternalImplementation {
512*67e74705SXin Li  if (!_internal)
513*67e74705SXin Li    return nil; // no-warning
514*67e74705SXin Li
515*67e74705SXin Li  return [_internal methodWithInternalImplementation];
516*67e74705SXin Li}
517*67e74705SXin Li
518*67e74705SXin Li- (id _Nonnull)methodReturningIvarInImplementation; {
519*67e74705SXin Li  return _internal == 0 ? nil : _internal->_someIvar; // no-warning
520*67e74705SXin Li}
521*67e74705SXin Li
522*67e74705SXin Li-(id _Nonnull)methodWithNilledOutInternal {
523*67e74705SXin Li  _nilledOutInternal = (id _Nonnull)nil;
524*67e74705SXin Li
525*67e74705SXin Li  return nil; // no-warning
526*67e74705SXin Li}
527*67e74705SXin Li@end
528