• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// RUN: %clang_cc1 -fblocks -fsyntax-only %s -verify
2
3// Tests Objective-C 'kindof' types.
4
5#if !__has_feature(objc_kindof)
6#error does not support __kindof
7#endif
8
9@protocol NSObject
10@end
11
12@protocol NSCopying
13- (id)copy;
14+ (Class)classCopy;
15@end
16
17@protocol NSRandomProto
18- (void)randomMethod;
19+ (void)randomClassMethod;
20@end
21
22__attribute__((objc_root_class))
23@interface NSObject <NSObject>
24- (NSObject *)retain;
25@end
26
27@interface NSString : NSObject <NSCopying>
28- (NSString *)stringByAppendingString:(NSString *)string;
29+ (instancetype)string;
30@end
31
32@interface NSMutableString : NSString
33- (void)appendString:(NSString *)string;
34@end
35
36@interface NSNumber : NSObject <NSCopying>
37- (NSNumber *)numberByAddingNumber:(NSNumber *)number;
38@end
39
40// ---------------------------------------------------------------------------
41// Parsing and semantic analysis for __kindof
42// ---------------------------------------------------------------------------
43
44// Test proper application of __kindof.
45typedef __kindof NSObject *typedef1;
46typedef NSObject __kindof *typedef2;
47typedef __kindof NSObject<NSCopying> typedef3;
48typedef NSObject<NSCopying> __kindof *typedef4;
49typedef __kindof id<NSCopying> typedef5;
50typedef __kindof Class<NSCopying> typedef6;
51
52// Test redundancy of __kindof.
53typedef __kindof id __kindof redundant_typedef1;
54typedef __kindof NSObject __kindof *redundant_typedef2;
55
56// Test application of __kindof to typedefs.
57typedef NSObject *NSObject_ptr_typedef;
58typedef NSObject NSObject_typedef;
59typedef __kindof NSObject_ptr_typedef typedef_typedef1;
60typedef __kindof NSObject_typedef typedef_typedef2;
61
62// Test application of __kindof to non-object types.
63typedef __kindof int nonobject_typedef1; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'int'}}
64typedef NSObject **NSObject_ptr_ptr;
65typedef __kindof NSObject_ptr_ptr nonobject_typedef2; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'NSObject_ptr_ptr' (aka 'NSObject **')}}
66
67// Test application of __kindof outside of the decl-specifiers.
68typedef NSObject * __kindof bad_specifier_location1; // expected-error{{'__kindof' type specifier must precede the declarator}}
69typedef NSObject bad_specifier_location2 __kindof; // expected-error{{expected ';' after top level declarator}}
70// expected-warning@-1{{declaration does not declare anything}}
71
72// ---------------------------------------------------------------------------
73// Pretty printing of __kindof
74// ---------------------------------------------------------------------------
75void test_pretty_print(int *ip) {
76  __kindof NSObject *kindof_NSObject;
77  ip = kindof_NSObject; // expected-warning{{from '__kindof NSObject *'}}
78
79  __kindof NSObject_ptr_typedef kindof_NSObject_ptr;
80  ip = kindof_NSObject_ptr; // expected-warning{{from '__kindof NSObject_ptr_typedef'}}
81
82  __kindof id <NSCopying> *kindof_NSCopying;
83  ip = kindof_NSCopying; // expected-warning{{from '__kindof id<NSCopying> *'}}
84
85  __kindof NSObject_ptr_typedef *kindof_NSObject_ptr_typedef;
86  ip = kindof_NSObject_ptr_typedef; // expected-warning{{from '__kindof NSObject_ptr_typedef *'}}
87}
88
89// ---------------------------------------------------------------------------
90// Basic implicit conversions (dropping __kindof, upcasts, etc.)
91// ---------------------------------------------------------------------------
92void test_add_remove_kindof_conversions(void) {
93  __kindof NSObject *kindof_NSObject_obj;
94  NSObject *NSObject_obj;
95
96  // Conversion back and forth
97  kindof_NSObject_obj = NSObject_obj;
98  NSObject_obj = kindof_NSObject_obj;
99
100  // Qualified-id conversion back and forth.
101  __kindof id <NSCopying> kindof_id_NSCopying_obj;
102  id <NSCopying> id_NSCopying_obj;
103  kindof_id_NSCopying_obj = id_NSCopying_obj;
104  id_NSCopying_obj = kindof_id_NSCopying_obj;
105}
106
107void test_upcast_conversions(void) {
108  __kindof NSObject *kindof_NSObject_obj;
109  NSObject *NSObject_obj;
110
111  // Upcasts
112  __kindof NSString *kindof_NSString_obj;
113  NSString *NSString_obj;
114  kindof_NSObject_obj = kindof_NSString_obj;
115  kindof_NSObject_obj = NSString_obj;
116  NSObject_obj = kindof_NSString_obj;
117  NSObject_obj = NSString_obj;
118
119  // "Upcasts" with qualified-id.
120  __kindof id <NSCopying> kindof_id_NSCopying_obj;
121  id <NSCopying> id_NSCopying_obj;
122  kindof_id_NSCopying_obj = kindof_NSString_obj;
123  kindof_id_NSCopying_obj = NSString_obj;
124  id_NSCopying_obj = kindof_NSString_obj;
125  id_NSCopying_obj = NSString_obj;
126}
127
128
129void test_ptr_object_conversions(void) {
130  __kindof NSObject **ptr_kindof_NSObject_obj;
131  NSObject **ptr_NSObject_obj;
132
133  // Conversions back and forth.
134  ptr_kindof_NSObject_obj = ptr_NSObject_obj;
135  ptr_NSObject_obj = ptr_kindof_NSObject_obj;
136
137  // Conversions back and forth with qualified-id.
138  __kindof id <NSCopying> *ptr_kindof_id_NSCopying_obj;
139  id <NSCopying> *ptr_id_NSCopying_obj;
140  ptr_kindof_id_NSCopying_obj = ptr_id_NSCopying_obj;
141  ptr_id_NSCopying_obj = ptr_kindof_id_NSCopying_obj;
142
143  // Upcasts.
144  __kindof NSString **ptr_kindof_NSString_obj;
145  NSString **ptr_NSString_obj;
146  ptr_kindof_NSObject_obj = ptr_kindof_NSString_obj;
147  ptr_kindof_NSObject_obj = ptr_NSString_obj;
148  ptr_NSObject_obj = ptr_kindof_NSString_obj;
149  ptr_NSObject_obj = ptr_NSString_obj;
150}
151
152// ---------------------------------------------------------------------------
153// Implicit downcasting
154// ---------------------------------------------------------------------------
155void test_downcast_conversions(void) {
156  __kindof NSObject *kindof_NSObject_obj;
157  NSObject *NSObject_obj;
158  __kindof NSString *kindof_NSString_obj;
159  NSString *NSString_obj;
160
161  // Implicit downcasting.
162  kindof_NSString_obj = kindof_NSObject_obj;
163  kindof_NSString_obj = NSObject_obj; // expected-warning{{assigning to '__kindof NSString *' from 'NSObject *'}}
164  NSString_obj = kindof_NSObject_obj;
165  NSString_obj = NSObject_obj; // expected-warning{{assigning to 'NSString *' from 'NSObject *'}}
166
167  // Implicit downcasting with qualified id.
168  __kindof id <NSCopying> kindof_NSCopying_obj;
169  id <NSCopying> NSCopying_obj;
170  kindof_NSString_obj = kindof_NSCopying_obj;
171  kindof_NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
172  NSString_obj = kindof_NSCopying_obj;
173  NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
174  kindof_NSObject_obj = kindof_NSCopying_obj;
175  kindof_NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
176  NSObject_obj = kindof_NSCopying_obj;
177  NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
178}
179
180void test_crosscast_conversions(void) {
181  __kindof NSString *kindof_NSString_obj;
182  NSString *NSString_obj;
183  __kindof NSNumber *kindof_NSNumber_obj;
184  NSNumber *NSNumber_obj;
185
186  NSString_obj = kindof_NSNumber_obj; // expected-warning{{from '__kindof NSNumber *'}}
187}
188
189// ---------------------------------------------------------------------------
190// Blocks
191// ---------------------------------------------------------------------------
192void test_block_conversions(void) {
193  // Adding/removing __kindof from return type.
194  __kindof NSString *(^kindof_NSString_void_block)(void);
195  NSString *(^NSString_void_block)(void);
196  kindof_NSString_void_block = NSString_void_block;
197  NSString_void_block = kindof_NSString_void_block;
198
199  // Covariant return type.
200  __kindof NSMutableString *(^kindof_NSMutableString_void_block)(void);
201  NSMutableString *(^NSMutableString_void_block)(void);
202  kindof_NSString_void_block = NSMutableString_void_block;
203  NSString_void_block = kindof_NSMutableString_void_block;
204  kindof_NSString_void_block = NSMutableString_void_block;
205  NSString_void_block = kindof_NSMutableString_void_block;
206
207  // "Covariant" return type via downcasting rule.
208  kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}}
209  NSMutableString_void_block = kindof_NSString_void_block;
210  kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}}
211  NSMutableString_void_block = kindof_NSString_void_block;
212
213  // Cross-casted return type.
214  __kindof NSNumber *(^kindof_NSNumber_void_block)(void);
215  NSNumber *(^NSNumber_void_block)(void);
216  kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}}
217  NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}}
218  kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}}
219  NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}}
220
221  // Adding/removing __kindof from argument type.
222  void (^void_kindof_NSString_block)(__kindof NSString *);
223  void (^void_NSString_block)(NSString *);
224  void_kindof_NSString_block = void_NSString_block;
225  void_NSString_block = void_kindof_NSString_block;
226
227  // Contravariant argument type.
228  void (^void_kindof_NSMutableString_block)(__kindof NSMutableString *);
229  void (^void_NSMutableString_block)(NSMutableString *);
230  void_kindof_NSMutableString_block = void_kindof_NSString_block;
231  void_kindof_NSMutableString_block = void_NSString_block;
232  void_NSMutableString_block = void_kindof_NSString_block;
233  void_NSMutableString_block = void_NSString_block;
234
235  // "Contravariant" argument type via downcasting rule.
236  void_kindof_NSString_block = void_kindof_NSMutableString_block;
237  void_kindof_NSString_block = void_NSMutableString_block;
238  void_NSString_block = void_kindof_NSMutableString_block; // expected-error{{from 'void (^)(__kindof NSMutableString *)'}}
239  void_NSString_block = void_NSMutableString_block; // expected-error{{from 'void (^)(NSMutableString *)'}}
240}
241
242// ---------------------------------------------------------------------------
243// Messaging __kindof types.
244// ---------------------------------------------------------------------------
245void message_kindof_object(__kindof NSString *kindof_NSString) {
246  [kindof_NSString retain]; // in superclass
247  [kindof_NSString stringByAppendingString:0]; // in class
248  [kindof_NSString appendString:0]; // in subclass
249  [kindof_NSString numberByAddingNumber: 0]; // FIXME: in unrelated class
250  [kindof_NSString randomMethod]; // in protocol
251}
252
253void message_kindof_qualified_id(__kindof id <NSCopying> kindof_NSCopying) {
254  [kindof_NSCopying copy]; // in protocol
255  [kindof_NSCopying stringByAppendingString:0]; // in some class
256  [kindof_NSCopying randomMethod]; // in unrelated protocol
257}
258
259void message_kindof_qualified_class(
260       __kindof Class <NSCopying> kindof_NSCopying) {
261  [kindof_NSCopying classCopy]; // in protocol
262  [kindof_NSCopying string]; // in some class
263  [kindof_NSCopying randomClassMethod]; // in unrelated protocol
264}
265
266// ---------------------------------------------------------------------------
267// __kindof within specialized types
268// ---------------------------------------------------------------------------
269@interface NSArray<T> : NSObject
270@end
271
272void implicit_convert_array(NSArray<__kindof NSString *> *kindofStringsArray,
273                            NSArray<NSString *> *stringsArray,
274                            NSArray<__kindof NSMutableString *>
275                              *kindofMutStringsArray,
276                            NSArray<NSMutableString *> *mutStringsArray) {
277  // Adding/removing __kindof is okay.
278  kindofStringsArray = stringsArray;
279  stringsArray = kindofStringsArray;
280
281  // Other covariant and contravariant conversions still not permitted.
282  kindofStringsArray = mutStringsArray; // expected-warning{{incompatible pointer types}}
283  stringsArray = kindofMutStringsArray; // expected-warning{{incompatible pointer types}}
284  mutStringsArray = kindofStringsArray; // expected-warning{{incompatible pointer types}}
285
286  // Adding/removing nested __kindof is okay.
287  NSArray<NSArray<__kindof NSString *> *> *kindofStringsArrayArray;
288  NSArray<NSArray<NSString *> *> *stringsArrayArray;
289  kindofStringsArrayArray = stringsArrayArray;
290  stringsArrayArray = kindofStringsArrayArray;
291}
292
293// ---------------------------------------------------------------------------
294// __kindof + nullability
295// ---------------------------------------------------------------------------
296
297void testNullability() {
298  // The base type being a pointer type tickles the bug.
299  extern __kindof id <NSCopying> _Nonnull getSomeCopyable();
300  NSString *string = getSomeCopyable(); // no-warning
301
302  void processCopyable(__typeof(getSomeCopyable()) string);
303  processCopyable(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
304}
305
306// Check that clang doesn't crash when a type parameter is illegal.
307@interface Array1<T> : NSObject
308@end
309
310@interface I1 : NSObject
311@end
312
313@interface Array1<__kindof I1*>(extensions1) // expected-error{{expected type parameter name}}
314@end
315
316@interface Array2<T1, T2, T3> : NSObject
317@end
318
319@interface Array2<T, T, __kindof I1*>(extensions2) // expected-error{{expected type parameter name}} expected-error{{redeclaration of type parameter 'T'}}
320@end
321