blob: 24ffe8975dd9e480460343979c2f79e734d73292 [file] [log] [blame]
George Karpenkov44a3b7c2018-03-12 18:27:36 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify
2typedef signed char BOOL;
3@protocol NSObject - (BOOL)isEqual:(id)object; @end
4@interface NSObject <NSObject> {}
5+(id)alloc;
6-(id)init;
7-(id)autorelease;
8-(id)copy;
9-(id)retain;
10@end
11
12typedef int dispatch_semaphore_t;
George Karpenkov628920b2018-03-23 00:16:02 +000013typedef int dispatch_group_t;
George Karpenkov44a3b7c2018-03-12 18:27:36 +000014typedef void (^block_t)();
15
16dispatch_semaphore_t dispatch_semaphore_create(int);
George Karpenkov628920b2018-03-23 00:16:02 +000017dispatch_group_t dispatch_group_create();
18void dispatch_group_enter(dispatch_group_t);
19void dispatch_group_leave(dispatch_group_t);
20void dispatch_group_wait(dispatch_group_t, int);
21
22
George Karpenkov44a3b7c2018-03-12 18:27:36 +000023void 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();
30
31void use_semaphor_antipattern() {
32 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
33
34 func(^{
35 dispatch_semaphore_signal(sema);
36 });
George Karpenkov47bb3f72018-05-16 22:46:47 +000037 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000038}
39
40// It's OK to use pattern in tests.
41// We simply match the containing function name against ^test.
42void test_no_warning() {
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() {
52 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
53
54 func(^{
55 dispatch_semaphore_signal(sema1);
56 });
George Karpenkov47bb3f72018-05-16 22:46:47 +000057 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000058
59 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
60
61 func(^{
62 dispatch_semaphore_signal(sema2);
63 });
George Karpenkov47bb3f72018-05-16 22:46:47 +000064 dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000065}
66
67void use_semaphor_antipattern_multiple_wait() {
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.
George Karpenkov47bb3f72018-05-16 22:46:47 +000074 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}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000076}
77
78void warn_incorrect_order() {
79 // FIXME: ASTMatchers do not allow ordered matching, so would match even
80 // if out of order.
81 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
82
George Karpenkov47bb3f72018-05-16 22:46:47 +000083 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000084 func(^{
85 dispatch_semaphore_signal(sema);
86 });
87}
88
89void warn_w_typedef() {
90 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
91
92 func_w_typedef(^{
93 dispatch_semaphore_signal(sema);
94 });
George Karpenkov47bb3f72018-05-16 22:46:47 +000095 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +000096}
97
98void warn_nested_ast() {
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 }
George Karpenkov47bb3f72018-05-16 22:46:47 +0000110 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000111}
112
113void use_semaphore_assignment() {
114 dispatch_semaphore_t sema;
115 sema = dispatch_semaphore_create(0);
116
117 func(^{
118 dispatch_semaphore_signal(sema);
119 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000120 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000121}
122
123void use_semaphore_assignment_init() {
124 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
125 sema = dispatch_semaphore_create(1);
126
127 func(^{
128 dispatch_semaphore_signal(sema);
129 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000130 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000131}
132
133void differentsemaphoreok() {
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-warning
141}
142
143void nosignalok() {
144 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
145 dispatch_semaphore_wait(sema1, 100);
146}
147
148void nowaitok() {
149 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
150 func(^{
151 dispatch_semaphore_signal(sema);
152 });
153}
154
155void noblockok() {
156 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
157 dispatch_semaphore_signal(sema);
158 dispatch_semaphore_wait(sema, 100);
159}
160
161void storedblockok() {
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() {
177 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
178
179 func(^{
180 dispatch_semaphore_signal((int)sema);
181 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000182 dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000183}
184
185@interface MyInterface1 : NSObject
186-(void)use_method_warn;
George Karpenkov460675e2018-03-13 17:27:01 +0000187-(void) pass_block_as_second_param_warn;
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000188-(void)use_objc_callback_warn;
George Karpenkov628920b2018-03-23 00:16:02 +0000189-(void) use_dispatch_group;
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000190-(void)testNoWarn;
191-(void)acceptBlock:(block_t)callback;
George Karpenkov460675e2018-03-13 17:27:01 +0000192-(void)flag:(int)flag acceptBlock:(block_t)callback;
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000193@end
194
195@implementation MyInterface1
196
197-(void)use_method_warn {
198 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
199
200 func(^{
201 dispatch_semaphore_signal(sema);
202 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000203 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000204}
205
George Karpenkov460675e2018-03-13 17:27:01 +0000206-(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 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000212 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
George Karpenkov460675e2018-03-13 17:27:01 +0000213}
214
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000215-(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
George Karpenkov460675e2018-03-13 17:27:01 +0000228-(void)flag:(int)flag acceptBlock:(block_t)callback {
229 callback();
230}
231
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000232-(void)use_objc_callback_warn {
233 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
234
235 [self acceptBlock:^{
236 dispatch_semaphore_signal(sema);
237 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000238 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000239}
240
George Karpenkov628920b2018-03-23 00:16:02 +0000241-(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 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000247 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
George Karpenkov628920b2018-03-23 00:16:02 +0000248
249}
250
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000251void 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 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000257 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000258
259 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
260
261 [t acceptBlock:^{
262 dispatch_semaphore_signal(sema1);
263 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000264 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback}}
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000265}
266@end
267
268// No warnings: class name contains "test"
269@interface Test1 : NSObject
270-(void)use_method_warn;
271@end
272
273@implementation Test1
274-(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@end
283
284
285// No warnings: class name contains "mock"
286@interface Mock1 : NSObject
287-(void)use_method_warn;
288@end
289
290@implementation Mock1
291-(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@end
George Karpenkov628920b2018-03-23 00:16:02 +0000300
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 });
George Karpenkov47bb3f72018-05-16 22:46:47 +0000308 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
George Karpenkov628920b2018-03-23 00:16:02 +0000309}
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 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000318 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
George Karpenkov628920b2018-03-23 00:16:02 +0000319}
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 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000327 dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
George Karpenkov628920b2018-03-23 00:16:02 +0000328
329 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
330
331 [M acceptBlock:^{
332 dispatch_semaphore_signal(sema1);
333 }];
George Karpenkov47bb3f72018-05-16 22:46:47 +0000334 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
George Karpenkov628920b2018-03-23 00:16:02 +0000335}
George Karpenkov09885d02018-07-16 20:32:57 +0000336
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-warning
344}
345