blob: 831c26ca3b25b7f5f035a7563b8310b4fd632e49 [file] [log] [blame]
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
2
3
4//-----------------------------------------//
5// Helper fields
6//-----------------------------------------//
7
8
9class __attribute__((lockable)) Mutex {
10 public:
11 void Lock() __attribute__((exclusive_lock_function));
12 void ReaderLock() __attribute__((shared_lock_function));
13 void Unlock() __attribute__((unlock_function));
14 bool TryLock() __attribute__((exclusive_trylock_function(true)));
15 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
16 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
17};
18
19
20Mutex sls_mu;
21
22Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
23int sls_guard_var __attribute__((guarded_var)) = 0;
24int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
25
26bool getBool();
27
28class MutexWrapper {
29public:
30 Mutex mu;
31 // int x __attribute__((guarded_by(mu))); // FIXME: scoping error
32};
33
34MutexWrapper sls_mw;
35
36void sls_fun_0() {
37 sls_mw.mu.Lock();
38 // sls_mw.x = 5; // FIXME: turn mu into sls_mw.mu
39 sls_mw.mu.Unlock();
40}
41
42
43void sls_fun_2() {
44 sls_mu.Lock();
45 int x = sls_guard_var;
46 sls_mu.Unlock();
47}
48
49void sls_fun_3() {
50 sls_mu.Lock();
51 sls_guard_var = 2;
52 sls_mu.Unlock();
53}
54
55void sls_fun_4() {
56 sls_mu2.Lock();
57 sls_guard_var = 2;
58 sls_mu2.Unlock();
59}
60
61void sls_fun_5() {
62 sls_mu.Lock();
63 int x = sls_guardby_var;
64 sls_mu.Unlock();
65}
66
67void sls_fun_6() {
68 sls_mu.Lock();
69 sls_guardby_var = 2;
70 sls_mu.Unlock();
71}
72
73void sls_fun_7() {
74 sls_mu.Lock();
75 sls_mu2.Lock();
76 sls_mu2.Unlock();
77 sls_mu.Unlock();
78}
79
80void sls_fun_8() {
81 sls_mu.Lock();
82 if (getBool())
83 sls_mu.Unlock();
84 else
85 sls_mu.Unlock();
86}
87
88void sls_fun_9() {
89 if (getBool())
90 sls_mu.Lock();
91 else
92 sls_mu.Lock();
93 sls_mu.Unlock();
94}
95
96void sls_fun_good_6() {
97 if (getBool()) {
98 sls_mu.Lock();
99 } else {
100 if (getBool()) {
101 getBool(); // EMPTY
102 } else {
103 getBool(); // EMPTY
104 }
105 sls_mu.Lock();
106 }
107 sls_mu.Unlock();
108}
109
110void sls_fun_good_7() {
111 sls_mu.Lock();
112 while (getBool()) {
113 sls_mu.Unlock();
114 if (getBool()) {
115 if (getBool()) {
116 sls_mu.Lock();
117 continue;
118 }
119 }
120 sls_mu.Lock();
121 }
122 sls_mu.Unlock();
123}
124
125void sls_fun_bad_1() {
126 sls_mu.Unlock(); // \
127 expected-warning {{unlocking 'sls_mu' that was not acquired}}
128}
129
130void sls_fun_bad_2() {
131 sls_mu.Lock();
132 sls_mu.Lock(); // \
133 expected-warning {{locking 'sls_mu' that is already acquired}}
134 sls_mu.Unlock();
135}
136
137void sls_fun_bad_3() {
138 sls_mu.Lock(); // \
139 expected-warning {{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_3'}}
140}
141
142void sls_fun_bad_4() {
143 if (getBool())
144 sls_mu.Lock(); // \
145 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
146 else
147 sls_mu2.Lock(); // \
148 expected-warning {{lock 'sls_mu2' is not released at the end of its scope}}
149}
150
151void sls_fun_bad_5() {
152 sls_mu.Lock(); // \
153 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
154 if (getBool())
155 sls_mu.Unlock();
156}
157
158void sls_fun_bad_6() {
159 if (getBool()) {
160 sls_mu.Lock(); // \
161 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
162 } else {
163 if (getBool()) {
164 getBool(); // EMPTY
165 } else {
166 getBool(); // EMPTY
167 }
168 }
169 sls_mu.Unlock(); // \
170 expected-warning {{unlocking 'sls_mu' that was not acquired}}
171}
172
173void sls_fun_bad_7() {
174 sls_mu.Lock();
175 while (getBool()) { // \
176 expected-warning {{expecting lock 'sls_mu' to be held at start of each loop}}
177 sls_mu.Unlock();
178 if (getBool()) {
179 if (getBool()) {
180 continue;
181 }
182 }
183 sls_mu.Lock(); // \
184 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
185 }
186 sls_mu.Unlock();
187}
188
189void sls_fun_bad_8() {
190 sls_mu.Lock();
191 do {
192 sls_mu.Unlock(); // \
193 expected-warning {{expecting lock 'sls_mu' to be held at start of each loop}}
194 } while (getBool());
195}
196
197void sls_fun_bad_9() {
198 do {
199 sls_mu.Lock(); // \
200 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
201 } while (getBool());
202 sls_mu.Unlock();
203}
204
205void sls_fun_bad_10() {
206 sls_mu.Lock(); // \
207 expected-warning {{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_10'}}
208 while(getBool()) { // \
209 expected-warning {{expecting lock 'sls_mu' to be held at start of each loop}}
210 sls_mu.Unlock();
211 }
212}
213
214void sls_fun_bad_11() {
215 while (getBool()) {
216 sls_mu.Lock(); // \
217 expected-warning {{lock 'sls_mu' is not released at the end of its scope}}
218 }
219 sls_mu.Unlock(); // \
220 expected-warning {{unlocking 'sls_mu' that was not acquired}}
221}
222
223
224//-----------------------------------------//
225// Handling lock expressions in attribute args
226// -------------------------------------------//
227
228Mutex aa_mu;
229
230class GlobalLocker {
231public:
232 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
233 void globalUnlock() __attribute__((unlock_function(aa_mu)));
234};
235
236GlobalLocker glock;
237
238void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
239void aa_elr_fun() { }
240
241void aa_fun_1() {
242 glock.globalLock();
243 glock.globalUnlock();
244}
245
246void aa_fun_2() {
247 aa_mu.Lock();
248 aa_elr_fun();
249 aa_mu.Unlock();
250}
251
252void aa_fun_bad_1() {
253 glock.globalUnlock(); // \
254 expected-warning {{unlocking 'aa_mu' that was not acquired}}
255}
256
257void aa_fun_bad_2() {
258 glock.globalLock();
259 glock.globalLock(); // \
260 expected-warning {{locking 'aa_mu' that is already acquired}}
261 glock.globalUnlock();
262}
263
264void aa_fun_bad_3() {
265 glock.globalLock(); // \
266 expected-warning {{lock 'aa_mu' is not released at the end of function 'aa_fun_bad_3'}}
267}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000268
269
270//--------------------------------------------------//
271// Regression tests for unusual method names
272//--------------------------------------------------//
273
274Mutex wmu;
275
276// Test diagnostics for other method names.
277class WeirdMethods {
278 WeirdMethods() {
279 wmu.Lock(); // \
280 expected-warning {{lock 'wmu' is not released at the end of function 'WeirdMethods'}}
281 }
282 ~WeirdMethods() {
283 wmu.Lock(); // \
284 expected-warning {{lock 'wmu' is not released at the end of function '~WeirdMethods'}}
285 }
286 void operator++() {
287 wmu.Lock(); // \
288 expected-warning {{lock 'wmu' is not released at the end of function 'operator++'}}
289 }
290 operator int*() {
291 wmu.Lock(); // \
292 expected-warning {{lock 'wmu' is not released at the end of function 'operator int *'}}
293 return 0;
294 }
295};
296
297