blob: 42e54dbfdc28ec2c67073816cc2f98d2d4fea738 [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;
13typedef void (^block_t)();
14
15dispatch_semaphore_t dispatch_semaphore_create(int);
16void dispatch_semaphore_wait(dispatch_semaphore_t, int);
17void dispatch_semaphore_signal(dispatch_semaphore_t);
18
19void func(void (^)(void));
20void func_w_typedef(block_t);
21
22int coin();
23
24void use_semaphor_antipattern() {
25 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
26
27 func(^{
28 dispatch_semaphore_signal(sema);
29 });
30 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
31}
32
33// It's OK to use pattern in tests.
34// We simply match the containing function name against ^test.
35void test_no_warning() {
36 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
37
38 func(^{
39 dispatch_semaphore_signal(sema);
40 });
41 dispatch_semaphore_wait(sema, 100);
42}
43
44void use_semaphor_antipattern_multiple_times() {
45 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
46
47 func(^{
48 dispatch_semaphore_signal(sema1);
49 });
50 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
51
52 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
53
54 func(^{
55 dispatch_semaphore_signal(sema2);
56 });
57 dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
58}
59
60void use_semaphor_antipattern_multiple_wait() {
61 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
62
63 func(^{
64 dispatch_semaphore_signal(sema1);
65 });
66 // FIXME: multiple waits on same semaphor should not raise a warning.
67 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
68 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
69}
70
71void warn_incorrect_order() {
72 // FIXME: ASTMatchers do not allow ordered matching, so would match even
73 // if out of order.
74 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
75
76 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
77 func(^{
78 dispatch_semaphore_signal(sema);
79 });
80}
81
82void warn_w_typedef() {
83 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
84
85 func_w_typedef(^{
86 dispatch_semaphore_signal(sema);
87 });
88 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
89}
90
91void warn_nested_ast() {
92 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
93
94 if (coin()) {
95 func(^{
96 dispatch_semaphore_signal(sema);
97 });
98 } else {
99 func(^{
100 dispatch_semaphore_signal(sema);
101 });
102 }
103 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
104}
105
106void use_semaphore_assignment() {
107 dispatch_semaphore_t sema;
108 sema = dispatch_semaphore_create(0);
109
110 func(^{
111 dispatch_semaphore_signal(sema);
112 });
113 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
114}
115
116void use_semaphore_assignment_init() {
117 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
118 sema = dispatch_semaphore_create(1);
119
120 func(^{
121 dispatch_semaphore_signal(sema);
122 });
123 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
124}
125
126void differentsemaphoreok() {
127 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
128 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
129
130 func(^{
131 dispatch_semaphore_signal(sema1);
132 });
133 dispatch_semaphore_wait(sema2, 100); // no-warning
134}
135
136void nosignalok() {
137 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
138 dispatch_semaphore_wait(sema1, 100);
139}
140
141void nowaitok() {
142 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
143 func(^{
144 dispatch_semaphore_signal(sema);
145 });
146}
147
148void noblockok() {
149 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
150 dispatch_semaphore_signal(sema);
151 dispatch_semaphore_wait(sema, 100);
152}
153
154void storedblockok() {
155 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
156 block_t b = ^{
157 dispatch_semaphore_signal(sema);
158 };
159 dispatch_semaphore_wait(sema, 100);
160}
161
162void passed_semaphore_ok(dispatch_semaphore_t sema) {
163 func(^{
164 dispatch_semaphore_signal(sema);
165 });
166 dispatch_semaphore_wait(sema, 100);
167}
168
169void warn_with_cast() {
170 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
171
172 func(^{
173 dispatch_semaphore_signal((int)sema);
174 });
175 dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
176}
177
178@interface MyInterface1 : NSObject
179-(void)use_method_warn;
George Karpenkov460675e2018-03-13 17:27:01 +0000180-(void) pass_block_as_second_param_warn;
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000181-(void)use_objc_callback_warn;
182-(void)testNoWarn;
183-(void)acceptBlock:(block_t)callback;
George Karpenkov460675e2018-03-13 17:27:01 +0000184-(void)flag:(int)flag acceptBlock:(block_t)callback;
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000185@end
186
187@implementation MyInterface1
188
189-(void)use_method_warn {
190 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
191
192 func(^{
193 dispatch_semaphore_signal(sema);
194 });
195 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
196}
197
George Karpenkov460675e2018-03-13 17:27:01 +0000198-(void) pass_block_as_second_param_warn {
199 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
200
201 [self flag:1 acceptBlock:^{
202 dispatch_semaphore_signal(sema);
203 }];
204 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
205}
206
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000207-(void)testNoWarn {
208 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
209
210 func(^{
211 dispatch_semaphore_signal(sema);
212 });
213 dispatch_semaphore_wait(sema, 100);
214}
215
216-(void)acceptBlock:(block_t) callback {
217 callback();
218}
219
George Karpenkov460675e2018-03-13 17:27:01 +0000220-(void)flag:(int)flag acceptBlock:(block_t)callback {
221 callback();
222}
223
George Karpenkov44a3b7c2018-03-12 18:27:36 +0000224-(void)use_objc_callback_warn {
225 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
226
227 [self acceptBlock:^{
228 dispatch_semaphore_signal(sema);
229 }];
230 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
231}
232
233void use_objc_and_c_callback(MyInterface1 *t) {
234 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
235
236 func(^{
237 dispatch_semaphore_signal(sema);
238 });
239 dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
240
241 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
242
243 [t acceptBlock:^{
244 dispatch_semaphore_signal(sema1);
245 }];
246 dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
247}
248@end
249
250// No warnings: class name contains "test"
251@interface Test1 : NSObject
252-(void)use_method_warn;
253@end
254
255@implementation Test1
256-(void)use_method_warn {
257 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
258
259 func(^{
260 dispatch_semaphore_signal(sema);
261 });
262 dispatch_semaphore_wait(sema, 100);
263}
264@end
265
266
267// No warnings: class name contains "mock"
268@interface Mock1 : NSObject
269-(void)use_method_warn;
270@end
271
272@implementation Mock1
273-(void)use_method_warn {
274 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
275
276 func(^{
277 dispatch_semaphore_signal(sema);
278 });
279 dispatch_semaphore_wait(sema, 100);
280}
281@end