blob: b119e63ffe2b33feb35ed65ad3be848d3f30ed37 [file] [log] [blame]
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +00001// RUN: %clang_cc1 -fobjc-arc -analyze -analyzer-checker=core,nullability -verify %s
Devin Coughlin4a330202016-01-22 01:01:11 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,nullability -verify %s
Gabor Horvath28690922015-08-26 23:17:43 +00003
4#define nil 0
5#define BOOL int
6
7@protocol NSObject
8+ (id)alloc;
9- (id)init;
10@end
11
12@protocol NSCopying
13@end
14
15__attribute__((objc_root_class))
16@interface
17NSObject<NSObject>
18@end
19
20@interface NSString : NSObject<NSCopying>
21- (BOOL)isEqualToString : (NSString *_Nonnull)aString;
22- (NSString *)stringByAppendingString:(NSString *_Nonnull)aString;
23@end
24
25@interface TestObject : NSObject
26- (int *_Nonnull)returnsNonnull;
27- (int *_Nullable)returnsNullable;
28- (int *)returnsUnspecified;
29- (void)takesNonnull:(int *_Nonnull)p;
30- (void)takesNullable:(int *_Nullable)p;
31- (void)takesUnspecified:(int *)p;
32@property(readonly, strong) NSString *stuff;
33@end
34
35TestObject * getUnspecifiedTestObject();
36TestObject *_Nonnull getNonnullTestObject();
37TestObject *_Nullable getNullableTestObject();
38
39int getRandom();
40
41typedef struct Dummy { int val; } Dummy;
42
43void takesNullable(Dummy *_Nullable);
44void takesNonnull(Dummy *_Nonnull);
45void takesUnspecified(Dummy *);
46
47Dummy *_Nullable returnsNullable();
48Dummy *_Nonnull returnsNonnull();
49Dummy *returnsUnspecified();
50int *_Nullable returnsNullableInt();
51
52template <typename T> T *eraseNullab(T *p) { return p; }
53
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +000054void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
55
Gabor Horvath28690922015-08-26 23:17:43 +000056void testBasicRules() {
57 Dummy *p = returnsNullable();
58 int *ptr = returnsNullableInt();
59 // Make every dereference a different path to avoid sinks after errors.
60 switch (getRandom()) {
61 case 0: {
62 Dummy &r = *p; // expected-warning {{}}
63 } break;
64 case 1: {
65 int b = p->val; // expected-warning {{}}
66 } break;
67 case 2: {
68 int stuff = *ptr; // expected-warning {{}}
69 } break;
70 case 3:
71 takesNonnull(p); // expected-warning {{}}
72 break;
73 case 4: {
74 Dummy d;
75 takesNullable(&d);
76 Dummy dd(d);
77 break;
78 }
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +000079 case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
80 default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
Gabor Horvath28690922015-08-26 23:17:43 +000081 }
82 if (p) {
83 takesNonnull(p);
84 if (getRandom()) {
85 Dummy &r = *p;
86 } else {
87 int b = p->val;
88 }
89 }
90 Dummy *q = 0;
91 if (getRandom()) {
92 takesNullable(q);
93 takesNonnull(q); // expected-warning {{}}
94 }
95 Dummy a;
96 Dummy *_Nonnull nonnull = &a;
97 nonnull = q; // expected-warning {{}}
98 q = &a;
99 takesNullable(q);
100 takesNonnull(q);
101}
102
103void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
104 Dummy *_Nonnull c);
105
106void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
107 Dummy *p = nullable;
108 Dummy *q = nonnull;
109 switch(getRandom()) {
110 case 1: nonnull = p; break; // expected-warning {{}}
111 case 2: p = 0; break;
112 case 3: q = p; break;
113 case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;
114 case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;
115 case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{}}
116 case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{}}
117 case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{}}
118 case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
119 }
120}
121
122Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
123 Dummy *p = a;
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000124 return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}
Gabor Horvath28690922015-08-26 23:17:43 +0000125}
126
127Dummy *_Nonnull testNullReturn() {
128 Dummy *p = 0;
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000129 return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
Gabor Horvath28690922015-08-26 23:17:43 +0000130}
131
132void testObjCMessageResultNullability() {
133 // The expected result: the most nullable of self and method return type.
134 TestObject *o = getUnspecifiedTestObject();
135 int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];
136 switch (getRandom()) {
137 case 0:
138 // The core analyzer assumes that the receiver is non-null after a message
139 // send. This is to avoid some false positives, and increase performance
140 // but it also reduces the coverage and makes this checker unable to reason
141 // about the nullness of the receiver.
142 [o takesNonnull:shouldBeNullable]; // No warning expected.
143 break;
144 case 1:
145 shouldBeNullable =
146 [eraseNullab(getNullableTestObject()) returnsUnspecified];
147 [o takesNonnull:shouldBeNullable]; // No warning expected.
148 break;
149 case 3:
150 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
151 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
152 break;
153 case 4:
154 shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];
155 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
156 break;
157 case 5:
158 shouldBeNullable =
159 [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
160 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
161 break;
162 case 6:
163 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
164 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
165 break;
166 case 7: {
167 int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
168 [o takesNonnull:shouldBeNonnull];
169 } break;
170 }
171}
172
Devin Coughlin755baa42015-12-29 17:40:49 +0000173Dummy * _Nonnull testDirectCastNullableToNonnull() {
174 Dummy *p = returnsNullable();
175 takesNonnull((Dummy * _Nonnull)p); // no-warning
176 return (Dummy * _Nonnull)p; // no-warning
177}
178
179Dummy * _Nonnull testIndirectCastNullableToNonnull() {
Gabor Horvath28690922015-08-26 23:17:43 +0000180 Dummy *p = (Dummy * _Nonnull)returnsNullable();
Devin Coughlin755baa42015-12-29 17:40:49 +0000181 takesNonnull(p); // no-warning
182 return p; // no-warning
183}
184
185Dummy * _Nonnull testDirectCastNilToNonnull() {
186 takesNonnull((Dummy * _Nonnull)0); // no-warning
187 return (Dummy * _Nonnull)0; // no-warning
188}
189
190void testIndirectCastNilToNonnullAndPass() {
191 Dummy *p = (Dummy * _Nonnull)0;
192 // FIXME: Ideally the cast above would suppress this warning.
193 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null argument}}
194}
195
196Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
197 Dummy *p = (Dummy * _Nonnull)0;
198 // FIXME: Ideally the cast above would suppress this warning.
199 return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
Gabor Horvath28690922015-08-26 23:17:43 +0000200}
201
202void testInvalidPropagation() {
203 Dummy *p = returnsUnspecified();
204 takesNullable(p);
205 takesNonnull(p);
206}
Gabor Horvathb47128a2015-09-03 23:16:21 +0000207
208void onlyReportFirstPreconditionViolationOnPath() {
209 Dummy *p = returnsNullable();
210 takesNonnull(p); // expected-warning {{}}
211 takesNonnull(p); // No warning.
212 // The first warning was not a sink. The analysis expected to continue.
213 int i = 0;
214 i = 5 / i; // expected-warning {{Division by zero}}
215 (void)i;
216}
217
218Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
219 Dummy *_Nonnull p) {
220 if (!p) {
221 Dummy *ret =
222 0; // avoid compiler warning (which is not generated by the analyzer)
223 if (getRandom())
224 return ret; // no warning
225 else
226 return p; // no warning
227 } else {
228 return p;
229 }
230}
231
232Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
233 if (!p) {
234 Dummy *ret =
235 0; // avoid compiler warning (which is not generated by the analyzer)
236 if (getRandom())
237 return ret; // no warning
238 else
239 return p; // no warning
240 } else {
241 return p;
242 }
243}
244
245void testPreconditionViolationInInlinedFunction(Dummy *p) {
246 doNotWarnWhenPreconditionIsViolated(p);
247}
248
249void inlinedNullable(Dummy *_Nullable p) {
250 if (p) return;
251}
252void inlinedNonnull(Dummy *_Nonnull p) {
253 if (p) return;
254}
255void inlinedUnspecified(Dummy *p) {
256 if (p) return;
257}
258
259Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
260 switch (getRandom()) {
261 case 1: inlinedNullable(p); break;
262 case 2: inlinedNonnull(p); break;
263 case 3: inlinedUnspecified(p); break;
264 }
265 if (getRandom())
Devin Coughlinc1986632015-11-24 19:15:11 +0000266 takesNonnull(p); // no-warning
267
268 if (getRandom()) {
269 Dummy *_Nonnull varWithInitializer = p; // no-warning
270
271 Dummy *_Nonnull var1WithInitializer = p, // no-warning
272 *_Nonnull var2WithInitializer = p; // no-warning
273 }
274
275 if (getRandom()) {
276 Dummy *_Nonnull varWithoutInitializer;
277 varWithoutInitializer = p; // no-warning
278 }
279
Gabor Horvathb47128a2015-09-03 23:16:21 +0000280 return p;
281}
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000282
Devin Coughlin4a330202016-01-22 01:01:11 +0000283
284@interface SomeClass : NSObject {
285 int instanceVar;
286}
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000287@end
288
289@implementation SomeClass (MethodReturn)
Devin Coughlin4a330202016-01-22 01:01:11 +0000290- (id)initWithSomething:(int)i {
291 if (self = [super init]) {
292 instanceVar = i;
293 }
294
295 return self;
296}
297
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000298- (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {
299 TestObject *local = getNullableTestObject();
300 return local; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000301}
302
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000303- (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {
304 TestObject *local = getNullableTestObject();
305 return (TestObject * _Nonnull)local; // no-warning
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000306}
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000307
308- (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {
309 TestObject *local = getNullableTestObject();
310 if (!p) // Pre-condition violated here.
311 return local; // no-warning
312 else
313 return p; // no-warning
314}
315@end
Devin Coughlin4a330202016-01-22 01:01:11 +0000316
317@interface ClassWithInitializers : NSObject
318@end
319
320@implementation ClassWithInitializers
321- (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {
322 // This defensive check is a common-enough idiom that we filter don't want
323 // to issue a diagnostic for it,
324 if (self = [super init]) {
325 }
326
327 return self; // no-warning
328}
329
330- (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
331 self = [super init];
332 // This leaks, but we're not checking for that here.
333
334 ClassWithInitializers *other = nil;
335 // Still warn when when not returning via self.
336 return other; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
337}
338@end
339
340@interface SubClassWithInitializers : ClassWithInitializers
341@end
342
343@implementation SubClassWithInitializers
344// Note: Because this is overridding
345// -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],
346// the return type of this method becomes implicitly id _Nonnull.
347- (id)initWithNonnullReturnAndSelfCheckingIdiom {
348 if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) {
349 }
350
351 return self; // no-warning
352}
353@end