1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
4 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
5
6 // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
7 // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
8
9 #include "thread-safety-annotations.h"
10
11 class LOCKABLE Mutex {
12 public:
13 void Lock() EXCLUSIVE_LOCK_FUNCTION();
14 void ReaderLock() SHARED_LOCK_FUNCTION();
15 void Unlock() UNLOCK_FUNCTION();
16 void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
17 void ReaderUnlock() SHARED_UNLOCK_FUNCTION();
18 bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
19 bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
20 void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION();
21
22 void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
23 void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
24
25 // for negative capabilities
operator !() const26 const Mutex& operator!() const { return *this; }
27
28 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
29 void AssertReaderHeld() ASSERT_SHARED_LOCK();
30 };
31
32 class SCOPED_LOCKABLE MutexLock {
33 public:
34 MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
35 MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);
36 ~MutexLock() UNLOCK_FUNCTION();
37 };
38
39 class SCOPED_LOCKABLE ReaderMutexLock {
40 public:
41 ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu);
42 ReaderMutexLock(Mutex *mu, bool adopt) SHARED_LOCKS_REQUIRED(mu);
43 ~ReaderMutexLock() UNLOCK_FUNCTION();
44 };
45
46 class SCOPED_LOCKABLE ReleasableMutexLock {
47 public:
48 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
49 ~ReleasableMutexLock() UNLOCK_FUNCTION();
50
51 void Release() UNLOCK_FUNCTION();
52 };
53
54 class SCOPED_LOCKABLE DoubleMutexLock {
55 public:
56 DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);
57 ~DoubleMutexLock() UNLOCK_FUNCTION();
58 };
59
60 // The universal lock, written "*", allows checking to be selectively turned
61 // off for a particular piece of code.
62 void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
63 void endNoWarnOnReads() UNLOCK_FUNCTION("*");
64 void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
65 void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
66
67
68 // For testing handling of smart pointers.
69 template<class T>
70 class SmartPtr {
71 public:
SmartPtr(T * p)72 SmartPtr(T* p) : ptr_(p) { }
SmartPtr(const SmartPtr<T> & p)73 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
74 ~SmartPtr();
75
get() const76 T* get() const { return ptr_; }
operator ->() const77 T* operator->() const { return ptr_; }
operator *() const78 T& operator*() const { return *ptr_; }
operator [](int i) const79 T& operator[](int i) const { return ptr_[i]; }
80
81 private:
82 T* ptr_;
83 };
84
85
86 // For testing destructor calls and cleanup.
87 class MyString {
88 public:
89 MyString(const char* s);
90 ~MyString();
91 };
92
93
94 // For testing operator overloading
95 template <class K, class T>
96 class MyMap {
97 public:
98 T& operator[](const K& k);
99 };
100
101
102 // For testing handling of containers.
103 template <class T>
104 class MyContainer {
105 public:
106 MyContainer();
107
108 typedef T* iterator;
109 typedef const T* const_iterator;
110
111 T* begin();
112 T* end();
113
114 const T* cbegin();
115 const T* cend();
116
117 T& operator[](int i);
118 const T& operator[](int i) const;
119
120 private:
121 T* ptr_;
122 };
123
124
125
126 Mutex sls_mu;
127
128 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
129 int sls_guard_var __attribute__((guarded_var)) = 0;
130 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
131
132 bool getBool();
133
134 class MutexWrapper {
135 public:
136 Mutex mu;
137 int x __attribute__((guarded_by(mu)));
138 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
139 };
140
141 MutexWrapper sls_mw;
142
sls_fun_0()143 void sls_fun_0() {
144 sls_mw.mu.Lock();
145 sls_mw.x = 5;
146 sls_mw.mu.Unlock();
147 }
148
sls_fun_2()149 void sls_fun_2() {
150 sls_mu.Lock();
151 int x = sls_guard_var;
152 sls_mu.Unlock();
153 }
154
sls_fun_3()155 void sls_fun_3() {
156 sls_mu.Lock();
157 sls_guard_var = 2;
158 sls_mu.Unlock();
159 }
160
sls_fun_4()161 void sls_fun_4() {
162 sls_mu2.Lock();
163 sls_guard_var = 2;
164 sls_mu2.Unlock();
165 }
166
sls_fun_5()167 void sls_fun_5() {
168 sls_mu.Lock();
169 int x = sls_guardby_var;
170 sls_mu.Unlock();
171 }
172
sls_fun_6()173 void sls_fun_6() {
174 sls_mu.Lock();
175 sls_guardby_var = 2;
176 sls_mu.Unlock();
177 }
178
sls_fun_7()179 void sls_fun_7() {
180 sls_mu.Lock();
181 sls_mu2.Lock();
182 sls_mu2.Unlock();
183 sls_mu.Unlock();
184 }
185
sls_fun_8()186 void sls_fun_8() {
187 sls_mu.Lock();
188 if (getBool())
189 sls_mu.Unlock();
190 else
191 sls_mu.Unlock();
192 }
193
sls_fun_9()194 void sls_fun_9() {
195 if (getBool())
196 sls_mu.Lock();
197 else
198 sls_mu.Lock();
199 sls_mu.Unlock();
200 }
201
sls_fun_good_6()202 void sls_fun_good_6() {
203 if (getBool()) {
204 sls_mu.Lock();
205 } else {
206 if (getBool()) {
207 getBool(); // EMPTY
208 } else {
209 getBool(); // EMPTY
210 }
211 sls_mu.Lock();
212 }
213 sls_mu.Unlock();
214 }
215
sls_fun_good_7()216 void sls_fun_good_7() {
217 sls_mu.Lock();
218 while (getBool()) {
219 sls_mu.Unlock();
220 if (getBool()) {
221 if (getBool()) {
222 sls_mu.Lock();
223 continue;
224 }
225 }
226 sls_mu.Lock();
227 }
228 sls_mu.Unlock();
229 }
230
sls_fun_good_8()231 void sls_fun_good_8() {
232 sls_mw.MyLock();
233 sls_mw.mu.Unlock();
234 }
235
sls_fun_bad_1()236 void sls_fun_bad_1() {
237 sls_mu.Unlock(); // \
238 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
239 }
240
sls_fun_bad_2()241 void sls_fun_bad_2() {
242 sls_mu.Lock(); // expected-note{{mutex acquired here}}
243 sls_mu.Lock(); // \
244 // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
245 sls_mu.Unlock();
246 }
247
sls_fun_bad_3()248 void sls_fun_bad_3() {
249 sls_mu.Lock(); // expected-note {{mutex acquired here}}
250 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
251
sls_fun_bad_4()252 void sls_fun_bad_4() {
253 if (getBool())
254 sls_mu.Lock(); // expected-note{{mutex acquired here}}
255 else
256 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
257 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
258 // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
259
sls_fun_bad_5()260 void sls_fun_bad_5() {
261 sls_mu.Lock(); // expected-note {{mutex acquired here}}
262 if (getBool())
263 sls_mu.Unlock();
264 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
265
sls_fun_bad_6()266 void sls_fun_bad_6() {
267 if (getBool()) {
268 sls_mu.Lock(); // expected-note {{mutex acquired here}}
269 } else {
270 if (getBool()) {
271 getBool(); // EMPTY
272 } else {
273 getBool(); // EMPTY
274 }
275 }
276 sls_mu.Unlock(); // \
277 expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
278 expected-warning{{releasing mutex 'sls_mu' that was not held}}
279 }
280
sls_fun_bad_7()281 void sls_fun_bad_7() {
282 sls_mu.Lock();
283 while (getBool()) {
284 sls_mu.Unlock();
285 if (getBool()) {
286 if (getBool()) {
287 continue; // \
288 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
289 }
290 }
291 sls_mu.Lock(); // expected-note {{mutex acquired here}}
292 }
293 sls_mu.Unlock();
294 }
295
sls_fun_bad_8()296 void sls_fun_bad_8() {
297 sls_mu.Lock(); // expected-note{{mutex acquired here}}
298
299 do {
300 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
301 } while (getBool());
302 }
303
sls_fun_bad_9()304 void sls_fun_bad_9() {
305 do {
306 sls_mu.Lock(); // \
307 // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
308 // expected-note{{mutex acquired here}}
309 } while (getBool());
310 sls_mu.Unlock();
311 }
312
sls_fun_bad_10()313 void sls_fun_bad_10() {
314 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
315 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
316 sls_mu.Unlock();
317 }
318 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
319
sls_fun_bad_11()320 void sls_fun_bad_11() {
321 while (getBool()) { // \
322 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
323 sls_mu.Lock(); // expected-note {{mutex acquired here}}
324 }
325 sls_mu.Unlock(); // \
326 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
327 }
328
sls_fun_bad_12()329 void sls_fun_bad_12() {
330 sls_mu.Lock(); // expected-note {{mutex acquired here}}
331 while (getBool()) {
332 sls_mu.Unlock();
333 if (getBool()) {
334 if (getBool()) {
335 break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
336 }
337 }
338 sls_mu.Lock();
339 }
340 sls_mu.Unlock(); // \
341 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
342 }
343
344 //-----------------------------------------//
345 // Handling lock expressions in attribute args
346 // -------------------------------------------//
347
348 Mutex aa_mu;
349
350 class GlobalLocker {
351 public:
352 void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu);
353 void globalUnlock() UNLOCK_FUNCTION(aa_mu);
354 };
355
356 GlobalLocker glock;
357
aa_fun_1()358 void aa_fun_1() {
359 glock.globalLock();
360 glock.globalUnlock();
361 }
362
aa_fun_bad_1()363 void aa_fun_bad_1() {
364 glock.globalUnlock(); // \
365 // expected-warning{{releasing mutex 'aa_mu' that was not held}}
366 }
367
aa_fun_bad_2()368 void aa_fun_bad_2() {
369 glock.globalLock(); // expected-note{{mutex acquired here}}
370 glock.globalLock(); // \
371 // expected-warning{{acquiring mutex 'aa_mu' that is already held}}
372 glock.globalUnlock();
373 }
374
aa_fun_bad_3()375 void aa_fun_bad_3() {
376 glock.globalLock(); // expected-note{{mutex acquired here}}
377 } // expected-warning{{mutex 'aa_mu' is still held at the end of function}}
378
379 //--------------------------------------------------//
380 // Regression tests for unusual method names
381 //--------------------------------------------------//
382
383 Mutex wmu;
384
385 // Test diagnostics for other method names.
386 class WeirdMethods {
387 // FIXME: can't currently check inside constructors and destructors.
WeirdMethods()388 WeirdMethods() {
389 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
390 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
~WeirdMethods()391 ~WeirdMethods() {
392 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
393 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
operator ++()394 void operator++() {
395 wmu.Lock(); // expected-note {{mutex acquired here}}
396 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
operator int*()397 operator int*() {
398 wmu.Lock(); // expected-note {{mutex acquired here}}
399 return 0;
400 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
401 };
402
403 //-----------------------------------------------//
404 // Errors for guarded by or guarded var variables
405 // ----------------------------------------------//
406
407 int *pgb_gvar __attribute__((pt_guarded_var));
408 int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
409
410 class PGBFoo {
411 public:
412 int x;
413 int *pgb_field __attribute__((guarded_by(sls_mu2)))
414 __attribute__((pt_guarded_by(sls_mu)));
testFoo()415 void testFoo() {
416 pgb_field = &x; // \
417 // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}
418 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
419 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
420 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
421 // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}
422 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
423 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
424 }
425 };
426
427 class GBFoo {
428 public:
429 int gb_field __attribute__((guarded_by(sls_mu)));
430
testFoo()431 void testFoo() {
432 gb_field = 0; // \
433 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
434 }
435
testNoAnal()436 void testNoAnal() NO_THREAD_SAFETY_ANALYSIS {
437 gb_field = 0;
438 }
439 };
440
441 GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
442
gb_fun_0()443 void gb_fun_0() {
444 sls_mu.Lock();
445 int x = *pgb_var;
446 sls_mu.Unlock();
447 }
448
gb_fun_1()449 void gb_fun_1() {
450 sls_mu.Lock();
451 *pgb_var = 2;
452 sls_mu.Unlock();
453 }
454
gb_fun_2()455 void gb_fun_2() {
456 int x;
457 pgb_var = &x;
458 }
459
gb_fun_3()460 void gb_fun_3() {
461 int *x = pgb_var;
462 }
463
gb_bad_0()464 void gb_bad_0() {
465 sls_guard_var = 1; // \
466 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
467 }
468
gb_bad_1()469 void gb_bad_1() {
470 int x = sls_guard_var; // \
471 // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}
472 }
473
gb_bad_2()474 void gb_bad_2() {
475 sls_guardby_var = 1; // \
476 // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}
477 }
478
gb_bad_3()479 void gb_bad_3() {
480 int x = sls_guardby_var; // \
481 // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}
482 }
483
gb_bad_4()484 void gb_bad_4() {
485 *pgb_gvar = 1; // \
486 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}
487 }
488
gb_bad_5()489 void gb_bad_5() {
490 int x = *pgb_gvar; // \
491 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}
492 }
493
gb_bad_6()494 void gb_bad_6() {
495 *pgb_var = 1; // \
496 // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}
497 }
498
gb_bad_7()499 void gb_bad_7() {
500 int x = *pgb_var; // \
501 // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}
502 }
503
gb_bad_8()504 void gb_bad_8() {
505 GBFoo G;
506 G.gb_field = 0; // \
507 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}
508 }
509
gb_bad_9()510 void gb_bad_9() {
511 sls_guard_var++; // \
512 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
513 sls_guard_var--; // \
514 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
515 ++sls_guard_var; // \
516 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
517 --sls_guard_var;// \
518 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
519 }
520
521 //-----------------------------------------------//
522 // Warnings on variables with late parsed attributes
523 // ----------------------------------------------//
524
525 class LateFoo {
526 public:
527 int a __attribute__((guarded_by(mu)));
528 int b;
529
foo()530 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
531
test()532 void test() {
533 a = 0; // \
534 // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}
535 b = a; // \
536 // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
537 c = 0; // \
538 // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}
539 }
540
541 int c __attribute__((guarded_by(mu)));
542
543 Mutex mu;
544 };
545
546 class LateBar {
547 public:
548 int a_ __attribute__((guarded_by(mu1_)));
549 int b_;
550 int *q __attribute__((pt_guarded_by(mu)));
551 Mutex mu1_;
552 Mutex mu;
553 LateFoo Foo;
554 LateFoo Foo2;
555 LateFoo *FooPointer;
556 };
557
558 LateBar b1, *b3;
559
late_0()560 void late_0() {
561 LateFoo FooA;
562 LateFoo FooB;
563 FooA.mu.Lock();
564 FooA.a = 5;
565 FooA.mu.Unlock();
566 }
567
late_1()568 void late_1() {
569 LateBar BarA;
570 BarA.FooPointer->mu.Lock();
571 BarA.FooPointer->a = 2;
572 BarA.FooPointer->mu.Unlock();
573 }
574
late_bad_0()575 void late_bad_0() {
576 LateFoo fooA;
577 LateFoo fooB;
578 fooA.mu.Lock();
579 fooB.a = 5; // \
580 // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \
581 // expected-note{{found near match 'fooA.mu'}}
582 fooA.mu.Unlock();
583 }
584
late_bad_1()585 void late_bad_1() {
586 Mutex mu;
587 mu.Lock();
588 b1.mu1_.Lock();
589 int res = b1.a_ + b3->b_;
590 b3->b_ = *b1.q; // \
591 // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}
592 b1.mu1_.Unlock();
593 b1.b_ = res;
594 mu.Unlock();
595 }
596
late_bad_2()597 void late_bad_2() {
598 LateBar BarA;
599 BarA.FooPointer->mu.Lock();
600 BarA.Foo.a = 2; // \
601 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \
602 // expected-note{{found near match 'BarA.FooPointer->mu'}}
603 BarA.FooPointer->mu.Unlock();
604 }
605
late_bad_3()606 void late_bad_3() {
607 LateBar BarA;
608 BarA.Foo.mu.Lock();
609 BarA.FooPointer->a = 2; // \
610 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \
611 // expected-note{{found near match 'BarA.Foo.mu'}}
612 BarA.Foo.mu.Unlock();
613 }
614
late_bad_4()615 void late_bad_4() {
616 LateBar BarA;
617 BarA.Foo.mu.Lock();
618 BarA.Foo2.a = 2; // \
619 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \
620 // expected-note{{found near match 'BarA.Foo.mu'}}
621 BarA.Foo.mu.Unlock();
622 }
623
624 //-----------------------------------------------//
625 // Extra warnings for shared vs. exclusive locks
626 // ----------------------------------------------//
627
shared_fun_0()628 void shared_fun_0() {
629 sls_mu.Lock();
630 do {
631 sls_mu.Unlock();
632 sls_mu.Lock();
633 } while (getBool());
634 sls_mu.Unlock();
635 }
636
shared_fun_1()637 void shared_fun_1() {
638 sls_mu.ReaderLock(); // \
639 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
640 do {
641 sls_mu.Unlock();
642 sls_mu.Lock(); // \
643 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
644 } while (getBool());
645 sls_mu.Unlock();
646 }
647
shared_fun_3()648 void shared_fun_3() {
649 if (getBool())
650 sls_mu.Lock();
651 else
652 sls_mu.Lock();
653 *pgb_var = 1;
654 sls_mu.Unlock();
655 }
656
shared_fun_4()657 void shared_fun_4() {
658 if (getBool())
659 sls_mu.ReaderLock();
660 else
661 sls_mu.ReaderLock();
662 int x = sls_guardby_var;
663 sls_mu.Unlock();
664 }
665
shared_fun_8()666 void shared_fun_8() {
667 if (getBool())
668 sls_mu.Lock(); // \
669 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
670 else
671 sls_mu.ReaderLock(); // \
672 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
673 sls_mu.Unlock();
674 }
675
shared_fun_9()676 void shared_fun_9() {
677 sls_mu.Lock();
678 sls_mu.ExclusiveUnlock();
679
680 sls_mu.ReaderLock();
681 sls_mu.ReaderUnlock();
682 }
683
shared_fun_10()684 void shared_fun_10() {
685 sls_mu.Lock();
686 sls_mu.DemoteExclusive();
687 sls_mu.ReaderUnlock();
688 }
689
shared_fun_11()690 void shared_fun_11() {
691 sls_mu.ReaderLock();
692 sls_mu.PromoteShared();
693 sls_mu.Unlock();
694 }
695
shared_bad_0()696 void shared_bad_0() {
697 sls_mu.Lock(); // \
698 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
699 do {
700 sls_mu.Unlock();
701 sls_mu.ReaderLock(); // \
702 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
703 } while (getBool());
704 sls_mu.Unlock();
705 }
706
shared_bad_1()707 void shared_bad_1() {
708 if (getBool())
709 sls_mu.Lock(); // \
710 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
711 else
712 sls_mu.ReaderLock(); // \
713 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
714 *pgb_var = 1;
715 sls_mu.Unlock();
716 }
717
shared_bad_2()718 void shared_bad_2() {
719 if (getBool())
720 sls_mu.ReaderLock(); // \
721 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
722 else
723 sls_mu.Lock(); // \
724 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
725 *pgb_var = 1;
726 sls_mu.Unlock();
727 }
728
shared_bad_3()729 void shared_bad_3() {
730 sls_mu.Lock(); // expected-note {{mutex acquired here}}
731 sls_mu.ReaderUnlock(); // \
732 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
733 }
734
shared_bad_4()735 void shared_bad_4() {
736 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
737 sls_mu.ExclusiveUnlock(); // \
738 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
739 }
740
shared_bad_5()741 void shared_bad_5() {
742 sls_mu.Lock(); // expected-note {{mutex acquired here}}
743 sls_mu.PromoteShared(); // \
744 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
745 sls_mu.ExclusiveUnlock();
746 }
747
shared_bad_6()748 void shared_bad_6() {
749 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
750 sls_mu.DemoteExclusive(); // \
751 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
752 sls_mu.ReaderUnlock();
753 }
754
755 // FIXME: Add support for functions (not only methods)
756 class LRBar {
757 public:
758 void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
759 void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu);
760 void le_fun() __attribute__((locks_excluded(sls_mu)));
761 };
762
763 class LRFoo {
764 public:
765 void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
766 void testShared() SHARED_LOCKS_REQUIRED(sls_mu2);
767 };
768
769 void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
elr_fun()770 void elr_fun() {}
771
772 LRFoo MyLRFoo;
773 LRBar Bar;
774
es_fun_0()775 void es_fun_0() {
776 aa_mu.Lock();
777 Bar.aa_elr_fun();
778 aa_mu.Unlock();
779 }
780
es_fun_1()781 void es_fun_1() {
782 aa_mu.Lock();
783 Bar.aa_elr_fun_s();
784 aa_mu.Unlock();
785 }
786
es_fun_2()787 void es_fun_2() {
788 aa_mu.ReaderLock();
789 Bar.aa_elr_fun_s();
790 aa_mu.Unlock();
791 }
792
es_fun_3()793 void es_fun_3() {
794 sls_mu.Lock();
795 MyLRFoo.test();
796 sls_mu.Unlock();
797 }
798
es_fun_4()799 void es_fun_4() {
800 sls_mu2.Lock();
801 MyLRFoo.testShared();
802 sls_mu2.Unlock();
803 }
804
es_fun_5()805 void es_fun_5() {
806 sls_mu2.ReaderLock();
807 MyLRFoo.testShared();
808 sls_mu2.Unlock();
809 }
810
es_fun_6()811 void es_fun_6() {
812 Bar.le_fun();
813 }
814
es_fun_7()815 void es_fun_7() {
816 sls_mu.Lock();
817 elr_fun();
818 sls_mu.Unlock();
819 }
820
821 void es_fun_8() NO_THREAD_SAFETY_ANALYSIS;
822
es_fun_8()823 void es_fun_8() {
824 Bar.aa_elr_fun_s();
825 }
826
827 void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu);
es_fun_9()828 void es_fun_9() {
829 Bar.aa_elr_fun_s();
830 }
831
832 void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
es_fun_10()833 void es_fun_10() {
834 Bar.aa_elr_fun_s();
835 }
836
es_bad_0()837 void es_bad_0() {
838 Bar.aa_elr_fun(); // \
839 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
840 }
841
es_bad_1()842 void es_bad_1() {
843 aa_mu.ReaderLock();
844 Bar.aa_elr_fun(); // \
845 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
846 aa_mu.Unlock();
847 }
848
es_bad_2()849 void es_bad_2() {
850 Bar.aa_elr_fun_s(); // \
851 // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}
852 }
853
es_bad_3()854 void es_bad_3() {
855 MyLRFoo.test(); // \
856 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
857 }
858
es_bad_4()859 void es_bad_4() {
860 MyLRFoo.testShared(); // \
861 // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}
862 }
863
es_bad_5()864 void es_bad_5() {
865 sls_mu.ReaderLock();
866 MyLRFoo.test(); // \
867 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
868 sls_mu.Unlock();
869 }
870
es_bad_6()871 void es_bad_6() {
872 sls_mu.Lock();
873 Bar.le_fun(); // \
874 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
875 sls_mu.Unlock();
876 }
877
es_bad_7()878 void es_bad_7() {
879 sls_mu.ReaderLock();
880 Bar.le_fun(); // \
881 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
882 sls_mu.Unlock();
883 }
884
885
886 //-----------------------------------------------//
887 // Unparseable lock expressions
888 // ----------------------------------------------//
889
890 // FIXME -- derive new tests for unhandled expressions
891
892
893 //----------------------------------------------------------------------------//
894 // The following test cases are ported from the gcc thread safety implementation
895 // They are each wrapped inside a namespace with the test number of the gcc test
896 //
897 // FIXME: add all the gcc tests, once this analysis passes them.
898 //----------------------------------------------------------------------------//
899
900 //-----------------------------------------//
901 // Good testcases (no errors)
902 //-----------------------------------------//
903
904 namespace thread_annot_lock_20 {
905 class Bar {
906 public:
907 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
908 static int b_ GUARDED_BY(mu1_);
909 static Mutex mu1_;
910 static int a_ GUARDED_BY(mu1_);
911 };
912
913 Bar b1;
914
func1()915 int Bar::func1()
916 {
917 int res = 5;
918
919 if (a_ == 4)
920 res = b_;
921 return res;
922 }
923 } // end namespace thread_annot_lock_20
924
925 namespace thread_annot_lock_22 {
926 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
927 // uses in class definitions.
928 Mutex mu;
929
930 class Bar {
931 public:
932 int a_ GUARDED_BY(mu1_);
933 int b_;
934 int *q PT_GUARDED_BY(mu);
935 Mutex mu1_ ACQUIRED_AFTER(mu);
936 };
937
938 Bar b1, *b3;
939 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
940 int res GUARDED_BY(mu) = 5;
941
func(int i)942 int func(int i)
943 {
944 int x;
945 mu.Lock();
946 b1.mu1_.Lock();
947 res = b1.a_ + b3->b_;
948 *p = i;
949 b1.a_ = res + b3->b_;
950 b3->b_ = *b1.q;
951 b1.mu1_.Unlock();
952 b1.b_ = res;
953 x = res;
954 mu.Unlock();
955 return x;
956 }
957 } // end namespace thread_annot_lock_22
958
959 namespace thread_annot_lock_27_modified {
960 // test lock annotations applied to function definitions
961 // Modified: applied annotations only to function declarations
962 Mutex mu1;
963 Mutex mu2 ACQUIRED_AFTER(mu1);
964
965 class Foo {
966 public:
967 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
968 };
969
method1(int i)970 int Foo::method1(int i) {
971 return i;
972 }
973
974
975 int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
foo(int i)976 int foo(int i) {
977 return i;
978 }
979
980 static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
bar(int i)981 static int bar(int i) {
982 return i;
983 }
984
main()985 void main() {
986 Foo a;
987
988 mu1.Lock();
989 mu2.Lock();
990 a.method1(1);
991 foo(2);
992 mu2.Unlock();
993 bar(3);
994 mu1.Unlock();
995 }
996 } // end namespace thread_annot_lock_27_modified
997
998
999 namespace thread_annot_lock_38 {
1000 // Test the case where a template member function is annotated with lock
1001 // attributes in a non-template class.
1002 class Foo {
1003 public:
1004 void func1(int y) LOCKS_EXCLUDED(mu_);
1005 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
1006 private:
1007 Mutex mu_;
1008 };
1009
1010 Foo *foo;
1011
main()1012 void main()
1013 {
1014 foo->func1(5);
1015 foo->func2(5);
1016 }
1017 } // end namespace thread_annot_lock_38
1018
1019 namespace thread_annot_lock_43 {
1020 // Tests lock canonicalization
1021 class Foo {
1022 public:
1023 Mutex *mu_;
1024 };
1025
1026 class FooBar {
1027 public:
1028 Foo *foo_;
GetA()1029 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
1030 int a_ GUARDED_BY(foo_->mu_);
1031 };
1032
1033 FooBar *fb;
1034
main()1035 void main()
1036 {
1037 int x;
1038 fb->foo_->mu_->Lock();
1039 x = fb->GetA();
1040 fb->foo_->mu_->Unlock();
1041 }
1042 } // end namespace thread_annot_lock_43
1043
1044 namespace thread_annot_lock_49 {
1045 // Test the support for use of lock expression in the annotations
1046 class Foo {
1047 public:
1048 Mutex foo_mu_;
1049 };
1050
1051 class Bar {
1052 private:
1053 Foo *foo;
1054 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
1055
1056 public:
Test1()1057 void Test1() {
1058 foo->foo_mu_.Lock();
1059 bar_mu_.Lock();
1060 bar_mu_.Unlock();
1061 foo->foo_mu_.Unlock();
1062 }
1063 };
1064
main()1065 void main() {
1066 Bar bar;
1067 bar.Test1();
1068 }
1069 } // end namespace thread_annot_lock_49
1070
1071 namespace thread_annot_lock_61_modified {
1072 // Modified to fix the compiler errors
1073 // Test the fix for a bug introduced by the support of pass-by-reference
1074 // parameters.
operator <<thread_annot_lock_61_modified::Foo1075 struct Foo { Foo &operator<< (bool) {return *this;} };
1076 Foo &getFoo();
functhread_annot_lock_61_modified::Bar1077 struct Bar { Foo &func () {return getFoo();} };
operator &thread_annot_lock_61_modified::Bas1078 struct Bas { void operator& (Foo &) {} };
mumble()1079 void mumble()
1080 {
1081 Bas() & Bar().func() << "" << "";
1082 Bas() & Bar().func() << "";
1083 }
1084 } // end namespace thread_annot_lock_61_modified
1085
1086
1087 namespace thread_annot_lock_65 {
1088 // Test the fix for a bug in the support of allowing reader locks for
1089 // non-const, non-modifying overload functions. (We didn't handle the builtin
1090 // properly.)
1091 enum MyFlags {
1092 Zero,
1093 One,
1094 Two,
1095 Three,
1096 Four,
1097 Five,
1098 Six,
1099 Seven,
1100 Eight,
1101 Nine
1102 };
1103
1104 inline MyFlags
operator |(MyFlags a,MyFlags b)1105 operator|(MyFlags a, MyFlags b)
1106 {
1107 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1108 }
1109
1110 inline MyFlags&
operator |=(MyFlags & a,MyFlags b)1111 operator|=(MyFlags& a, MyFlags b)
1112 {
1113 return a = a | b;
1114 }
1115 } // end namespace thread_annot_lock_65
1116
1117 namespace thread_annot_lock_66_modified {
1118 // Modified: Moved annotation to function defn
1119 // Test annotations on out-of-line definitions of member functions where the
1120 // annotations refer to locks that are also data members in the class.
1121 Mutex mu;
1122
1123 class Foo {
1124 public:
1125 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1126 int data GUARDED_BY(mu1);
1127 Mutex *mu1;
1128 Mutex *mu2;
1129 };
1130
method1(int i)1131 int Foo::method1(int i)
1132 {
1133 return data + i;
1134 }
1135
main()1136 void main()
1137 {
1138 Foo a;
1139
1140 a.mu2->Lock();
1141 a.mu1->Lock();
1142 mu.Lock();
1143 a.method1(1);
1144 mu.Unlock();
1145 a.mu1->Unlock();
1146 a.mu2->Unlock();
1147 }
1148 } // end namespace thread_annot_lock_66_modified
1149
1150 namespace thread_annot_lock_68_modified {
1151 // Test a fix to a bug in the delayed name binding with nested template
1152 // instantiation. We use a stack to make sure a name is not resolved to an
1153 // inner context.
1154 template <typename T>
1155 class Bar {
1156 Mutex mu_;
1157 };
1158
1159 template <typename T>
1160 class Foo {
1161 public:
func(T x)1162 void func(T x) {
1163 mu_.Lock();
1164 count_ = x;
1165 mu_.Unlock();
1166 }
1167
1168 private:
1169 T count_ GUARDED_BY(mu_);
1170 Bar<T> bar_;
1171 Mutex mu_;
1172 };
1173
main()1174 void main()
1175 {
1176 Foo<int> *foo;
1177 foo->func(5);
1178 }
1179 } // end namespace thread_annot_lock_68_modified
1180
1181 namespace thread_annot_lock_30_modified {
1182 // Test delay parsing of lock attribute arguments with nested classes.
1183 // Modified: trylocks replaced with exclusive_lock_fun
1184 int a = 0;
1185
1186 class Bar {
1187 struct Foo;
1188
1189 public:
1190 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1191
func()1192 int func() {
1193 MyLock();
1194 // if (foo == 0) {
1195 // return 0;
1196 // }
1197 a = 5;
1198 mu.Unlock();
1199 return 1;
1200 }
1201
1202 class FooBar {
1203 int x;
1204 int y;
1205 };
1206
1207 private:
1208 Mutex mu;
1209 };
1210
1211 Bar *bar;
1212
main()1213 void main()
1214 {
1215 bar->func();
1216 }
1217 } // end namespace thread_annot_lock_30_modified
1218
1219 namespace thread_annot_lock_47 {
1220 // Test the support for annotations on virtual functions.
1221 // This is a good test case. (i.e. There should be no warning emitted by the
1222 // compiler.)
1223 class Base {
1224 public:
1225 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1226 virtual void func2() LOCKS_EXCLUDED(mu_);
1227 Mutex mu_;
1228 };
1229
1230 class Child : public Base {
1231 public:
1232 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1233 virtual void func2() LOCKS_EXCLUDED(mu_);
1234 };
1235
main()1236 void main() {
1237 Child *c;
1238 Base *b = c;
1239
1240 b->mu_.Lock();
1241 b->func1();
1242 b->mu_.Unlock();
1243 b->func2();
1244
1245 c->mu_.Lock();
1246 c->func1();
1247 c->mu_.Unlock();
1248 c->func2();
1249 }
1250 } // end namespace thread_annot_lock_47
1251
1252 //-----------------------------------------//
1253 // Tests which produce errors
1254 //-----------------------------------------//
1255
1256 namespace thread_annot_lock_13 {
1257 Mutex mu1;
1258 Mutex mu2;
1259
1260 int g GUARDED_BY(mu1);
1261 int w GUARDED_BY(mu2);
1262
1263 class Foo {
1264 public:
1265 void bar() LOCKS_EXCLUDED(mu_, mu1);
1266 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1267
1268 private:
1269 int a_ GUARDED_BY(mu_);
1270 public:
1271 Mutex mu_ ACQUIRED_AFTER(mu1);
1272 };
1273
foo()1274 int Foo::foo()
1275 {
1276 int res;
1277 w = 5;
1278 res = a_ + 5;
1279 return res;
1280 }
1281
bar()1282 void Foo::bar()
1283 {
1284 int x;
1285 mu_.Lock();
1286 x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}
1287 a_ = x + 1;
1288 mu_.Unlock();
1289 if (x > 5) {
1290 mu1.Lock();
1291 g = 2;
1292 mu1.Unlock();
1293 }
1294 }
1295
main()1296 void main()
1297 {
1298 Foo f1, *f2;
1299 f1.mu_.Lock();
1300 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}
1301 mu2.Lock();
1302 f1.foo();
1303 mu2.Unlock();
1304 f1.mu_.Unlock();
1305 f2->mu_.Lock();
1306 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}
1307 f2->mu_.Unlock();
1308 mu2.Lock();
1309 w = 2;
1310 mu2.Unlock();
1311 }
1312 } // end namespace thread_annot_lock_13
1313
1314 namespace thread_annot_lock_18_modified {
1315 // Modified: Trylocks removed
1316 // Test the ability to distnguish between the same lock field of
1317 // different objects of a class.
1318 class Bar {
1319 public:
1320 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1321 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1322 int a_ GUARDED_BY(mu1_);
1323
1324 private:
1325 Mutex mu1_;
1326 };
1327
1328 Bar *b1, *b2;
1329
func()1330 void func()
1331 {
1332 b1->MyLock();
1333 b1->a_ = 5;
1334 b2->a_ = 3; // \
1335 // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \
1336 // expected-note {{found near match 'b1->mu1_'}}
1337 b2->MyLock();
1338 b2->MyUnlock();
1339 b1->MyUnlock();
1340 }
1341 } // end namespace thread_annot_lock_18_modified
1342
1343 namespace thread_annot_lock_21 {
1344 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1345 // uses in class definitions.
1346 Mutex mu;
1347
1348 class Bar {
1349 public:
1350 int a_ GUARDED_BY(mu1_);
1351 int b_;
1352 int *q PT_GUARDED_BY(mu);
1353 Mutex mu1_ ACQUIRED_AFTER(mu);
1354 };
1355
1356 Bar b1, *b3;
1357 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1358
1359 int res GUARDED_BY(mu) = 5;
1360
func(int i)1361 int func(int i)
1362 {
1363 int x;
1364 b3->mu1_.Lock();
1365 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \
1366 // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \
1367 // expected-note {{found near match 'b3->mu1_'}}
1368 *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \
1369 // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}
1370 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \
1371 // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \
1372 // expected-note {{found near match 'b3->mu1_'}}
1373 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}
1374 b3->mu1_.Unlock();
1375 b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1376 x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1377 return x;
1378 }
1379 } // end namespace thread_annot_lock_21
1380
1381 namespace thread_annot_lock_35_modified {
1382 // Test the analyzer's ability to distinguish the lock field of different
1383 // objects.
1384 class Foo {
1385 private:
1386 Mutex lock_;
1387 int a_ GUARDED_BY(lock_);
1388
1389 public:
Func(Foo * child)1390 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1391 Foo *new_foo = new Foo;
1392
1393 lock_.Lock();
1394
1395 child->Func(new_foo); // There shouldn't be any warning here as the
1396 // acquired lock is not in child.
1397 child->bar(7); // \
1398 // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \
1399 // expected-note {{found near match 'lock_'}}
1400 child->a_ = 5; // \
1401 // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \
1402 // expected-note {{found near match 'lock_'}}
1403 lock_.Unlock();
1404 }
1405
bar(int y)1406 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1407 a_ = y;
1408 }
1409 };
1410
1411 Foo *x;
1412
main()1413 void main() {
1414 Foo *child = new Foo;
1415 x->Func(child);
1416 }
1417 } // end namespace thread_annot_lock_35_modified
1418
1419 namespace thread_annot_lock_36_modified {
1420 // Modified to move the annotations to function defns.
1421 // Test the analyzer's ability to distinguish the lock field of different
1422 // objects
1423 class Foo {
1424 private:
1425 Mutex lock_;
1426 int a_ GUARDED_BY(lock_);
1427
1428 public:
1429 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1430 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1431 };
1432
Func(Foo * child)1433 void Foo::Func(Foo* child) {
1434 Foo *new_foo = new Foo;
1435
1436 lock_.Lock();
1437
1438 child->lock_.Lock();
1439 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}
1440 child->bar(7);
1441 child->a_ = 5;
1442 child->lock_.Unlock();
1443
1444 lock_.Unlock();
1445 }
1446
bar(int y)1447 void Foo::bar(int y) {
1448 a_ = y;
1449 }
1450
1451
1452 Foo *x;
1453
main()1454 void main() {
1455 Foo *child = new Foo;
1456 x->Func(child);
1457 }
1458 } // end namespace thread_annot_lock_36_modified
1459
1460
1461 namespace thread_annot_lock_42 {
1462 // Test support of multiple lock attributes of the same kind on a decl.
1463 class Foo {
1464 private:
1465 Mutex mu1, mu2, mu3;
1466 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1467 int y GUARDED_BY(mu2);
1468
f2()1469 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1470 mu2.Lock();
1471 y = 2;
1472 mu2.Unlock();
1473 }
1474
1475 public:
f1()1476 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1477 x = 5;
1478 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \
1479 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}
1480 }
1481 };
1482
1483 Foo *foo;
1484
func()1485 void func()
1486 {
1487 foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \
1488 // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}
1489 }
1490 } // end namespace thread_annot_lock_42
1491
1492 namespace thread_annot_lock_46 {
1493 // Test the support for annotations on virtual functions.
1494 class Base {
1495 public:
1496 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1497 virtual void func2() LOCKS_EXCLUDED(mu_);
1498 Mutex mu_;
1499 };
1500
1501 class Child : public Base {
1502 public:
1503 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1504 virtual void func2() LOCKS_EXCLUDED(mu_);
1505 };
1506
main()1507 void main() {
1508 Child *c;
1509 Base *b = c;
1510
1511 b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}}
1512 b->mu_.Lock();
1513 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}}
1514 b->mu_.Unlock();
1515
1516 c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}
1517 c->mu_.Lock();
1518 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}
1519 c->mu_.Unlock();
1520 }
1521 } // end namespace thread_annot_lock_46
1522
1523 namespace thread_annot_lock_67_modified {
1524 // Modified: attributes on definitions moved to declarations
1525 // Test annotations on out-of-line definitions of member functions where the
1526 // annotations refer to locks that are also data members in the class.
1527 Mutex mu;
1528 Mutex mu3;
1529
1530 class Foo {
1531 public:
1532 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1533 int data GUARDED_BY(mu1);
1534 Mutex *mu1;
1535 Mutex *mu2;
1536 };
1537
method1(int i)1538 int Foo::method1(int i) {
1539 return data + i;
1540 }
1541
main()1542 void main()
1543 {
1544 Foo a;
1545 a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \
1546 // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \
1547 // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \
1548 // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}
1549 }
1550 } // end namespace thread_annot_lock_67_modified
1551
1552
1553 namespace substitution_test {
1554 class MyData {
1555 public:
1556 Mutex mu;
1557
1558 void lockData() EXCLUSIVE_LOCK_FUNCTION(mu);
1559 void unlockData() UNLOCK_FUNCTION(mu);
1560
doSomething()1561 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
1562 };
1563
1564
1565 class DataLocker {
1566 public:
1567 void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu);
1568 void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu);
1569 };
1570
1571
1572 class Foo {
1573 public:
foo(MyData * d)1574 void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { }
1575
bar1(MyData * d)1576 void bar1(MyData* d) {
1577 d->lockData();
1578 foo(d);
1579 d->unlockData();
1580 }
1581
bar2(MyData * d)1582 void bar2(MyData* d) {
1583 DataLocker dlr;
1584 dlr.lockData(d);
1585 foo(d);
1586 dlr.unlockData(d);
1587 }
1588
bar3(MyData * d1,MyData * d2)1589 void bar3(MyData* d1, MyData* d2) {
1590 DataLocker dlr;
1591 dlr.lockData(d1); // expected-note {{mutex acquired here}}
1592 dlr.unlockData(d2); // \
1593 // expected-warning {{releasing mutex 'd2->mu' that was not held}}
1594 } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}
1595
bar4(MyData * d1,MyData * d2)1596 void bar4(MyData* d1, MyData* d2) {
1597 DataLocker dlr;
1598 dlr.lockData(d1);
1599 foo(d2); // \
1600 // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \
1601 // expected-note {{found near match 'd1->mu'}}
1602 dlr.unlockData(d1);
1603 }
1604 };
1605 } // end namespace substituation_test
1606
1607
1608
1609 namespace constructor_destructor_tests {
1610 Mutex fooMu;
1611 int myVar GUARDED_BY(fooMu);
1612
1613 class Foo {
1614 public:
EXCLUSIVE_LOCK_FUNCTION(fooMu)1615 Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { }
UNLOCK_FUNCTION(fooMu)1616 ~Foo() UNLOCK_FUNCTION(fooMu) { }
1617 };
1618
fooTest()1619 void fooTest() {
1620 Foo foo;
1621 myVar = 0;
1622 }
1623 }
1624
1625
1626 namespace template_member_test {
1627
1628 struct S { int n; };
1629 struct T {
1630 Mutex m;
1631 S *s GUARDED_BY(this->m);
1632 };
1633 Mutex m;
1634 struct U {
1635 union {
1636 int n;
1637 };
1638 } *u GUARDED_BY(m);
1639
1640 template<typename U>
1641 struct IndirectLock {
DoNaughtyThingstemplate_member_test::IndirectLock1642 int DoNaughtyThings(T *t) {
1643 u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}
1644 return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}
1645 }
1646 };
1647
1648 template struct IndirectLock<int>; // expected-note {{here}}
1649
1650 struct V {
1651 void f(int);
1652 void f(double);
1653
1654 Mutex m;
1655 V *p GUARDED_BY(this->m);
1656 };
1657 template<typename U> struct W {
1658 V v;
ftemplate_member_test::W1659 void f(U u) {
1660 v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}
1661 }
1662 };
1663 template struct W<int>; // expected-note {{here}}
1664
1665 }
1666
1667 namespace test_scoped_lockable {
1668
1669 struct TestScopedLockable {
1670 Mutex mu1;
1671 Mutex mu2;
1672 int a __attribute__((guarded_by(mu1)));
1673 int b __attribute__((guarded_by(mu2)));
1674
1675 bool getBool();
1676
foo1test_scoped_lockable::TestScopedLockable1677 void foo1() {
1678 MutexLock mulock(&mu1);
1679 a = 5;
1680 }
1681
foo2test_scoped_lockable::TestScopedLockable1682 void foo2() {
1683 ReaderMutexLock mulock1(&mu1);
1684 if (getBool()) {
1685 MutexLock mulock2a(&mu2);
1686 b = a + 1;
1687 }
1688 else {
1689 MutexLock mulock2b(&mu2);
1690 b = a + 2;
1691 }
1692 }
1693
foo3test_scoped_lockable::TestScopedLockable1694 void foo3() {
1695 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}
1696 MutexLock mulock_b(&mu1); // \
1697 // expected-warning {{acquiring mutex 'mu1' that is already held}}
1698 }
1699
foo4test_scoped_lockable::TestScopedLockable1700 void foo4() {
1701 MutexLock mulock1(&mu1), mulock2(&mu2);
1702 a = b+1;
1703 b = a+1;
1704 }
1705
foo5test_scoped_lockable::TestScopedLockable1706 void foo5() {
1707 DoubleMutexLock mulock(&mu1, &mu2);
1708 a = b + 1;
1709 b = a + 1;
1710 }
1711 };
1712
1713 } // end namespace test_scoped_lockable
1714
1715
1716 namespace FunctionAttrTest {
1717
1718 class Foo {
1719 public:
1720 Mutex mu_;
1721 int a GUARDED_BY(mu_);
1722 };
1723
1724 Foo fooObj;
1725
1726 void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1727
bar()1728 void bar() {
1729 foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}
1730 fooObj.mu_.Lock();
1731 foo();
1732 fooObj.mu_.Unlock();
1733 }
1734
1735 }; // end namespace FunctionAttrTest
1736
1737
1738 namespace TryLockTest {
1739
1740 struct TestTryLock {
1741 Mutex mu;
1742 int a GUARDED_BY(mu);
1743 bool cond;
1744
foo1TryLockTest::TestTryLock1745 void foo1() {
1746 if (mu.TryLock()) {
1747 a = 1;
1748 mu.Unlock();
1749 }
1750 }
1751
foo2TryLockTest::TestTryLock1752 void foo2() {
1753 if (!mu.TryLock()) return;
1754 a = 2;
1755 mu.Unlock();
1756 }
1757
foo2_builtin_expectTryLockTest::TestTryLock1758 void foo2_builtin_expect() {
1759 if (__builtin_expect(!mu.TryLock(), false))
1760 return;
1761 a = 2;
1762 mu.Unlock();
1763 }
1764
foo3TryLockTest::TestTryLock1765 void foo3() {
1766 bool b = mu.TryLock();
1767 if (b) {
1768 a = 3;
1769 mu.Unlock();
1770 }
1771 }
1772
foo3_builtin_expectTryLockTest::TestTryLock1773 void foo3_builtin_expect() {
1774 bool b = mu.TryLock();
1775 if (__builtin_expect(b, true)) {
1776 a = 3;
1777 mu.Unlock();
1778 }
1779 }
1780
foo4TryLockTest::TestTryLock1781 void foo4() {
1782 bool b = mu.TryLock();
1783 if (!b) return;
1784 a = 4;
1785 mu.Unlock();
1786 }
1787
foo5TryLockTest::TestTryLock1788 void foo5() {
1789 while (mu.TryLock()) {
1790 a = a + 1;
1791 mu.Unlock();
1792 }
1793 }
1794
foo6TryLockTest::TestTryLock1795 void foo6() {
1796 bool b = mu.TryLock();
1797 b = !b;
1798 if (b) return;
1799 a = 6;
1800 mu.Unlock();
1801 }
1802
foo7TryLockTest::TestTryLock1803 void foo7() {
1804 bool b1 = mu.TryLock();
1805 bool b2 = !b1;
1806 bool b3 = !b2;
1807 if (b3) {
1808 a = 7;
1809 mu.Unlock();
1810 }
1811 }
1812
1813 // Test use-def chains: join points
foo8TryLockTest::TestTryLock1814 void foo8() {
1815 bool b = mu.TryLock();
1816 bool b2 = b;
1817 if (cond)
1818 b = true;
1819 if (b) { // b should be unknown at this point, because of the join point
1820 a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1821 }
1822 if (b2) { // b2 should be known at this point.
1823 a = 8;
1824 mu.Unlock();
1825 }
1826 }
1827
1828 // Test use-def-chains: back edges
foo9TryLockTest::TestTryLock1829 void foo9() {
1830 bool b = mu.TryLock();
1831
1832 for (int i = 0; i < 10; ++i);
1833
1834 if (b) { // b is still known, because the loop doesn't alter it
1835 a = 9;
1836 mu.Unlock();
1837 }
1838 }
1839
1840 // Test use-def chains: back edges
foo10TryLockTest::TestTryLock1841 void foo10() {
1842 bool b = mu.TryLock();
1843
1844 while (cond) {
1845 if (b) { // b should be unknown at this point b/c of the loop
1846 a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1847 }
1848 b = !b;
1849 }
1850 }
1851
1852 // Test merge of exclusive trylock
foo11TryLockTest::TestTryLock1853 void foo11() {
1854 if (cond) {
1855 if (!mu.TryLock())
1856 return;
1857 }
1858 else {
1859 mu.Lock();
1860 }
1861 a = 10;
1862 mu.Unlock();
1863 }
1864
1865 // Test merge of shared trylock
foo12TryLockTest::TestTryLock1866 void foo12() {
1867 if (cond) {
1868 if (!mu.ReaderTryLock())
1869 return;
1870 }
1871 else {
1872 mu.ReaderLock();
1873 }
1874 int i = a;
1875 mu.Unlock();
1876 }
1877
1878 // Test with conditional operator
foo13TryLockTest::TestTryLock1879 void foo13() {
1880 if (mu.TryLock() ? 1 : 0)
1881 mu.Unlock();
1882 }
1883
foo14TryLockTest::TestTryLock1884 void foo14() {
1885 if (mu.TryLock() ? 0 : 1)
1886 return;
1887 mu.Unlock();
1888 }
1889
foo15TryLockTest::TestTryLock1890 void foo15() {
1891 if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
1892 mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}
1893 } // expected-warning{{mutex 'mu' is not held on every path through here}}
1894 }; // end TestTrylock
1895
1896 } // end namespace TrylockTest
1897
1898
1899 namespace TestTemplateAttributeInstantiation {
1900
1901 class Foo1 {
1902 public:
1903 Mutex mu_;
1904 int a GUARDED_BY(mu_);
1905 };
1906
1907 class Foo2 {
1908 public:
1909 int a GUARDED_BY(mu_);
1910 Mutex mu_;
1911 };
1912
1913
1914 class Bar {
1915 public:
1916 // Test non-dependent expressions in attributes on template functions
1917 template <class T>
barND(Foo1 * foo,T * fooT)1918 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1919 foo->a = 0;
1920 }
1921
1922 // Test dependent expressions in attributes on template functions
1923 template <class T>
barD(Foo1 * foo,T * fooT)1924 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1925 fooT->a = 0;
1926 }
1927 };
1928
1929
1930 template <class T>
1931 class BarT {
1932 public:
1933 Foo1 fooBase;
1934 T fooBaseT;
1935
1936 // Test non-dependent expression in ordinary method on template class
barND()1937 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1938 fooBase.a = 0;
1939 }
1940
1941 // Test dependent expressions in ordinary methods on template class
barD()1942 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1943 fooBaseT.a = 0;
1944 }
1945
1946 // Test dependent expressions in template method in template class
1947 template <class T2>
barTD(T2 * fooT)1948 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1949 fooBaseT.a = 0;
1950 fooT->a = 0;
1951 }
1952 };
1953
1954 template <class T>
1955 class Cell {
1956 public:
1957 Mutex mu_;
1958 // Test dependent guarded_by
1959 T data GUARDED_BY(mu_);
1960
fooEx()1961 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1962 data = 0;
1963 }
1964
foo()1965 void foo() {
1966 mu_.Lock();
1967 data = 0;
1968 mu_.Unlock();
1969 }
1970 };
1971
test()1972 void test() {
1973 Bar b;
1974 BarT<Foo2> bt;
1975 Foo1 f1;
1976 Foo2 f2;
1977
1978 f1.mu_.Lock();
1979 f2.mu_.Lock();
1980 bt.fooBase.mu_.Lock();
1981 bt.fooBaseT.mu_.Lock();
1982
1983 b.barND(&f1, &f2);
1984 b.barD(&f1, &f2);
1985 bt.barND();
1986 bt.barD();
1987 bt.barTD(&f2);
1988
1989 f1.mu_.Unlock();
1990 bt.barTD(&f1); // \
1991 // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \
1992 // expected-note {{found near match 'bt.fooBase.mu_'}}
1993
1994 bt.fooBase.mu_.Unlock();
1995 bt.fooBaseT.mu_.Unlock();
1996 f2.mu_.Unlock();
1997
1998 Cell<int> cell;
1999 cell.data = 0; // \
2000 // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}
2001 cell.foo();
2002 cell.mu_.Lock();
2003 cell.fooEx();
2004 cell.mu_.Unlock();
2005 }
2006
2007
2008 template <class T>
2009 class CellDelayed {
2010 public:
2011 // Test dependent guarded_by
2012 T data GUARDED_BY(mu_);
2013 static T static_data GUARDED_BY(static_mu_);
2014
fooEx(CellDelayed<T> * other)2015 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
2016 this->data = other->data;
2017 }
2018
2019 template <class T2>
fooExT(CellDelayed<T2> * otherT)2020 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
2021 this->data = otherT->data;
2022 }
2023
foo()2024 void foo() {
2025 mu_.Lock();
2026 data = 0;
2027 mu_.Unlock();
2028 }
2029
2030 Mutex mu_;
2031 static Mutex static_mu_;
2032 };
2033
testDelayed()2034 void testDelayed() {
2035 CellDelayed<int> celld;
2036 CellDelayed<int> celld2;
2037 celld.foo();
2038 celld.mu_.Lock();
2039 celld2.mu_.Lock();
2040
2041 celld.fooEx(&celld2);
2042 celld.fooExT(&celld2);
2043
2044 celld2.mu_.Unlock();
2045 celld.mu_.Unlock();
2046 }
2047
2048 }; // end namespace TestTemplateAttributeInstantiation
2049
2050
2051 namespace FunctionDeclDefTest {
2052
2053 class Foo {
2054 public:
2055 Mutex mu_;
2056 int a GUARDED_BY(mu_);
2057
2058 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
2059 };
2060
2061 // EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
foo1(Foo * f_defined)2062 void Foo::foo1(Foo *f_defined) {
2063 f_defined->a = 0;
2064 };
2065
test()2066 void test() {
2067 Foo myfoo;
2068 myfoo.foo1(&myfoo); // \
2069 // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}
2070 myfoo.mu_.Lock();
2071 myfoo.foo1(&myfoo);
2072 myfoo.mu_.Unlock();
2073 }
2074
2075 };
2076
2077 namespace GoingNative {
2078
2079 struct LOCKABLE mutex {
2080 void lock() EXCLUSIVE_LOCK_FUNCTION();
2081 void unlock() UNLOCK_FUNCTION();
2082 // ...
2083 };
2084 bool foo();
2085 bool bar();
2086 mutex m;
test()2087 void test() {
2088 m.lock();
2089 while (foo()) {
2090 m.unlock();
2091 // ...
2092 if (bar()) {
2093 // ...
2094 if (foo())
2095 continue; // expected-warning {{expecting mutex 'm' to be held at start of each loop}}
2096 //...
2097 }
2098 // ...
2099 m.lock(); // expected-note {{mutex acquired here}}
2100 }
2101 m.unlock();
2102 }
2103
2104 }
2105
2106
2107
2108 namespace FunctionDefinitionTest {
2109
2110 class Foo {
2111 public:
2112 void foo1();
2113 void foo2();
2114 void foo3(Foo *other);
2115
2116 template<class T>
2117 void fooT1(const T& dummy1);
2118
2119 template<class T>
2120 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2121
2122 Mutex mu_;
2123 int a GUARDED_BY(mu_);
2124 };
2125
2126 template<class T>
2127 class FooT {
2128 public:
2129 void foo();
2130
2131 Mutex mu_;
2132 T a GUARDED_BY(mu_);
2133 };
2134
2135
foo1()2136 void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2137 a = 1;
2138 }
2139
foo2()2140 void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2141 a = 2;
2142 }
2143
foo3(Foo * other)2144 void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2145 other->a = 3;
2146 }
2147
2148 template<class T>
fooT1(const T & dummy1)2149 void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2150 a = dummy1;
2151 }
2152
2153 /* TODO -- uncomment with template instantiation of attributes.
2154 template<class T>
2155 void Foo::fooT2(const T& dummy2) {
2156 a = dummy2;
2157 }
2158 */
2159
fooF1(Foo * f)2160 void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2161 f->a = 1;
2162 }
2163
2164 void fooF2(Foo *f);
fooF2(Foo * f)2165 void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2166 f->a = 2;
2167 }
2168
2169 void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
fooF3(Foo * f)2170 void fooF3(Foo *f) {
2171 f->a = 3;
2172 }
2173
2174 template<class T>
foo()2175 void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2176 a = 0;
2177 }
2178
test()2179 void test() {
2180 int dummy = 0;
2181 Foo myFoo;
2182
2183 myFoo.foo2(); // \
2184 // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}
2185 myFoo.foo3(&myFoo); // \
2186 // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
2187 myFoo.fooT1(dummy); // \
2188 // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2189
2190 myFoo.fooT2(dummy); // \
2191 // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2192
2193 fooF1(&myFoo); // \
2194 // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
2195 fooF2(&myFoo); // \
2196 // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}
2197 fooF3(&myFoo); // \
2198 // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}
2199
2200 myFoo.mu_.Lock();
2201 myFoo.foo2();
2202 myFoo.foo3(&myFoo);
2203 myFoo.fooT1(dummy);
2204
2205 myFoo.fooT2(dummy);
2206
2207 fooF1(&myFoo);
2208 fooF2(&myFoo);
2209 fooF3(&myFoo);
2210 myFoo.mu_.Unlock();
2211
2212 FooT<int> myFooT;
2213 myFooT.foo(); // \
2214 // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}
2215 }
2216
2217 } // end namespace FunctionDefinitionTest
2218
2219
2220 namespace SelfLockingTest {
2221
2222 class LOCKABLE MyLock {
2223 public:
2224 int foo GUARDED_BY(this);
2225
2226 void lock() EXCLUSIVE_LOCK_FUNCTION();
2227 void unlock() UNLOCK_FUNCTION();
2228
doSomething()2229 void doSomething() {
2230 this->lock(); // allow 'this' as a lock expression
2231 foo = 0;
2232 doSomethingElse();
2233 this->unlock();
2234 }
2235
doSomethingElse()2236 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2237 foo = 1;
2238 };
2239
test()2240 void test() {
2241 foo = 2; // \
2242 // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}
2243 }
2244 };
2245
2246
2247 class LOCKABLE MyLock2 {
2248 public:
2249 Mutex mu_;
2250 int foo GUARDED_BY(this);
2251
2252 // don't check inside lock and unlock functions
lock()2253 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
unlock()2254 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2255
2256 // don't check inside constructors and destructors
MyLock2()2257 MyLock2() { foo = 1; }
~MyLock2()2258 ~MyLock2() { foo = 0; }
2259 };
2260
2261
2262 } // end namespace SelfLockingTest
2263
2264
2265 namespace InvalidNonstatic {
2266
2267 // Forward decl here causes bogus "invalid use of non-static data member"
2268 // on reference to mutex_ in guarded_by attribute.
2269 class Foo;
2270
2271 class Foo {
2272 Mutex* mutex_;
2273
2274 int foo __attribute__((guarded_by(mutex_)));
2275 };
2276
2277 } // end namespace InvalidNonStatic
2278
2279
2280 namespace NoReturnTest {
2281
2282 bool condition();
2283 void fatal() __attribute__((noreturn));
2284
2285 Mutex mu_;
2286
test1()2287 void test1() {
2288 MutexLock lock(&mu_);
2289 if (condition()) {
2290 fatal();
2291 return;
2292 }
2293 }
2294
2295 } // end namespace NoReturnTest
2296
2297
2298 namespace TestMultiDecl {
2299
2300 class Foo {
2301 public:
2302 int GUARDED_BY(mu_) a;
2303 int GUARDED_BY(mu_) b, c;
2304
foo()2305 void foo() {
2306 a = 0; // \
2307 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2308 b = 0; // \
2309 // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2310 c = 0; // \
2311 // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
2312 }
2313
2314 private:
2315 Mutex mu_;
2316 };
2317
2318 } // end namespace TestMultiDecl
2319
2320
2321 namespace WarnNoDecl {
2322
2323 class Foo {
2324 void foo(int a); __attribute__(( // \
2325 // expected-warning {{declaration does not declare anything}}
2326 exclusive_locks_required(a))); // \
2327 // expected-warning {{attribute exclusive_locks_required ignored}}
2328 };
2329
2330 } // end namespace WarnNoDecl
2331
2332
2333
2334 namespace MoreLockExpressions {
2335
2336 class Foo {
2337 public:
2338 Mutex mu_;
2339 int a GUARDED_BY(mu_);
2340 };
2341
2342 class Bar {
2343 public:
2344 int b;
2345 Foo* f;
2346
getFoo()2347 Foo& getFoo() { return *f; }
getFoo2(int c)2348 Foo& getFoo2(int c) { return *f; }
getFoo3(int c,int d)2349 Foo& getFoo3(int c, int d) { return *f; }
2350
getFooey()2351 Foo& getFooey() { return *f; }
2352 };
2353
getBarFoo(Bar & bar,int c)2354 Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2355
test()2356 void test() {
2357 Foo foo;
2358 Foo *fooArray;
2359 Foo &(*fooFuncPtr)();
2360 Bar bar;
2361 int a;
2362 int b;
2363 int c;
2364
2365 bar.getFoo().mu_.Lock();
2366 bar.getFoo().a = 0;
2367 bar.getFoo().mu_.Unlock();
2368
2369 (bar.getFoo().mu_).Lock(); // test parenthesis
2370 bar.getFoo().a = 0;
2371 (bar.getFoo().mu_).Unlock();
2372
2373 bar.getFoo2(a).mu_.Lock();
2374 bar.getFoo2(a).a = 0;
2375 bar.getFoo2(a).mu_.Unlock();
2376
2377 bar.getFoo3(a, b).mu_.Lock();
2378 bar.getFoo3(a, b).a = 0;
2379 bar.getFoo3(a, b).mu_.Unlock();
2380
2381 getBarFoo(bar, a).mu_.Lock();
2382 getBarFoo(bar, a).a = 0;
2383 getBarFoo(bar, a).mu_.Unlock();
2384
2385 bar.getFoo2(10).mu_.Lock();
2386 bar.getFoo2(10).a = 0;
2387 bar.getFoo2(10).mu_.Unlock();
2388
2389 bar.getFoo2(a + 1).mu_.Lock();
2390 bar.getFoo2(a + 1).a = 0;
2391 bar.getFoo2(a + 1).mu_.Unlock();
2392
2393 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2394 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2395 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2396
2397 fooFuncPtr().mu_.Lock();
2398 fooFuncPtr().a = 0;
2399 fooFuncPtr().mu_.Unlock();
2400 }
2401
2402
test2()2403 void test2() {
2404 Foo *fooArray;
2405 Bar bar;
2406 int a;
2407 int b;
2408 int c;
2409
2410 bar.getFoo().mu_.Lock();
2411 bar.getFooey().a = 0; // \
2412 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \
2413 // expected-note {{found near match 'bar.getFoo().mu_'}}
2414 bar.getFoo().mu_.Unlock();
2415
2416 bar.getFoo2(a).mu_.Lock();
2417 bar.getFoo2(b).a = 0; // \
2418 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \
2419 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
2420 bar.getFoo2(a).mu_.Unlock();
2421
2422 bar.getFoo3(a, b).mu_.Lock();
2423 bar.getFoo3(a, c).a = 0; // \
2424 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
2425 // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
2426 bar.getFoo3(a, b).mu_.Unlock();
2427
2428 getBarFoo(bar, a).mu_.Lock();
2429 getBarFoo(bar, b).a = 0; // \
2430 // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
2431 // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
2432 getBarFoo(bar, a).mu_.Unlock();
2433
2434 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2435 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2436 // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
2437 // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
2438 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2439 }
2440
2441
2442 } // end namespace MoreLockExpressions
2443
2444
2445 namespace TrylockJoinPoint {
2446
2447 class Foo {
2448 Mutex mu;
2449 bool c;
2450
foo()2451 void foo() {
2452 if (c) {
2453 if (!mu.TryLock())
2454 return;
2455 } else {
2456 mu.Lock();
2457 }
2458 mu.Unlock();
2459 }
2460 };
2461
2462 } // end namespace TrylockJoinPoint
2463
2464
2465 namespace LockReturned {
2466
2467 class Foo {
2468 public:
2469 int a GUARDED_BY(mu_);
2470 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2471 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2472
2473 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2474
2475 Mutex* getMu() LOCK_RETURNED(mu_);
2476
2477 Mutex mu_;
2478
2479 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2480 };
2481
2482
2483 // Calls getMu() directly to lock and unlock
test1(Foo * f1,Foo * f2)2484 void test1(Foo* f1, Foo* f2) {
2485 f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}
2486 f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}
2487
2488 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \
2489 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}
2490 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}
2491
2492 f1->getMu()->Lock();
2493
2494 f1->a = 0;
2495 f1->foo();
2496 f1->foo2(f2); // \
2497 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \
2498 // expected-note {{found near match 'f1->mu_'}}
2499
2500 Foo::getMu(f2)->Lock();
2501 f1->foo2(f2);
2502 Foo::getMu(f2)->Unlock();
2503
2504 Foo::sfoo(f1);
2505
2506 f1->getMu()->Unlock();
2507 }
2508
2509
2510 Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2511
2512 class Bar : public Foo {
2513 public:
2514 int b GUARDED_BY(getMu());
2515 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2516 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2517
2518 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2519 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2520 };
2521
2522
2523
2524 // Use getMu() within other attributes.
2525 // This requires at lest levels of substitution, more in the case of
test2(Bar * b1,Bar * b2)2526 void test2(Bar* b1, Bar* b2) {
2527 b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}
2528 b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}
2529 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \
2530 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}
2531 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}
2532 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}
2533
2534 b1->getMu()->Lock();
2535
2536 b1->b = 0;
2537 b1->bar();
2538 b1->bar2(b2); // \
2539 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \
2540 // // expected-note {{found near match 'b1->mu_'}}
2541
2542 b2->getMu()->Lock();
2543 b1->bar2(b2);
2544
2545 b2->getMu()->Unlock();
2546
2547 Bar::sbar(b1);
2548 Bar::sbar2(b1);
2549
2550 b1->getMu()->Unlock();
2551 }
2552
2553
2554 // Sanity check -- lock the mutex directly, but use attributes that call getMu()
2555 // Also lock the mutex using getFooMu, which calls a lock_returned function.
test3(Bar * b1,Bar * b2)2556 void test3(Bar* b1, Bar* b2) {
2557 b1->mu_.Lock();
2558 b1->b = 0;
2559 b1->bar();
2560
2561 getFooMu(b2)->Lock();
2562 b1->bar2(b2);
2563 getFooMu(b2)->Unlock();
2564
2565 Bar::sbar(b1);
2566 Bar::sbar2(b1);
2567
2568 b1->mu_.Unlock();
2569 }
2570
2571 } // end namespace LockReturned
2572
2573
2574 namespace ReleasableScopedLock {
2575
2576 class Foo {
2577 Mutex mu_;
2578 bool c;
2579 int a GUARDED_BY(mu_);
2580
2581 void test1();
2582 void test2();
2583 void test3();
2584 void test4();
2585 void test5();
2586 void test6();
2587 };
2588
2589
test1()2590 void Foo::test1() {
2591 ReleasableMutexLock rlock(&mu_);
2592 rlock.Release();
2593 }
2594
test2()2595 void Foo::test2() {
2596 ReleasableMutexLock rlock(&mu_);
2597 if (c) { // test join point -- held/not held during release
2598 rlock.Release();
2599 }
2600 // No warning on join point because the lock will be released by the scope object anyway.
2601 }
2602
test3()2603 void Foo::test3() {
2604 ReleasableMutexLock rlock(&mu_);
2605 a = 0;
2606 rlock.Release();
2607 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2608 }
2609
test4()2610 void Foo::test4() {
2611 ReleasableMutexLock rlock(&mu_);
2612 rlock.Release(); // expected-note{{mutex released here}}
2613 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2614 }
2615
test5()2616 void Foo::test5() {
2617 ReleasableMutexLock rlock(&mu_);
2618 if (c) {
2619 rlock.Release();
2620 }
2621 // No warning on join point because the lock will be released by the scope object anyway.
2622 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2623 }
2624
test6()2625 void Foo::test6() {
2626 ReleasableMutexLock rlock(&mu_);
2627 do {
2628 if (c) {
2629 rlock.Release();
2630 break;
2631 }
2632 } while (c);
2633 // No warning on join point because the lock will be released by the scope object anyway
2634 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2635 }
2636
2637
2638 } // end namespace ReleasableScopedLock
2639
2640
2641 namespace RelockableScopedLock {
2642
2643 class DeferTraits {};
2644
2645 class SCOPED_LOCKABLE RelockableExclusiveMutexLock {
2646 public:
2647 RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2648 RelockableExclusiveMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2649 ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();
2650
2651 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2652 void Unlock() UNLOCK_FUNCTION();
2653 };
2654
2655 struct SharedTraits {};
2656 struct ExclusiveTraits {};
2657
2658 class SCOPED_LOCKABLE RelockableMutexLock {
2659 public:
2660 RelockableMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2661 RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu);
2662 RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu);
2663 ~RelockableMutexLock() UNLOCK_FUNCTION();
2664
2665 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2666 void Unlock() UNLOCK_FUNCTION();
2667
2668 void ReaderLock() SHARED_LOCK_FUNCTION();
2669 void ReaderUnlock() UNLOCK_FUNCTION();
2670
2671 void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
2672 void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
2673 };
2674
2675 Mutex mu;
2676 int x GUARDED_BY(mu);
2677 bool b;
2678
2679 void print(int);
2680
relock()2681 void relock() {
2682 RelockableExclusiveMutexLock scope(&mu);
2683 x = 2;
2684 scope.Unlock();
2685
2686 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2687
2688 scope.Lock();
2689 x = 4;
2690 }
2691
deferLock()2692 void deferLock() {
2693 RelockableExclusiveMutexLock scope(&mu, DeferTraits{});
2694 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2695 scope.Lock();
2696 x = 3;
2697 }
2698
relockExclusive()2699 void relockExclusive() {
2700 RelockableMutexLock scope(&mu, SharedTraits{});
2701 print(x);
2702 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2703 scope.ReaderUnlock();
2704
2705 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2706
2707 scope.Lock();
2708 print(x);
2709 x = 4;
2710
2711 scope.DemoteExclusive();
2712 print(x);
2713 x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2714 }
2715
relockShared()2716 void relockShared() {
2717 RelockableMutexLock scope(&mu, ExclusiveTraits{});
2718 print(x);
2719 x = 2;
2720 scope.Unlock();
2721
2722 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2723
2724 scope.ReaderLock();
2725 print(x);
2726 x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2727
2728 scope.PromoteShared();
2729 print(x);
2730 x = 5;
2731 }
2732
deferLockShared()2733 void deferLockShared() {
2734 RelockableMutexLock scope(&mu, DeferTraits{});
2735 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2736 scope.ReaderLock();
2737 print(x);
2738 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2739 }
2740
doubleUnlock()2741 void doubleUnlock() {
2742 RelockableExclusiveMutexLock scope(&mu);
2743 scope.Unlock(); // expected-note{{mutex released here}}
2744 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
2745 }
2746
doubleLock1()2747 void doubleLock1() {
2748 RelockableExclusiveMutexLock scope(&mu); // expected-note{{mutex acquired here}}
2749 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2750 }
2751
doubleLock2()2752 void doubleLock2() {
2753 RelockableExclusiveMutexLock scope(&mu);
2754 scope.Unlock();
2755 scope.Lock(); // expected-note{{mutex acquired here}}
2756 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2757 }
2758
lockJoin()2759 void lockJoin() {
2760 RelockableMutexLock scope(&mu, DeferTraits{});
2761 if (b)
2762 scope.Lock();
2763 // No warning on join point because the lock will be released by the scope object anyway.
2764 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2765 }
2766
unlockJoin()2767 void unlockJoin() {
2768 RelockableMutexLock scope(&mu, DeferTraits{});
2769 scope.Lock();
2770 if (b)
2771 scope.Unlock();
2772 // No warning on join point because the lock will be released by the scope object anyway.
2773 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2774 }
2775
loopAcquire()2776 void loopAcquire() {
2777 RelockableMutexLock scope(&mu, DeferTraits{});
2778 for (unsigned i = 1; i < 10; ++i)
2779 scope.Lock(); // We could catch this double lock with negative capabilities.
2780 }
2781
loopRelease()2782 void loopRelease() {
2783 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2784 // We have to warn on this join point despite the lock being managed ...
2785 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2786 x = 1; // ... because we might miss that this doesn't always happen under lock.
2787 if (i == 5)
2788 scope.Unlock();
2789 }
2790 }
2791
loopPromote()2792 void loopPromote() {
2793 RelockableMutexLock scope(&mu, SharedTraits{});
2794 for (unsigned i = 1; i < 10; ++i) {
2795 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2796 if (i == 5)
2797 scope.PromoteShared();
2798 }
2799 }
2800
loopDemote()2801 void loopDemote() {
2802 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2803 // We have to warn on this join point despite the lock being managed ...
2804 for (unsigned i = 1; i < 10; ++i) {
2805 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2806 if (i == 5)
2807 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2808 }
2809 }
2810
loopAcquireContinue()2811 void loopAcquireContinue() {
2812 RelockableMutexLock scope(&mu, DeferTraits{});
2813 for (unsigned i = 1; i < 10; ++i) {
2814 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2815 if (i == 5) {
2816 scope.Lock();
2817 continue;
2818 }
2819 }
2820 }
2821
loopReleaseContinue()2822 void loopReleaseContinue() {
2823 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2824 // We have to warn on this join point despite the lock being managed ...
2825 for (unsigned i = 1; i < 10; ++i) {
2826 x = 1; // ... because we might miss that this doesn't always happen under lock.
2827 if (i == 5) {
2828 scope.Unlock();
2829 continue; // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2830 }
2831 }
2832 }
2833
loopPromoteContinue()2834 void loopPromoteContinue() {
2835 RelockableMutexLock scope(&mu, SharedTraits{});
2836 for (unsigned i = 1; i < 10; ++i) {
2837 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2838 if (i == 5) {
2839 scope.PromoteShared();
2840 continue;
2841 }
2842 }
2843 }
2844
loopDemoteContinue()2845 void loopDemoteContinue() {
2846 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2847 // We have to warn on this join point despite the lock being managed ...
2848 for (unsigned i = 1; i < 10; ++i) {
2849 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2850 if (i == 5) {
2851 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2852 continue;
2853 }
2854 }
2855 }
2856
exclusiveSharedJoin()2857 void exclusiveSharedJoin() {
2858 RelockableMutexLock scope(&mu, DeferTraits{});
2859 if (b)
2860 scope.Lock();
2861 else
2862 scope.ReaderLock();
2863 // No warning on join point because the lock will be released by the scope object anyway.
2864 print(x);
2865 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2866 }
2867
sharedExclusiveJoin()2868 void sharedExclusiveJoin() {
2869 RelockableMutexLock scope(&mu, DeferTraits{});
2870 if (b)
2871 scope.ReaderLock();
2872 else
2873 scope.Lock();
2874 // No warning on join point because the lock will be released by the scope object anyway.
2875 print(x);
2876 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2877 }
2878
assertJoin()2879 void assertJoin() {
2880 RelockableMutexLock scope(&mu, DeferTraits{});
2881 if (b)
2882 scope.Lock();
2883 else
2884 mu.AssertHeld();
2885 x = 2;
2886 }
2887
assertSharedJoin()2888 void assertSharedJoin() {
2889 RelockableMutexLock scope(&mu, DeferTraits{});
2890 if (b)
2891 scope.ReaderLock();
2892 else
2893 mu.AssertReaderHeld();
2894 print(x);
2895 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2896 }
2897
assertStrongerJoin()2898 void assertStrongerJoin() {
2899 RelockableMutexLock scope(&mu, DeferTraits{});
2900 if (b)
2901 scope.ReaderLock();
2902 else
2903 mu.AssertHeld();
2904 print(x);
2905 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2906 }
2907
assertWeakerJoin()2908 void assertWeakerJoin() {
2909 RelockableMutexLock scope(&mu, DeferTraits{});
2910 if (b)
2911 scope.Lock();
2912 else
2913 mu.AssertReaderHeld();
2914 print(x);
2915 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2916 }
2917
directUnlock()2918 void directUnlock() {
2919 RelockableExclusiveMutexLock scope(&mu);
2920 mu.Unlock();
2921 // Debatable that there is no warning. Currently we don't track in the scoped
2922 // object whether it is active, but just check if the contained locks can be
2923 // reacquired. Here they can, because mu has been unlocked manually.
2924 scope.Lock();
2925 }
2926
directRelock()2927 void directRelock() {
2928 RelockableExclusiveMutexLock scope(&mu);
2929 scope.Unlock();
2930 mu.Lock();
2931 // Similarly debatable that there is no warning.
2932 scope.Unlock();
2933 }
2934
2935 // Doesn't make a lot of sense, just making sure there is no crash.
destructLock()2936 void destructLock() {
2937 RelockableExclusiveMutexLock scope(&mu);
2938 scope.~RelockableExclusiveMutexLock();
2939 scope.Lock(); // Should be UB, so we don't really care.
2940 }
2941
2942 class SCOPED_LOCKABLE MemberLock {
2943 public:
2944 MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2945 ~MemberLock() UNLOCK_FUNCTION(mutex);
2946 void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2947 Mutex mutex;
2948 };
2949
relockShared2()2950 void relockShared2() {
2951 MemberLock lock; // expected-note{{mutex acquired here}}
2952 lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}}
2953 }
2954
2955 class SCOPED_LOCKABLE WeirdScope {
2956 private:
2957 Mutex *other;
2958
2959 public:
2960 WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
2961 void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other);
2962 void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other);
2963 ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION();
2964
2965 void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other);
2966 };
2967
relockWeird()2968 void relockWeird() {
2969 WeirdScope scope(&mu);
2970 x = 1;
2971 scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}}
2972 x = 2; // \
2973 // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2974 scope.requireOther(); // \
2975 // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}}
2976 scope.lock(); // expected-note {{mutex acquired here}}
2977 x = 3;
2978 scope.requireOther();
2979 } // expected-warning {{mutex 'scope.other' is still held at the end of function}}
2980
2981 } // end namespace RelockableScopedLock
2982
2983
2984 namespace ScopedUnlock {
2985
2986 class SCOPED_LOCKABLE MutexUnlock {
2987 public:
2988 MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu);
2989 ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
2990
2991 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
2992 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
2993 };
2994
2995 class SCOPED_LOCKABLE ReaderMutexUnlock {
2996 public:
2997 ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu);
2998 ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
2999
3000 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
3001 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
3002 };
3003
3004 Mutex mu;
3005 int x GUARDED_BY(mu);
3006 bool c;
3007 void print(int);
3008
simple()3009 void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3010 x = 1;
3011 MutexUnlock scope(&mu);
3012 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3013 }
3014
simpleShared()3015 void simpleShared() SHARED_LOCKS_REQUIRED(mu) {
3016 print(x);
3017 ReaderMutexUnlock scope(&mu);
3018 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3019 }
3020
innerUnlock()3021 void innerUnlock() {
3022 MutexLock outer(&mu);
3023 if (x == 0) {
3024 MutexUnlock inner(&mu);
3025 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3026 }
3027 x = 2;
3028 }
3029
innerUnlockShared()3030 void innerUnlockShared() {
3031 ReaderMutexLock outer(&mu);
3032 if (x == 0) {
3033 ReaderMutexUnlock inner(&mu);
3034 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3035 }
3036 print(x);
3037 }
3038
manual()3039 void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3040 MutexUnlock scope(&mu);
3041 scope.Lock();
3042 x = 2;
3043 scope.Unlock();
3044 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3045 }
3046
join()3047 void join() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3048 MutexUnlock scope(&mu);
3049 if (c)
3050 scope.Lock();
3051 // No warning on join point because the lock will be released by the scope object anyway.
3052 scope.Lock();
3053 }
3054
doubleLock()3055 void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3056 MutexUnlock scope(&mu);
3057 scope.Lock(); // expected-note{{mutex acquired here}}
3058 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
3059 }
3060
doubleUnlock()3061 void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3062 MutexUnlock scope(&mu); // expected-note{{mutex released here}}
3063 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
3064 }
3065
3066 class SCOPED_LOCKABLE MutexLockUnlock {
3067 public:
3068 MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2);
3069 ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3070
3071 void Release() EXCLUSIVE_UNLOCK_FUNCTION();
3072 void Acquire() EXCLUSIVE_LOCK_FUNCTION();
3073 };
3074
3075 Mutex other;
3076 void fn() EXCLUSIVE_LOCKS_REQUIRED(other);
3077
lockUnlock()3078 void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3079 MutexLockUnlock scope(&mu, &other);
3080 fn();
3081 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3082 }
3083
3084 } // end namespace ScopedUnlock
3085
3086
3087 namespace TrylockFunctionTest {
3088
3089 class Foo {
3090 public:
3091 Mutex mu1_;
3092 Mutex mu2_;
3093 bool c;
3094
3095 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
3096 };
3097
lockBoth()3098 bool Foo::lockBoth() {
3099 if (!mu1_.TryLock())
3100 return false;
3101
3102 mu2_.Lock();
3103 if (!c) {
3104 mu1_.Unlock();
3105 mu2_.Unlock();
3106 return false;
3107 }
3108
3109 return true;
3110 }
3111
3112
3113 } // end namespace TrylockFunctionTest
3114
3115
3116
3117 namespace DoubleLockBug {
3118
3119 class Foo {
3120 public:
3121 Mutex mu_;
3122 int a GUARDED_BY(mu_);
3123
3124 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3125 int foo2() SHARED_LOCKS_REQUIRED(mu_);
3126 };
3127
3128
foo1()3129 void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
3130 a = 0;
3131 }
3132
foo2()3133 int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
3134 return a;
3135 }
3136
3137 }
3138
3139
3140
3141 namespace UnlockBug {
3142
3143 class Foo {
3144 public:
3145 Mutex mutex_;
3146
foo1()3147 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3148 mutex_.Unlock();
3149 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3150
3151
foo2()3152 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3153 mutex_.Unlock();
3154 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3155 };
3156
3157 } // end namespace UnlockBug
3158
3159
3160
3161 namespace FoolishScopedLockableBug {
3162
3163 class SCOPED_LOCKABLE WTF_ScopedLockable {
3164 public:
3165 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
3166
3167 // have to call release() manually;
3168 ~WTF_ScopedLockable();
3169
3170 void release() UNLOCK_FUNCTION();
3171 };
3172
3173
3174 class Foo {
3175 Mutex mu_;
3176 int a GUARDED_BY(mu_);
3177 bool c;
3178
3179 void doSomething();
3180
test1()3181 void test1() {
3182 WTF_ScopedLockable wtf(&mu_);
3183 wtf.release();
3184 }
3185
test2()3186 void test2() {
3187 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3188 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
3189
test3()3190 void test3() {
3191 if (c) {
3192 WTF_ScopedLockable wtf(&mu_);
3193 wtf.release();
3194 }
3195 }
3196
test4()3197 void test4() {
3198 if (c) {
3199 doSomething();
3200 }
3201 else {
3202 WTF_ScopedLockable wtf(&mu_);
3203 wtf.release();
3204 }
3205 }
3206
test5()3207 void test5() {
3208 if (c) {
3209 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3210 }
3211 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3212
test6()3213 void test6() {
3214 if (c) {
3215 doSomething();
3216 }
3217 else {
3218 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3219 }
3220 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3221 };
3222
3223
3224 } // end namespace FoolishScopedLockableBug
3225
3226
3227
3228 namespace TemporaryCleanupExpr {
3229
3230 class Foo {
3231 int a GUARDED_BY(getMutexPtr().get());
3232
3233 SmartPtr<Mutex> getMutexPtr();
3234
3235 void test();
3236 };
3237
3238
test()3239 void Foo::test() {
3240 {
3241 ReaderMutexLock lock(getMutexPtr().get());
3242 int b = a;
3243 }
3244 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}
3245 }
3246
3247 #ifdef __cpp_guaranteed_copy_elision
3248
guaranteed_copy_elision()3249 void guaranteed_copy_elision() {
3250 MutexLock lock = MutexLock{&sls_mu};
3251 sls_guard_var = 0;
3252 }
3253
guaranteed_copy_elision_const()3254 void guaranteed_copy_elision_const() {
3255 const MutexLock lock = MutexLock{&sls_mu};
3256 sls_guard_var = 0;
3257 }
3258
3259 #endif
3260
3261 } // end namespace TemporaryCleanupExpr
3262
3263
3264
3265 namespace SmartPointerTests {
3266
3267 class Foo {
3268 public:
3269 SmartPtr<Mutex> mu_;
3270 int a GUARDED_BY(mu_);
3271 int b GUARDED_BY(mu_.get());
3272 int c GUARDED_BY(*mu_);
3273
3274 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3275 void Unlock() UNLOCK_FUNCTION(mu_);
3276
3277 void test0();
3278 void test1();
3279 void test2();
3280 void test3();
3281 void test4();
3282 void test5();
3283 void test6();
3284 void test7();
3285 void test8();
3286 };
3287
test0()3288 void Foo::test0() {
3289 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3290 b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
3291 c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
3292 }
3293
test1()3294 void Foo::test1() {
3295 mu_->Lock();
3296 a = 0;
3297 b = 0;
3298 c = 0;
3299 mu_->Unlock();
3300 }
3301
test2()3302 void Foo::test2() {
3303 (*mu_).Lock();
3304 a = 0;
3305 b = 0;
3306 c = 0;
3307 (*mu_).Unlock();
3308 }
3309
3310
test3()3311 void Foo::test3() {
3312 mu_.get()->Lock();
3313 a = 0;
3314 b = 0;
3315 c = 0;
3316 mu_.get()->Unlock();
3317 }
3318
3319
test4()3320 void Foo::test4() {
3321 MutexLock lock(mu_.get());
3322 a = 0;
3323 b = 0;
3324 c = 0;
3325 }
3326
3327
test5()3328 void Foo::test5() {
3329 MutexLock lock(&(*mu_));
3330 a = 0;
3331 b = 0;
3332 c = 0;
3333 }
3334
3335
test6()3336 void Foo::test6() {
3337 Lock();
3338 a = 0;
3339 b = 0;
3340 c = 0;
3341 Unlock();
3342 }
3343
3344
test7()3345 void Foo::test7() {
3346 {
3347 Lock();
3348 mu_->Unlock();
3349 }
3350 {
3351 mu_->Lock();
3352 Unlock();
3353 }
3354 {
3355 mu_.get()->Lock();
3356 mu_->Unlock();
3357 }
3358 {
3359 mu_->Lock();
3360 mu_.get()->Unlock();
3361 }
3362 {
3363 mu_.get()->Lock();
3364 (*mu_).Unlock();
3365 }
3366 {
3367 (*mu_).Lock();
3368 mu_->Unlock();
3369 }
3370 }
3371
3372
test8()3373 void Foo::test8() {
3374 mu_->Lock(); // expected-note 2 {{mutex acquired here}}
3375 mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3376 (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3377 mu_.get()->Unlock(); // expected-note {{mutex released here}}
3378 Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}
3379 }
3380
3381
3382 class Bar {
3383 SmartPtr<Foo> foo;
3384
3385 void test0();
3386 void test1();
3387 void test2();
3388 void test3();
3389 };
3390
3391
test0()3392 void Bar::test0() {
3393 foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
3394 (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
3395 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
3396 }
3397
3398
test1()3399 void Bar::test1() {
3400 foo->mu_->Lock();
3401 foo->a = 0;
3402 (*foo).b = 0;
3403 foo.get()->c = 0;
3404 foo->mu_->Unlock();
3405 }
3406
3407
test2()3408 void Bar::test2() {
3409 (*foo).mu_->Lock();
3410 foo->a = 0;
3411 (*foo).b = 0;
3412 foo.get()->c = 0;
3413 foo.get()->mu_->Unlock();
3414 }
3415
3416
test3()3417 void Bar::test3() {
3418 MutexLock lock(foo->mu_.get());
3419 foo->a = 0;
3420 (*foo).b = 0;
3421 foo.get()->c = 0;
3422 }
3423
3424 } // end namespace SmartPointerTests
3425
3426
3427
3428 namespace DuplicateAttributeTest {
3429
3430 class LOCKABLE Foo {
3431 public:
3432 Mutex mu1_;
3433 Mutex mu2_;
3434 Mutex mu3_;
3435 int a GUARDED_BY(mu1_);
3436 int b GUARDED_BY(mu2_);
3437 int c GUARDED_BY(mu3_);
3438
3439 void lock() EXCLUSIVE_LOCK_FUNCTION();
3440 void unlock() UNLOCK_FUNCTION();
3441
3442 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
3443 void slock1() SHARED_LOCK_FUNCTION(mu1_);
3444 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3445 void locklots()
3446 EXCLUSIVE_LOCK_FUNCTION(mu1_)
3447 EXCLUSIVE_LOCK_FUNCTION(mu2_)
3448 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3449
3450 void unlock1() UNLOCK_FUNCTION(mu1_);
3451 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3452 void unlocklots()
3453 UNLOCK_FUNCTION(mu1_)
3454 UNLOCK_FUNCTION(mu2_)
3455 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3456 };
3457
3458
lock()3459 void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
unlock()3460 void Foo::unlock() UNLOCK_FUNCTION() { }
3461
lock1()3462 void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
3463 mu1_.Lock();
3464 }
3465
slock1()3466 void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
3467 mu1_.ReaderLock();
3468 }
3469
lock3()3470 void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
3471 mu1_.Lock();
3472 mu2_.Lock();
3473 mu3_.Lock();
3474 }
3475
locklots()3476 void Foo::locklots()
3477 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
3478 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
3479 mu1_.Lock();
3480 mu2_.Lock();
3481 mu3_.Lock();
3482 }
3483
unlock1()3484 void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
3485 mu1_.Unlock();
3486 }
3487
unlock3()3488 void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
3489 mu1_.Unlock();
3490 mu2_.Unlock();
3491 mu3_.Unlock();
3492 }
3493
unlocklots()3494 void Foo::unlocklots()
3495 UNLOCK_FUNCTION(mu1_, mu2_)
3496 UNLOCK_FUNCTION(mu2_, mu3_) {
3497 mu1_.Unlock();
3498 mu2_.Unlock();
3499 mu3_.Unlock();
3500 }
3501
3502
test0()3503 void test0() {
3504 Foo foo;
3505 foo.lock();
3506 foo.unlock();
3507
3508 foo.lock(); // expected-note{{mutex acquired here}}
3509 foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}
3510 foo.unlock(); // expected-note{{mutex released here}}
3511 foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}
3512 }
3513
3514
test1()3515 void test1() {
3516 Foo foo;
3517 foo.lock1();
3518 foo.a = 0;
3519 foo.unlock1();
3520
3521 foo.lock1(); // expected-note{{mutex acquired here}}
3522 foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3523 foo.a = 0;
3524 foo.unlock1(); // expected-note{{mutex released here}}
3525 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3526 }
3527
3528
test2()3529 int test2() {
3530 Foo foo;
3531 foo.slock1();
3532 int d1 = foo.a;
3533 foo.unlock1();
3534
3535 foo.slock1(); // expected-note{{mutex acquired here}}
3536 foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3537 int d2 = foo.a;
3538 foo.unlock1(); // expected-note{{mutex released here}}
3539 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3540 return d1 + d2;
3541 }
3542
3543
test3()3544 void test3() {
3545 Foo foo;
3546 foo.lock3();
3547 foo.a = 0;
3548 foo.b = 0;
3549 foo.c = 0;
3550 foo.unlock3();
3551
3552 foo.lock3(); // expected-note 3 {{mutex acquired here}}
3553 foo.lock3(); // \
3554 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3555 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3556 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3557 foo.a = 0;
3558 foo.b = 0;
3559 foo.c = 0;
3560 foo.unlock3(); // expected-note 3 {{mutex released here}}
3561 foo.unlock3(); // \
3562 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3563 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3564 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3565 }
3566
3567
testlots()3568 void testlots() {
3569 Foo foo;
3570 foo.locklots();
3571 foo.a = 0;
3572 foo.b = 0;
3573 foo.c = 0;
3574 foo.unlocklots();
3575
3576 foo.locklots(); // expected-note 3 {{mutex acquired here}}
3577 foo.locklots(); // \
3578 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3579 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3580 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3581 foo.a = 0;
3582 foo.b = 0;
3583 foo.c = 0;
3584 foo.unlocklots(); // expected-note 3 {{mutex released here}}
3585 foo.unlocklots(); // \
3586 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3587 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3588 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3589 }
3590
3591 } // end namespace DuplicateAttributeTest
3592
3593
3594
3595 namespace TryLockEqTest {
3596
3597 class Foo {
3598 Mutex mu_;
3599 int a GUARDED_BY(mu_);
3600 bool c;
3601
3602 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3603 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3604 void unlock() UNLOCK_FUNCTION(mu_);
3605
3606 void test1();
3607 void test2();
3608 };
3609
3610
test1()3611 void Foo::test1() {
3612 if (tryLockMutexP() == 0) {
3613 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3614 return;
3615 }
3616 a = 0;
3617 unlock();
3618
3619 if (tryLockMutexP() != 0) {
3620 a = 0;
3621 unlock();
3622 }
3623
3624 if (0 != tryLockMutexP()) {
3625 a = 0;
3626 unlock();
3627 }
3628
3629 if (!(tryLockMutexP() == 0)) {
3630 a = 0;
3631 unlock();
3632 }
3633
3634 if (tryLockMutexI() == 0) {
3635 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3636 return;
3637 }
3638 a = 0;
3639 unlock();
3640
3641 if (0 == tryLockMutexI()) {
3642 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3643 return;
3644 }
3645 a = 0;
3646 unlock();
3647
3648 if (tryLockMutexI() == 1) {
3649 a = 0;
3650 unlock();
3651 }
3652
3653 if (mu_.TryLock() == false) {
3654 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3655 return;
3656 }
3657 a = 0;
3658 unlock();
3659
3660 if (mu_.TryLock() == true) {
3661 a = 0;
3662 unlock();
3663 }
3664 else {
3665 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3666 }
3667
3668 #if __has_feature(cxx_nullptr)
3669 if (tryLockMutexP() == nullptr) {
3670 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3671 return;
3672 }
3673 a = 0;
3674 unlock();
3675 #endif
3676 }
3677
3678 } // end namespace TryLockEqTest
3679
3680
3681 namespace ExistentialPatternMatching {
3682
3683 class Graph {
3684 public:
3685 Mutex mu_;
3686 };
3687
3688 void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3689 void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3690
3691 class Node {
3692 public:
3693 int a GUARDED_BY(&Graph::mu_);
3694
foo()3695 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3696 a = 0;
3697 }
3698 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3699 };
3700
test()3701 void test() {
3702 Graph g1;
3703 Graph g2;
3704 Node n1;
3705
3706 n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3707 n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3708 n1.foo2();
3709
3710 g1.mu_.Lock();
3711 n1.a = 0;
3712 n1.foo();
3713 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3714 g1.mu_.Unlock();
3715
3716 g2.mu_.Lock();
3717 n1.a = 0;
3718 n1.foo();
3719 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3720 g2.mu_.Unlock();
3721
3722 LockAllGraphs();
3723 n1.a = 0;
3724 n1.foo();
3725 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3726 UnlockAllGraphs();
3727
3728 LockAllGraphs();
3729 g1.mu_.Unlock();
3730
3731 LockAllGraphs();
3732 g2.mu_.Unlock();
3733
3734 LockAllGraphs(); // expected-note{{mutex acquired here}}
3735 g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}
3736 g1.mu_.Unlock();
3737 }
3738
3739 } // end namespace ExistentialPatternMatching
3740
3741
3742 namespace StringIgnoreTest {
3743
3744 class Foo {
3745 public:
3746 Mutex mu_;
3747 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3748 void unlock() UNLOCK_FUNCTION("");
3749 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3750 void roober() SHARED_LOCKS_REQUIRED("");
3751 };
3752
3753
3754 class Bar : public Foo {
3755 public:
bar(Foo * f)3756 void bar(Foo* f) {
3757 f->unlock();
3758 f->goober();
3759 f->roober();
3760 f->lock();
3761 };
3762 };
3763
3764 } // end namespace StringIgnoreTest
3765
3766
3767 namespace LockReturnedScopeFix {
3768
3769 class Base {
3770 protected:
3771 struct Inner;
3772 bool c;
3773
3774 const Mutex& getLock(const Inner* i);
3775
3776 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3777 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3778 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3779
3780 void bar(Inner* i);
3781 };
3782
3783
3784 struct Base::Inner {
3785 Mutex lock_;
3786 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3787 };
3788
3789
getLock(const Inner * i)3790 const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3791 return i->lock_;
3792 }
3793
3794
foo(Inner * i)3795 void Base::foo(Inner* i) {
3796 i->doSomething();
3797 }
3798
bar(Inner * i)3799 void Base::bar(Inner* i) {
3800 if (c) {
3801 i->lock_.Lock();
3802 unlockInner(i);
3803 }
3804 else {
3805 lockInner(i);
3806 i->lock_.Unlock();
3807 }
3808 }
3809
3810 } // end namespace LockReturnedScopeFix
3811
3812
3813 namespace TrylockWithCleanups {
3814
3815 struct Foo {
3816 Mutex mu_;
3817 int a GUARDED_BY(mu_);
3818 };
3819
3820 Foo* GetAndLockFoo(const MyString& s)
3821 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3822
test()3823 static void test() {
3824 Foo* lt = GetAndLockFoo("foo");
3825 if (!lt) return;
3826 int a = lt->a;
3827 lt->mu_.Unlock();
3828 }
3829
3830 } // end namespace TrylockWithCleanups
3831
3832
3833 namespace UniversalLock {
3834
3835 class Foo {
3836 Mutex mu_;
3837 bool c;
3838
3839 int a GUARDED_BY(mu_);
3840 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3841 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3842
test1()3843 void test1() {
3844 int b;
3845
3846 beginNoWarnOnReads();
3847 b = a;
3848 r_foo();
3849 endNoWarnOnReads();
3850
3851 beginNoWarnOnWrites();
3852 a = 0;
3853 w_foo();
3854 endNoWarnOnWrites();
3855 }
3856
3857 // don't warn on joins with universal lock
test2()3858 void test2() {
3859 if (c) {
3860 beginNoWarnOnWrites();
3861 }
3862 a = 0; // \
3863 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3864 endNoWarnOnWrites(); // \
3865 // expected-warning {{releasing mutex '*' that was not held}}
3866 }
3867
3868
3869 // make sure the universal lock joins properly
test3()3870 void test3() {
3871 if (c) {
3872 mu_.Lock();
3873 beginNoWarnOnWrites();
3874 }
3875 else {
3876 beginNoWarnOnWrites();
3877 mu_.Lock();
3878 }
3879 a = 0;
3880 endNoWarnOnWrites();
3881 mu_.Unlock();
3882 }
3883
3884
3885 // combine universal lock with other locks
test4()3886 void test4() {
3887 beginNoWarnOnWrites();
3888 mu_.Lock();
3889 mu_.Unlock();
3890 endNoWarnOnWrites();
3891
3892 mu_.Lock();
3893 beginNoWarnOnWrites();
3894 endNoWarnOnWrites();
3895 mu_.Unlock();
3896
3897 mu_.Lock();
3898 beginNoWarnOnWrites();
3899 mu_.Unlock();
3900 endNoWarnOnWrites();
3901 }
3902 };
3903
3904 } // end namespace UniversalLock
3905
3906
3907 namespace TemplateLockReturned {
3908
3909 template<class T>
3910 class BaseT {
3911 public:
3912 virtual void baseMethod() = 0;
get_mutex()3913 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3914
3915 Mutex mutex_;
3916 int a GUARDED_BY(mutex_);
3917 };
3918
3919
3920 class Derived : public BaseT<int> {
3921 public:
baseMethod()3922 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3923 a = 0;
3924 }
3925 };
3926
3927 } // end namespace TemplateLockReturned
3928
3929
3930 namespace ExprMatchingBugFix {
3931
3932 class Foo {
3933 public:
3934 Mutex mu_;
3935 };
3936
3937
3938 class Bar {
3939 public:
3940 bool c;
3941 Foo* foo;
Bar(Foo * f)3942 Bar(Foo* f) : foo(f) { }
3943
3944 struct Nested {
3945 Foo* foo;
NestedExprMatchingBugFix::Bar::Nested3946 Nested(Foo* f) : foo(f) { }
3947
3948 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3949 };
3950
3951 void test();
3952 };
3953
3954
test()3955 void Bar::test() {
3956 foo->mu_.Lock();
3957 if (c) {
3958 Nested *n = new Nested(foo);
3959 n->unlockFoo();
3960 }
3961 else {
3962 foo->mu_.Unlock();
3963 }
3964 }
3965
3966 }; // end namespace ExprMatchingBugfix
3967
3968
3969 namespace ComplexNameTest {
3970
3971 class Foo {
3972 public:
3973 static Mutex mu_;
3974
EXCLUSIVE_LOCKS_REQUIRED(mu_)3975 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
EXCLUSIVE_LOCKS_REQUIRED(mu_)3976 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3977
operator [](int i)3978 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3979 };
3980
3981 class Bar {
3982 public:
3983 static Mutex mu_;
3984
LOCKS_EXCLUDED(mu_)3985 Bar() LOCKS_EXCLUDED(mu_) { }
LOCKS_EXCLUDED(mu_)3986 ~Bar() LOCKS_EXCLUDED(mu_) { }
3987
operator [](int i)3988 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3989 };
3990
3991
test1()3992 void test1() {
3993 Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}
3994 int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}
3995 } // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}
3996
3997
test2()3998 void test2() {
3999 Bar::mu_.Lock();
4000 {
4001 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}
4002 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}
4003 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}
4004 Bar::mu_.Unlock();
4005 }
4006
4007 }; // end namespace ComplexNameTest
4008
4009
4010 namespace UnreachableExitTest {
4011
4012 class FemmeFatale {
4013 public:
4014 FemmeFatale();
4015 ~FemmeFatale() __attribute__((noreturn));
4016 };
4017
4018 void exitNow() __attribute__((noreturn));
4019 void exitDestruct(const MyString& ms) __attribute__((noreturn));
4020
4021 Mutex fatalmu_;
4022
test1()4023 void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4024 exitNow();
4025 }
4026
test2()4027 void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4028 FemmeFatale femme;
4029 }
4030
4031 bool c;
4032
test3()4033 void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4034 if (c) {
4035 exitNow();
4036 }
4037 else {
4038 FemmeFatale femme;
4039 }
4040 }
4041
test4()4042 void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4043 exitDestruct("foo");
4044 }
4045
4046 } // end namespace UnreachableExitTest
4047
4048
4049 namespace VirtualMethodCanonicalizationTest {
4050
4051 class Base {
4052 public:
4053 virtual Mutex* getMutex() = 0;
4054 };
4055
4056 class Base2 : public Base {
4057 public:
4058 Mutex* getMutex();
4059 };
4060
4061 class Base3 : public Base2 {
4062 public:
4063 Mutex* getMutex();
4064 };
4065
4066 class Derived : public Base3 {
4067 public:
4068 Mutex* getMutex(); // overrides Base::getMutex()
4069 };
4070
baseFun(Base * b)4071 void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
4072
derivedFun(Derived * d)4073 void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
4074 baseFun(d);
4075 }
4076
4077 } // end namespace VirtualMethodCanonicalizationTest
4078
4079
4080 namespace TemplateFunctionParamRemapTest {
4081
4082 template <class T>
4083 struct Cell {
4084 T dummy_;
4085 Mutex* mu_;
4086 };
4087
4088 class Foo {
4089 public:
4090 template <class T>
4091 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4092
4093 void test();
4094 };
4095
4096 template<class T>
elr(Cell<T> * c1)4097 void Foo::elr(Cell<T>* c1) { }
4098
test()4099 void Foo::test() {
4100 Cell<int> cell;
4101 elr(&cell); // \
4102 // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}
4103 }
4104
4105
4106 template<class T>
4107 void globalELR(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4108
4109 template<class T>
globalELR(Cell<T> * c1)4110 void globalELR(Cell<T>* c1) { }
4111
globalTest()4112 void globalTest() {
4113 Cell<int> cell;
4114 globalELR(&cell); // \
4115 // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}
4116 }
4117
4118
4119 template<class T>
4120 void globalELR2(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4121
4122 // second declaration
4123 template<class T>
4124 void globalELR2(Cell<T>* c2);
4125
4126 template<class T>
globalELR2(Cell<T> * c3)4127 void globalELR2(Cell<T>* c3) { }
4128
4129 // re-declaration after definition
4130 template<class T>
4131 void globalELR2(Cell<T>* c4);
4132
globalTest2()4133 void globalTest2() {
4134 Cell<int> cell;
4135 globalELR2(&cell); // \
4136 // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}
4137 }
4138
4139
4140 template<class T>
4141 class FooT {
4142 public:
4143 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4144 };
4145
4146 template<class T>
elr(Cell<T> * c1)4147 void FooT<T>::elr(Cell<T>* c1) { }
4148
testFooT()4149 void testFooT() {
4150 Cell<int> cell;
4151 FooT<int> foo;
4152 foo.elr(&cell); // \
4153 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
4154 }
4155
4156 } // end namespace TemplateFunctionParamRemapTest
4157
4158
4159 namespace SelfConstructorTest {
4160
4161 class SelfLock {
4162 public:
4163 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
4164 ~SelfLock() UNLOCK_FUNCTION(mu_);
4165
4166 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
4167
4168 Mutex mu_;
4169 };
4170
4171 class LOCKABLE SelfLock2 {
4172 public:
4173 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
4174 ~SelfLock2() UNLOCK_FUNCTION();
4175
4176 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
4177 };
4178
4179
test()4180 void test() {
4181 SelfLock s;
4182 s.foo();
4183 }
4184
test2()4185 void test2() {
4186 SelfLock2 s2;
4187 s2.foo();
4188 }
4189
4190 } // end namespace SelfConstructorTest
4191
4192
4193 namespace MultipleAttributeTest {
4194
4195 class Foo {
4196 Mutex mu1_;
4197 Mutex mu2_;
4198 int a GUARDED_BY(mu1_);
4199 int b GUARDED_BY(mu2_);
4200 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
4201 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
4202
4203 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
4204 EXCLUSIVE_LOCKS_REQUIRED(mu2_);
4205 void foo2() SHARED_LOCKS_REQUIRED(mu1_)
4206 SHARED_LOCKS_REQUIRED(mu2_);
4207 void foo3() LOCKS_EXCLUDED(mu1_)
4208 LOCKS_EXCLUDED(mu2_);
4209 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
4210 EXCLUSIVE_LOCK_FUNCTION(mu2_);
4211 void readerlock() SHARED_LOCK_FUNCTION(mu1_)
4212 SHARED_LOCK_FUNCTION(mu2_);
4213 void unlock() UNLOCK_FUNCTION(mu1_)
4214 UNLOCK_FUNCTION(mu2_);
4215 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
4216 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
4217 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
4218 SHARED_TRYLOCK_FUNCTION(true, mu2_);
4219 void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
4220 ASSERT_EXCLUSIVE_LOCK(mu2_);
4221
4222 void alsoAssertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_, mu2_);
4223
4224 void assertShared() ASSERT_SHARED_LOCK(mu1_)
4225 ASSERT_SHARED_LOCK(mu2_);
4226
4227 void alsoAssertShared() ASSERT_SHARED_LOCK(mu1_, mu2_);
4228
4229 void test();
4230 void testAssert();
4231 void testAssertShared();
4232 };
4233
4234
foo1()4235 void Foo::foo1() {
4236 a = 1;
4237 b = 2;
4238 }
4239
foo2()4240 void Foo::foo2() {
4241 int result = a + b;
4242 }
4243
foo3()4244 void Foo::foo3() { }
lock()4245 void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
readerlock()4246 void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
unlock()4247 void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
trylock()4248 bool Foo::trylock() { return true; }
readertrylock()4249 bool Foo::readertrylock() { return true; }
4250
4251
test()4252 void Foo::test() {
4253 mu1_.Lock();
4254 foo1(); // expected-warning {{}}
4255 c = 0; // expected-warning {{}}
4256 *d = 0; // expected-warning {{}}
4257 mu1_.Unlock();
4258
4259 mu1_.ReaderLock();
4260 foo2(); // expected-warning {{}}
4261 int x = c; // expected-warning {{}}
4262 int y = *d; // expected-warning {{}}
4263 mu1_.Unlock();
4264
4265 mu2_.Lock();
4266 foo3(); // expected-warning {{}}
4267 mu2_.Unlock();
4268
4269 lock();
4270 a = 0;
4271 b = 0;
4272 unlock();
4273
4274 readerlock();
4275 int z = a + b;
4276 unlock();
4277
4278 if (trylock()) {
4279 a = 0;
4280 b = 0;
4281 unlock();
4282 }
4283
4284 if (readertrylock()) {
4285 int zz = a + b;
4286 unlock();
4287 }
4288 }
4289
4290 // Force duplication of attributes
assertBoth()4291 void Foo::assertBoth() { }
alsoAssertBoth()4292 void Foo::alsoAssertBoth() { }
assertShared()4293 void Foo::assertShared() { }
alsoAssertShared()4294 void Foo::alsoAssertShared() { }
4295
testAssert()4296 void Foo::testAssert() {
4297 {
4298 assertBoth();
4299 a = 0;
4300 b = 0;
4301 }
4302 {
4303 alsoAssertBoth();
4304 a = 0;
4305 b = 0;
4306 }
4307 }
4308
testAssertShared()4309 void Foo::testAssertShared() {
4310 {
4311 assertShared();
4312 int zz = a + b;
4313 }
4314
4315 {
4316 alsoAssertShared();
4317 int zz = a + b;
4318 }
4319 }
4320
4321
4322 } // end namespace MultipleAttributeTest
4323
4324
4325 namespace GuardedNonPrimitiveTypeTest {
4326
4327
4328 class Data {
4329 public:
Data(int i)4330 Data(int i) : dat(i) { }
4331
getValue() const4332 int getValue() const { return dat; }
setValue(int i)4333 void setValue(int i) { dat = i; }
4334
operator [](int i) const4335 int operator[](int i) const { return dat; }
operator [](int i)4336 int& operator[](int i) { return dat; }
4337
operator ()()4338 void operator()() { }
4339
4340 private:
4341 int dat;
4342 };
4343
4344
4345 class DataCell {
4346 public:
DataCell(const Data & d)4347 DataCell(const Data& d) : dat(d) { }
4348
4349 private:
4350 Data dat;
4351 };
4352
4353
4354 void showDataCell(const DataCell& dc);
4355
4356
4357 class Foo {
4358 public:
4359 // method call tests
test()4360 void test() {
4361 data_.setValue(0); // FIXME -- should be writing \
4362 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4363 int a = data_.getValue(); // \
4364 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4365
4366 datap1_->setValue(0); // FIXME -- should be writing \
4367 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4368 a = datap1_->getValue(); // \
4369 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4370
4371 datap2_->setValue(0); // FIXME -- should be writing \
4372 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4373 a = datap2_->getValue(); // \
4374 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4375
4376 (*datap2_).setValue(0); // FIXME -- should be writing \
4377 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4378 a = (*datap2_).getValue(); // \
4379 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4380
4381 mu_.Lock();
4382 data_.setValue(1);
4383 datap1_->setValue(1);
4384 datap2_->setValue(1);
4385 mu_.Unlock();
4386
4387 mu_.ReaderLock();
4388 a = data_.getValue();
4389 datap1_->setValue(0); // reads datap1_, writes *datap1_
4390 a = datap1_->getValue();
4391 a = datap2_->getValue();
4392 mu_.Unlock();
4393 }
4394
4395 // operator tests
test2()4396 void test2() {
4397 data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4398 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \
4399 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4400 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \
4401 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4402 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4403 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4404 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4405 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4406
4407 data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4408 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4409
4410 data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4411 }
4412
4413 // const operator tests
test3() const4414 void test3() const {
4415 Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4416
4417 //FIXME
4418 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4419 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4420
4421 int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4422 }
4423
4424 private:
4425 Mutex mu_;
4426 Data data_ GUARDED_BY(mu_);
4427 Data* datap1_ GUARDED_BY(mu_);
4428 Data* datap2_ PT_GUARDED_BY(mu_);
4429 };
4430
4431 } // end namespace GuardedNonPrimitiveTypeTest
4432
4433
4434 namespace GuardedNonPrimitive_MemberAccess {
4435
4436 class Cell {
4437 public:
4438 Cell(int i);
4439
4440 void cellMethod();
4441
4442 int a;
4443 };
4444
4445
4446 class Foo {
4447 public:
4448 int a;
4449 Cell c GUARDED_BY(cell_mu_);
4450 Cell* cp PT_GUARDED_BY(cell_mu_);
4451
4452 void myMethod();
4453
4454 Mutex cell_mu_;
4455 };
4456
4457
4458 class Bar {
4459 private:
4460 Mutex mu_;
4461 Foo foo GUARDED_BY(mu_);
4462 Foo* foop PT_GUARDED_BY(mu_);
4463
test()4464 void test() {
4465 foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4466
4467 int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4468 foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}
4469
4470 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4471 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4472
4473 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4474 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4475
4476 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \
4477 // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}
4478 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \
4479 // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}
4480
4481 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4482 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4483 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4484 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4485
4486 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4487 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4488 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4489 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4490 };
4491 };
4492
4493 } // namespace GuardedNonPrimitive_MemberAccess
4494
4495
4496 namespace TestThrowExpr {
4497
4498 class Foo {
4499 Mutex mu_;
4500
4501 bool hasError();
4502
test()4503 void test() {
4504 mu_.Lock();
4505 if (hasError()) {
4506 throw "ugly";
4507 }
4508 mu_.Unlock();
4509 }
4510 };
4511
4512 } // end namespace TestThrowExpr
4513
4514
4515 namespace UnevaluatedContextTest {
4516
4517 // parse attribute expressions in an unevaluated context.
4518
4519 static inline Mutex* getMutex1();
4520 static inline Mutex* getMutex2();
4521
4522 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());
4523
4524 void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
4525
4526 } // end namespace UnevaluatedContextTest
4527
4528
4529 namespace LockUnlockFunctionTest {
4530
4531 // Check built-in lock functions
4532 class LOCKABLE MyLockable {
4533 public:
lock()4534 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
readerLock()4535 void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
unlock()4536 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
4537
4538 private:
4539 Mutex mu_;
4540 };
4541
4542
4543 class Foo {
4544 public:
4545 // Correct lock/unlock functions
lock()4546 void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
4547 mu_.Lock();
4548 }
4549
readerLock()4550 void readerLock() SHARED_LOCK_FUNCTION(mu_) {
4551 mu_.ReaderLock();
4552 }
4553
unlock()4554 void unlock() UNLOCK_FUNCTION(mu_) {
4555 mu_.Unlock();
4556 }
4557
unlockExclusive()4558 void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) {
4559 mu_.Unlock();
4560 }
4561
unlockShared()4562 void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) {
4563 mu_.ReaderUnlock();
4564 }
4565
4566 // Check failure to lock.
lockBad()4567 void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4568 mu2_.Lock();
4569 mu2_.Unlock();
4570 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4571
readerLockBad()4572 void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4573 mu2_.Lock();
4574 mu2_.Unlock();
4575 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4576
unlockBad()4577 void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4578 mu2_.Lock();
4579 mu2_.Unlock();
4580 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4581
4582 // Check locking the wrong thing.
lockBad2()4583 void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4584 mu2_.Lock(); // expected-note {{mutex acquired here}}
4585 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4586 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4587
4588
readerLockBad2()4589 void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4590 mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
4591 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4592 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4593
4594
unlockBad2()4595 void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4596 mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}
4597 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4598
4599 private:
4600 Mutex mu_;
4601 Mutex mu2_;
4602 };
4603
4604 } // end namespace LockUnlockFunctionTest
4605
4606
4607 namespace AssertHeldTest {
4608
4609 class Foo {
4610 public:
4611 int c;
4612 int a GUARDED_BY(mu_);
4613 Mutex mu_;
4614
test1()4615 void test1() {
4616 mu_.AssertHeld();
4617 int b = a;
4618 a = 0;
4619 }
4620
test2()4621 void test2() {
4622 mu_.AssertReaderHeld();
4623 int b = a;
4624 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
4625 }
4626
test3()4627 void test3() {
4628 if (c) {
4629 mu_.AssertHeld();
4630 }
4631 else {
4632 mu_.AssertHeld();
4633 }
4634 int b = a;
4635 a = 0;
4636 }
4637
test4()4638 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4639 mu_.AssertHeld();
4640 int b = a;
4641 a = 0;
4642 }
4643
test5()4644 void test5() UNLOCK_FUNCTION(mu_) {
4645 mu_.AssertHeld();
4646 mu_.Unlock();
4647 }
4648
test6()4649 void test6() {
4650 mu_.AssertHeld();
4651 mu_.Unlock(); // should this be a warning?
4652 }
4653
test7()4654 void test7() {
4655 if (c) {
4656 mu_.AssertHeld();
4657 }
4658 else {
4659 mu_.Lock();
4660 }
4661 int b = a;
4662 a = 0;
4663 mu_.Unlock();
4664 }
4665
test8()4666 void test8() {
4667 if (c) {
4668 mu_.Lock();
4669 }
4670 else {
4671 mu_.AssertHeld();
4672 }
4673 // FIXME: should warn, because it's unclear whether we need to release or not.
4674 int b = a;
4675 a = 0;
4676 mu_.Unlock(); // should this be a warning?
4677 }
4678
test9()4679 void test9() {
4680 if (c) {
4681 mu_.AssertHeld();
4682 }
4683 else {
4684 mu_.Lock(); // expected-note {{mutex acquired here}}
4685 }
4686 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4687
test10()4688 void test10() {
4689 if (c) {
4690 mu_.Lock(); // expected-note {{mutex acquired here}}
4691 }
4692 else {
4693 mu_.AssertHeld();
4694 }
4695 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4696
4697 void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
4698
test11()4699 void test11() {
4700 assertMu();
4701 int b = a;
4702 a = 0;
4703 }
4704
test12()4705 void test12() {
4706 if (c)
4707 mu_.ReaderLock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4708 else
4709 mu_.AssertHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4710 // FIXME: should instead warn because it's unclear whether we need to release or not.
4711 int b = a;
4712 a = 0;
4713 mu_.Unlock();
4714 }
4715
test13()4716 void test13() {
4717 if (c)
4718 mu_.Lock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4719 else
4720 mu_.AssertReaderHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4721 // FIXME: should instead warn because it's unclear whether we need to release or not.
4722 int b = a;
4723 a = 0;
4724 mu_.Unlock();
4725 }
4726 };
4727
4728 } // end namespace AssertHeldTest
4729
4730
4731 namespace LogicalConditionalTryLock {
4732
4733 class Foo {
4734 public:
4735 Mutex mu;
4736 int a GUARDED_BY(mu);
4737 bool c;
4738
4739 bool newc();
4740
test1()4741 void test1() {
4742 if (c && mu.TryLock()) {
4743 a = 0;
4744 mu.Unlock();
4745 }
4746 }
4747
test2()4748 void test2() {
4749 bool b = mu.TryLock();
4750 if (c && b) {
4751 a = 0;
4752 mu.Unlock();
4753 }
4754 }
4755
test3()4756 void test3() {
4757 if (c || !mu.TryLock())
4758 return;
4759 a = 0;
4760 mu.Unlock();
4761 }
4762
test4()4763 void test4() {
4764 while (c && mu.TryLock()) {
4765 a = 0;
4766 c = newc();
4767 mu.Unlock();
4768 }
4769 }
4770
test5()4771 void test5() {
4772 while (c) {
4773 if (newc() || !mu.TryLock())
4774 break;
4775 a = 0;
4776 mu.Unlock();
4777 }
4778 }
4779
test6()4780 void test6() {
4781 mu.Lock();
4782 do {
4783 a = 0;
4784 mu.Unlock();
4785 } while (newc() && mu.TryLock());
4786 }
4787
test7()4788 void test7() {
4789 for (bool b = mu.TryLock(); c && b;) {
4790 a = 0;
4791 mu.Unlock();
4792 }
4793 }
4794
test8()4795 void test8() {
4796 if (c && newc() && mu.TryLock()) {
4797 a = 0;
4798 mu.Unlock();
4799 }
4800 }
4801
test9()4802 void test9() {
4803 if (!(c && newc() && mu.TryLock()))
4804 return;
4805 a = 0;
4806 mu.Unlock();
4807 }
4808
test10()4809 void test10() {
4810 if (!(c || !mu.TryLock())) {
4811 a = 0;
4812 mu.Unlock();
4813 }
4814 }
4815 };
4816
4817 } // end namespace LogicalConditionalTryLock
4818
4819
4820
4821 namespace PtGuardedByTest {
4822
4823 void doSomething();
4824
4825 class Cell {
4826 public:
4827 int a;
4828 };
4829
4830
4831 // This mainly duplicates earlier tests, but just to make sure...
4832 class PtGuardedBySanityTest {
4833 Mutex mu1;
4834 Mutex mu2;
4835 int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4836 Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4837 int sa[10] GUARDED_BY(mu1);
4838 Cell sc[10] GUARDED_BY(mu1);
4839
test1()4840 void test1() {
4841 mu1.Lock();
4842 if (a == 0) doSomething(); // OK, we don't dereference.
4843 a = 0;
4844 c = 0;
4845 if (sa[0] == 42) doSomething();
4846 sa[0] = 57;
4847 if (sc[0].a == 42) doSomething();
4848 sc[0].a = 57;
4849 mu1.Unlock();
4850 }
4851
test2()4852 void test2() {
4853 mu1.ReaderLock();
4854 if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4855 *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4856
4857 if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4858 c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4859
4860 if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4861 (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4862
4863 if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4864 a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4865 if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4866 c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4867 mu1.Unlock();
4868 }
4869
test3()4870 void test3() {
4871 mu2.Lock();
4872 if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4873 *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4874
4875 if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4876 c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4877
4878 if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4879 (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4880
4881 if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4882 a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4883 if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4884 c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4885 mu2.Unlock();
4886 }
4887
test4()4888 void test4() { // Literal arrays
4889 if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4890 sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4891 if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4892 sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4893
4894 if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4895 *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4896 if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4897 (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4898 if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4899 sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4900 }
4901
test5()4902 void test5() {
4903 mu1.ReaderLock(); // OK -- correct use.
4904 mu2.Lock();
4905 if (*a == 0) doSomething();
4906 *a = 0;
4907
4908 if (c->a == 0) doSomething();
4909 c->a = 0;
4910
4911 if ((*c).a == 0) doSomething();
4912 (*c).a = 0;
4913 mu2.Unlock();
4914 mu1.Unlock();
4915 }
4916 };
4917
4918
4919 class SmartPtr_PtGuardedBy_Test {
4920 Mutex mu1;
4921 Mutex mu2;
4922 SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4923 SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4924
test1()4925 void test1() {
4926 mu1.ReaderLock();
4927 mu2.Lock();
4928
4929 sp.get();
4930 if (*sp == 0) doSomething();
4931 *sp = 0;
4932 sq->a = 0;
4933
4934 if (sp[0] == 0) doSomething();
4935 sp[0] = 0;
4936
4937 mu2.Unlock();
4938 mu1.Unlock();
4939 }
4940
test2()4941 void test2() {
4942 mu2.Lock();
4943
4944 sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4945 if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4946 *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4947 sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4948
4949 if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4950 sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4951 if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4952 sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4953
4954 mu2.Unlock();
4955 }
4956
test3()4957 void test3() {
4958 mu1.Lock();
4959
4960 sp.get();
4961 if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4962 *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4963 sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4964
4965 if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4966 sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4967 if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4968 sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4969
4970 mu1.Unlock();
4971 }
4972 };
4973
4974 } // end namespace PtGuardedByTest
4975
4976
4977 namespace NonMemberCalleeICETest {
4978
4979 class A {
Run()4980 void Run() {
4981 (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
4982 }
4983
4984 void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M);
4985 Mutex M;
4986 };
4987
4988 } // end namespace NonMemberCalleeICETest
4989
4990
4991 namespace pt_guard_attribute_type {
4992 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
4993 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
4994
test()4995 void test() {
4996 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to non-static data members and global variables}}
4997 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to non-static data members and global variables}}
4998
4999 typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to}}
5000 typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to}}
5001 }
5002 } // end namespace pt_guard_attribute_type
5003
5004
5005 namespace ThreadAttributesOnLambdas {
5006
5007 class Foo {
5008 Mutex mu_;
5009
5010 void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);
5011
test()5012 void test() {
5013 auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
5014 LockedFunction();
5015 };
5016
5017 auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {
5018 LockedFunction();
5019 };
5020
5021 auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {
5022 mu_.Lock();
5023 };
5024
5025 func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}
5026 func2();
5027 func3();
5028 mu_.Unlock();
5029 }
5030 };
5031
5032 } // end namespace ThreadAttributesOnLambdas
5033
5034
5035
5036 namespace AttributeExpressionCornerCases {
5037
5038 class Foo {
5039 int a GUARDED_BY(getMu());
5040
5041 Mutex* getMu() LOCK_RETURNED("");
5042 Mutex* getUniv() LOCK_RETURNED("*");
5043
test1()5044 void test1() {
5045 a = 0;
5046 }
5047
test2()5048 void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
5049 a = 0;
5050 }
5051
5052 void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
5053
test3()5054 void test3() {
5055 foo(nullptr);
5056 }
5057 };
5058
5059
5060 class MapTest {
5061 struct MuCell { Mutex* mu; };
5062
5063 MyMap<MyString, Mutex*> map;
5064 MyMap<MyString, MuCell> mapCell;
5065
5066 int a GUARDED_BY(map["foo"]);
5067 int b GUARDED_BY(mapCell["foo"].mu);
5068
test()5069 void test() {
5070 map["foo"]->Lock();
5071 a = 0;
5072 map["foo"]->Unlock();
5073 }
5074
test2()5075 void test2() {
5076 mapCell["foo"].mu->Lock();
5077 b = 0;
5078 mapCell["foo"].mu->Unlock();
5079 }
5080 };
5081
5082
5083 class PreciseSmartPtr {
5084 SmartPtr<Mutex> mu;
5085 int val GUARDED_BY(mu);
5086
compare(PreciseSmartPtr & a,PreciseSmartPtr & b)5087 static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
5088 a.mu->Lock();
5089 bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
5090 // expected-note {{found near match 'a.mu'}}
5091 a.mu->Unlock();
5092 return result;
5093 }
5094 };
5095
5096
5097 class SmartRedeclare {
5098 SmartPtr<Mutex> mu;
5099 int val GUARDED_BY(mu);
5100
5101 void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
5102 void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5103 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5104 };
5105
5106
test()5107 void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
5108 val = 0;
5109 }
5110
test2()5111 void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5112 val = 0;
5113 }
5114
test3()5115 void SmartRedeclare::test3() {
5116 val = 0;
5117 }
5118
5119
5120 namespace CustomMutex {
5121
5122
5123 class LOCKABLE BaseMutex { };
5124 class DerivedMutex : public BaseMutex { };
5125
5126 void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
5127 void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
5128
5129 static struct DerivedMutex custMu;
5130
doSomethingRequiringLock()5131 static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
5132
customTest()5133 void customTest() {
5134 customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
5135 doSomethingRequiringLock();
5136 customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
5137 }
5138
5139 } // end namespace CustomMutex
5140
5141 } // end AttributeExpressionCornerCases
5142
5143
5144 namespace ScopedLockReturnedInvalid {
5145
5146 class Opaque;
5147
5148 Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
5149
test(Opaque * o)5150 void test(Opaque* o) {
5151 MutexLock lock(getMutex(o));
5152 }
5153
5154 } // end namespace ScopedLockReturnedInvalid
5155
5156
5157 namespace NegativeRequirements {
5158
5159 class Bar {
5160 Mutex mu;
5161 int a GUARDED_BY(mu);
5162
5163 public:
baz()5164 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5165 mu.Lock();
5166 a = 0;
5167 mu.Unlock();
5168 }
5169 };
5170
5171
5172 class Foo {
5173 Mutex mu;
5174 int a GUARDED_BY(mu);
5175
5176 public:
foo()5177 void foo() {
5178 mu.Lock(); // warning? needs !mu?
5179 baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
5180 bar();
5181 mu.Unlock();
5182 }
5183
bar()5184 void bar() {
5185 bar2(); // expected-warning {{calling function 'bar2' requires negative capability '!mu'}}
5186 }
5187
bar2()5188 void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5189 baz();
5190 }
5191
baz()5192 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5193 mu.Lock();
5194 a = 0;
5195 mu.Unlock();
5196 }
5197
test()5198 void test() {
5199 Bar b;
5200 b.baz(); // no warning -- in different class.
5201 }
5202 };
5203
5204 } // end namespace NegativeRequirements
5205
5206
5207 namespace NegativeThreadRoles {
5208
5209 typedef int __attribute__((capability("role"))) ThreadRole;
5210
acquire(ThreadRole R)5211 void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
release(ThreadRole R)5212 void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
5213
5214 ThreadRole FlightControl, Logger;
5215
5216 extern void enque_log_msg(const char *msg);
log_msg(const char * msg)5217 void log_msg(const char *msg) {
5218 enque_log_msg(msg);
5219 }
5220
dispatch_log(const char * msg)5221 void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
dispatch_log2(const char * msg)5222 void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
5223
flight_control_entry(void)5224 void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
5225 dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
5226 dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
5227 }
5228
spawn_fake_flight_control_thread(void)5229 void spawn_fake_flight_control_thread(void) {
5230 acquire(FlightControl);
5231 flight_control_entry();
5232 release(FlightControl);
5233 }
5234
5235 extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
logger_entry(void)5236 void logger_entry(void) __attribute__((requires_capability(Logger)))
5237 __attribute__((requires_capability(!FlightControl))) {
5238 const char *msg;
5239
5240 while ((msg = deque_log_msg())) {
5241 dispatch_log(msg);
5242 }
5243 }
5244
spawn_fake_logger_thread(void)5245 void spawn_fake_logger_thread(void) __attribute__((requires_capability(!FlightControl))) {
5246 acquire(Logger);
5247 logger_entry();
5248 release(Logger);
5249 }
5250
main(void)5251 int main(void) __attribute__((requires_capability(!FlightControl))) {
5252 spawn_fake_flight_control_thread();
5253 spawn_fake_logger_thread();
5254
5255 for (;;)
5256 ; /* Pretend to dispatch things. */
5257
5258 return 0;
5259 }
5260
5261 } // end namespace NegativeThreadRoles
5262
5263
5264 namespace AssertSharedExclusive {
5265
5266 void doSomething();
5267
5268 class Foo {
5269 Mutex mu;
5270 int a GUARDED_BY(mu);
5271
test()5272 void test() SHARED_LOCKS_REQUIRED(mu) {
5273 mu.AssertHeld();
5274 if (a > 0)
5275 doSomething();
5276 }
5277 };
5278
5279 } // end namespace AssertSharedExclusive
5280
5281
5282 namespace RangeBasedForAndReferences {
5283
5284 class Foo {
5285 struct MyStruct {
5286 int a;
5287 };
5288
5289 Mutex mu;
5290 int a GUARDED_BY(mu);
5291 MyContainer<int> cntr GUARDED_BY(mu);
5292 MyStruct s GUARDED_BY(mu);
5293 int arr[10] GUARDED_BY(mu);
5294
nonref_test()5295 void nonref_test() {
5296 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5297 b = 0; // no warning
5298 }
5299
auto_test()5300 void auto_test() {
5301 auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5302 b = 0; // no warning
5303 auto &c = a; // no warning
5304 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5305 }
5306
ref_test()5307 void ref_test() {
5308 int &b = a;
5309 int &c = b;
5310 int &d = c;
5311 b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5312 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5313 d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5314
5315 MyStruct &rs = s;
5316 rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
5317
5318 int (&rarr)[10] = arr;
5319 rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
5320 }
5321
ptr_test()5322 void ptr_test() {
5323 int *b = &a;
5324 *b = 0; // no expected warning yet
5325 }
5326
for_test()5327 void for_test() {
5328 int total = 0;
5329 for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
5330 total += i;
5331 }
5332 }
5333 };
5334
5335
5336 } // end namespace RangeBasedForAndReferences
5337
5338
5339
5340 namespace PassByRefTest {
5341
5342 class Foo {
5343 public:
Foo()5344 Foo() : a(0), b(0) { }
5345
5346 int a;
5347 int b;
5348
5349 void operator+(const Foo& f);
5350
5351 void operator[](const Foo& g);
5352
5353 void operator()();
5354 };
5355
5356 template<class T>
5357 T&& mymove(T& f);
5358
5359
5360 // test top-level functions
5361 void copy(Foo f);
5362 void write1(Foo& f);
5363 void write2(int a, Foo& f);
5364 void read1(const Foo& f);
5365 void read2(int a, const Foo& f);
5366 void destroy(Foo&& f);
5367
5368 void operator/(const Foo& f, const Foo& g);
5369 void operator*(const Foo& f, const Foo& g);
5370
5371 // Test constructors.
5372 struct FooRead {
5373 FooRead(const Foo &);
5374 };
5375 struct FooWrite {
5376 FooWrite(Foo &);
5377 };
5378
5379 // Test variadic functions
5380 template<typename... T>
copyVariadic(T...)5381 void copyVariadic(T...) {}
5382 template<typename... T>
writeVariadic(T &...)5383 void writeVariadic(T&...) {}
5384 template<typename... T>
readVariadic(const T &...)5385 void readVariadic(const T&...) {}
5386
5387 void copyVariadicC(int, ...);
5388
5389 class Bar {
5390 public:
5391 Mutex mu;
5392 Foo foo GUARDED_BY(mu);
5393 Foo foo2 GUARDED_BY(mu);
5394 Foo* foop PT_GUARDED_BY(mu);
5395 SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
5396
5397 // test methods.
5398 void mwrite1(Foo& f);
5399 void mwrite2(int a, Foo& f);
5400 void mread1(const Foo& f);
5401 void mread2(int a, const Foo& f);
5402
5403 // static methods
5404 static void smwrite1(Foo& f);
5405 static void smwrite2(int a, Foo& f);
5406 static void smread1(const Foo& f);
5407 static void smread2(int a, const Foo& f);
5408
5409 void operator<<(const Foo& f);
5410
test1()5411 void test1() {
5412 copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5413 write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5414 write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5415 read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5416 read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5417 destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5418
5419 copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5420 readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5421 writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5422 copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5423
5424 FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5425 FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5426
5427 mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5428 mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5429 mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5430 mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5431
5432 smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5433 smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5434 smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5435 smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5436
5437 foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5438 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5439 foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5440 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5441 foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5442 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5443 foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5444 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5445 foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5446 (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5447
5448 copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
5449 write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5450 write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5451 read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5452 read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5453 destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5454
5455 copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5456 write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5457 write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5458 read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5459 read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5460 destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5461
5462 // TODO -- these require better smart pointer handling.
5463 copy(*foosp.get());
5464 write1(*foosp.get());
5465 write2(10, *foosp.get());
5466 read1(*foosp.get());
5467 read2(10, *foosp.get());
5468 destroy(mymove(*foosp.get()));
5469 }
5470 };
5471
5472
5473 } // end namespace PassByRefTest
5474
5475
5476 namespace AcquiredBeforeAfterText {
5477
5478 class Foo {
5479 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5480 Mutex mu2;
5481 Mutex mu3;
5482
test1()5483 void test1() {
5484 mu1.Lock();
5485 mu2.Lock();
5486 mu3.Lock();
5487
5488 mu3.Unlock();
5489 mu2.Unlock();
5490 mu1.Unlock();
5491 }
5492
test2()5493 void test2() {
5494 mu2.Lock();
5495 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5496 mu1.Unlock();
5497 mu2.Unlock();
5498 }
5499
test3()5500 void test3() {
5501 mu3.Lock();
5502 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5503 mu1.Unlock();
5504 mu3.Unlock();
5505 }
5506
test4()5507 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {
5508 mu2.Lock();
5509 mu2.Unlock();
5510 }
5511
test5()5512 void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5513 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5514 mu1.Unlock();
5515 }
5516
test6()5517 void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5518 mu1.AssertHeld();
5519 }
5520
test7()5521 void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }
5522
test8()5523 void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }
5524 };
5525
5526
5527 class Foo2 {
5528 Mutex mu1;
5529 Mutex mu2 ACQUIRED_AFTER(mu1);
5530 Mutex mu3 ACQUIRED_AFTER(mu1);
5531
test1()5532 void test1() {
5533 mu1.Lock();
5534 mu2.Lock();
5535 mu3.Lock();
5536
5537 mu3.Unlock();
5538 mu2.Unlock();
5539 mu1.Unlock();
5540 }
5541
test2()5542 void test2() {
5543 mu2.Lock();
5544 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5545 mu1.Unlock();
5546 mu2.Unlock();
5547 }
5548
test3()5549 void test3() {
5550 mu3.Lock();
5551 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5552 mu1.Unlock();
5553 mu3.Unlock();
5554 }
5555 };
5556
5557
5558 class Foo3 {
5559 Mutex mu1 ACQUIRED_BEFORE(mu2);
5560 Mutex mu2;
5561 Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);
5562 Mutex mu4;
5563
test1()5564 void test1() {
5565 mu1.Lock();
5566 mu2.Lock();
5567 mu3.Lock();
5568 mu4.Lock();
5569
5570 mu4.Unlock();
5571 mu3.Unlock();
5572 mu2.Unlock();
5573 mu1.Unlock();
5574 }
5575
test2()5576 void test2() {
5577 mu4.Lock();
5578 mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}
5579
5580 mu2.Unlock();
5581 mu4.Unlock();
5582 }
5583
test3()5584 void test3() {
5585 mu4.Lock();
5586 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}
5587
5588 mu1.Unlock();
5589 mu4.Unlock();
5590 }
5591
test4()5592 void test4() {
5593 mu3.Lock();
5594 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5595
5596 mu1.Unlock();
5597 mu3.Unlock();
5598 }
5599 };
5600
5601
5602 // Test transitive DAG traversal with AFTER
5603 class Foo4 {
5604 Mutex mu1;
5605 Mutex mu2 ACQUIRED_AFTER(mu1);
5606 Mutex mu3 ACQUIRED_AFTER(mu1);
5607 Mutex mu4 ACQUIRED_AFTER(mu2, mu3);
5608 Mutex mu5 ACQUIRED_AFTER(mu4);
5609 Mutex mu6 ACQUIRED_AFTER(mu4);
5610 Mutex mu7 ACQUIRED_AFTER(mu5, mu6);
5611 Mutex mu8 ACQUIRED_AFTER(mu7);
5612
test()5613 void test() {
5614 mu8.Lock();
5615 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5616 mu1.Unlock();
5617 mu8.Unlock();
5618 }
5619 };
5620
5621
5622 // Test transitive DAG traversal with BEFORE
5623 class Foo5 {
5624 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5625 Mutex mu2 ACQUIRED_BEFORE(mu4);
5626 Mutex mu3 ACQUIRED_BEFORE(mu4);
5627 Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);
5628 Mutex mu5 ACQUIRED_BEFORE(mu7);
5629 Mutex mu6 ACQUIRED_BEFORE(mu7);
5630 Mutex mu7 ACQUIRED_BEFORE(mu8);
5631 Mutex mu8;
5632
test()5633 void test() {
5634 mu8.Lock();
5635 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5636 mu1.Unlock();
5637 mu8.Unlock();
5638 }
5639 };
5640
5641
5642 class Foo6 {
5643 Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}}
5644 Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}}
5645 Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}}
5646
5647 Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}}
5648 Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}}
5649
test0()5650 void test0() {
5651 mu_a.Lock();
5652 mu_b.Lock();
5653 mu_b.Unlock();
5654 mu_a.Unlock();
5655 }
5656
test1a()5657 void test1a() {
5658 mu1.Lock();
5659 mu1.Unlock();
5660 }
5661
test1b()5662 void test1b() {
5663 mu1.Lock();
5664 mu_a.Lock();
5665 mu_b.Lock();
5666 mu_b.Unlock();
5667 mu_a.Unlock();
5668 mu1.Unlock();
5669 }
5670
test()5671 void test() {
5672 mu2.Lock();
5673 mu2.Unlock();
5674 }
5675
test3()5676 void test3() {
5677 mu3.Lock();
5678 mu3.Unlock();
5679 }
5680 };
5681
5682 } // end namespace AcquiredBeforeAfterTest
5683
5684
5685 namespace ScopedAdoptTest {
5686
5687 class Foo {
5688 Mutex mu;
5689 int a GUARDED_BY(mu);
5690 int b;
5691
test1()5692 void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {
5693 MutexLock slock(&mu, true);
5694 a = 0;
5695 }
5696
test2()5697 void test2() SHARED_UNLOCK_FUNCTION(mu) {
5698 ReaderMutexLock slock(&mu, true);
5699 b = a;
5700 }
5701
test3()5702 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5703 MutexLock slock(&mu, true);
5704 a = 0;
5705 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5706
test4()5707 void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5708 ReaderMutexLock slock(&mu, true);
5709 b = a;
5710 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5711
5712 };
5713
5714 } // end namespace ScopedAdoptTest
5715
5716
5717 namespace TestReferenceNoThreadSafetyAnalysis {
5718
5719 #define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
5720
5721 // Takes a reference to a guarded data member, and returns an unguarded
5722 // reference.
5723 template <class T>
ts_unchecked_read(const T & v)5724 inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
5725 return v;
5726 }
5727
5728 template <class T>
ts_unchecked_read(T & v)5729 inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
5730 return v;
5731 }
5732
5733
5734 class Foo {
5735 public:
Foo()5736 Foo(): a(0) { }
5737
5738 int a;
5739 };
5740
5741
5742 class Bar {
5743 public:
Bar()5744 Bar() : a(0) { }
5745
5746 Mutex mu;
5747 int a GUARDED_BY(mu);
5748 Foo foo GUARDED_BY(mu);
5749 };
5750
5751
test()5752 void test() {
5753 Bar bar;
5754 const Bar cbar;
5755
5756 int a = TS_UNCHECKED_READ(bar.a); // nowarn
5757 TS_UNCHECKED_READ(bar.a) = 1; // nowarn
5758
5759 int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
5760 TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
5761
5762 int c = TS_UNCHECKED_READ(cbar.a); // nowarn
5763 }
5764
5765 #undef TS_UNCHECKED_READ
5766
5767 } // end namespace TestReferenceNoThreadSafetyAnalysis
5768
5769
5770 namespace GlobalAcquiredBeforeAfterTest {
5771
5772 Mutex mu1;
5773 Mutex mu2 ACQUIRED_AFTER(mu1);
5774
test3()5775 void test3() {
5776 mu2.Lock();
5777 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5778 mu1.Unlock();
5779 mu2.Unlock();
5780 }
5781
5782 } // end namespace GlobalAcquiredBeforeAfterTest
5783
5784
5785 namespace LifetimeExtensionText {
5786
5787 struct Holder {
~HolderLifetimeExtensionText::Holder5788 virtual ~Holder() throw() {}
5789 int i = 0;
5790 };
5791
test()5792 void test() {
5793 // Should not crash.
5794 const auto &value = Holder().i;
5795 }
5796
5797 } // end namespace LifetimeExtensionTest
5798
5799
5800 namespace LockableUnions {
5801
5802 union LOCKABLE MutexUnion {
5803 int a;
5804 char* b;
5805
5806 void Lock() EXCLUSIVE_LOCK_FUNCTION();
5807 void Unlock() UNLOCK_FUNCTION();
5808 };
5809
5810 MutexUnion muun2;
5811 MutexUnion muun1 ACQUIRED_BEFORE(muun2);
5812
test()5813 void test() {
5814 muun2.Lock();
5815 muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
5816 muun1.Unlock();
5817 muun2.Unlock();
5818 }
5819
5820 } // end namespace LockableUnions
5821
5822 // This used to crash.
5823 class acquired_before_empty_str {
WaitUntilSpaceAvailable()5824 void WaitUntilSpaceAvailable() {
5825 lock_.ReaderLock(); // expected-note {{acquired here}}
5826 } // expected-warning {{mutex 'lock_' is still held at the end of function}}
5827 Mutex lock_ ACQUIRED_BEFORE("");
5828 };
5829
5830 namespace PR34800 {
5831 struct A {
5832 operator int() const;
5833 };
5834 struct B {
5835 bool g() __attribute__((locks_excluded(h))); // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}}
5836 int h;
5837 };
5838 struct C {
5839 B *operator[](int);
5840 };
5841 C c;
f()5842 void f() { c[A()]->g(); }
5843 } // namespace PR34800
5844
5845 namespace ReturnScopedLockable {
5846 template<typename Object> class SCOPED_LOCKABLE ReadLockedPtr {
5847 public:
5848 ReadLockedPtr(Object *ptr) SHARED_LOCK_FUNCTION((*this)->mutex);
5849 ReadLockedPtr(ReadLockedPtr &&) SHARED_LOCK_FUNCTION((*this)->mutex);
5850 ~ReadLockedPtr() UNLOCK_FUNCTION();
5851
operator ->() const5852 Object *operator->() const { return object; }
5853
5854 private:
5855 Object *object;
5856 };
5857
5858 struct Object {
5859 int f() SHARED_LOCKS_REQUIRED(mutex);
5860 Mutex mutex;
5861 };
5862
5863 ReadLockedPtr<Object> get();
use()5864 int use() {
5865 auto ptr = get();
5866 return ptr->f();
5867 }
use_constructor()5868 void use_constructor() {
5869 auto ptr = ReadLockedPtr<Object>(nullptr);
5870 ptr->f();
5871 auto ptr2 = ReadLockedPtr<Object>{nullptr};
5872 ptr2->f();
5873 auto ptr3 = (ReadLockedPtr<Object>{nullptr});
5874 ptr3->f();
5875 }
5876 struct Convertible {
5877 Convertible();
5878 operator ReadLockedPtr<Object>();
5879 };
use_conversion()5880 void use_conversion() {
5881 ReadLockedPtr<Object> ptr = Convertible();
5882 ptr->f();
5883 }
5884 }
5885
5886 namespace PR38640 {
f()5887 void f() {
5888 // Self-referencing assignment previously caused an infinite loop when thread
5889 // safety analysis was enabled.
5890 int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}}
5891 }
5892 }
5893
5894 namespace Derived_Smart_Pointer {
5895 template <class T>
5896 class SmartPtr_Derived : public SmartPtr<T> {};
5897
5898 class Foo {
5899 public:
5900 SmartPtr_Derived<Mutex> mu_;
5901 int a GUARDED_BY(mu_);
5902 int b GUARDED_BY(mu_.get());
5903 int c GUARDED_BY(*mu_);
5904
5905 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
5906 void Unlock() UNLOCK_FUNCTION(mu_);
5907
test0()5908 void test0() {
5909 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
5910 b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
5911 c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
5912 }
5913
test1()5914 void test1() {
5915 Lock();
5916 a = 1;
5917 b = 1;
5918 c = 1;
5919 Unlock();
5920 }
5921 };
5922
5923 class Bar {
5924 SmartPtr_Derived<Foo> foo;
5925
test0()5926 void test0() {
5927 foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
5928 (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
5929 foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
5930 }
5931
test1()5932 void test1() {
5933 foo->Lock();
5934 foo->a = 1;
5935 foo->Unlock();
5936
5937 foo->mu_->Lock();
5938 foo->b = 1;
5939 foo->mu_->Unlock();
5940
5941 MutexLock lock(foo->mu_.get());
5942 foo->c = 1;
5943 }
5944 };
5945
5946 class PointerGuard {
5947 Mutex mu1;
5948 Mutex mu2;
5949 SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
5950
test0()5951 void test0() {
5952 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
5953 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \
5954 // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
5955
5956 }
5957
test1()5958 void test1() {
5959 mu1.Lock();
5960
5961 i.get();
5962 *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
5963
5964 mu1.Unlock();
5965 }
5966
test2()5967 void test2() {
5968 mu2.Lock();
5969
5970 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
5971 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
5972
5973 mu2.Unlock();
5974 }
5975
test3()5976 void test3() {
5977 mu1.Lock();
5978 mu2.Lock();
5979
5980 i.get();
5981 *i = 2;
5982
5983 mu2.Unlock();
5984 mu1.Unlock();
5985 }
5986 };
5987 }
5988