1258 lines · plain
1// RUN: %clang_cc1 -verify -fsyntax-only -fblocks -fobjc-exceptions -Wcompletion-handler -Wno-pointer-to-int-cast %s2 3#define NULL (void *)04#define nil (id)05#define CALLED_ONCE __attribute__((called_once))6#define NORETURN __attribute__((noreturn))7#define LIKELY(X) __builtin_expect(!!(X), 1)8#define UNLIKELY(X) __builtin_expect(!!(X), 0)9#define LIKELY_WITH_PROBA(X, P) __builtin_expect_with_probability(!!(X), 1, P)10#define UNLIKELY_WITH_PROBA(X, P) __builtin_expect_with_probability(!!(X), 0, P)11#define UNPRED(X) __builtin_unpredictable((long)(X))12 13@protocol NSObject14@end15@interface NSObject <NSObject>16- (instancetype)init;17- (id)copy;18- (id)class;19- autorelease;20@end21 22typedef unsigned int NSUInteger;23typedef struct {24} NSFastEnumerationState;25 26@interface NSArray <__covariant NSFastEnumeration>27- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;28@end29@interface NSMutableArray<ObjectType> : NSArray <ObjectType>30- addObject:anObject;31@end32@class NSString, Protocol;33extern void NSLog(NSString *format, ...);34 35typedef int group_t;36typedef struct dispatch_queue_s *dispatch_queue_t;37typedef void (^dispatch_block_t)(void);38extern dispatch_queue_t queue;39 40void dispatch_group_async(dispatch_queue_t queue,41 group_t group,42 dispatch_block_t block);43void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);44 45void escape(void (^callback)(void));46void escape_void(void *);47void indirect_call(void (^callback)(void) CALLED_ONCE);48void indirect_conv(void (^completionHandler)(void));49void filler(void);50void exit(int) NORETURN;51 52void double_call_one_block(void (^callback)(void) CALLED_ONCE) {53 callback(); // expected-note{{previous call is here}}54 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}55}56 57void double_call_one_block_parens(void (^callback)(void) CALLED_ONCE) {58 (callback)(); // expected-note{{previous call is here}}59 (callback)(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}60}61 62void double_call_one_block_ptr(void (*callback)(void) CALLED_ONCE) {63 callback(); // expected-note{{previous call is here}}64 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}65}66 67void double_call_one_block_ptr_deref(void (*callback)(void) CALLED_ONCE) {68 (*callback)(); // expected-note{{previous call is here}}69 (*callback)(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}70}71 72void multiple_call_one_block(void (^callback)(void) CALLED_ONCE) {73 // We don't really need to repeat the same warning for the same parameter.74 callback(); // no-warning75 callback(); // no-warning76 callback(); // no-warning77 callback(); // expected-note{{previous call is here}}78 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}79}80 81void double_call_branching_1(int cond, void (^callback)(void) CALLED_ONCE) {82 if (cond) {83 callback(); // expected-note{{previous call is here}}84 } else {85 cond += 42;86 }87 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}88}89 90void double_call_branching_2(int cond, void (^callback)(void) CALLED_ONCE) {91 callback();92 // expected-note@-1{{previous call is here; set to nil to indicate it cannot be called afterwards}}93 94 if (cond) {95 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}96 } else {97 cond += 42;98 }99}100 101void double_call_branching_3(int cond, void (^callback)(void) CALLED_ONCE) {102 if (cond) {103 callback();104 } else {105 callback();106 }107 // no-warning108}109 110void double_call_branching_4(int cond1, int cond2, void (^callback)(void) CALLED_ONCE) {111 if (cond1) {112 cond2 = !cond2;113 } else {114 callback();115 // expected-note@-1{{previous call is here; set to nil to indicate it cannot be called afterwards}}116 }117 118 if (cond2) {119 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}120 }121}122 123void double_call_loop(int counter, void (^callback)(void) CALLED_ONCE) {124 while (counter > 0) {125 counter--;126 // Both note and warning are on the same line, which is a common situation127 // in loops.128 callback(); // expected-note{{previous call is here}}129 // expected-warning@-1{{'callback' parameter marked 'called_once' is called twice}}130 }131}132 133void never_called_trivial(void (^callback)(void) CALLED_ONCE) {134 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called}}135}136 137int never_called_branching(int x, void (^callback)(void) CALLED_ONCE) {138 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called}}139 x -= 42;140 141 if (x == 10) {142 return 0;143 }144 145 return x + 15;146}147 148void escaped_one_block_1(void (^callback)(void) CALLED_ONCE) {149 escape(callback); // no-warning150}151 152void escaped_one_block_2(void (^callback)(void) CALLED_ONCE) {153 escape(callback); // no-warning154 callback();155}156 157void escaped_one_path_1(int cond, void (^callback)(void) CALLED_ONCE) {158 if (cond) {159 escape(callback); // no-warning160 } else {161 callback();162 }163}164 165void escaped_one_path_2(int cond, void (^callback)(void) CALLED_ONCE) {166 if (cond) {167 escape(callback); // no-warning168 }169 170 callback();171}172 173void escaped_one_path_3(int cond, void (^callback)(void) CALLED_ONCE) {174 if (cond) {175 // expected-warning@-1{{'callback' parameter marked 'called_once' is never used when taking false branch}}176 escape(callback);177 }178}179 180void escape_in_between_1(void (^callback)(void) CALLED_ONCE) {181 callback(); // expected-note{{previous call is here}}182 escape(callback);183 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}184}185 186void escape_in_between_2(int cond, void (^callback)(void) CALLED_ONCE) {187 callback(); // expected-note{{previous call is here}}188 if (cond) {189 escape(callback);190 }191 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}192}193 194void escape_in_between_3(int cond, void (^callback)(void) CALLED_ONCE) {195 callback(); // expected-note{{previous call is here}}196 197 if (cond) {198 escape(callback);199 } else {200 escape_void((__bridge void *)callback);201 }202 203 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}204}205 206void escaped_as_void_ptr(void (^callback)(void) CALLED_ONCE) {207 escape_void((__bridge void *)callback); // no-warning208}209 210void indirect_call_no_warning_1(void (^callback)(void) CALLED_ONCE) {211 indirect_call(callback); // no-warning212}213 214void indirect_call_no_warning_2(int cond, void (^callback)(void) CALLED_ONCE) {215 if (cond) {216 indirect_call(callback);217 } else {218 callback();219 }220 // no-warning221}222 223void indirect_call_double_call(void (^callback)(void) CALLED_ONCE) {224 indirect_call(callback); // expected-note{{previous call is here}}225 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}226}227 228void indirect_call_within_direct_call(void (^callback)(void) CALLED_ONCE,229 void (^meta)(void (^param)(void) CALLED_ONCE) CALLED_ONCE) {230 // TODO: Report warning for 'callback'.231 // At the moment, it is not possible to access 'called_once' attribute from the type232 // alone when there is no actual declaration of the marked parameter.233 meta(callback);234 callback();235 // no-warning236}237 238void block_call_1(void (^callback)(void) CALLED_ONCE) {239 indirect_call( // expected-note{{previous call is here}}240 ^{241 callback();242 });243 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}244}245 246void block_call_2(void (^callback)(void) CALLED_ONCE) {247 escape(^{248 callback();249 });250 callback();251 // no-warning252}253 254void block_call_3(int cond, void (^callback)(void) CALLED_ONCE) {255 ^{256 if (cond) {257 callback(); // expected-note{{previous call is here}}258 }259 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}260 }(); // no-warning261}262 263void block_call_4(int cond, void (^callback)(void) CALLED_ONCE) {264 ^{265 if (cond) {266 // expected-warning@-1{{'callback' parameter marked 'called_once' is never used when taking false branch}}267 escape(callback);268 }269 }(); // no-warning270}271 272void block_call_5(void (^outer)(void) CALLED_ONCE) {273 ^(void (^inner)(void) CALLED_ONCE) {274 // expected-warning@-1{{'inner' parameter marked 'called_once' is never called}}275 }(outer);276}277 278void block_with_called_once(void (^outer)(void) CALLED_ONCE) {279 escape_void((__bridge void *)^(void (^inner)(void) CALLED_ONCE) {280 inner(); // expected-note{{previous call is here}}281 inner(); // expected-warning{{'inner' parameter marked 'called_once' is called twice}}282 });283 outer(); // expected-note{{previous call is here}}284 outer(); // expected-warning{{'outer' parameter marked 'called_once' is called twice}}285}286 287void block_dispatch_call(int cond, void (^callback)(void) CALLED_ONCE) {288 dispatch_async(queue, ^{289 if (cond) // expected-warning{{'callback' parameter marked 'called_once' is never called when taking false branch}}290 callback();291 });292}293 294void block_escape_call_1(int cond, void (^callback)(void) CALLED_ONCE) {295 escape_void((__bridge void *)^{296 if (cond) {297 // no-warning298 callback();299 }300 });301}302 303void block_escape_call_2(int cond, void (^callback)(void) CALLED_ONCE) {304 escape_void((__bridge void *)^{305 if (cond) {306 callback(); // expected-note{{previous call is here}}307 }308 // Double call can still be reported.309 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}310 });311}312 313void never_called_one_exit(int cond, void (^callback)(void) CALLED_ONCE) {314 if (!cond) // expected-warning{{'callback' parameter marked 'called_once' is never called when taking true branch}}315 return;316 317 callback();318}319 320void never_called_if_then_1(int cond, void (^callback)(void) CALLED_ONCE) {321 if (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking true branch}}322 } else {323 callback();324 }325}326 327void never_called_if_then_2(int cond, void (^callback)(void) CALLED_ONCE) {328 if (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking true branch}}329 // This way the first statement in the basic block is different from330 // the first statement in the compound statement331 (void)cond;332 } else {333 callback();334 }335}336 337void never_called_if_else_1(int cond, void (^callback)(void) CALLED_ONCE) {338 if (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking false branch}}339 callback();340 } else {341 }342}343 344void never_called_if_else_2(int cond, void (^callback)(void) CALLED_ONCE) {345 if (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking false branch}}346 callback();347 }348}349 350void never_called_two_ifs(int cond1, int cond2, void (^callback)(void) CALLED_ONCE) {351 if (cond1) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking false branch}}352 if (cond2) { // expected-warning{{'callback' parameter marked 'called_once' is never called when taking true branch}}353 return;354 }355 callback();356 }357}358 359void never_called_ternary_then(int cond, void (^other)(void), void (^callback)(void) CALLED_ONCE) {360 return cond ? // expected-warning{{'callback' parameter marked 'called_once' is never called when taking true branch}}361 other()362 : callback();363}364 365void never_called_for_false(int size, void (^callback)(void) CALLED_ONCE) {366 for (int i = 0; i < size; ++i) {367 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called when skipping the loop}}368 callback();369 break;370 }371}372 373void never_called_for_true(int size, void (^callback)(void) CALLED_ONCE) {374 for (int i = 0; i < size; ++i) {375 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called when entering the loop}}376 return;377 }378 callback();379}380 381void never_called_while_false(int cond, void (^callback)(void) CALLED_ONCE) {382 while (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when skipping the loop}}383 callback();384 break;385 }386}387 388void never_called_while_true(int cond, void (^callback)(void) CALLED_ONCE) {389 while (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when entering the loop}}390 return;391 }392 callback();393}394 395void never_called_switch_case(int cond, void (^callback)(void) CALLED_ONCE) {396 switch (cond) {397 case 1:398 callback();399 break;400 case 2:401 callback();402 break;403 case 3: // expected-warning{{'callback' parameter marked 'called_once' is never called when handling this case}}404 break;405 default:406 callback();407 break;408 }409}410 411void never_called_switch_default(int cond, void (^callback)(void) CALLED_ONCE) {412 switch (cond) {413 case 1:414 callback();415 break;416 case 2:417 callback();418 break;419 default: // expected-warning{{'callback' parameter marked 'called_once' is never called when handling this case}}420 break;421 }422}423 424void never_called_switch_two_cases(int cond, void (^callback)(void) CALLED_ONCE) {425 switch (cond) {426 case 1: // expected-warning{{'callback' parameter marked 'called_once' is never called when handling this case}}427 break;428 case 2: // expected-warning{{'callback' parameter marked 'called_once' is never called when handling this case}}429 break;430 default:431 callback();432 break;433 }434}435 436void never_called_switch_none(int cond, void (^callback)(void) CALLED_ONCE) {437 switch (cond) { // expected-warning{{'callback' parameter marked 'called_once' is never called when none of the cases applies}}438 case 1:439 callback();440 break;441 case 2:442 callback();443 break;444 }445}446 447enum YesNoOrMaybe {448 YES,449 NO,450 MAYBE451};452 453void exhaustive_switch(enum YesNoOrMaybe cond, void (^callback)(void) CALLED_ONCE) {454 switch (cond) {455 case YES:456 callback();457 break;458 case NO:459 callback();460 break;461 case MAYBE:462 callback();463 break;464 }465 // no-warning466}467 468void called_twice_exceptions(void (^callback)(void) CALLED_ONCE) {469 // TODO: Obj-C exceptions are not supported in CFG,470 // we should report warnings in these as well.471 @try {472 callback();473 callback();474 }475 @finally {476 callback();477 }478}479 480void noreturn_1(int cond, void (^callback)(void) CALLED_ONCE) {481 if (cond) {482 exit(1);483 } else {484 callback();485 }486 // no-warning487}488 489void noreturn_2(int cond, void (^callback)(void) CALLED_ONCE) {490 if (cond) {491 callback();492 exit(1);493 } else {494 callback();495 }496 // no-warning497}498 499void noreturn_3(int cond, void (^callback)(void) CALLED_ONCE) {500 if (cond) {501 exit(1);502 }503 504 callback();505 // no-warning506}507 508void noreturn_4(void (^callback)(void) CALLED_ONCE) {509 exit(1);510 // no-warning511}512 513void noreturn_5(int cond, void (^callback)(void) CALLED_ONCE) {514 if (cond) {515 // NOTE: This is an ambiguous case caused by the fact that we do a backward516 // analysis. We can probably report it here, but for the sake of517 // the simplicity of our analysis, we don't.518 if (cond == 42) {519 callback();520 }521 exit(1);522 }523 callback();524 // no-warning525}526 527void never_called_noreturn_1(int cond, void (^callback)(void) CALLED_ONCE) {528 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called}}529 if (cond) {530 exit(1);531 }532}533 534void double_call_noreturn(int cond, void (^callback)(void) CALLED_ONCE) {535 callback(); // expected-note{{previous call is here}}536 537 if (cond) {538 if (cond == 42) {539 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}540 }541 exit(1);542 }543}544 545void call_with_check_1(void (^callback)(void) CALLED_ONCE) {546 if (callback)547 callback();548 // no-warning549}550 551void call_with_check_2(void (^callback)(void) CALLED_ONCE) {552 if (!callback) {553 } else {554 callback();555 }556 // no-warning557}558 559void call_with_check_3(void (^callback)(void) CALLED_ONCE) {560 if (callback != NULL)561 callback();562 // no-warning563}564 565void call_with_check_4(void (^callback)(void) CALLED_ONCE) {566 if (NULL != callback)567 callback();568 // no-warning569}570 571void call_with_check_5(void (^callback)(void) CALLED_ONCE) {572 if (callback == NULL) {573 } else {574 callback();575 }576 // no-warning577}578 579void call_with_check_6(void (^callback)(void) CALLED_ONCE) {580 if (NULL == callback) {581 } else {582 callback();583 }584 // no-warning585}586 587int call_with_check_7(int (^callback)(void) CALLED_ONCE) {588 return callback ? callback() : 0;589 // no-warning590}591 592void call_with_builtin_check_1(int (^callback)(void) CALLED_ONCE) {593 if (LIKELY(callback))594 callback();595 // no-warning596}597 598void call_with_builtin_check_2(int (^callback)(void) CALLED_ONCE) {599 if (!UNLIKELY(callback)) {600 } else {601 callback();602 }603 // no-warning604}605 606void call_with_builtin_check_3(int (^callback)(void) CALLED_ONCE) {607 if (__builtin_expect((long)callback, 0L)) {608 } else {609 callback();610 }611 // no-warning612}613 614void call_with_builtin_check_4(int (^callback)(void) CALLED_ONCE) {615 if (__builtin_expect(0L, (long)callback)) {616 } else {617 callback();618 }619 // no-warning620}621 622void call_with_builtin_check_5(int (^callback)(void) CALLED_ONCE) {623 if (LIKELY_WITH_PROBA(callback, 0.9))624 callback();625 // no-warning626}627 628void call_with_builtin_check_6(int (^callback)(void) CALLED_ONCE) {629 if (!UNLIKELY_WITH_PROBA(callback, 0.9)) {630 } else {631 callback();632 }633 // no-warning634}635 636void call_with_builtin_check_7(int (^callback)(void) CALLED_ONCE) {637 if (UNPRED(callback)) {638 } else {639 callback();640 }641 // no-warning642}643 644void call_with_builtin_check_8(int (^callback)(void) CALLED_ONCE) {645 if (LIKELY(callback != nil))646 callback();647 // no-warning648}649 650void call_with_builtin_check_9(int (^callback)(void) CALLED_ONCE) {651 if (!UNLIKELY(callback == NULL))652 callback();653 // no-warning654}655 656void unreachable_true_branch(void (^callback)(void) CALLED_ONCE) {657 if (0) {658 659 } else {660 callback();661 }662 // no-warning663}664 665void unreachable_false_branch(void (^callback)(void) CALLED_ONCE) {666 if (1) {667 callback();668 }669 // no-warning670}671 672void never_called_conv_1(void (^completionHandler)(void)) {673 // expected-warning@-1{{completion handler is never called}}674}675 676void never_called_conv_2(void (^completion)(void)) {677 // expected-warning@-1{{completion handler is never called}}678}679 680void never_called_conv_WithCompletion(void (^callback)(void)) {681 // expected-warning@-1{{completion handler is never called}}682}683 684void indirectly_called_conv(void (^completionHandler)(void)) {685 indirect_conv(completionHandler);686 // no-warning687}688 689void escape_through_assignment_1(void (^callback)(void) CALLED_ONCE) {690 id escapee;691 escapee = callback;692 escape(escapee);693 // no-warning694}695 696void escape_through_assignment_2(void (^callback)(void) CALLED_ONCE) {697 id escapee = callback;698 escape(escapee);699 // no-warning700}701 702void escape_through_assignment_3(void (^callback1)(void) CALLED_ONCE,703 void (^callback2)(void) CALLED_ONCE) {704 id escapee1 = callback1, escapee2 = callback2;705 escape(escapee1);706 escape(escapee2);707 // no-warning708}709 710void not_called_in_throw_branch_1(id exception, void (^callback)(void) CALLED_ONCE) {711 if (exception) {712 @throw exception;713 }714 715 callback();716}717 718void not_called_in_throw_branch_2(id exception, void (^callback)(void) CALLED_ONCE) {719 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called}}720 if (exception) {721 @throw exception;722 }723}724 725void conventional_error_path_1(int error, void (^completionHandler)(void)) {726 if (error) {727 // expected-warning@-1{{completion handler is never called when taking true branch}}728 // This behavior might be tweaked in the future729 return;730 }731 732 completionHandler();733}734 735void conventional_error_path_2(int error, void (^callback)(void) CALLED_ONCE) {736 // Conventions do not apply to explicitly marked parameters.737 if (error) {738 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called when taking true branch}}739 return;740 }741 742 callback();743}744 745void suppression_1(void (^callback)(void) CALLED_ONCE) {746 // This is a way to tell the analysis that we know about this path,747 // and we do not want to call the callback here.748 (void)callback; // no-warning749}750 751void suppression_2(int cond, void (^callback)(void) CALLED_ONCE) {752 if (cond) {753 (void)callback; // no-warning754 } else {755 callback();756 }757}758 759void suppression_3(int cond, void (^callback)(void) CALLED_ONCE) {760 // Even if we do this on one of the paths, it doesn't mean we should761 // forget about other paths.762 if (cond) {763 // expected-warning@-1{{'callback' parameter marked 'called_once' is never used when taking false branch}}764 (void)callback;765 }766}767 768@interface TestBase : NSObject769- (void)escape:(void (^)(void))callback;770- (void)indirect_call:(void (^)(void))CALLED_ONCE callback;771- (void)indirect_call_conv_1:(int)cond772 completionHandler:(void (^)(void))completionHandler;773- (void)indirect_call_conv_2:(int)cond774 completionHandler:(void (^)(void))handler;775- (void)indirect_call_conv_3WithCompletion:(void (^)(void))handler;776- (void)indirect_call_conv_4:(void (^)(void))handler777 __attribute__((swift_async(swift_private, 1)));778- (void)exit:(int)code NORETURN;779- (int)condition;780@end781 782@interface TestClass : TestBase783@property(strong) NSMutableArray *handlers;784@property(strong) id storedHandler;785@property int wasCanceled;786@property(getter=hasErrors) int error;787@end788 789@implementation TestClass790 791- (void)double_indirect_call_1:(void (^)(void))CALLED_ONCE callback {792 [self indirect_call:callback]; // expected-note{{previous call is here}}793 [self indirect_call:callback]; // expected-warning{{'callback' parameter marked 'called_once' is called twice}}794}795 796- (void)double_indirect_call_2:(void (^)(void))CALLED_ONCE callback {797 [self indirect_call_conv_1:0 // expected-note{{previous call is here}}798 completionHandler:callback];799 [self indirect_call_conv_1:1 // expected-warning{{'callback' parameter marked 'called_once' is called twice}}800 completionHandler:callback];801}802 803- (void)double_indirect_call_3:(void (^)(void))completionHandler {804 [self indirect_call_conv_2:0 // expected-note{{previous call is here}}805 completionHandler:completionHandler];806 [self indirect_call_conv_2:1 // expected-warning{{completion handler is called twice}}807 completionHandler:completionHandler];808}809 810- (void)double_indirect_call_4:(void (^)(void))completion {811 [self indirect_call_conv_2:0 // expected-note{{previous call is here}}812 completionHandler:completion];813 [self indirect_call_conv_2:1 // expected-warning{{completion handler is called twice}}814 completionHandler:completion];815}816 817- (void)double_indirect_call_5:(void (^)(void))withCompletionHandler {818 [self indirect_call_conv_2:0 // expected-note{{previous call is here}}819 completionHandler:withCompletionHandler];820 [self indirect_call_conv_2:1 // expected-warning{{completion handler is called twice}}821 completionHandler:withCompletionHandler];822}823 824- (void)double_indirect_call_6:(void (^)(void))completionHandler {825 [self indirect_call_conv_3WithCompletion: // expected-note{{previous call is here}}826 completionHandler];827 [self indirect_call_conv_3WithCompletion: // expected-warning{{completion handler is called twice}}828 completionHandler];829}830 831- (void)double_indirect_call_7:(void (^)(void))completionHandler {832 [self indirect_call_conv_4: // expected-note{{previous call is here}}833 completionHandler];834 [self indirect_call_conv_4: // expected-warning{{completion handler is called twice}}835 completionHandler];836}837 838- (void)never_called_trivial:(void (^)(void))CALLED_ONCE callback {839 // expected-warning@-1{{'callback' parameter marked 'called_once' is never called}}840 filler();841}842 843- (void)noreturn:(int)cond callback:(void (^)(void))CALLED_ONCE callback {844 if (cond) {845 [self exit:1];846 }847 848 callback();849 // no-warning850}851 852- (void)escaped_one_path:(int)cond callback:(void (^)(void))CALLED_ONCE callback {853 if (cond) {854 [self escape:callback]; // no-warning855 } else {856 callback();857 }858}859 860- (void)block_call_1:(void (^)(void))CALLED_ONCE callback {861 // We consider captures by blocks as escapes862 [self indirect_call:(^{ // expected-note{{previous call is here}}863 callback();864 })];865 callback(); // expected-warning{{'callback' parameter marked 'called_once' is called twice}}866}867 868- (void)block_call_2:(int)cond callback:(void (^)(void))CALLED_ONCE callback {869 [self indirect_call:870 ^{871 if (cond) {872 // expected-warning@-1{{'callback' parameter marked 'called_once' is never used when taking false branch}}873 [self escape:callback];874 }875 }];876}877 878- (void)block_call_3:(int)cond879 completionHandler:(void (^)(void))callback {880 [self indirect_call:881 ^{882 if (cond) {883 // expected-warning@-1{{completion handler is never used when taking false branch}}884 [self escape:callback];885 }886 }];887}888 889- (void)block_call_4WithCompletion:(void (^)(void))callback {890 [self indirect_call:891 ^{892 if ([self condition]) {893 // expected-warning@-1{{completion handler is never used when taking false branch}}894 [self escape:callback];895 }896 }];897}898 899- (void)never_called_conv:(void (^)(void))completionHandler {900 // expected-warning@-1{{completion handler is never called}}901 filler();902}903 904- (void)indirectly_called_conv:(void (^)(void))completionHandler {905 indirect_conv(completionHandler);906 // no-warning907}908 909- (void)never_called_one_exit_conv:(int)cond completionHandler:(void (^)(void))handler {910 if (!cond) // expected-warning{{completion handler is never called when taking true branch}}911 return;912 913 handler();914}915 916- (void)escape_through_assignment:(void (^)(void))completionHandler {917 _storedHandler = completionHandler;918 // no-warning919}920 921- (void)escape_through_copy:(void (^)(void))completionHandler {922 _storedHandler = [completionHandler copy];923 // no-warning924}925 926- (void)escape_through_copy_and_autorelease:(void (^)(void))completionHandler {927 _storedHandler = [[completionHandler copy] autorelease];928 // no-warning929}930 931- (void)complex_escape:(void (^)(void))completionHandler {932 if (completionHandler) {933 [_handlers addObject:[[completionHandler copy] autorelease]];934 }935 // no-warning936}937 938- (void)test_crash:(void (^)(void))completionHandler cond:(int)cond {939 if (cond) {940 // expected-warning@-1{{completion handler is never used when taking false branch}}941 for (id _ in _handlers) {942 }943 944 [_handlers addObject:completionHandler];945 }946}947 948- (void)conventional_error_path_1:(void (^)(void))completionHandler {949 if (self.wasCanceled)950 // expected-warning@-1{{completion handler is never called when taking true branch}}951 // This behavior might be tweaked in the future952 return;953 954 completionHandler();955}956 957- (void)conventional_error_path_2:(void (^)(void))completionHandler {958 if (self.wasCanceled)959 // expected-warning@-1{{completion handler is never used when taking true branch}}960 // This behavior might be tweaked in the future961 return;962 963 [_handlers addObject:completionHandler];964}965 966- (void)conventional_error_path_3:(void (^)(void))completionHandler {967 if (self.hasErrors)968 // expected-warning@-1{{completion handler is never called when taking true branch}}969 // This behavior might be tweaked in the future970 return;971 972 completionHandler();973}974 975- (void)conventional_error_path_3:(int)cond completionHandler:(void (^)(void))handler {976 if (self.wasCanceled)977 // expected-warning@-1{{completion handler is never called when taking true branch}}978 // TODO: When we have an error on some other path, in order not to prevent it from979 // being reported, we report this one as well.980 // Probably, we should address this at some point.981 return;982 983 if (cond) {984 // expected-warning@-1{{completion handler is never called when taking false branch}}985 handler();986 }987}988 989#define NSAssert(condition, desc, ...) NSLog(desc, ##__VA_ARGS__);990 991- (void)empty_base_1:(void (^)(void))completionHandler {992 NSAssert(0, @"Subclass must implement");993 // no-warning994}995 996- (void)empty_base_2:(void (^)(void))completionHandler {997 // no-warning998}999 1000- (int)empty_base_3:(void (^)(void))completionHandler {1001 return 1;1002 // no-warning1003}1004 1005- (int)empty_base_4:(void (^)(void))completionHandler {1006 NSAssert(0, @"Subclass must implement");1007 return 1;1008 // no-warning1009}1010 1011- (int)empty_base_5:(void (^)(void))completionHandler {1012 NSAssert(0, @"%@ doesn't support", [self class]);1013 return 1;1014 // no-warning1015}1016 1017#undef NSAssert1018#define NSAssert(condition, desc, ...) \1019 if (!(condition)) { \1020 NSLog(desc, ##__VA_ARGS__); \1021 }1022 1023- (int)empty_base_6:(void (^)(void))completionHandler {1024 NSAssert(0, @"%@ doesn't support", [self class]);1025 return 1;1026 // no-warning1027}1028 1029#undef NSAssert1030#define NSAssert(condition, desc, ...) \1031 do { \1032 NSLog(desc, ##__VA_ARGS__); \1033 } while (0)1034 1035- (int)empty_base_7:(void (^)(void))completionHandler {1036 NSAssert(0, @"%@ doesn't support", [self class]);1037 return 1;1038 // no-warning1039}1040 1041- (void)two_conditions_1:(int)first1042 second:(int)second1043 completionHandler:(void (^)(void))completionHandler {1044 if (first && second) {1045 // expected-warning@-1{{completion handler is never called when taking false branch}}1046 completionHandler();1047 }1048}1049 1050- (void)two_conditions_2:(int)first1051 second:(int)second1052 completionHandler:(void (^)(void))completionHandler {1053 if (first || second) {1054 // expected-warning@-1{{completion handler is never called when taking true branch}}1055 return;1056 }1057 1058 completionHandler();1059}1060 1061- (void)testWithCompletionHandler:(void (^)(void))callback {1062 if ([self condition]) {1063 // expected-warning@-1{{completion handler is never called when taking false branch}}1064 callback();1065 }1066}1067 1068- (void)testWithCompletion:(void (^)(void))callback {1069 if ([self condition]) {1070 // expected-warning@-1{{completion handler is never called when taking false branch}}1071 callback();1072 }1073}1074 1075- (void)test:(int)cond fooWithReplyTo:(void (^)(void))handler {1076 if (cond) {1077 // expected-warning@-1{{completion handler is never called when taking false branch}}1078 handler();1079 }1080}1081 1082- (void)test:(int)cond with:(void (^)(void))fooWithCompletionBlock {1083 if (cond) {1084 // expected-warning@-1{{completion handler is never called when taking false branch}}1085 fooWithCompletionBlock();1086 }1087}1088 1089- (void)completion_handler_wrong_type:(int (^)(void))completionHandler {1090 // We don't want to consider completion handlers with non-void return types.1091 if ([self condition]) {1092 // no-warning1093 completionHandler();1094 }1095}1096 1097- (void)test_swift_async_none:(int)cond1098 completionHandler:(void (^)(void))handler __attribute__((swift_async(none))) {1099 if (cond) {1100 // no-warning1101 handler();1102 }1103}1104 1105- (void)test_swift_async_param:(int)cond1106 callback:(void (^)(void))callback1107 __attribute__((swift_async(swift_private, 2))) {1108 if (cond) {1109 // expected-warning@-1{{completion handler is never called when taking false branch}}1110 callback();1111 }1112}1113 1114- (void)test_nil_suggestion:(int)cond11115 second:(int)cond21116 completion:(void (^)(void))handler {1117 if (cond1) {1118 handler();1119 // expected-note@-1{{previous call is here; set to nil to indicate it cannot be called afterwards}}1120 }1121 1122 if (cond2) {1123 handler(); // expected-warning{{completion handler is called twice}}1124 }1125}1126 1127- (void)test_nil_suppression_1:(int)cond11128 second:(int)cond21129 completion:(void (^)(void))handler {1130 if (cond1) {1131 handler();1132 handler = nil;1133 // no-warning1134 }1135 1136 if (cond2) {1137 handler();1138 }1139}1140 1141- (void)test_nil_suppression_2:(int)cond11142 second:(int)cond21143 completion:(void (^)(void))handler {1144 if (cond1) {1145 handler();1146 handler = NULL;1147 // no-warning1148 }1149 1150 if (cond2) {1151 handler();1152 }1153}1154 1155- (void)test_nil_suppression_3:(int)cond11156 second:(int)cond21157 completion:(void (^)(void))handler {1158 if (cond1) {1159 handler();1160 handler = 0;1161 // no-warning1162 }1163 1164 if (cond2) {1165 handler();1166 }1167}1168 1169- (void)test_escape_before_branch:(int)cond1170 withCompletion:(void (^)(void))handler {1171 if (cond) {1172 filler();1173 }1174 1175 void (^copiedHandler)(void) = ^{1176 handler();1177 };1178 1179 if (cond) {1180 // no-warning1181 handler();1182 } else {1183 copiedHandler();1184 }1185}1186 1187- (void)test_escape_after_branch:(int)cond1188 withCompletion:(void (^)(void))handler {1189 if (cond) {1190 // no-warning1191 handler();1192 }1193 1194 escape(handler);1195}1196 1197- (void)test_termination:(int)cond1198 withCompletion:(void (^)(void))handler {1199 // The code below was able to cause non-termination but should be1200 // fixed now:1201 do {1202 escape(handler); 1203 handler(); // expected-warning{{completion handler is called twice}} expected-note{{previous call is here; set to nil to indicate it cannot be called afterwards}}1204 } while (cond);1205}1206 1207typedef void (^DeferredBlock)(void);1208static inline void DefferedCallback(DeferredBlock *inBlock) { (*inBlock)(); }1209#define _DEFERCONCAT(a, b) a##b1210#define _DEFERNAME(a) _DEFERCONCAT(__DeferredVar_, a)1211#define DEFER __extension__ __attribute__((cleanup(DefferedCallback), unused)) \1212 DeferredBlock _DEFERNAME(__COUNTER__) = ^1213 1214- (void)test_cleanup_1:(int)cond1215 withCompletion:(void (^)(void))handler {1216 int error = 0;1217 DEFER {1218 if (error)1219 handler();1220 };1221 1222 if (cond) {1223 error = 1;1224 } else {1225 // no-warning1226 handler();1227 }1228}1229 1230- (void)test_cleanup_2:(int)cond1231 withCompletion:(void (^)(void))handler {1232 int error = 0;1233 DEFER {1234 if (error)1235 handler();1236 };1237 1238 if (cond) {1239 error = 1;1240 } else {1241 handler(); // expected-note{{previous call is here}}1242 }1243 1244 // We still can warn about double call even in this case.1245 handler(); // expected-warning{{completion handler is called twice}}1246}1247 1248- (void)initWithAdditions:(int)cond1249 withCompletion:(void (^)(void))handler {1250 self = [self init];1251 if (self) {1252 escape(handler);1253 }1254 // no-warning1255}1256 1257@end1258