346 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify2typedef signed char BOOL;3@protocol NSObject - (BOOL)isEqual:(id)object; @end4@interface NSObject <NSObject> {}5+(id)alloc;6-(id)init;7-(id)autorelease;8-(id)copy;9-(id)retain;10@end11 12typedef int dispatch_semaphore_t;13typedef int dispatch_group_t;14typedef void (^block_t)(void);15 16dispatch_semaphore_t dispatch_semaphore_create(int);17dispatch_group_t dispatch_group_create(void);18void dispatch_group_enter(dispatch_group_t);19void dispatch_group_leave(dispatch_group_t);20void dispatch_group_wait(dispatch_group_t, int);21 22 23void dispatch_semaphore_wait(dispatch_semaphore_t, int);24void dispatch_semaphore_signal(dispatch_semaphore_t);25 26void func(void (^)(void));27void func_w_typedef(block_t);28 29int coin(void);30 31void use_semaphor_antipattern(void) {32 dispatch_semaphore_t sema = dispatch_semaphore_create(0);33 34 func(^{35 dispatch_semaphore_signal(sema);36 });37 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}38}39 40// It's OK to use pattern in tests.41// We simply match the containing function name against ^test.42void test_no_warning(void) {43 dispatch_semaphore_t sema = dispatch_semaphore_create(0);44 45 func(^{46 dispatch_semaphore_signal(sema);47 });48 dispatch_semaphore_wait(sema, 100);49}50 51void use_semaphor_antipattern_multiple_times(void) {52 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);53 54 func(^{55 dispatch_semaphore_signal(sema1);56 });57 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}58 59 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);60 61 func(^{62 dispatch_semaphore_signal(sema2);63 });64 dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a callback using a semaphore}}65}66 67void use_semaphor_antipattern_multiple_wait(void) {68 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);69 70 func(^{71 dispatch_semaphore_signal(sema1);72 });73 // FIXME: multiple waits on same semaphor should not raise a warning.74 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}75 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}76}77 78void warn_incorrect_order(void) {79 // FIXME: ASTMatchers do not allow ordered matching, so would match even80 // if out of order.81 dispatch_semaphore_t sema = dispatch_semaphore_create(0);82 83 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}84 func(^{85 dispatch_semaphore_signal(sema);86 });87}88 89void warn_w_typedef(void) {90 dispatch_semaphore_t sema = dispatch_semaphore_create(0);91 92 func_w_typedef(^{93 dispatch_semaphore_signal(sema);94 });95 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}96}97 98void warn_nested_ast(void) {99 dispatch_semaphore_t sema = dispatch_semaphore_create(0);100 101 if (coin()) {102 func(^{103 dispatch_semaphore_signal(sema);104 });105 } else {106 func(^{107 dispatch_semaphore_signal(sema);108 });109 }110 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}111}112 113void use_semaphore_assignment(void) {114 dispatch_semaphore_t sema;115 sema = dispatch_semaphore_create(0);116 117 func(^{118 dispatch_semaphore_signal(sema);119 });120 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}121}122 123void use_semaphore_assignment_init(void) {124 dispatch_semaphore_t sema = dispatch_semaphore_create(0);125 sema = dispatch_semaphore_create(1);126 127 func(^{128 dispatch_semaphore_signal(sema);129 });130 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}131}132 133void differentsemaphoreok(void) {134 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);135 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);136 137 func(^{138 dispatch_semaphore_signal(sema1);139 });140 dispatch_semaphore_wait(sema2, 100); // no-warning141}142 143void nosignalok(void) {144 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);145 dispatch_semaphore_wait(sema1, 100);146}147 148void nowaitok(void) {149 dispatch_semaphore_t sema = dispatch_semaphore_create(0);150 func(^{151 dispatch_semaphore_signal(sema);152 });153}154 155void noblockok(void) {156 dispatch_semaphore_t sema = dispatch_semaphore_create(0);157 dispatch_semaphore_signal(sema);158 dispatch_semaphore_wait(sema, 100);159}160 161void storedblockok(void) {162 dispatch_semaphore_t sema = dispatch_semaphore_create(0);163 block_t b = ^{164 dispatch_semaphore_signal(sema);165 };166 dispatch_semaphore_wait(sema, 100);167}168 169void passed_semaphore_ok(dispatch_semaphore_t sema) {170 func(^{171 dispatch_semaphore_signal(sema);172 });173 dispatch_semaphore_wait(sema, 100);174}175 176void warn_with_cast(void) {177 dispatch_semaphore_t sema = dispatch_semaphore_create(0);178 179 func(^{180 dispatch_semaphore_signal((int)sema);181 });182 dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}183}184 185@interface MyInterface1 : NSObject186-(void)use_method_warn;187-(void) pass_block_as_second_param_warn;188-(void)use_objc_callback_warn;189-(void) use_dispatch_group;190-(void)testNoWarn;191-(void)acceptBlock:(block_t)callback;192-(void)flag:(int)flag acceptBlock:(block_t)callback;193@end194 195@implementation MyInterface1196 197-(void)use_method_warn {198 dispatch_semaphore_t sema = dispatch_semaphore_create(0);199 200 func(^{201 dispatch_semaphore_signal(sema);202 });203 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}204}205 206-(void) pass_block_as_second_param_warn {207 dispatch_semaphore_t sema = dispatch_semaphore_create(0);208 209 [self flag:1 acceptBlock:^{210 dispatch_semaphore_signal(sema);211 }];212 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}213}214 215-(void)testNoWarn {216 dispatch_semaphore_t sema = dispatch_semaphore_create(0);217 218 func(^{219 dispatch_semaphore_signal(sema);220 });221 dispatch_semaphore_wait(sema, 100);222}223 224-(void)acceptBlock:(block_t) callback {225 callback();226}227 228-(void)flag:(int)flag acceptBlock:(block_t)callback {229 callback();230}231 232-(void)use_objc_callback_warn {233 dispatch_semaphore_t sema = dispatch_semaphore_create(0);234 235 [self acceptBlock:^{236 dispatch_semaphore_signal(sema);237 }];238 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}239}240 241-(void)use_dispatch_group {242 dispatch_group_t group = dispatch_group_create();243 dispatch_group_enter(group);244 [self acceptBlock:^{245 dispatch_group_leave(group);246 }];247 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}248 249}250 251void use_objc_and_c_callback(MyInterface1 *t) {252 dispatch_semaphore_t sema = dispatch_semaphore_create(0);253 254 func(^{255 dispatch_semaphore_signal(sema);256 });257 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}258 259 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);260 261 [t acceptBlock:^{262 dispatch_semaphore_signal(sema1);263 }];264 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback}}265}266@end267 268// No warnings: class name contains "test"269@interface Test1 : NSObject270-(void)use_method_warn;271@end272 273@implementation Test1274-(void)use_method_warn {275 dispatch_semaphore_t sema = dispatch_semaphore_create(0);276 277 func(^{278 dispatch_semaphore_signal(sema);279 });280 dispatch_semaphore_wait(sema, 100);281}282@end283 284 285// No warnings: class name contains "mock"286@interface Mock1 : NSObject287-(void)use_method_warn;288@end289 290@implementation Mock1291-(void)use_method_warn {292 dispatch_semaphore_t sema = dispatch_semaphore_create(0);293 294 func(^{295 dispatch_semaphore_signal(sema);296 });297 dispatch_semaphore_wait(sema, 100);298}299@end300 301void dispatch_group_wait_func(MyInterface1 *M) {302 dispatch_group_t group = dispatch_group_create();303 dispatch_group_enter(group);304 305 func(^{306 dispatch_group_leave(group);307 });308 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}309}310 311 312void dispatch_group_wait_cfunc(MyInterface1 *M) {313 dispatch_group_t group = dispatch_group_create();314 dispatch_group_enter(group);315 [M acceptBlock:^{316 dispatch_group_leave(group);317 }];318 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}319}320 321void dispatch_group_and_semaphore_use(MyInterface1 *M) {322 dispatch_group_t group = dispatch_group_create();323 dispatch_group_enter(group);324 [M acceptBlock:^{325 dispatch_group_leave(group);326 }];327 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}328 329 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);330 331 [M acceptBlock:^{332 dispatch_semaphore_signal(sema1);333 }];334 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}335}336 337void no_warn_on_nonzero_semaphore(MyInterface1 *M) {338 dispatch_semaphore_t sema1 = dispatch_semaphore_create(1);339 340 [M acceptBlock:^{341 dispatch_semaphore_signal(sema1);342 }];343 dispatch_semaphore_wait(sema1, 100); // no-warning344}345 346