1 // RUN: %clang_cc1 -fblocks -fsyntax-only %s -verify -Wmethod-signatures 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> // expected-note{{receiver is instance of class declared here}} 28 - (void)compare:(NSString *)string; 29 - (NSString *)stringByAppendingString:(NSString *)string; 30 + (instancetype)string; 31 @end 32 33 @interface NSMutableString : NSString 34 - (void)appendString:(NSString *)string; 35 @end 36 37 @interface NSNumber : NSObject <NSCopying> 38 - (NSNumber *)numberByAddingNumber:(NSNumber *)number; 39 @end 40 41 // --------------------------------------------------------------------------- 42 // Parsing and semantic analysis for __kindof 43 // --------------------------------------------------------------------------- 44 45 // Test proper application of __kindof. 46 typedef __kindof NSObject *typedef1; 47 typedef NSObject __kindof *typedef2; 48 typedef __kindof NSObject<NSCopying> typedef3; 49 typedef NSObject<NSCopying> __kindof *typedef4; 50 typedef __kindof id<NSCopying> typedef5; 51 typedef __kindof Class<NSCopying> typedef6; 52 53 // Test redundancy of __kindof. 54 typedef __kindof id __kindof redundant_typedef1; 55 typedef __kindof NSObject __kindof *redundant_typedef2; 56 57 // Test application of __kindof to typedefs. 58 typedef NSObject *NSObject_ptr_typedef; 59 typedef NSObject NSObject_typedef; 60 typedef __kindof NSObject_ptr_typedef typedef_typedef1; 61 typedef __kindof NSObject_typedef typedef_typedef2; 62 63 // Test application of __kindof to non-object types. 64 typedef __kindof int nonobject_typedef1; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'int'}} 65 typedef NSObject **NSObject_ptr_ptr; 66 typedef __kindof NSObject_ptr_ptr nonobject_typedef2; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'NSObject_ptr_ptr' (aka 'NSObject **')}} 67 68 // Test application of __kindof outside of the decl-specifiers. 69 typedef NSObject * __kindof bad_specifier_location1; // expected-error{{'__kindof' type specifier must precede the declarator}} 70 typedef NSObject bad_specifier_location2 __kindof; // expected-error{{expected ';' after top level declarator}} 71 // expected-warning@-1{{declaration does not declare anything}} 72 73 // --------------------------------------------------------------------------- 74 // Pretty printing of __kindof 75 // --------------------------------------------------------------------------- 76 void test_pretty_print(int *ip) { 77 __kindof NSObject *kindof_NSObject; 78 ip = kindof_NSObject; // expected-warning{{from '__kindof NSObject *'}} 79 80 __kindof NSObject_ptr_typedef kindof_NSObject_ptr; 81 ip = kindof_NSObject_ptr; // expected-warning{{from '__kindof NSObject_ptr_typedef'}} 82 83 __kindof id <NSCopying> *kindof_NSCopying; 84 ip = kindof_NSCopying; // expected-warning{{from '__kindof id<NSCopying> *'}} 85 86 __kindof NSObject_ptr_typedef *kindof_NSObject_ptr_typedef; 87 ip = kindof_NSObject_ptr_typedef; // expected-warning{{from '__kindof NSObject_ptr_typedef *'}} 88 } 89 90 // --------------------------------------------------------------------------- 91 // Basic implicit conversions (dropping __kindof, upcasts, etc.) 92 // --------------------------------------------------------------------------- 93 void test_add_remove_kindof_conversions(void) { 94 __kindof NSObject *kindof_NSObject_obj; 95 NSObject *NSObject_obj; 96 97 // Conversion back and forth 98 kindof_NSObject_obj = NSObject_obj; 99 NSObject_obj = kindof_NSObject_obj; 100 101 // Qualified-id conversion back and forth. 102 __kindof id <NSCopying> kindof_id_NSCopying_obj; 103 id <NSCopying> id_NSCopying_obj; 104 kindof_id_NSCopying_obj = id_NSCopying_obj; 105 id_NSCopying_obj = kindof_id_NSCopying_obj; 106 } 107 108 void test_upcast_conversions(void) { 109 __kindof NSObject *kindof_NSObject_obj; 110 NSObject *NSObject_obj; 111 112 // Upcasts 113 __kindof NSString *kindof_NSString_obj; 114 NSString *NSString_obj; 115 kindof_NSObject_obj = kindof_NSString_obj; 116 kindof_NSObject_obj = NSString_obj; 117 NSObject_obj = kindof_NSString_obj; 118 NSObject_obj = NSString_obj; 119 120 // "Upcasts" with qualified-id. 121 __kindof id <NSCopying> kindof_id_NSCopying_obj; 122 id <NSCopying> id_NSCopying_obj; 123 kindof_id_NSCopying_obj = kindof_NSString_obj; 124 kindof_id_NSCopying_obj = NSString_obj; 125 id_NSCopying_obj = kindof_NSString_obj; 126 id_NSCopying_obj = NSString_obj; 127 } 128 129 130 void test_ptr_object_conversions(void) { 131 __kindof NSObject **ptr_kindof_NSObject_obj; 132 NSObject **ptr_NSObject_obj; 133 134 // Conversions back and forth. 135 ptr_kindof_NSObject_obj = ptr_NSObject_obj; 136 ptr_NSObject_obj = ptr_kindof_NSObject_obj; 137 138 // Conversions back and forth with qualified-id. 139 __kindof id <NSCopying> *ptr_kindof_id_NSCopying_obj; 140 id <NSCopying> *ptr_id_NSCopying_obj; 141 ptr_kindof_id_NSCopying_obj = ptr_id_NSCopying_obj; 142 ptr_id_NSCopying_obj = ptr_kindof_id_NSCopying_obj; 143 144 // Upcasts. 145 __kindof NSString **ptr_kindof_NSString_obj; 146 NSString **ptr_NSString_obj; 147 ptr_kindof_NSObject_obj = ptr_kindof_NSString_obj; 148 ptr_kindof_NSObject_obj = ptr_NSString_obj; 149 ptr_NSObject_obj = ptr_kindof_NSString_obj; 150 ptr_NSObject_obj = ptr_NSString_obj; 151 } 152 153 // --------------------------------------------------------------------------- 154 // Implicit downcasting 155 // --------------------------------------------------------------------------- 156 void test_downcast_conversions(void) { 157 __kindof NSObject *kindof_NSObject_obj; 158 NSObject *NSObject_obj; 159 __kindof NSString *kindof_NSString_obj; 160 NSString *NSString_obj; 161 162 // Implicit downcasting. 163 kindof_NSString_obj = kindof_NSObject_obj; 164 kindof_NSString_obj = NSObject_obj; // expected-warning{{assigning to '__kindof NSString *' from 'NSObject *'}} 165 NSString_obj = kindof_NSObject_obj; 166 NSString_obj = NSObject_obj; // expected-warning{{assigning to 'NSString *' from 'NSObject *'}} 167 168 // Implicit downcasting with qualified id. 169 __kindof id <NSCopying> kindof_NSCopying_obj; 170 id <NSCopying> NSCopying_obj; 171 kindof_NSString_obj = kindof_NSCopying_obj; 172 kindof_NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}} 173 NSString_obj = kindof_NSCopying_obj; 174 NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}} 175 kindof_NSObject_obj = kindof_NSCopying_obj; 176 kindof_NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}} 177 NSObject_obj = kindof_NSCopying_obj; 178 NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}} 179 } 180 181 void test_crosscast_conversions(void) { 182 __kindof NSString *kindof_NSString_obj; 183 NSString *NSString_obj; 184 __kindof NSNumber *kindof_NSNumber_obj; 185 NSNumber *NSNumber_obj; 186 187 NSString_obj = kindof_NSNumber_obj; // expected-warning{{from '__kindof NSNumber *'}} 188 } 189 190 @interface NSCell : NSObject 191 @end 192 @interface NSCellSub : NSCell 193 @end 194 @interface NSCellSub2 : NSCell 195 @end 196 @interface NSCellSubSub : NSCellSub 197 @end 198 199 typedef signed char BOOL; 200 void test_conditional(BOOL flag) { 201 NSCellSubSub *result; 202 __kindof NSCellSub *kindof_Sub; 203 NSCell *cell; 204 NSCellSub *sub; 205 NSCellSub2 *sub2; 206 NSCellSubSub *subsub; 207 208 // LHS is kindof NSCellSub, RHS is NSCell --> kindof NSCell 209 // LHS is kindof NSCellSub, RHS is NSCellSub --> kindof NSCellSub 210 // LHS is kindof NSCellSub, RHS is NSCellSub2 --> kindof NSCell 211 // LHS is kindof NSCellSub, RHS is NSCellSubSub --> kindof NSCellSub 212 result = flag ? kindof_Sub : cell; 213 result = flag ? kindof_Sub : sub; 214 result = flag ? kindof_Sub : sub2; 215 result = flag ? kindof_Sub : subsub; 216 217 result = flag ? cell : kindof_Sub; 218 result = flag ? sub : kindof_Sub; 219 result = flag ? sub2 : kindof_Sub; 220 result = flag ? subsub : kindof_Sub; 221 } 222 223 // --------------------------------------------------------------------------- 224 // Blocks 225 // --------------------------------------------------------------------------- 226 void test_block_conversions(void) { 227 // Adding/removing __kindof from return type. 228 __kindof NSString *(^kindof_NSString_void_block)(void); 229 NSString *(^NSString_void_block)(void); 230 kindof_NSString_void_block = NSString_void_block; 231 NSString_void_block = kindof_NSString_void_block; 232 233 // Covariant return type. 234 __kindof NSMutableString *(^kindof_NSMutableString_void_block)(void); 235 NSMutableString *(^NSMutableString_void_block)(void); 236 kindof_NSString_void_block = NSMutableString_void_block; 237 NSString_void_block = kindof_NSMutableString_void_block; 238 kindof_NSString_void_block = NSMutableString_void_block; 239 NSString_void_block = kindof_NSMutableString_void_block; 240 241 // "Covariant" return type via downcasting rule. 242 kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}} 243 NSMutableString_void_block = kindof_NSString_void_block; 244 kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}} 245 NSMutableString_void_block = kindof_NSString_void_block; 246 247 // Cross-casted return type. 248 __kindof NSNumber *(^kindof_NSNumber_void_block)(void); 249 NSNumber *(^NSNumber_void_block)(void); 250 kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}} 251 NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}} 252 kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}} 253 NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}} 254 255 // Adding/removing __kindof from argument type. 256 void (^void_kindof_NSString_block)(__kindof NSString *); 257 void (^void_NSString_block)(NSString *); 258 void_kindof_NSString_block = void_NSString_block; 259 void_NSString_block = void_kindof_NSString_block; 260 261 // Contravariant argument type. 262 void (^void_kindof_NSMutableString_block)(__kindof NSMutableString *); 263 void (^void_NSMutableString_block)(NSMutableString *); 264 void_kindof_NSMutableString_block = void_kindof_NSString_block; 265 void_kindof_NSMutableString_block = void_NSString_block; 266 void_NSMutableString_block = void_kindof_NSString_block; 267 void_NSMutableString_block = void_NSString_block; 268 269 // "Contravariant" argument type via downcasting rule. 270 void_kindof_NSString_block = void_kindof_NSMutableString_block; 271 void_kindof_NSString_block = void_NSMutableString_block; 272 void_NSString_block = void_kindof_NSMutableString_block; // expected-error{{from 'void (^)(__kindof NSMutableString *)'}} 273 void_NSString_block = void_NSMutableString_block; // expected-error{{from 'void (^)(NSMutableString *)'}} 274 } 275 276 // --------------------------------------------------------------------------- 277 // Messaging __kindof types. 278 // --------------------------------------------------------------------------- 279 void message_kindof_object(__kindof NSString *kindof_NSString) { 280 [kindof_NSString retain]; // in superclass 281 [kindof_NSString stringByAppendingString:0]; // in class 282 [kindof_NSString appendString:0]; // in subclass 283 [kindof_NSString numberByAddingNumber: 0]; // expected-warning{{instance method '-numberByAddingNumber:' not found (return type defaults to 'id')}} 284 [kindof_NSString randomMethod]; // in protocol 285 } 286 287 void message_kindof_qualified_id(__kindof id <NSCopying> kindof_NSCopying) { 288 [kindof_NSCopying copy]; // in protocol 289 [kindof_NSCopying stringByAppendingString:0]; // in some class 290 [kindof_NSCopying randomMethod]; // in unrelated protocol 291 } 292 293 void message_kindof_qualified_class( 294 __kindof Class <NSCopying> kindof_NSCopying) { 295 [kindof_NSCopying classCopy]; // in protocol 296 [kindof_NSCopying string]; // in some class 297 [kindof_NSCopying randomClassMethod]; // in unrelated protocol 298 } 299 300 // Make sure we don't emit warning about multiple methods found. 301 typedef int NSInteger; 302 @interface Foo : NSObject 303 - (NSString*)test; 304 @end 305 @interface Bar : NSObject 306 - (NSInteger)test; 307 @end 308 void test(__kindof Bar *kBar) { 309 [kBar test]; 310 } 311 312 // Make sure we don't emit warning about no method found. 313 @interface A : NSObject 314 @property (readonly, getter=isActive) BOOL active; 315 @end 316 @interface B : NSObject 317 @property (getter=isActive, readonly) BOOL active; 318 @end 319 void foo() { 320 __kindof B *NSApp; 321 if ([NSApp isActive]) { 322 } 323 } 324 325 typedef const struct CGPath *CGPathRef; 326 @interface C : NSObject 327 @property (copy) NSString *path; 328 @end 329 @interface D : NSObject 330 @property CGPathRef path __attribute__((availability(macosx,unavailable))); 331 @end 332 // Make sure we choose "NSString *path" for [s1 path]. 333 void bar(id s1, id s2) { 334 return [[s1 path] compare:[s2 path]]; 335 } 336 337 // --------------------------------------------------------------------------- 338 // __kindof within specialized types 339 // --------------------------------------------------------------------------- 340 @interface NSArray<T> : NSObject 341 @end 342 343 void implicit_convert_array(NSArray<__kindof NSString *> *kindofStringsArray, 344 NSArray<NSString *> *stringsArray, 345 NSArray<__kindof NSMutableString *> 346 *kindofMutStringsArray, 347 NSArray<NSMutableString *> *mutStringsArray) { 348 // Adding/removing __kindof is okay. 349 kindofStringsArray = stringsArray; 350 stringsArray = kindofStringsArray; 351 352 // Other covariant and contravariant conversions still not permitted. 353 kindofStringsArray = mutStringsArray; // expected-warning{{incompatible pointer types}} 354 stringsArray = kindofMutStringsArray; // expected-warning{{incompatible pointer types}} 355 mutStringsArray = kindofStringsArray; // expected-warning{{incompatible pointer types}} 356 357 // Adding/removing nested __kindof is okay. 358 NSArray<NSArray<__kindof NSString *> *> *kindofStringsArrayArray; 359 NSArray<NSArray<NSString *> *> *stringsArrayArray; 360 kindofStringsArrayArray = stringsArrayArray; 361 stringsArrayArray = kindofStringsArrayArray; 362 } 363 364 // --------------------------------------------------------------------------- 365 // __kindof + nullability 366 // --------------------------------------------------------------------------- 367 368 void testNullability() { 369 // The base type being a pointer type tickles the bug. 370 extern __kindof id <NSCopying> _Nonnull getSomeCopyable(); 371 NSString *string = getSomeCopyable(); // no-warning 372 373 void processCopyable(__typeof(getSomeCopyable()) string); 374 processCopyable(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 375 } 376 377 // Make sure that we don't emit a warning about conflicting parameter types 378 // between __kindof id and id. 379 @interface A2 : NSObject 380 - (void)test:(__kindof id)T; 381 @end 382 @implementation A2 383 - (void)test:(id)T { 384 } 385 @end 386 387 @interface NSGeneric<ObjectType> : NSObject 388 - (void)test:(__kindof ObjectType)T; 389 - (void)mapUsingBlock:(id (^)(__kindof ObjectType))block; 390 @end 391 @implementation NSGeneric 392 - (void)test:(id)T { 393 } 394 - (void)mapUsingBlock:(id (^)(id))block { 395 } 396 @end 397 398 // Check that clang doesn't crash when a type parameter is illegal. 399 @interface Array1<T> : NSObject 400 @end 401 402 @interface I1 : NSObject 403 @end 404 405 @interface Array1<__kindof I1*>(extensions1) // expected-error{{expected type parameter name}} 406 @end 407 408 @interface Array2<T1, T2, T3> : NSObject 409 @end 410 411 @interface Array2<T, T, __kindof I1*>(extensions2) // expected-error{{expected type parameter name}} expected-error{{redeclaration of type parameter 'T'}} 412 @end 413