blob: aa909fbb8c420071767e8d275fd446b1772aa68a [file] [log] [blame]
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +00001// RUN: %clang_cc1 -fobjc-arc -analyze -analyzer-checker=core,nullability -verify %s
Gabor Horvath28690922015-08-26 23:17:43 +00002
3#define nil 0
4#define BOOL int
5
6@protocol NSObject
7+ (id)alloc;
8- (id)init;
9@end
10
11@protocol NSCopying
12@end
13
14__attribute__((objc_root_class))
15@interface
16NSObject<NSObject>
17@end
18
19@interface NSString : NSObject<NSCopying>
20- (BOOL)isEqualToString : (NSString *_Nonnull)aString;
21- (NSString *)stringByAppendingString:(NSString *_Nonnull)aString;
22@end
23
24@interface TestObject : NSObject
25- (int *_Nonnull)returnsNonnull;
26- (int *_Nullable)returnsNullable;
27- (int *)returnsUnspecified;
28- (void)takesNonnull:(int *_Nonnull)p;
29- (void)takesNullable:(int *_Nullable)p;
30- (void)takesUnspecified:(int *)p;
31@property(readonly, strong) NSString *stuff;
32@end
33
34TestObject * getUnspecifiedTestObject();
35TestObject *_Nonnull getNonnullTestObject();
36TestObject *_Nullable getNullableTestObject();
37
38int getRandom();
39
40typedef struct Dummy { int val; } Dummy;
41
42void takesNullable(Dummy *_Nullable);
43void takesNonnull(Dummy *_Nonnull);
44void takesUnspecified(Dummy *);
45
46Dummy *_Nullable returnsNullable();
47Dummy *_Nonnull returnsNonnull();
48Dummy *returnsUnspecified();
49int *_Nullable returnsNullableInt();
50
51template <typename T> T *eraseNullab(T *p) { return p; }
52
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +000053void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
54
Gabor Horvath28690922015-08-26 23:17:43 +000055void testBasicRules() {
56 Dummy *p = returnsNullable();
57 int *ptr = returnsNullableInt();
58 // Make every dereference a different path to avoid sinks after errors.
59 switch (getRandom()) {
60 case 0: {
61 Dummy &r = *p; // expected-warning {{}}
62 } break;
63 case 1: {
64 int b = p->val; // expected-warning {{}}
65 } break;
66 case 2: {
67 int stuff = *ptr; // expected-warning {{}}
68 } break;
69 case 3:
70 takesNonnull(p); // expected-warning {{}}
71 break;
72 case 4: {
73 Dummy d;
74 takesNullable(&d);
75 Dummy dd(d);
76 break;
77 }
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +000078 case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
79 default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
Gabor Horvath28690922015-08-26 23:17:43 +000080 }
81 if (p) {
82 takesNonnull(p);
83 if (getRandom()) {
84 Dummy &r = *p;
85 } else {
86 int b = p->val;
87 }
88 }
89 Dummy *q = 0;
90 if (getRandom()) {
91 takesNullable(q);
92 takesNonnull(q); // expected-warning {{}}
93 }
94 Dummy a;
95 Dummy *_Nonnull nonnull = &a;
96 nonnull = q; // expected-warning {{}}
97 q = &a;
98 takesNullable(q);
99 takesNonnull(q);
100}
101
102void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,
103 Dummy *_Nonnull c);
104
105void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {
106 Dummy *p = nullable;
107 Dummy *q = nonnull;
108 switch(getRandom()) {
109 case 1: nonnull = p; break; // expected-warning {{}}
110 case 2: p = 0; break;
111 case 3: q = p; break;
112 case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;
113 case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;
114 case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{}}
115 case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{}}
116 case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{}}
117 case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;
118 }
119}
120
121Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
122 Dummy *p = a;
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000123 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 +0000124}
125
126Dummy *_Nonnull testNullReturn() {
127 Dummy *p = 0;
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000128 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 +0000129}
130
131void testObjCMessageResultNullability() {
132 // The expected result: the most nullable of self and method return type.
133 TestObject *o = getUnspecifiedTestObject();
134 int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];
135 switch (getRandom()) {
136 case 0:
137 // The core analyzer assumes that the receiver is non-null after a message
138 // send. This is to avoid some false positives, and increase performance
139 // but it also reduces the coverage and makes this checker unable to reason
140 // about the nullness of the receiver.
141 [o takesNonnull:shouldBeNullable]; // No warning expected.
142 break;
143 case 1:
144 shouldBeNullable =
145 [eraseNullab(getNullableTestObject()) returnsUnspecified];
146 [o takesNonnull:shouldBeNullable]; // No warning expected.
147 break;
148 case 3:
149 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
150 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
151 break;
152 case 4:
153 shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];
154 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
155 break;
156 case 5:
157 shouldBeNullable =
158 [eraseNullab(getUnspecifiedTestObject()) returnsNullable];
159 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
160 break;
161 case 6:
162 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];
163 [o takesNonnull:shouldBeNullable]; // expected-warning {{}}
164 break;
165 case 7: {
166 int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];
167 [o takesNonnull:shouldBeNonnull];
168 } break;
169 }
170}
171
Devin Coughlin755baa42015-12-29 17:40:49 +0000172Dummy * _Nonnull testDirectCastNullableToNonnull() {
173 Dummy *p = returnsNullable();
174 takesNonnull((Dummy * _Nonnull)p); // no-warning
175 return (Dummy * _Nonnull)p; // no-warning
176}
177
178Dummy * _Nonnull testIndirectCastNullableToNonnull() {
Gabor Horvath28690922015-08-26 23:17:43 +0000179 Dummy *p = (Dummy * _Nonnull)returnsNullable();
Devin Coughlin755baa42015-12-29 17:40:49 +0000180 takesNonnull(p); // no-warning
181 return p; // no-warning
182}
183
184Dummy * _Nonnull testDirectCastNilToNonnull() {
185 takesNonnull((Dummy * _Nonnull)0); // no-warning
186 return (Dummy * _Nonnull)0; // no-warning
187}
188
189void testIndirectCastNilToNonnullAndPass() {
190 Dummy *p = (Dummy * _Nonnull)0;
191 // FIXME: Ideally the cast above would suppress this warning.
192 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null argument}}
193}
194
195Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
196 Dummy *p = (Dummy * _Nonnull)0;
197 // FIXME: Ideally the cast above would suppress this warning.
198 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 +0000199}
200
201void testInvalidPropagation() {
202 Dummy *p = returnsUnspecified();
203 takesNullable(p);
204 takesNonnull(p);
205}
Gabor Horvathb47128a2015-09-03 23:16:21 +0000206
207void onlyReportFirstPreconditionViolationOnPath() {
208 Dummy *p = returnsNullable();
209 takesNonnull(p); // expected-warning {{}}
210 takesNonnull(p); // No warning.
211 // The first warning was not a sink. The analysis expected to continue.
212 int i = 0;
213 i = 5 / i; // expected-warning {{Division by zero}}
214 (void)i;
215}
216
217Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
218 Dummy *_Nonnull p) {
219 if (!p) {
220 Dummy *ret =
221 0; // avoid compiler warning (which is not generated by the analyzer)
222 if (getRandom())
223 return ret; // no warning
224 else
225 return p; // no warning
226 } else {
227 return p;
228 }
229}
230
231Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
232 if (!p) {
233 Dummy *ret =
234 0; // avoid compiler warning (which is not generated by the analyzer)
235 if (getRandom())
236 return ret; // no warning
237 else
238 return p; // no warning
239 } else {
240 return p;
241 }
242}
243
244void testPreconditionViolationInInlinedFunction(Dummy *p) {
245 doNotWarnWhenPreconditionIsViolated(p);
246}
247
248void inlinedNullable(Dummy *_Nullable p) {
249 if (p) return;
250}
251void inlinedNonnull(Dummy *_Nonnull p) {
252 if (p) return;
253}
254void inlinedUnspecified(Dummy *p) {
255 if (p) return;
256}
257
258Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
259 switch (getRandom()) {
260 case 1: inlinedNullable(p); break;
261 case 2: inlinedNonnull(p); break;
262 case 3: inlinedUnspecified(p); break;
263 }
264 if (getRandom())
Devin Coughlinc1986632015-11-24 19:15:11 +0000265 takesNonnull(p); // no-warning
266
267 if (getRandom()) {
268 Dummy *_Nonnull varWithInitializer = p; // no-warning
269
270 Dummy *_Nonnull var1WithInitializer = p, // no-warning
271 *_Nonnull var2WithInitializer = p; // no-warning
272 }
273
274 if (getRandom()) {
275 Dummy *_Nonnull varWithoutInitializer;
276 varWithoutInitializer = p; // no-warning
277 }
278
Gabor Horvathb47128a2015-09-03 23:16:21 +0000279 return p;
280}
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000281
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000282@interface SomeClass : NSObject
283@end
284
285@implementation SomeClass (MethodReturn)
286- (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {
287 TestObject *local = getNullableTestObject();
288 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 +0000289}
290
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000291- (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {
292 TestObject *local = getNullableTestObject();
293 return (TestObject * _Nonnull)local; // no-warning
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000294}
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000295
296- (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {
297 TestObject *local = getNullableTestObject();
298 if (!p) // Pre-condition violated here.
299 return local; // no-warning
300 else
301 return p; // no-warning
302}
303@end