]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/gcdantipatternchecker_test.m
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / test / Analysis / gcdantipatternchecker_test.m
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify
2 typedef 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
12 typedef int dispatch_semaphore_t;
13 typedef int dispatch_group_t;
14 typedef void (^block_t)();
15
16 dispatch_semaphore_t dispatch_semaphore_create(int);
17 dispatch_group_t dispatch_group_create();
18 void dispatch_group_enter(dispatch_group_t);
19 void dispatch_group_leave(dispatch_group_t);
20 void dispatch_group_wait(dispatch_group_t, int);
21
22
23 void dispatch_semaphore_wait(dispatch_semaphore_t, int);
24 void dispatch_semaphore_signal(dispatch_semaphore_t);
25
26 void func(void (^)(void));
27 void func_w_typedef(block_t);
28
29 int coin();
30
31 void use_semaphor_antipattern() {
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.
42 void 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
51 void use_semaphor_antipattern_multiple_times() {
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
67 void 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.
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
78 void 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
83   dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
84   func(^{
85       dispatch_semaphore_signal(sema);
86   });
87 }
88
89 void warn_w_typedef() {
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
98 void 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   }
110   dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
111 }
112
113 void use_semaphore_assignment() {
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
123 void 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   });
130   dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
131 }
132
133 void 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
143 void nosignalok() {
144   dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
145   dispatch_semaphore_wait(sema1, 100);
146 }
147
148 void nowaitok() {
149   dispatch_semaphore_t sema = dispatch_semaphore_create(0);
150   func(^{
151       dispatch_semaphore_signal(sema);
152   });
153 }
154
155 void noblockok() {
156   dispatch_semaphore_t sema = dispatch_semaphore_create(0);
157   dispatch_semaphore_signal(sema);
158   dispatch_semaphore_wait(sema, 100);
159 }
160
161 void 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
169 void passed_semaphore_ok(dispatch_semaphore_t sema) {
170   func(^{
171       dispatch_semaphore_signal(sema);
172   });
173   dispatch_semaphore_wait(sema, 100);
174 }
175
176 void warn_with_cast() {
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 : NSObject
186 -(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 @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   });
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
251 void 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 @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
300
301 void 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
312 void 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
321 void 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
337 void 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