blob: 34ce02c23fe13bcdeaed6eee795661e481b6fe50 [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
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000042void sls_fun_2() {
43 sls_mu.Lock();
44 int x = sls_guard_var;
45 sls_mu.Unlock();
46}
47
48void sls_fun_3() {
49 sls_mu.Lock();
50 sls_guard_var = 2;
51 sls_mu.Unlock();
52}
53
54void sls_fun_4() {
55 sls_mu2.Lock();
56 sls_guard_var = 2;
57 sls_mu2.Unlock();
58}
59
60void sls_fun_5() {
61 sls_mu.Lock();
62 int x = sls_guardby_var;
63 sls_mu.Unlock();
64}
65
66void sls_fun_6() {
67 sls_mu.Lock();
68 sls_guardby_var = 2;
69 sls_mu.Unlock();
70}
71
72void sls_fun_7() {
73 sls_mu.Lock();
74 sls_mu2.Lock();
75 sls_mu2.Unlock();
76 sls_mu.Unlock();
77}
78
79void sls_fun_8() {
80 sls_mu.Lock();
81 if (getBool())
82 sls_mu.Unlock();
83 else
84 sls_mu.Unlock();
85}
86
87void sls_fun_9() {
88 if (getBool())
89 sls_mu.Lock();
90 else
91 sls_mu.Lock();
92 sls_mu.Unlock();
93}
94
95void sls_fun_good_6() {
96 if (getBool()) {
97 sls_mu.Lock();
98 } else {
99 if (getBool()) {
100 getBool(); // EMPTY
101 } else {
102 getBool(); // EMPTY
103 }
104 sls_mu.Lock();
105 }
106 sls_mu.Unlock();
107}
108
109void sls_fun_good_7() {
110 sls_mu.Lock();
111 while (getBool()) {
112 sls_mu.Unlock();
113 if (getBool()) {
114 if (getBool()) {
115 sls_mu.Lock();
116 continue;
117 }
118 }
119 sls_mu.Lock();
120 }
121 sls_mu.Unlock();
122}
123
124void sls_fun_bad_1() {
125 sls_mu.Unlock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000126 // expected-warning{{unlocking 'sls_mu' that was not acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000127}
128
129void sls_fun_bad_2() {
130 sls_mu.Lock();
131 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000132 // expected-warning{{locking 'sls_mu' that is already acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000133 sls_mu.Unlock();
134}
135
136void sls_fun_bad_3() {
137 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000138 // expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000139}
140
141void sls_fun_bad_4() {
142 if (getBool())
143 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000144 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000145 else
146 sls_mu2.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000147 // expected-warning{{lock 'sls_mu2' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000148}
149
150void sls_fun_bad_5() {
151 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000152 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000153 if (getBool())
154 sls_mu.Unlock();
155}
156
157void sls_fun_bad_6() {
158 if (getBool()) {
159 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000160 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000161 } else {
162 if (getBool()) {
163 getBool(); // EMPTY
164 } else {
165 getBool(); // EMPTY
166 }
167 }
168 sls_mu.Unlock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000169 // expected-warning{{unlocking 'sls_mu' that was not acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000170}
171
172void sls_fun_bad_7() {
173 sls_mu.Lock();
174 while (getBool()) { // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000175 // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000176 sls_mu.Unlock();
177 if (getBool()) {
178 if (getBool()) {
179 continue;
180 }
181 }
182 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000183 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000184 }
185 sls_mu.Unlock();
186}
187
188void sls_fun_bad_8() {
189 sls_mu.Lock();
190 do {
191 sls_mu.Unlock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000192 // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000193 } while (getBool());
194}
195
196void sls_fun_bad_9() {
197 do {
198 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000199 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000200 } while (getBool());
201 sls_mu.Unlock();
202}
203
204void sls_fun_bad_10() {
205 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000206 // expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_10'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000207 while(getBool()) { // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000208 // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000209 sls_mu.Unlock();
210 }
211}
212
213void sls_fun_bad_11() {
214 while (getBool()) {
215 sls_mu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000216 // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000217 }
218 sls_mu.Unlock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000219 // expected-warning{{unlocking 'sls_mu' that was not acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000220}
221
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222//-----------------------------------------//
223// Handling lock expressions in attribute args
224// -------------------------------------------//
225
226Mutex aa_mu;
227
228class GlobalLocker {
229public:
230 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
231 void globalUnlock() __attribute__((unlock_function(aa_mu)));
232};
233
234GlobalLocker glock;
235
236void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
237void aa_elr_fun() { }
238
239void aa_fun_1() {
240 glock.globalLock();
241 glock.globalUnlock();
242}
243
244void aa_fun_2() {
245 aa_mu.Lock();
246 aa_elr_fun();
247 aa_mu.Unlock();
248}
249
250void aa_fun_bad_1() {
251 glock.globalUnlock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000252 // expected-warning{{unlocking 'aa_mu' that was not acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000253}
254
255void aa_fun_bad_2() {
256 glock.globalLock();
257 glock.globalLock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000258 // expected-warning{{locking 'aa_mu' that is already acquired}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000259 glock.globalUnlock();
260}
261
262void aa_fun_bad_3() {
263 glock.globalLock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000264 // expected-warning{{lock 'aa_mu' is not released at the end of function 'aa_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000265}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000266
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000267//--------------------------------------------------//
268// Regression tests for unusual method names
269//--------------------------------------------------//
270
271Mutex wmu;
272
273// Test diagnostics for other method names.
274class WeirdMethods {
275 WeirdMethods() {
276 wmu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000277 // expected-warning {{lock 'wmu' is not released at the end of function 'WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000278 }
279 ~WeirdMethods() {
280 wmu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000281 // expected-warning {{lock 'wmu' is not released at the end of function '~WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000282 }
283 void operator++() {
284 wmu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000285 // expected-warning {{lock 'wmu' is not released at the end of function 'operator++'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000286 }
287 operator int*() {
288 wmu.Lock(); // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000289 // expected-warning {{lock 'wmu' is not released at the end of function 'operator int *'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000290 return 0;
291 }
292};
293
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000294//-----------------------------------------------//
295// Errors for guarded by or guarded var variables
296// ----------------------------------------------//
297
298int *pgb_gvar __attribute__((pt_guarded_var));
299int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
300
301class PGBFoo {
302 public:
303 int x;
304 int *pgb_field __attribute__((guarded_by(sls_mu2)))
305 __attribute__((pt_guarded_by(sls_mu)));
306 void testFoo() {
307 pgb_field = &x; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000308 // expected-warning {{writing variable 'pgb_field' requires lock 'sls_mu2' to be held exclusively}}
309 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
310 // expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
311 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
312 // expected-warning {{reading the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held}}
313 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
314 // expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000315 }
316};
317
318class GBFoo {
319 public:
320 int gb_field __attribute__((guarded_by(sls_mu)));
321
322 void testFoo() {
323 gb_field = 0; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000324 // expected-warning {{writing variable 'gb_field' requires lock 'sls_mu' to be held exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000325 }
326};
327
328GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
329
330void gb_fun_0() {
331 sls_mu.Lock();
332 int x = *pgb_var;
333 sls_mu.Unlock();
334}
335
336void gb_fun_1() {
337 sls_mu.Lock();
338 *pgb_var = 2;
339 sls_mu.Unlock();
340}
341
342void gb_fun_2() {
343 int x;
344 pgb_var = &x;
345}
346
347void gb_fun_3() {
348 int *x = pgb_var;
349}
350
351void gb_bad_0() {
352 sls_guard_var = 1; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000353 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000354}
355
356void gb_bad_1() {
357 int x = sls_guard_var; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000358 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000359}
360
361void gb_bad_2() {
362 sls_guardby_var = 1; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000363 // expected-warning {{writing variable 'sls_guardby_var' requires lock 'sls_mu' to be held exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000364}
365
366void gb_bad_3() {
367 int x = sls_guardby_var; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000368 // expected-warning {{reading variable 'sls_guardby_var' requires lock 'sls_mu' to be held}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000369}
370
371void gb_bad_4() {
372 *pgb_gvar = 1; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000373 // expected-warning {{accessing the value pointed to by 'pgb_gvar' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000374}
375
376void gb_bad_5() {
377 int x = *pgb_gvar; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000378 // expected-warning {{accessing the value pointed to by 'pgb_gvar' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000379}
380
381void gb_bad_6() {
382 *pgb_var = 1; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000383 // expected-warning {{writing the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000384}
385
386void gb_bad_7() {
387 int x = *pgb_var; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000388 // expected-warning {{reading the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000389}
390
391void gb_bad_8() {
392 GBFoo G;
393 G.gb_field = 0; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000394 // expected-warning {{writing variable 'gb_field' requires lock 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000395}
396
397void gb_bad_9() {
398 sls_guard_var++; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000399 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000400 sls_guard_var--; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000401 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000402 ++sls_guard_var; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000403 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000404 --sls_guard_var; // \
Caitlin Sadowski3bb43582011-09-08 18:07:26 +0000405 // expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000406}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000407
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000408//-----------------------------------------------//
409// Warnings on variables with late parsed attributes
410// ----------------------------------------------//
411
412class LateFoo {
413public:
414 int a __attribute__((guarded_by(mu)));
415 int b;
416
417 void foo() __attribute__((exclusive_locks_required(mu))) { }
418
419 void test() {
420 a = 0; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000421 // expected-warning{{writing variable 'a' requires lock 'mu' to be held exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000422 b = a; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000423 // expected-warning {{reading variable 'a' requires lock 'mu' to be held}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000424 c = 0; // \
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000425 // expected-warning {{writing variable 'c' requires lock 'mu' to be held exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000426 }
427
428 int c __attribute__((guarded_by(mu)));
429
430 Mutex mu;
431};
432
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000433//-----------------------------------------------//
434// Extra warnings for shared vs. exclusive locks
435// ----------------------------------------------//
436
437void shared_fun_0() {
438 sls_mu.Lock();
439 do {
440 sls_mu.Unlock();
441 sls_mu.Lock();
442 } while (getBool());
443 sls_mu.Unlock();
444}
445
446void shared_fun_1() {
447 sls_mu.ReaderLock();
448 do {
449 sls_mu.Unlock();
450 sls_mu.Lock(); // \
451 // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
452 } while (getBool());
453 sls_mu.Unlock();
454}
455
456void shared_fun_3() {
457 if (getBool())
458 sls_mu.Lock();
459 else
460 sls_mu.Lock();
461 *pgb_var = 1;
462 sls_mu.Unlock();
463}
464
465void shared_fun_4() {
466 if (getBool())
467 sls_mu.ReaderLock();
468 else
469 sls_mu.ReaderLock();
470 int x = sls_guardby_var;
471 sls_mu.Unlock();
472}
473
474void shared_fun_8() {
475 if (getBool())
476 sls_mu.Lock(); // \
477 // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
478 else
479 sls_mu.ReaderLock(); // \
480 // expected-note {{the other acquire of lock 'sls_mu' is here}}
481 sls_mu.Unlock();
482}
483
484void shared_bad_0() {
485 sls_mu.Lock();
486 do {
487 sls_mu.Unlock();
488 sls_mu.ReaderLock(); // \
489 // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
490 } while (getBool());
491 sls_mu.Unlock();
492}
493
494void shared_bad_1() {
495 if (getBool())
496 sls_mu.Lock(); // \
497 // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
498 else
499 sls_mu.ReaderLock(); // \
500 // expected-note {{the other acquire of lock 'sls_mu' is here}}
501 *pgb_var = 1;
502 sls_mu.Unlock();
503}
504
505void shared_bad_2() {
506 if (getBool())
507 sls_mu.ReaderLock(); // \
508 // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
509 else
510 sls_mu.Lock(); // \
511 // expected-note {{the other acquire of lock 'sls_mu' is here}}
512 *pgb_var = 1;
513 sls_mu.Unlock();
514}