1 | // RUN: %clang_cc1 -fsyntax-only -fblocks -Woverriding-method-mismatch -Wno-nullability-declspec -Wnullable-to-nonnull-conversion %s -verify |
2 | |
3 | __attribute__((objc_root_class)) |
4 | @interface NSFoo |
5 | - (void)methodTakingIntPtr:(_Nonnull int *)ptr; |
6 | - (_Nonnull int *)methodReturningIntPtr; |
7 | @end |
8 | |
9 | // Nullability applies to all pointer types. |
10 | typedef NSFoo * _Nonnull nonnull_NSFoo_ptr; |
11 | typedef id _Nonnull nonnull_id; |
12 | typedef SEL _Nonnull nonnull_SEL; |
13 | |
14 | // Nullability can move into Objective-C pointer types. |
15 | typedef _Nonnull NSFoo * nonnull_NSFoo_ptr_2; |
16 | |
17 | // Conflicts from nullability moving into Objective-C pointer type. |
18 | typedef _Nonnull NSFoo * _Nullable conflict_NSFoo_ptr_2; // expected-error{{'_Nonnull' cannot be applied to non-pointer type 'NSFoo'}} |
19 | |
20 | void testBlocksPrinting(NSFoo * _Nullable (^bp)(int)) { |
21 | int *ip = bp; // expected-error{{'NSFoo * _Nullable (^)(int)'}} |
22 | } |
23 | |
24 | // Check returning nil from a _Nonnull-returning method. |
25 | @implementation NSFoo |
26 | - (void)methodTakingIntPtr:(_Nonnull int *)ptr { } |
27 | - (_Nonnull int *)methodReturningIntPtr { |
28 | return 0; // no warning |
29 | } |
30 | @end |
31 | |
32 | // Context-sensitive keywords and property attributes for nullability. |
33 | __attribute__((objc_root_class)) |
34 | @interface NSBar |
35 | - (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo; |
36 | |
37 | - (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}} |
38 | // expected-note@-1{{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'NSFoo **'}} |
39 | - (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier 'nonnull' conflicts with existing specifier '_Nullable'}} |
40 | - (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier 'nonnull'}} |
41 | |
42 | @property(nonnull,retain) NSFoo *property1; |
43 | @property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}} |
44 | // expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}} |
45 | @property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier '_Nullable'}} |
46 | @property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier 'nonnull'}} |
47 | |
48 | @property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}} |
49 | @property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}} |
50 | @end |
51 | |
52 | @interface NSBar () |
53 | @property(nonnull,retain) NSFoo *property2; |
54 | @property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}} |
55 | // expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}} |
56 | @property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier '_Nullable'}} |
57 | @property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier 'nonnull'}} |
58 | @end |
59 | |
60 | void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, _Nonnull NSBar *bar) { |
61 | [foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} |
62 | [bar methodWithFoo: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} |
63 | bar.property1 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} |
64 | bar.property2 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} |
65 | [bar setProperty1: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} |
66 | [bar setProperty2: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} |
67 | int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}} |
68 | } |
69 | |
70 | // Check returning nil from a nonnull-returning method. |
71 | @implementation NSBar |
72 | - (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo { |
73 | return 0; // no warning |
74 | } |
75 | |
76 | - (NSFoo **)invalidMethod1 { |
77 | return 0; |
78 | } |
79 | |
80 | - (NSFoo *)conflictingMethod1 { |
81 | return 0; // no warning |
82 | } |
83 | - (NSFoo *)redundantMethod1 { |
84 | int *ip = 0; |
85 | return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} |
86 | } |
87 | @end |
88 | |
89 | __attribute__((objc_root_class)) |
90 | @interface NSMerge |
91 | - (nonnull NSFoo *)methodA:(nonnull NSFoo*)foo; |
92 | - (nonnull NSFoo *)methodB:(nonnull NSFoo*)foo; |
93 | - (NSFoo *)methodC:(NSFoo*)foo; |
94 | @end |
95 | |
96 | @implementation NSMerge |
97 | - (NSFoo *)methodA:(NSFoo*)foo { |
98 | int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}} |
99 | return ptr; // expected-warning{{result type 'NSFoo * _Nonnull'}} |
100 | } |
101 | |
102 | - (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \ |
103 | // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier 'nonnull'}} |
104 | return 0; |
105 | } |
106 | |
107 | - (nonnull NSFoo *)methodC:(nullable NSFoo*)foo { |
108 | int *ip = 0; |
109 | return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} |
110 | } |
111 | @end |
112 | |
113 | // Checking merging of nullability when sending a message. |
114 | @interface NSMergeReceiver |
115 | - (id)returnsNone; |
116 | - (nonnull id)returnsNonNull; |
117 | - (nullable id)returnsNullable; |
118 | - (null_unspecified id)returnsNullUnspecified; |
119 | @end |
120 | |
121 | void test_receiver_merge(NSMergeReceiver *none, |
122 | _Nonnull NSMergeReceiver *nonnull, |
123 | _Nullable NSMergeReceiver *nullable, |
124 | _Null_unspecified NSMergeReceiver *null_unspecified) { |
125 | int *ptr; |
126 | |
127 | ptr = [nullable returnsNullable]; // expected-warning{{'id _Nullable'}} |
128 | ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id _Nullable'}} |
129 | ptr = [nullable returnsNonNull]; // expected-warning{{'id _Nullable'}} |
130 | ptr = [nullable returnsNone]; // expected-warning{{'id _Nullable'}} |
131 | |
132 | ptr = [null_unspecified returnsNullable]; // expected-warning{{'id _Nullable'}} |
133 | ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}} |
134 | ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id _Null_unspecified'}} |
135 | ptr = [null_unspecified returnsNone]; // expected-warning{{'id'}} |
136 | |
137 | ptr = [nonnull returnsNullable]; // expected-warning{{'id _Nullable'}} |
138 | ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}} |
139 | ptr = [nonnull returnsNonNull]; // expected-warning{{'id _Nonnull'}} |
140 | ptr = [nonnull returnsNone]; // expected-warning{{'id'}} |
141 | |
142 | ptr = [none returnsNullable]; // expected-warning{{'id _Nullable'}} |
143 | ptr = [none returnsNullUnspecified]; // expected-warning{{'id'}} |
144 | ptr = [none returnsNonNull]; // expected-warning{{'id'}} |
145 | ptr = [none returnsNone]; // expected-warning{{'id'}} |
146 | |
147 | } |
148 | |
149 | // instancetype |
150 | @protocol Initializable |
151 | - (instancetype)initWithBlah:(id)blah; |
152 | @end |
153 | |
154 | __attribute__((objc_root_class)) |
155 | @interface InitializableClass <Initializable> |
156 | - (nonnull instancetype)initWithBlah:(nonnull id)blah; |
157 | - (nullable instancetype)returnMe; |
158 | + (nullable instancetype)returnInstanceOfMe; |
159 | |
160 | - (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier 'nonnull' conflicts with existing specifier '_Nullable'}} |
161 | - (instancetype _Nullable)returnMe2; |
162 | + (_Nonnull instancetype)returnInstanceOfMe2; |
163 | @end |
164 | |
165 | void test_instancetype(InitializableClass * _Nonnull ic, id _Nonnull object) { |
166 | int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * _Nullable'}} |
167 | ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}} |
168 | ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}} |
169 | ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}} |
170 | |
171 | ip = [ic returnMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}} |
172 | ip = [InitializableClass returnInstanceOfMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nonnull'}} |
173 | } |
174 | |
175 | // Check null_resettable getters/setters. |
176 | __attribute__((objc_root_class)) |
177 | @interface NSResettable |
178 | @property(null_resettable,retain) NSResettable *resettable1; // expected-note{{passing argument to parameter 'resettable1' here}} |
179 | @property(null_resettable,retain,nonatomic) NSResettable *resettable2; |
180 | @property(null_resettable,retain,nonatomic) NSResettable *resettable3; |
181 | @property(null_resettable,retain,nonatomic) NSResettable *resettable4; |
182 | @property(null_resettable,retain,nonatomic) NSResettable *resettable5; |
183 | @property(null_resettable,retain,nonatomic) NSResettable *resettable6; |
184 | @end |
185 | |
186 | void test_null_resettable(NSResettable *r, int *ip) { |
187 | [r setResettable1:ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'NSResettable * _Nullable'}} |
188 | r.resettable1 = ip; // expected-warning{{incompatible pointer types assigning to 'NSResettable * _Nullable' from 'int *'}} |
189 | } |
190 | |
191 | @implementation NSResettable // expected-warning{{synthesized setter 'setResettable4:' for null_resettable property 'resettable4' does not handle nil}} |
192 | - (NSResettable *)resettable1 { |
193 | int *ip = 0; |
194 | return ip; // expected-warning{{result type 'NSResettable * _Nonnull'}} |
195 | } |
196 | |
197 | - (void)setResettable1:(NSResettable *)param { |
198 | } |
199 | |
200 | @synthesize resettable2; // no warning; not synthesized |
201 | @synthesize resettable3; // expected-warning{{synthesized setter 'setResettable3:' for null_resettable property 'resettable3' does not handle nil}} |
202 | |
203 | - (void)setResettable2:(NSResettable *)param { |
204 | } |
205 | |
206 | @dynamic resettable5; |
207 | |
208 | - (NSResettable *)resettable6 { |
209 | return 0; // no warning |
210 | } |
211 | @end |
212 | |
213 | // rdar://problem/19814852 |
214 | @interface MultiProp |
215 | @property (nullable, copy) id a, b, c; |
216 | @property (nullable, copy) MultiProp *d, *(^e)(int); |
217 | @end |
218 | |
219 | void testMultiProp(MultiProp *foo) { |
220 | int *ip; |
221 | ip = foo.a; // expected-warning{{from 'id _Nullable'}} |
222 | ip = foo.d; // expected-warning{{from 'MultiProp * _Nullable'}} |
223 | ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ _Nullable)(int)'}} |
224 | } |
225 | |
226 | void testBlockLiterals() { |
227 | (void)(^id(void) { return 0; }); |
228 | (void)(^id _Nullable (void) { return 0; }); |
229 | (void)(^ _Nullable id(void) { return 0; }); |
230 | |
231 | int *x = (^ _Nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id _Nullable'}} |
232 | } |
233 | |
234 | // Check nullability of conditional expressions. |
235 | void conditional_expr(int c) { |
236 | NSFoo * _Nonnull p; |
237 | NSFoo * _Nonnull nonnullP; |
238 | NSFoo * _Nullable nullableP; |
239 | NSFoo * _Null_unspecified unspecifiedP; |
240 | NSFoo *noneP; |
241 | |
242 | p = c ? nonnullP : nonnullP; |
243 | p = c ? nonnullP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
244 | p = c ? nonnullP : unspecifiedP; |
245 | p = c ? nonnullP : noneP; |
246 | p = c ? nullableP : nonnullP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
247 | p = c ? nullableP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
248 | p = c ? nullableP : unspecifiedP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
249 | p = c ? nullableP : noneP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
250 | p = c ? unspecifiedP : nonnullP; |
251 | p = c ? unspecifiedP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
252 | p = c ? unspecifiedP : unspecifiedP; |
253 | p = c ? unspecifiedP : noneP; |
254 | p = c ? noneP : nonnullP; |
255 | p = c ? noneP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}} |
256 | p = c ? noneP : unspecifiedP; |
257 | p = c ? noneP : noneP; |
258 | } |
259 | |
260 | typedef int INTS[4]; |
261 | @interface ArraysInMethods |
262 | - (void)simple:(int [_Nonnull 2])x; |
263 | - (void)nested:(void *_Nullable [_Nonnull 2])x; |
264 | - (void)nestedBad:(int [2][_Nonnull 2])x; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}} |
265 | |
266 | - (void)withTypedef:(INTS _Nonnull)x; |
267 | - (void)withTypedefBad:(INTS _Nonnull[2])x; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}} |
268 | |
269 | - (void)simpleSugar:(nonnull int [2])x; |
270 | - (void)nestedSugar:(nonnull void *_Nullable [2])x; // expected-error {{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'void * _Nullable [2]'}} expected-note {{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'void * _Nullable [2]'}} |
271 | - (void)sugarWithTypedef:(nonnull INTS)x; |
272 | @end |
273 | |
274 | void test(ArraysInMethods *obj) { |
275 | [obj simple:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
276 | [obj nested:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
277 | [obj withTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
278 | |
279 | [obj simpleSugar:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
280 | [obj sugarWithTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
281 | } |
282 | |
283 | // Check that we don't propagate the nullability specifier on the receiver to |
284 | // the result type of a message send if the result type cannot have a |
285 | // nullability specifier. |
286 | @interface C0 |
287 | -(int) count; |
288 | @end |
289 | |
290 | void testMessageSendResultType(C0 * _Nullable c0) { |
291 | int *p = [c0 count]; // expected-warning {{incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int'}} |
292 | } |
293 | |