1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.GCDAsyncSemaphore %s -fblocks -verify
//
typedef int dispatch_semaphore_t;
typedef void (^block_t)();
dispatch_semaphore_t dispatch_semaphore_create(int);
void dispatch_semaphore_wait(dispatch_semaphore_t, int);
void dispatch_semaphore_signal(dispatch_semaphore_t);
void func(void (^)(void));
void func_w_typedef(block_t);
int coin();
void use_semaphor_antipattern() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
// It's OK to use pattern in tests.
// We simply match the containing function name against ^test.
void test_no_warning() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100);
}
void use_semaphor_antipattern_multiple_times() {
dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema1);
});
dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema2);
});
dispatch_semaphore_wait(sema2, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void use_semaphor_antipattern_multiple_wait() {
dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema1);
});
// FIXME: multiple waits on same semaphor should not raise a warning.
dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void warn_incorrect_order() {
// FIXME: ASTMatchers do not allow ordered matching, so would match even
// if out of order.
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
func(^{
dispatch_semaphore_signal(sema);
});
}
void warn_w_typedef() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
func_w_typedef(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void warn_nested_ast() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
if (coin()) {
func(^{
dispatch_semaphore_signal(sema);
});
} else {
func(^{
dispatch_semaphore_signal(sema);
});
}
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void use_semaphore_assignment() {
dispatch_semaphore_t sema;
sema = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void use_semaphore_assignment_init() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
sema = dispatch_semaphore_create(1);
func(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
void differentsemaphoreok() {
dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema1);
});
dispatch_semaphore_wait(sema2, 100); // no-warning
}
void nosignalok() {
dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
dispatch_semaphore_wait(sema1, 100);
}
void nowaitok() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal(sema);
});
}
void noblockok() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_semaphore_signal(sema);
dispatch_semaphore_wait(sema, 100);
}
void storedblockok() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
block_t b = ^{
dispatch_semaphore_signal(sema);
};
dispatch_semaphore_wait(sema, 100);
}
void passed_semaphore_ok(dispatch_semaphore_t sema) {
func(^{
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, 100);
}
void warn_with_cast() {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
func(^{
dispatch_semaphore_signal((int)sema);
});
dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
}
|