Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / warn-thread-safety-analysis.cpp
blob205cfa284f6c9c96c4db5e811050d62b5afd8666
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
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
9 #include "thread-safety-annotations.h"
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();
22 void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
23 void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
25 // for negative capabilities
26 const Mutex& operator!() const { return *this; }
28 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
29 void AssertReaderHeld() ASSERT_SHARED_LOCK();
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();
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();
46 class SCOPED_LOCKABLE ReleasableMutexLock {
47 public:
48 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
49 ~ReleasableMutexLock() UNLOCK_FUNCTION();
51 void Release() UNLOCK_FUNCTION();
54 class SCOPED_LOCKABLE DoubleMutexLock {
55 public:
56 DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);
57 ~DoubleMutexLock() UNLOCK_FUNCTION();
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("*");
68 // For testing handling of smart pointers.
69 template<class T>
70 class SmartPtr {
71 public:
72 SmartPtr(T* p) : ptr_(p) { }
73 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
74 ~SmartPtr();
76 T* get() const { return ptr_; }
77 T* operator->() const { return ptr_; }
78 T& operator*() const { return *ptr_; }
79 T& operator[](int i) const { return ptr_[i]; }
81 private:
82 T* ptr_;
85 template<typename T, typename U>
86 U& operator->*(const SmartPtr<T>& ptr, U T::*p) { return ptr->*p; }
89 // For testing destructor calls and cleanup.
90 class MyString {
91 public:
92 MyString(const char* s);
93 ~MyString();
97 // For testing operator overloading
98 template <class K, class T>
99 class MyMap {
100 public:
101 T& operator[](const K& k);
105 // For testing handling of containers.
106 template <class T>
107 class MyContainer {
108 public:
109 MyContainer();
111 typedef T* iterator;
112 typedef const T* const_iterator;
114 T* begin();
115 T* end();
117 const T* cbegin();
118 const T* cend();
120 T& operator[](int i);
121 const T& operator[](int i) const;
123 private:
124 T* ptr_;
129 Mutex sls_mu;
131 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
132 int sls_guard_var __attribute__((guarded_var)) = 0;
133 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
135 bool getBool();
137 class MutexWrapper {
138 public:
139 Mutex mu;
140 int x __attribute__((guarded_by(mu)));
141 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
144 MutexWrapper sls_mw;
146 void sls_fun_0() {
147 sls_mw.mu.Lock();
148 sls_mw.x = 5;
149 sls_mw.mu.Unlock();
152 void sls_fun_2() {
153 sls_mu.Lock();
154 int x = sls_guard_var;
155 sls_mu.Unlock();
158 void sls_fun_3() {
159 sls_mu.Lock();
160 sls_guard_var = 2;
161 sls_mu.Unlock();
164 void sls_fun_4() {
165 sls_mu2.Lock();
166 sls_guard_var = 2;
167 sls_mu2.Unlock();
170 void sls_fun_5() {
171 sls_mu.Lock();
172 int x = sls_guardby_var;
173 sls_mu.Unlock();
176 void sls_fun_6() {
177 sls_mu.Lock();
178 sls_guardby_var = 2;
179 sls_mu.Unlock();
182 void sls_fun_7() {
183 sls_mu.Lock();
184 sls_mu2.Lock();
185 sls_mu2.Unlock();
186 sls_mu.Unlock();
189 void sls_fun_8() {
190 sls_mu.Lock();
191 if (getBool())
192 sls_mu.Unlock();
193 else
194 sls_mu.Unlock();
197 void sls_fun_9() {
198 if (getBool())
199 sls_mu.Lock();
200 else
201 sls_mu.Lock();
202 sls_mu.Unlock();
205 void sls_fun_good_6() {
206 if (getBool()) {
207 sls_mu.Lock();
208 } else {
209 if (getBool()) {
210 getBool(); // EMPTY
211 } else {
212 getBool(); // EMPTY
214 sls_mu.Lock();
216 sls_mu.Unlock();
219 void sls_fun_good_7() {
220 sls_mu.Lock();
221 while (getBool()) {
222 sls_mu.Unlock();
223 if (getBool()) {
224 if (getBool()) {
225 sls_mu.Lock();
226 continue;
229 sls_mu.Lock();
231 sls_mu.Unlock();
234 void sls_fun_good_8() {
235 sls_mw.MyLock();
236 sls_mw.mu.Unlock();
239 void sls_fun_bad_1() {
240 sls_mu.Unlock(); // \
241 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
244 void sls_fun_bad_2() {
245 sls_mu.Lock(); // expected-note{{mutex acquired here}}
246 sls_mu.Lock(); // \
247 // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
248 sls_mu.Unlock();
251 void sls_fun_bad_3() {
252 sls_mu.Lock(); // expected-note {{mutex acquired here}}
253 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
255 void sls_fun_bad_4() {
256 if (getBool())
257 sls_mu.Lock(); // expected-note{{mutex acquired here}}
258 else
259 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
260 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
261 // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
263 void sls_fun_bad_5() {
264 sls_mu.Lock(); // expected-note {{mutex acquired here}}
265 if (getBool())
266 sls_mu.Unlock();
267 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
269 void sls_fun_bad_6() {
270 if (getBool()) {
271 sls_mu.Lock(); // expected-note {{mutex acquired here}}
272 } else {
273 if (getBool()) {
274 getBool(); // EMPTY
275 } else {
276 getBool(); // EMPTY
279 sls_mu.Unlock(); // \
280 expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
281 expected-warning{{releasing mutex 'sls_mu' that was not held}}
284 void sls_fun_bad_7() {
285 sls_mu.Lock();
286 while (getBool()) { // \
287 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
288 sls_mu.Unlock();
289 if (getBool()) {
290 if (getBool()) {
291 continue;
294 sls_mu.Lock(); // expected-note {{mutex acquired here}}
296 sls_mu.Unlock();
299 void sls_fun_bad_8() {
300 sls_mu.Lock(); // expected-note{{mutex acquired here}}
302 do {
303 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
304 } while (getBool());
307 void sls_fun_bad_9() {
308 do {
309 sls_mu.Lock(); // \
310 // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
311 // expected-note{{mutex acquired here}}
312 } while (getBool());
313 sls_mu.Unlock();
316 void sls_fun_bad_10() {
317 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
318 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
319 sls_mu.Unlock();
321 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
323 void sls_fun_bad_11() {
324 while (getBool()) { // \
325 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
326 sls_mu.Lock(); // expected-note {{mutex acquired here}}
328 sls_mu.Unlock(); // \
329 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
332 void sls_fun_bad_12() {
333 sls_mu.Lock(); // expected-note {{mutex acquired here}}
334 while (getBool()) {
335 sls_mu.Unlock();
336 if (getBool()) {
337 if (getBool()) {
338 break;
341 sls_mu.Lock();
343 sls_mu.Unlock(); // \
344 expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
345 expected-warning{{releasing mutex 'sls_mu' that was not held}}
348 //-----------------------------------------//
349 // Handling lock expressions in attribute args
350 // -------------------------------------------//
352 Mutex aa_mu;
354 class GlobalLocker {
355 public:
356 void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu);
357 void globalUnlock() UNLOCK_FUNCTION(aa_mu);
360 GlobalLocker glock;
362 void aa_fun_1() {
363 glock.globalLock();
364 glock.globalUnlock();
367 void aa_fun_bad_1() {
368 glock.globalUnlock(); // \
369 // expected-warning{{releasing mutex 'aa_mu' that was not held}}
372 void aa_fun_bad_2() {
373 glock.globalLock(); // expected-note{{mutex acquired here}}
374 glock.globalLock(); // \
375 // expected-warning{{acquiring mutex 'aa_mu' that is already held}}
376 glock.globalUnlock();
379 void aa_fun_bad_3() {
380 glock.globalLock(); // expected-note{{mutex acquired here}}
381 } // expected-warning{{mutex 'aa_mu' is still held at the end of function}}
383 //--------------------------------------------------//
384 // Regression tests for unusual method names
385 //--------------------------------------------------//
387 Mutex wmu;
389 // Test diagnostics for other method names.
390 class WeirdMethods {
391 // FIXME: can't currently check inside constructors and destructors.
392 WeirdMethods() {
393 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
394 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
395 ~WeirdMethods() {
396 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
397 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
398 void operator++() {
399 wmu.Lock(); // expected-note {{mutex acquired here}}
400 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
401 operator int*() {
402 wmu.Lock(); // expected-note {{mutex acquired here}}
403 return 0;
404 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
407 //-----------------------------------------------//
408 // Errors for guarded by or guarded var variables
409 // ----------------------------------------------//
411 int *pgb_gvar __attribute__((pt_guarded_var));
412 int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
414 class PGBFoo {
415 public:
416 int x;
417 int *pgb_field __attribute__((guarded_by(sls_mu2)))
418 __attribute__((pt_guarded_by(sls_mu)));
419 void testFoo() {
420 pgb_field = &x; // \
421 // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}
422 *pgb_field = x; // 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 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
425 // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}
426 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
427 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
431 class GBFoo {
432 public:
433 int gb_field __attribute__((guarded_by(sls_mu)));
435 void testFoo() {
436 gb_field = 0; // \
437 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
440 void testNoAnal() NO_THREAD_SAFETY_ANALYSIS {
441 gb_field = 0;
445 GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
447 void gb_fun_0() {
448 sls_mu.Lock();
449 int x = *pgb_var;
450 sls_mu.Unlock();
453 void gb_fun_1() {
454 sls_mu.Lock();
455 *pgb_var = 2;
456 sls_mu.Unlock();
459 void gb_fun_2() {
460 int x;
461 pgb_var = &x;
464 void gb_fun_3() {
465 int *x = pgb_var;
468 void gb_bad_0() {
469 sls_guard_var = 1; // \
470 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
473 void gb_bad_1() {
474 int x = sls_guard_var; // \
475 // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}
478 void gb_bad_2() {
479 sls_guardby_var = 1; // \
480 // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}
483 void gb_bad_3() {
484 int x = sls_guardby_var; // \
485 // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}
488 void gb_bad_4() {
489 *pgb_gvar = 1; // \
490 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}
493 void gb_bad_5() {
494 int x = *pgb_gvar; // \
495 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}
498 void gb_bad_6() {
499 *pgb_var = 1; // \
500 // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}
503 void gb_bad_7() {
504 int x = *pgb_var; // \
505 // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}
508 void gb_bad_8() {
509 GBFoo G;
510 G.gb_field = 0; // \
511 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}
514 void gb_bad_9() {
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 ++sls_guard_var; // \
520 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
521 --sls_guard_var;// \
522 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
525 //-----------------------------------------------//
526 // Warnings on variables with late parsed attributes
527 // ----------------------------------------------//
529 class LateFoo {
530 public:
531 int a __attribute__((guarded_by(mu)));
532 int b;
534 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
536 void test() {
537 a = 0; // \
538 // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}
539 b = a; // \
540 // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
541 c = 0; // \
542 // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}
545 int c __attribute__((guarded_by(mu)));
547 Mutex mu;
550 class LateBar {
551 public:
552 int a_ __attribute__((guarded_by(mu1_)));
553 int b_;
554 int *q __attribute__((pt_guarded_by(mu)));
555 Mutex mu1_;
556 Mutex mu;
557 LateFoo Foo;
558 LateFoo Foo2;
559 LateFoo *FooPointer;
562 LateBar b1, *b3;
564 void late_0() {
565 LateFoo FooA;
566 LateFoo FooB;
567 FooA.mu.Lock();
568 FooA.a = 5;
569 FooA.mu.Unlock();
572 void late_1() {
573 LateBar BarA;
574 BarA.FooPointer->mu.Lock();
575 BarA.FooPointer->a = 2;
576 BarA.FooPointer->mu.Unlock();
579 void late_bad_0() {
580 LateFoo fooA;
581 LateFoo fooB;
582 fooA.mu.Lock();
583 fooB.a = 5; // \
584 // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \
585 // expected-note{{found near match 'fooA.mu'}}
586 fooA.mu.Unlock();
589 void late_bad_1() {
590 Mutex mu;
591 mu.Lock();
592 b1.mu1_.Lock();
593 int res = b1.a_ + b3->b_;
594 b3->b_ = *b1.q; // \
595 // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}
596 b1.mu1_.Unlock();
597 b1.b_ = res;
598 mu.Unlock();
601 void late_bad_2() {
602 LateBar BarA;
603 BarA.FooPointer->mu.Lock();
604 BarA.Foo.a = 2; // \
605 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \
606 // expected-note{{found near match 'BarA.FooPointer->mu'}}
607 BarA.FooPointer->mu.Unlock();
610 void late_bad_3() {
611 LateBar BarA;
612 BarA.Foo.mu.Lock();
613 BarA.FooPointer->a = 2; // \
614 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \
615 // expected-note{{found near match 'BarA.Foo.mu'}}
616 BarA.Foo.mu.Unlock();
619 void late_bad_4() {
620 LateBar BarA;
621 BarA.Foo.mu.Lock();
622 BarA.Foo2.a = 2; // \
623 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \
624 // expected-note{{found near match 'BarA.Foo.mu'}}
625 BarA.Foo.mu.Unlock();
628 //-----------------------------------------------//
629 // Extra warnings for shared vs. exclusive locks
630 // ----------------------------------------------//
632 void shared_fun_0() {
633 sls_mu.Lock();
634 do {
635 sls_mu.Unlock();
636 sls_mu.Lock();
637 } while (getBool());
638 sls_mu.Unlock();
641 void shared_fun_1() {
642 sls_mu.ReaderLock(); // \
643 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
644 do {
645 sls_mu.Unlock();
646 sls_mu.Lock(); // \
647 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
648 } while (getBool());
649 sls_mu.Unlock();
652 void shared_fun_3() {
653 if (getBool())
654 sls_mu.Lock();
655 else
656 sls_mu.Lock();
657 *pgb_var = 1;
658 sls_mu.Unlock();
661 void shared_fun_4() {
662 if (getBool())
663 sls_mu.ReaderLock();
664 else
665 sls_mu.ReaderLock();
666 int x = sls_guardby_var;
667 sls_mu.Unlock();
670 void shared_fun_8() {
671 if (getBool())
672 sls_mu.Lock(); // \
673 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
674 else
675 sls_mu.ReaderLock(); // \
676 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
677 sls_mu.Unlock();
680 void shared_fun_9() {
681 sls_mu.Lock();
682 sls_mu.ExclusiveUnlock();
684 sls_mu.ReaderLock();
685 sls_mu.ReaderUnlock();
688 void shared_fun_10() {
689 sls_mu.Lock();
690 sls_mu.DemoteExclusive();
691 sls_mu.ReaderUnlock();
694 void shared_fun_11() {
695 sls_mu.ReaderLock();
696 sls_mu.PromoteShared();
697 sls_mu.Unlock();
700 void shared_bad_0() {
701 sls_mu.Lock(); // \
702 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
703 do {
704 sls_mu.Unlock();
705 sls_mu.ReaderLock(); // \
706 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
707 } while (getBool());
708 sls_mu.Unlock();
711 void shared_bad_1() {
712 if (getBool())
713 sls_mu.Lock(); // \
714 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
715 else
716 sls_mu.ReaderLock(); // \
717 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
718 *pgb_var = 1;
719 sls_mu.Unlock();
722 void shared_bad_2() {
723 if (getBool())
724 sls_mu.ReaderLock(); // \
725 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
726 else
727 sls_mu.Lock(); // \
728 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
729 *pgb_var = 1;
730 sls_mu.Unlock();
733 void shared_bad_3() {
734 sls_mu.Lock(); // expected-note {{mutex acquired here}}
735 sls_mu.ReaderUnlock(); // \
736 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
739 void shared_bad_4() {
740 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
741 sls_mu.ExclusiveUnlock(); // \
742 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
745 void shared_bad_5() {
746 sls_mu.Lock(); // expected-note {{mutex acquired here}}
747 sls_mu.PromoteShared(); // \
748 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
749 sls_mu.ExclusiveUnlock();
752 void shared_bad_6() {
753 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
754 sls_mu.DemoteExclusive(); // \
755 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
756 sls_mu.ReaderUnlock();
759 // FIXME: Add support for functions (not only methods)
760 class LRBar {
761 public:
762 void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
763 void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu);
764 void le_fun() __attribute__((locks_excluded(sls_mu)));
767 class LRFoo {
768 public:
769 void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
770 void testShared() SHARED_LOCKS_REQUIRED(sls_mu2);
773 void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
774 void elr_fun() {}
776 LRFoo MyLRFoo;
777 LRBar Bar;
779 void es_fun_0() {
780 aa_mu.Lock();
781 Bar.aa_elr_fun();
782 aa_mu.Unlock();
785 void es_fun_1() {
786 aa_mu.Lock();
787 Bar.aa_elr_fun_s();
788 aa_mu.Unlock();
791 void es_fun_2() {
792 aa_mu.ReaderLock();
793 Bar.aa_elr_fun_s();
794 aa_mu.Unlock();
797 void es_fun_3() {
798 sls_mu.Lock();
799 MyLRFoo.test();
800 sls_mu.Unlock();
803 void es_fun_4() {
804 sls_mu2.Lock();
805 MyLRFoo.testShared();
806 sls_mu2.Unlock();
809 void es_fun_5() {
810 sls_mu2.ReaderLock();
811 MyLRFoo.testShared();
812 sls_mu2.Unlock();
815 void es_fun_6() {
816 Bar.le_fun();
819 void es_fun_7() {
820 sls_mu.Lock();
821 elr_fun();
822 sls_mu.Unlock();
825 void es_fun_8() NO_THREAD_SAFETY_ANALYSIS;
827 void es_fun_8() {
828 Bar.aa_elr_fun_s();
831 void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu);
832 void es_fun_9() {
833 Bar.aa_elr_fun_s();
836 void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
837 void es_fun_10() {
838 Bar.aa_elr_fun_s();
841 void es_bad_0() {
842 Bar.aa_elr_fun(); // \
843 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
846 void es_bad_1() {
847 aa_mu.ReaderLock();
848 Bar.aa_elr_fun(); // \
849 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
850 aa_mu.Unlock();
853 void es_bad_2() {
854 Bar.aa_elr_fun_s(); // \
855 // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}
858 void es_bad_3() {
859 MyLRFoo.test(); // \
860 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
863 void es_bad_4() {
864 MyLRFoo.testShared(); // \
865 // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}
868 void es_bad_5() {
869 sls_mu.ReaderLock();
870 MyLRFoo.test(); // \
871 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
872 sls_mu.Unlock();
875 void es_bad_6() {
876 sls_mu.Lock();
877 Bar.le_fun(); // \
878 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
879 sls_mu.Unlock();
882 void es_bad_7() {
883 sls_mu.ReaderLock();
884 Bar.le_fun(); // \
885 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
886 sls_mu.Unlock();
890 //-----------------------------------------------//
891 // Unparseable lock expressions
892 // ----------------------------------------------//
894 // FIXME -- derive new tests for unhandled expressions
897 //----------------------------------------------------------------------------//
898 // The following test cases are ported from the gcc thread safety implementation
899 // They are each wrapped inside a namespace with the test number of the gcc test
901 // FIXME: add all the gcc tests, once this analysis passes them.
902 //----------------------------------------------------------------------------//
904 //-----------------------------------------//
905 // Good testcases (no errors)
906 //-----------------------------------------//
908 namespace thread_annot_lock_20 {
909 class Bar {
910 public:
911 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
912 static int b_ GUARDED_BY(mu1_);
913 static Mutex mu1_;
914 static int a_ GUARDED_BY(mu1_);
917 Bar b1;
919 int Bar::func1()
921 int res = 5;
923 if (a_ == 4)
924 res = b_;
925 return res;
927 } // end namespace thread_annot_lock_20
929 namespace thread_annot_lock_22 {
930 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
931 // uses in class definitions.
932 Mutex mu;
934 class Bar {
935 public:
936 int a_ GUARDED_BY(mu1_);
937 int b_;
938 int *q PT_GUARDED_BY(mu);
939 Mutex mu1_ ACQUIRED_AFTER(mu);
942 Bar b1, *b3;
943 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
944 int res GUARDED_BY(mu) = 5;
946 int func(int i)
948 int x;
949 mu.Lock();
950 b1.mu1_.Lock();
951 res = b1.a_ + b3->b_;
952 *p = i;
953 b1.a_ = res + b3->b_;
954 b3->b_ = *b1.q;
955 b1.mu1_.Unlock();
956 b1.b_ = res;
957 x = res;
958 mu.Unlock();
959 return x;
961 } // end namespace thread_annot_lock_22
963 namespace thread_annot_lock_27_modified {
964 // test lock annotations applied to function definitions
965 // Modified: applied annotations only to function declarations
966 Mutex mu1;
967 Mutex mu2 ACQUIRED_AFTER(mu1);
969 class Foo {
970 public:
971 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
974 int Foo::method1(int i) {
975 return i;
979 int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
980 int foo(int i) {
981 return i;
984 static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
985 static int bar(int i) {
986 return i;
989 void main() {
990 Foo a;
992 mu1.Lock();
993 mu2.Lock();
994 a.method1(1);
995 foo(2);
996 mu2.Unlock();
997 bar(3);
998 mu1.Unlock();
1000 } // end namespace thread_annot_lock_27_modified
1003 namespace thread_annot_lock_38 {
1004 // Test the case where a template member function is annotated with lock
1005 // attributes in a non-template class.
1006 class Foo {
1007 public:
1008 void func1(int y) LOCKS_EXCLUDED(mu_);
1009 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
1010 private:
1011 Mutex mu_;
1014 Foo *foo;
1016 void main()
1018 foo->func1(5);
1019 foo->func2(5);
1021 } // end namespace thread_annot_lock_38
1023 namespace thread_annot_lock_43 {
1024 // Tests lock canonicalization
1025 class Foo {
1026 public:
1027 Mutex *mu_;
1030 class FooBar {
1031 public:
1032 Foo *foo_;
1033 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
1034 int a_ GUARDED_BY(foo_->mu_);
1037 FooBar *fb;
1039 void main()
1041 int x;
1042 fb->foo_->mu_->Lock();
1043 x = fb->GetA();
1044 fb->foo_->mu_->Unlock();
1046 } // end namespace thread_annot_lock_43
1048 namespace thread_annot_lock_49 {
1049 // Test the support for use of lock expression in the annotations
1050 class Foo {
1051 public:
1052 Mutex foo_mu_;
1055 class Bar {
1056 private:
1057 Foo *foo;
1058 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
1060 public:
1061 void Test1() {
1062 foo->foo_mu_.Lock();
1063 bar_mu_.Lock();
1064 bar_mu_.Unlock();
1065 foo->foo_mu_.Unlock();
1069 void main() {
1070 Bar bar;
1071 bar.Test1();
1073 } // end namespace thread_annot_lock_49
1075 namespace thread_annot_lock_61_modified {
1076 // Modified to fix the compiler errors
1077 // Test the fix for a bug introduced by the support of pass-by-reference
1078 // parameters.
1079 struct Foo { Foo &operator<< (bool) {return *this;} };
1080 Foo &getFoo();
1081 struct Bar { Foo &func () {return getFoo();} };
1082 struct Bas { void operator& (Foo &) {} };
1083 void mumble()
1085 Bas() & Bar().func() << "" << "";
1086 Bas() & Bar().func() << "";
1088 } // end namespace thread_annot_lock_61_modified
1091 namespace thread_annot_lock_65 {
1092 // Test the fix for a bug in the support of allowing reader locks for
1093 // non-const, non-modifying overload functions. (We didn't handle the builtin
1094 // properly.)
1095 enum MyFlags {
1096 Zero,
1097 One,
1098 Two,
1099 Three,
1100 Four,
1101 Five,
1102 Six,
1103 Seven,
1104 Eight,
1105 Nine
1108 inline MyFlags
1109 operator|(MyFlags a, MyFlags b)
1111 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1114 inline MyFlags&
1115 operator|=(MyFlags& a, MyFlags b)
1117 return a = a | b;
1119 } // end namespace thread_annot_lock_65
1121 namespace thread_annot_lock_66_modified {
1122 // Modified: Moved annotation to function defn
1123 // Test annotations on out-of-line definitions of member functions where the
1124 // annotations refer to locks that are also data members in the class.
1125 Mutex mu;
1127 class Foo {
1128 public:
1129 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1130 int data GUARDED_BY(mu1);
1131 Mutex *mu1;
1132 Mutex *mu2;
1135 int Foo::method1(int i)
1137 return data + i;
1140 void main()
1142 Foo a;
1144 a.mu2->Lock();
1145 a.mu1->Lock();
1146 mu.Lock();
1147 a.method1(1);
1148 mu.Unlock();
1149 a.mu1->Unlock();
1150 a.mu2->Unlock();
1152 } // end namespace thread_annot_lock_66_modified
1154 namespace thread_annot_lock_68_modified {
1155 // Test a fix to a bug in the delayed name binding with nested template
1156 // instantiation. We use a stack to make sure a name is not resolved to an
1157 // inner context.
1158 template <typename T>
1159 class Bar {
1160 Mutex mu_;
1163 template <typename T>
1164 class Foo {
1165 public:
1166 void func(T x) {
1167 mu_.Lock();
1168 count_ = x;
1169 mu_.Unlock();
1172 private:
1173 T count_ GUARDED_BY(mu_);
1174 Bar<T> bar_;
1175 Mutex mu_;
1178 void main()
1180 Foo<int> *foo;
1181 foo->func(5);
1183 } // end namespace thread_annot_lock_68_modified
1185 namespace thread_annot_lock_30_modified {
1186 // Test delay parsing of lock attribute arguments with nested classes.
1187 // Modified: trylocks replaced with exclusive_lock_fun
1188 int a = 0;
1190 class Bar {
1191 struct Foo;
1193 public:
1194 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1196 int func() {
1197 MyLock();
1198 // if (foo == 0) {
1199 // return 0;
1200 // }
1201 a = 5;
1202 mu.Unlock();
1203 return 1;
1206 class FooBar {
1207 int x;
1208 int y;
1211 private:
1212 Mutex mu;
1215 Bar *bar;
1217 void main()
1219 bar->func();
1221 } // end namespace thread_annot_lock_30_modified
1223 namespace thread_annot_lock_47 {
1224 // Test the support for annotations on virtual functions.
1225 // This is a good test case. (i.e. There should be no warning emitted by the
1226 // compiler.)
1227 class Base {
1228 public:
1229 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1230 virtual void func2() LOCKS_EXCLUDED(mu_);
1231 Mutex mu_;
1234 class Child : public Base {
1235 public:
1236 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1237 virtual void func2() LOCKS_EXCLUDED(mu_);
1240 void main() {
1241 Child *c;
1242 Base *b = c;
1244 b->mu_.Lock();
1245 b->func1();
1246 b->mu_.Unlock();
1247 b->func2();
1249 c->mu_.Lock();
1250 c->func1();
1251 c->mu_.Unlock();
1252 c->func2();
1254 } // end namespace thread_annot_lock_47
1256 //-----------------------------------------//
1257 // Tests which produce errors
1258 //-----------------------------------------//
1260 namespace thread_annot_lock_13 {
1261 Mutex mu1;
1262 Mutex mu2;
1264 int g GUARDED_BY(mu1);
1265 int w GUARDED_BY(mu2);
1267 class Foo {
1268 public:
1269 void bar() LOCKS_EXCLUDED(mu_, mu1);
1270 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1272 private:
1273 int a_ GUARDED_BY(mu_);
1274 public:
1275 Mutex mu_ ACQUIRED_AFTER(mu1);
1278 int Foo::foo()
1280 int res;
1281 w = 5;
1282 res = a_ + 5;
1283 return res;
1286 void Foo::bar()
1288 int x;
1289 mu_.Lock();
1290 x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}
1291 a_ = x + 1;
1292 mu_.Unlock();
1293 if (x > 5) {
1294 mu1.Lock();
1295 g = 2;
1296 mu1.Unlock();
1300 void main()
1302 Foo f1, *f2;
1303 f1.mu_.Lock();
1304 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}
1305 mu2.Lock();
1306 f1.foo();
1307 mu2.Unlock();
1308 f1.mu_.Unlock();
1309 f2->mu_.Lock();
1310 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}
1311 f2->mu_.Unlock();
1312 mu2.Lock();
1313 w = 2;
1314 mu2.Unlock();
1316 } // end namespace thread_annot_lock_13
1318 namespace thread_annot_lock_18_modified {
1319 // Modified: Trylocks removed
1320 // Test the ability to distnguish between the same lock field of
1321 // different objects of a class.
1322 class Bar {
1323 public:
1324 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1325 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1326 int a_ GUARDED_BY(mu1_);
1328 private:
1329 Mutex mu1_;
1332 Bar *b1, *b2;
1334 void func()
1336 b1->MyLock();
1337 b1->a_ = 5;
1338 b2->a_ = 3; // \
1339 // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \
1340 // expected-note {{found near match 'b1->mu1_'}}
1341 b2->MyLock();
1342 b2->MyUnlock();
1343 b1->MyUnlock();
1345 } // end namespace thread_annot_lock_18_modified
1347 namespace thread_annot_lock_21 {
1348 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1349 // uses in class definitions.
1350 Mutex mu;
1352 class Bar {
1353 public:
1354 int a_ GUARDED_BY(mu1_);
1355 int b_;
1356 int *q PT_GUARDED_BY(mu);
1357 Mutex mu1_ ACQUIRED_AFTER(mu);
1360 Bar b1, *b3;
1361 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1363 int res GUARDED_BY(mu) = 5;
1365 int func(int i)
1367 int x;
1368 b3->mu1_.Lock();
1369 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \
1370 // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \
1371 // expected-note {{found near match 'b3->mu1_'}}
1372 *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \
1373 // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}
1374 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \
1375 // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \
1376 // expected-note {{found near match 'b3->mu1_'}}
1377 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}
1378 b3->mu1_.Unlock();
1379 b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1380 x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1381 return x;
1383 } // end namespace thread_annot_lock_21
1385 namespace thread_annot_lock_35_modified {
1386 // Test the analyzer's ability to distinguish the lock field of different
1387 // objects.
1388 class Foo {
1389 private:
1390 Mutex lock_;
1391 int a_ GUARDED_BY(lock_);
1393 public:
1394 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1395 Foo *new_foo = new Foo;
1397 lock_.Lock();
1399 child->Func(new_foo); // There shouldn't be any warning here as the
1400 // acquired lock is not in child.
1401 child->bar(7); // \
1402 // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \
1403 // expected-note {{found near match 'lock_'}}
1404 child->a_ = 5; // \
1405 // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \
1406 // expected-note {{found near match 'lock_'}}
1407 lock_.Unlock();
1410 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1411 a_ = y;
1415 Foo *x;
1417 void main() {
1418 Foo *child = new Foo;
1419 x->Func(child);
1421 } // end namespace thread_annot_lock_35_modified
1423 namespace thread_annot_lock_36_modified {
1424 // Modified to move the annotations to function defns.
1425 // Test the analyzer's ability to distinguish the lock field of different
1426 // objects
1427 class Foo {
1428 private:
1429 Mutex lock_;
1430 int a_ GUARDED_BY(lock_);
1432 public:
1433 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1434 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1437 void Foo::Func(Foo* child) {
1438 Foo *new_foo = new Foo;
1440 lock_.Lock();
1442 child->lock_.Lock();
1443 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}
1444 child->bar(7);
1445 child->a_ = 5;
1446 child->lock_.Unlock();
1448 lock_.Unlock();
1451 void Foo::bar(int y) {
1452 a_ = y;
1456 Foo *x;
1458 void main() {
1459 Foo *child = new Foo;
1460 x->Func(child);
1462 } // end namespace thread_annot_lock_36_modified
1465 namespace thread_annot_lock_42 {
1466 // Test support of multiple lock attributes of the same kind on a decl.
1467 class Foo {
1468 private:
1469 Mutex mu1, mu2, mu3;
1470 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1471 int y GUARDED_BY(mu2);
1473 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1474 mu2.Lock();
1475 y = 2;
1476 mu2.Unlock();
1479 public:
1480 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1481 x = 5;
1482 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \
1483 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}
1487 Foo *foo;
1489 void func()
1491 foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \
1492 // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}
1494 } // end namespace thread_annot_lock_42
1496 namespace thread_annot_lock_46 {
1497 // Test the support for annotations on virtual functions.
1498 class Base {
1499 public:
1500 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1501 virtual void func2() LOCKS_EXCLUDED(mu_);
1502 Mutex mu_;
1505 class Child : public Base {
1506 public:
1507 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1508 virtual void func2() LOCKS_EXCLUDED(mu_);
1511 void main() {
1512 Child *c;
1513 Base *b = c;
1515 b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}}
1516 b->mu_.Lock();
1517 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}}
1518 b->mu_.Unlock();
1520 c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}
1521 c->mu_.Lock();
1522 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}
1523 c->mu_.Unlock();
1525 } // end namespace thread_annot_lock_46
1527 namespace thread_annot_lock_67_modified {
1528 // Modified: attributes on definitions moved to declarations
1529 // Test annotations on out-of-line definitions of member functions where the
1530 // annotations refer to locks that are also data members in the class.
1531 Mutex mu;
1532 Mutex mu3;
1534 class Foo {
1535 public:
1536 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1537 int data GUARDED_BY(mu1);
1538 Mutex *mu1;
1539 Mutex *mu2;
1542 int Foo::method1(int i) {
1543 return data + i;
1546 void main()
1548 Foo a;
1549 a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \
1550 // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \
1551 // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \
1552 // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}
1554 } // end namespace thread_annot_lock_67_modified
1557 namespace substitution_test {
1558 class MyData {
1559 public:
1560 Mutex mu;
1562 void lockData() EXCLUSIVE_LOCK_FUNCTION(mu);
1563 void unlockData() UNLOCK_FUNCTION(mu);
1565 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
1569 class DataLocker {
1570 public:
1571 void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu);
1572 void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu);
1576 class Foo {
1577 public:
1578 void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { }
1580 void bar1(MyData* d) {
1581 d->lockData();
1582 foo(d);
1583 d->unlockData();
1586 void bar2(MyData* d) {
1587 DataLocker dlr;
1588 dlr.lockData(d);
1589 foo(d);
1590 dlr.unlockData(d);
1593 void bar3(MyData* d1, MyData* d2) {
1594 DataLocker dlr;
1595 dlr.lockData(d1); // expected-note {{mutex acquired here}}
1596 dlr.unlockData(d2); // \
1597 // expected-warning {{releasing mutex 'd2->mu' that was not held}}
1598 } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}
1600 void bar4(MyData* d1, MyData* d2) {
1601 DataLocker dlr;
1602 dlr.lockData(d1);
1603 foo(d2); // \
1604 // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \
1605 // expected-note {{found near match 'd1->mu'}}
1606 dlr.unlockData(d1);
1610 // Automatic object destructor calls don't appear as expressions in the CFG,
1611 // so we have to handle them separately whenever substitutions are required.
1612 struct DestructorRequires {
1613 Mutex mu;
1614 ~DestructorRequires() EXCLUSIVE_LOCKS_REQUIRED(mu);
1617 void destructorRequires() {
1618 DestructorRequires rd;
1619 rd.mu.AssertHeld();
1622 struct DestructorExcludes {
1623 Mutex mu;
1624 ~DestructorExcludes() LOCKS_EXCLUDED(mu);
1627 void destructorExcludes() {
1628 DestructorExcludes ed;
1629 ed.mu.Lock(); // expected-note {{mutex acquired here}}
1630 } // expected-warning {{cannot call function '~DestructorExcludes' while mutex 'ed.mu' is held}}
1631 // expected-warning@-1 {{mutex 'ed.mu' is still held at the end of function}}
1633 } // end namespace substituation_test
1637 namespace constructor_destructor_tests {
1638 Mutex fooMu;
1639 int myVar GUARDED_BY(fooMu);
1641 class Foo {
1642 public:
1643 Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { }
1644 ~Foo() UNLOCK_FUNCTION(fooMu) { }
1647 void fooTest() {
1648 Foo foo;
1649 myVar = 0;
1654 namespace template_member_test {
1656 struct S { int n; };
1657 struct T {
1658 Mutex m;
1659 S *s GUARDED_BY(this->m);
1661 Mutex m;
1662 struct U {
1663 union {
1664 int n;
1666 } *u GUARDED_BY(m);
1668 template<typename U>
1669 struct IndirectLock {
1670 int DoNaughtyThings(T *t) {
1671 u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}
1672 return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}
1676 template struct IndirectLock<int>; // expected-note {{here}}
1678 struct V {
1679 void f(int);
1680 void f(double);
1682 Mutex m;
1683 V *p GUARDED_BY(this->m);
1685 template<typename U> struct W {
1686 V v;
1687 void f(U u) {
1688 v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}
1691 template struct W<int>; // expected-note {{here}}
1695 namespace test_scoped_lockable {
1697 struct TestScopedLockable {
1698 Mutex mu1;
1699 Mutex mu2;
1700 int a __attribute__((guarded_by(mu1)));
1701 int b __attribute__((guarded_by(mu2)));
1703 bool getBool();
1705 void foo1() {
1706 MutexLock mulock(&mu1);
1707 a = 5;
1710 #ifdef __cpp_guaranteed_copy_elision
1711 void const_lock() {
1712 const MutexLock mulock = MutexLock(&mu1);
1713 a = 5;
1715 #endif
1717 void temporary() {
1718 MutexLock{&mu1}, a = 5;
1721 void lifetime_extension() {
1722 const MutexLock &mulock = MutexLock(&mu1);
1723 a = 5;
1726 void foo2() {
1727 ReaderMutexLock mulock1(&mu1);
1728 if (getBool()) {
1729 MutexLock mulock2a(&mu2);
1730 b = a + 1;
1732 else {
1733 MutexLock mulock2b(&mu2);
1734 b = a + 2;
1738 void foo3() {
1739 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}
1740 MutexLock mulock_b(&mu1); // \
1741 // expected-warning {{acquiring mutex 'mu1' that is already held}}
1744 void temporary_double_lock() {
1745 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}
1746 MutexLock{&mu1}; // \
1747 // expected-warning {{acquiring mutex 'mu1' that is already held}}
1750 void foo4() {
1751 MutexLock mulock1(&mu1), mulock2(&mu2);
1752 a = b+1;
1753 b = a+1;
1756 void foo5() {
1757 DoubleMutexLock mulock(&mu1, &mu2);
1758 a = b + 1;
1759 b = a + 1;
1763 } // end namespace test_scoped_lockable
1766 namespace FunctionAttrTest {
1768 class Foo {
1769 public:
1770 Mutex mu_;
1771 int a GUARDED_BY(mu_);
1774 Foo fooObj;
1776 void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1778 void bar() {
1779 foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}
1780 fooObj.mu_.Lock();
1781 foo();
1782 fooObj.mu_.Unlock();
1785 }; // end namespace FunctionAttrTest
1788 namespace TryLockTest {
1790 struct TestTryLock {
1791 Mutex mu;
1792 int a GUARDED_BY(mu);
1793 bool cond;
1795 void foo1() {
1796 if (mu.TryLock()) {
1797 a = 1;
1798 mu.Unlock();
1802 void foo2() {
1803 if (!mu.TryLock()) return;
1804 a = 2;
1805 mu.Unlock();
1808 void foo2_builtin_expect() {
1809 if (__builtin_expect(!mu.TryLock(), false))
1810 return;
1811 a = 2;
1812 mu.Unlock();
1815 void foo3() {
1816 bool b = mu.TryLock();
1817 if (b) {
1818 a = 3;
1819 mu.Unlock();
1823 void foo3_builtin_expect() {
1824 bool b = mu.TryLock();
1825 if (__builtin_expect(b, true)) {
1826 a = 3;
1827 mu.Unlock();
1831 void foo4() {
1832 bool b = mu.TryLock();
1833 if (!b) return;
1834 a = 4;
1835 mu.Unlock();
1838 void foo5() {
1839 while (mu.TryLock()) {
1840 a = a + 1;
1841 mu.Unlock();
1845 void foo6() {
1846 bool b = mu.TryLock();
1847 b = !b;
1848 if (b) return;
1849 a = 6;
1850 mu.Unlock();
1853 void foo7() {
1854 bool b1 = mu.TryLock();
1855 bool b2 = !b1;
1856 bool b3 = !b2;
1857 if (b3) {
1858 a = 7;
1859 mu.Unlock();
1863 // Test use-def chains: join points
1864 void foo8() {
1865 bool b = mu.TryLock();
1866 bool b2 = b;
1867 if (cond)
1868 b = true;
1869 if (b) { // b should be unknown at this point, because of the join point
1870 a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1872 if (b2) { // b2 should be known at this point.
1873 a = 8;
1874 mu.Unlock();
1878 // Test use-def-chains: back edges
1879 void foo9() {
1880 bool b = mu.TryLock();
1882 for (int i = 0; i < 10; ++i);
1884 if (b) { // b is still known, because the loop doesn't alter it
1885 a = 9;
1886 mu.Unlock();
1890 // Test use-def chains: back edges
1891 void foo10() {
1892 bool b = mu.TryLock();
1894 while (cond) {
1895 if (b) { // b should be unknown at this point b/c of the loop
1896 a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1898 b = !b;
1902 // Test merge of exclusive trylock
1903 void foo11() {
1904 if (cond) {
1905 if (!mu.TryLock())
1906 return;
1908 else {
1909 mu.Lock();
1911 a = 10;
1912 mu.Unlock();
1915 // Test merge of shared trylock
1916 void foo12() {
1917 if (cond) {
1918 if (!mu.ReaderTryLock())
1919 return;
1921 else {
1922 mu.ReaderLock();
1924 int i = a;
1925 mu.Unlock();
1928 // Test with conditional operator
1929 void foo13() {
1930 if (mu.TryLock() ? 1 : 0)
1931 mu.Unlock();
1934 void foo14() {
1935 if (mu.TryLock() ? 0 : 1)
1936 return;
1937 mu.Unlock();
1940 void foo15() {
1941 if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
1942 mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}
1943 } // expected-warning{{mutex 'mu' is not held on every path through here}}
1944 }; // end TestTrylock
1946 } // end namespace TrylockTest
1949 namespace TestTemplateAttributeInstantiation {
1951 class Foo1 {
1952 public:
1953 Mutex mu_;
1954 int a GUARDED_BY(mu_);
1957 class Foo2 {
1958 public:
1959 int a GUARDED_BY(mu_);
1960 Mutex mu_;
1964 class Bar {
1965 public:
1966 // Test non-dependent expressions in attributes on template functions
1967 template <class T>
1968 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1969 foo->a = 0;
1972 // Test dependent expressions in attributes on template functions
1973 template <class T>
1974 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1975 fooT->a = 0;
1980 template <class T>
1981 class BarT {
1982 public:
1983 Foo1 fooBase;
1984 T fooBaseT;
1986 // Test non-dependent expression in ordinary method on template class
1987 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1988 fooBase.a = 0;
1991 // Test dependent expressions in ordinary methods on template class
1992 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1993 fooBaseT.a = 0;
1996 // Test dependent expressions in template method in template class
1997 template <class T2>
1998 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1999 fooBaseT.a = 0;
2000 fooT->a = 0;
2004 template <class T>
2005 class Cell {
2006 public:
2007 Mutex mu_;
2008 // Test dependent guarded_by
2009 T data GUARDED_BY(mu_);
2011 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2012 data = 0;
2015 void foo() {
2016 mu_.Lock();
2017 data = 0;
2018 mu_.Unlock();
2022 void test() {
2023 Bar b;
2024 BarT<Foo2> bt;
2025 Foo1 f1;
2026 Foo2 f2;
2028 f1.mu_.Lock();
2029 f2.mu_.Lock();
2030 bt.fooBase.mu_.Lock();
2031 bt.fooBaseT.mu_.Lock();
2033 b.barND(&f1, &f2);
2034 b.barD(&f1, &f2);
2035 bt.barND();
2036 bt.barD();
2037 bt.barTD(&f2);
2039 f1.mu_.Unlock();
2040 bt.barTD(&f1); // \
2041 // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \
2042 // expected-note {{found near match 'bt.fooBase.mu_'}}
2044 bt.fooBase.mu_.Unlock();
2045 bt.fooBaseT.mu_.Unlock();
2046 f2.mu_.Unlock();
2048 Cell<int> cell;
2049 cell.data = 0; // \
2050 // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}
2051 cell.foo();
2052 cell.mu_.Lock();
2053 cell.fooEx();
2054 cell.mu_.Unlock();
2058 template <class T>
2059 class CellDelayed {
2060 public:
2061 // Test dependent guarded_by
2062 T data GUARDED_BY(mu_);
2063 static T static_data GUARDED_BY(static_mu_);
2065 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
2066 this->data = other->data;
2069 template <class T2>
2070 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
2071 this->data = otherT->data;
2074 void foo() {
2075 mu_.Lock();
2076 data = 0;
2077 mu_.Unlock();
2080 Mutex mu_;
2081 static Mutex static_mu_;
2084 void testDelayed() {
2085 CellDelayed<int> celld;
2086 CellDelayed<int> celld2;
2087 celld.foo();
2088 celld.mu_.Lock();
2089 celld2.mu_.Lock();
2091 celld.fooEx(&celld2);
2092 celld.fooExT(&celld2);
2094 celld2.mu_.Unlock();
2095 celld.mu_.Unlock();
2098 }; // end namespace TestTemplateAttributeInstantiation
2101 namespace FunctionDeclDefTest {
2103 class Foo {
2104 public:
2105 Mutex mu_;
2106 int a GUARDED_BY(mu_);
2108 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
2111 // EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
2112 void Foo::foo1(Foo *f_defined) {
2113 f_defined->a = 0;
2116 void test() {
2117 Foo myfoo;
2118 myfoo.foo1(&myfoo); // \
2119 // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}
2120 myfoo.mu_.Lock();
2121 myfoo.foo1(&myfoo);
2122 myfoo.mu_.Unlock();
2127 namespace GoingNative {
2129 struct LOCKABLE mutex {
2130 void lock() EXCLUSIVE_LOCK_FUNCTION();
2131 void unlock() UNLOCK_FUNCTION();
2132 // ...
2134 bool foo();
2135 bool bar();
2136 mutex m;
2137 void test() {
2138 m.lock();
2139 while (foo()) { // expected-warning {{expecting mutex 'm' to be held at start of each loop}}
2140 m.unlock();
2141 // ...
2142 if (bar()) {
2143 // ...
2144 if (foo())
2145 continue;
2146 //...
2148 // ...
2149 m.lock(); // expected-note {{mutex acquired here}}
2151 m.unlock();
2158 namespace FunctionDefinitionTest {
2160 class Foo {
2161 public:
2162 void foo1();
2163 void foo2();
2164 void foo3(Foo *other);
2166 template<class T>
2167 void fooT1(const T& dummy1);
2169 template<class T>
2170 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2172 Mutex mu_;
2173 int a GUARDED_BY(mu_);
2176 template<class T>
2177 class FooT {
2178 public:
2179 void foo();
2181 Mutex mu_;
2182 T a GUARDED_BY(mu_);
2186 void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2187 a = 1;
2190 void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2191 a = 2;
2194 void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2195 other->a = 3;
2198 template<class T>
2199 void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2200 a = dummy1;
2203 /* TODO -- uncomment with template instantiation of attributes.
2204 template<class T>
2205 void Foo::fooT2(const T& dummy2) {
2206 a = dummy2;
2210 void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2211 f->a = 1;
2214 void fooF2(Foo *f);
2215 void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2216 f->a = 2;
2219 void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2220 void fooF3(Foo *f) {
2221 f->a = 3;
2224 template<class T>
2225 void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2226 a = 0;
2229 void test() {
2230 int dummy = 0;
2231 Foo myFoo;
2233 myFoo.foo2(); // \
2234 // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}
2235 myFoo.foo3(&myFoo); // \
2236 // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
2237 myFoo.fooT1(dummy); // \
2238 // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2240 myFoo.fooT2(dummy); // \
2241 // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2243 fooF1(&myFoo); // \
2244 // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
2245 fooF2(&myFoo); // \
2246 // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}
2247 fooF3(&myFoo); // \
2248 // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}
2250 myFoo.mu_.Lock();
2251 myFoo.foo2();
2252 myFoo.foo3(&myFoo);
2253 myFoo.fooT1(dummy);
2255 myFoo.fooT2(dummy);
2257 fooF1(&myFoo);
2258 fooF2(&myFoo);
2259 fooF3(&myFoo);
2260 myFoo.mu_.Unlock();
2262 FooT<int> myFooT;
2263 myFooT.foo(); // \
2264 // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}
2267 } // end namespace FunctionDefinitionTest
2270 namespace SelfLockingTest {
2272 class LOCKABLE MyLock {
2273 public:
2274 int foo GUARDED_BY(this);
2276 void lock() EXCLUSIVE_LOCK_FUNCTION();
2277 void unlock() UNLOCK_FUNCTION();
2279 void doSomething() {
2280 this->lock(); // allow 'this' as a lock expression
2281 foo = 0;
2282 doSomethingElse();
2283 this->unlock();
2286 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2287 foo = 1;
2290 void test() {
2291 foo = 2; // \
2292 // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}
2297 class LOCKABLE MyLock2 {
2298 public:
2299 Mutex mu_;
2300 int foo GUARDED_BY(this);
2302 // don't check inside lock and unlock functions
2303 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2304 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2306 // don't check inside constructors and destructors
2307 MyLock2() { foo = 1; }
2308 ~MyLock2() { foo = 0; }
2312 } // end namespace SelfLockingTest
2315 namespace InvalidNonstatic {
2317 // Forward decl here causes bogus "invalid use of non-static data member"
2318 // on reference to mutex_ in guarded_by attribute.
2319 class Foo;
2321 class Foo {
2322 Mutex* mutex_;
2324 int foo __attribute__((guarded_by(mutex_)));
2327 } // end namespace InvalidNonStatic
2330 namespace NoReturnTest {
2332 bool condition();
2333 void fatal() __attribute__((noreturn));
2335 Mutex mu_;
2337 void test1() {
2338 MutexLock lock(&mu_);
2339 if (condition()) {
2340 fatal();
2341 return;
2345 } // end namespace NoReturnTest
2348 namespace TestMultiDecl {
2350 class Foo {
2351 public:
2352 int GUARDED_BY(mu_) a;
2353 int GUARDED_BY(mu_) b, c;
2355 void foo() {
2356 a = 0; // \
2357 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2358 b = 0; // \
2359 // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2360 c = 0; // \
2361 // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
2364 private:
2365 Mutex mu_;
2368 } // end namespace TestMultiDecl
2371 namespace WarnNoDecl {
2373 class Foo {
2374 void foo(int a); __attribute__(( // \
2375 // expected-warning {{declaration does not declare anything}}
2376 exclusive_locks_required(a))); // \
2377 // expected-warning {{attribute exclusive_locks_required ignored}}
2380 } // end namespace WarnNoDecl
2384 namespace MoreLockExpressions {
2386 class Foo {
2387 public:
2388 Mutex mu_;
2389 int a GUARDED_BY(mu_);
2392 class Bar {
2393 public:
2394 int b;
2395 Foo* f;
2397 Foo& getFoo() { return *f; }
2398 Foo& getFoo2(int c) { return *f; }
2399 Foo& getFoo3(int c, int d) { return *f; }
2401 Foo& getFooey() { return *f; }
2404 Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2406 void test() {
2407 Foo foo;
2408 Foo *fooArray;
2409 Foo &(*fooFuncPtr)();
2410 Bar bar;
2411 int a;
2412 int b;
2413 int c;
2415 bar.getFoo().mu_.Lock();
2416 bar.getFoo().a = 0;
2417 bar.getFoo().mu_.Unlock();
2419 (bar.getFoo().mu_).Lock(); // test parenthesis
2420 bar.getFoo().a = 0;
2421 (bar.getFoo().mu_).Unlock();
2423 bar.getFoo2(a).mu_.Lock();
2424 bar.getFoo2(a).a = 0;
2425 bar.getFoo2(a).mu_.Unlock();
2427 bar.getFoo3(a, b).mu_.Lock();
2428 bar.getFoo3(a, b).a = 0;
2429 bar.getFoo3(a, b).mu_.Unlock();
2431 getBarFoo(bar, a).mu_.Lock();
2432 getBarFoo(bar, a).a = 0;
2433 getBarFoo(bar, a).mu_.Unlock();
2435 bar.getFoo2(10).mu_.Lock();
2436 bar.getFoo2(10).a = 0;
2437 bar.getFoo2(10).mu_.Unlock();
2439 bar.getFoo2(a + 1).mu_.Lock();
2440 bar.getFoo2(a + 1).a = 0;
2441 bar.getFoo2(a + 1).mu_.Unlock();
2443 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2444 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2445 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2447 fooFuncPtr().mu_.Lock();
2448 fooFuncPtr().a = 0;
2449 fooFuncPtr().mu_.Unlock();
2453 void test2() {
2454 Foo *fooArray;
2455 Bar bar;
2456 int a;
2457 int b;
2458 int c;
2460 bar.getFoo().mu_.Lock();
2461 bar.getFooey().a = 0; // \
2462 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \
2463 // expected-note {{found near match 'bar.getFoo().mu_'}}
2464 bar.getFoo().mu_.Unlock();
2466 bar.getFoo2(a).mu_.Lock();
2467 bar.getFoo2(b).a = 0; // \
2468 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \
2469 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
2470 bar.getFoo2(a).mu_.Unlock();
2472 bar.getFoo3(a, b).mu_.Lock();
2473 bar.getFoo3(a, c).a = 0; // \
2474 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
2475 // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
2476 bar.getFoo3(a, b).mu_.Unlock();
2478 getBarFoo(bar, a).mu_.Lock();
2479 getBarFoo(bar, b).a = 0; // \
2480 // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
2481 // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
2482 getBarFoo(bar, a).mu_.Unlock();
2484 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2485 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2486 // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
2487 // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
2488 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2492 } // end namespace MoreLockExpressions
2495 namespace TrylockJoinPoint {
2497 class Foo {
2498 Mutex mu;
2499 bool c;
2501 void foo() {
2502 if (c) {
2503 if (!mu.TryLock())
2504 return;
2505 } else {
2506 mu.Lock();
2508 mu.Unlock();
2512 } // end namespace TrylockJoinPoint
2515 namespace LockReturned {
2517 class Foo {
2518 public:
2519 int a GUARDED_BY(mu_);
2520 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2521 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2523 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2525 Mutex* getMu() LOCK_RETURNED(mu_);
2527 Mutex mu_;
2529 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2533 // Calls getMu() directly to lock and unlock
2534 void test1(Foo* f1, Foo* f2) {
2535 f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}
2536 f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}
2538 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \
2539 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}
2540 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}
2542 f1->getMu()->Lock();
2544 f1->a = 0;
2545 f1->foo();
2546 f1->foo2(f2); // \
2547 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \
2548 // expected-note {{found near match 'f1->mu_'}}
2550 Foo::getMu(f2)->Lock();
2551 f1->foo2(f2);
2552 Foo::getMu(f2)->Unlock();
2554 Foo::sfoo(f1);
2556 f1->getMu()->Unlock();
2560 Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2562 class Bar : public Foo {
2563 public:
2564 int b GUARDED_BY(getMu());
2565 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2566 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2568 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2569 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2574 // Use getMu() within other attributes.
2575 // This requires at lest levels of substitution, more in the case of
2576 void test2(Bar* b1, Bar* b2) {
2577 b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}
2578 b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}
2579 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \
2580 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}
2581 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}
2582 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}
2584 b1->getMu()->Lock();
2586 b1->b = 0;
2587 b1->bar();
2588 b1->bar2(b2); // \
2589 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \
2590 // // expected-note {{found near match 'b1->mu_'}}
2592 b2->getMu()->Lock();
2593 b1->bar2(b2);
2595 b2->getMu()->Unlock();
2597 Bar::sbar(b1);
2598 Bar::sbar2(b1);
2600 b1->getMu()->Unlock();
2604 // Lock the mutex directly, but use attributes that call getMu()
2605 // Also lock the mutex using getFooMu, which calls a lock_returned function.
2606 void test3(Bar* b1, Bar* b2) {
2607 b1->mu_.Lock();
2608 b1->b = 0;
2609 b1->bar();
2611 getFooMu(b2)->Lock();
2612 b1->bar2(b2);
2613 getFooMu(b2)->Unlock();
2615 Bar::sbar(b1);
2616 Bar::sbar2(b1);
2618 b1->mu_.Unlock();
2621 } // end namespace LockReturned
2624 namespace ReleasableScopedLock {
2626 class Foo {
2627 Mutex mu_;
2628 bool c;
2629 int a GUARDED_BY(mu_);
2631 void test1();
2632 void test2();
2633 void test3();
2634 void test4();
2635 void test5();
2636 void test6();
2640 void Foo::test1() {
2641 ReleasableMutexLock rlock(&mu_);
2642 rlock.Release();
2645 void Foo::test2() {
2646 ReleasableMutexLock rlock(&mu_);
2647 if (c) { // test join point -- held/not held during release
2648 rlock.Release();
2650 // No warning on join point because the lock will be released by the scope object anyway.
2653 void Foo::test3() {
2654 ReleasableMutexLock rlock(&mu_);
2655 a = 0;
2656 rlock.Release();
2657 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2660 void Foo::test4() {
2661 ReleasableMutexLock rlock(&mu_);
2662 rlock.Release(); // expected-note{{mutex released here}}
2663 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2666 void Foo::test5() {
2667 ReleasableMutexLock rlock(&mu_);
2668 if (c) {
2669 rlock.Release();
2671 // No warning on join point because the lock will be released by the scope object anyway.
2672 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2675 void Foo::test6() {
2676 ReleasableMutexLock rlock(&mu_);
2677 do {
2678 if (c) {
2679 rlock.Release();
2680 break;
2682 } while (c);
2683 // No warning on join point because the lock will be released by the scope object anyway
2684 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2688 } // end namespace ReleasableScopedLock
2691 namespace RelockableScopedLock {
2693 class DeferTraits {};
2695 class SCOPED_LOCKABLE RelockableExclusiveMutexLock {
2696 public:
2697 RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2698 RelockableExclusiveMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2699 ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();
2701 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2702 void Unlock() UNLOCK_FUNCTION();
2705 struct SharedTraits {};
2706 struct ExclusiveTraits {};
2708 class SCOPED_LOCKABLE RelockableMutexLock {
2709 public:
2710 RelockableMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2711 RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu);
2712 RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu);
2713 ~RelockableMutexLock() UNLOCK_FUNCTION();
2715 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2716 void Unlock() UNLOCK_FUNCTION();
2718 void ReaderLock() SHARED_LOCK_FUNCTION();
2719 void ReaderUnlock() UNLOCK_FUNCTION();
2721 void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
2722 void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
2725 Mutex mu;
2726 int x GUARDED_BY(mu);
2727 bool b;
2729 void print(int);
2731 void relock() {
2732 RelockableExclusiveMutexLock scope(&mu);
2733 x = 2;
2734 scope.Unlock();
2736 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2738 scope.Lock();
2739 x = 4;
2742 void deferLock() {
2743 RelockableExclusiveMutexLock scope(&mu, DeferTraits{});
2744 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2745 scope.Lock();
2746 x = 3;
2749 void relockExclusive() {
2750 RelockableMutexLock scope(&mu, SharedTraits{});
2751 print(x);
2752 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2753 scope.ReaderUnlock();
2755 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2757 scope.Lock();
2758 print(x);
2759 x = 4;
2761 scope.DemoteExclusive();
2762 print(x);
2763 x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2766 void relockShared() {
2767 RelockableMutexLock scope(&mu, ExclusiveTraits{});
2768 print(x);
2769 x = 2;
2770 scope.Unlock();
2772 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2774 scope.ReaderLock();
2775 print(x);
2776 x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2778 scope.PromoteShared();
2779 print(x);
2780 x = 5;
2783 void deferLockShared() {
2784 RelockableMutexLock scope(&mu, DeferTraits{});
2785 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2786 scope.ReaderLock();
2787 print(x);
2788 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2791 void doubleUnlock() {
2792 RelockableExclusiveMutexLock scope(&mu);
2793 scope.Unlock(); // expected-note{{mutex released here}}
2794 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
2797 void doubleLock1() {
2798 RelockableExclusiveMutexLock scope(&mu); // expected-note{{mutex acquired here}}
2799 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2802 void doubleLock2() {
2803 RelockableExclusiveMutexLock scope(&mu);
2804 scope.Unlock();
2805 scope.Lock(); // expected-note{{mutex acquired here}}
2806 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2809 void lockJoin() {
2810 RelockableMutexLock scope(&mu, DeferTraits{});
2811 if (b)
2812 scope.Lock();
2813 // No warning on join point because the lock will be released by the scope object anyway.
2814 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2817 void unlockJoin() {
2818 RelockableMutexLock scope(&mu, DeferTraits{});
2819 scope.Lock();
2820 if (b)
2821 scope.Unlock();
2822 // No warning on join point because the lock will be released by the scope object anyway.
2823 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2826 void loopAcquire() {
2827 RelockableMutexLock scope(&mu, DeferTraits{});
2828 for (unsigned i = 1; i < 10; ++i)
2829 scope.Lock(); // We could catch this double lock with negative capabilities.
2832 void loopRelease() {
2833 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2834 // We have to warn on this join point despite the lock being managed ...
2835 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2836 x = 1; // ... because we might miss that this doesn't always happen under lock.
2837 if (i == 5)
2838 scope.Unlock();
2842 void loopPromote() {
2843 RelockableMutexLock scope(&mu, SharedTraits{});
2844 for (unsigned i = 1; i < 10; ++i) {
2845 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2846 if (i == 5)
2847 scope.PromoteShared();
2851 void loopDemote() {
2852 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2853 // We have to warn on this join point despite the lock being managed ...
2854 for (unsigned i = 1; i < 10; ++i) {
2855 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2856 if (i == 5)
2857 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2861 void loopAcquireContinue() {
2862 RelockableMutexLock scope(&mu, DeferTraits{});
2863 for (unsigned i = 1; i < 10; ++i) {
2864 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2865 if (i == 5) {
2866 scope.Lock();
2867 continue;
2872 void loopReleaseContinue() {
2873 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2874 // We have to warn on this join point despite the lock being managed ...
2875 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2876 x = 1; // ... because we might miss that this doesn't always happen under lock.
2877 if (i == 5) {
2878 scope.Unlock();
2879 continue;
2884 void loopPromoteContinue() {
2885 RelockableMutexLock scope(&mu, SharedTraits{});
2886 for (unsigned i = 1; i < 10; ++i) {
2887 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2888 if (i == 5) {
2889 scope.PromoteShared();
2890 continue;
2895 void loopDemoteContinue() {
2896 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2897 // We have to warn on this join point despite the lock being managed ...
2898 for (unsigned i = 1; i < 10; ++i) {
2899 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2900 if (i == 5) {
2901 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2902 continue;
2907 void exclusiveSharedJoin() {
2908 RelockableMutexLock scope(&mu, DeferTraits{});
2909 if (b)
2910 scope.Lock();
2911 else
2912 scope.ReaderLock();
2913 // No warning on join point because the lock will be released by the scope object anyway.
2914 print(x);
2915 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2918 void sharedExclusiveJoin() {
2919 RelockableMutexLock scope(&mu, DeferTraits{});
2920 if (b)
2921 scope.ReaderLock();
2922 else
2923 scope.Lock();
2924 // No warning on join point because the lock will be released by the scope object anyway.
2925 print(x);
2926 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2929 void assertJoin() {
2930 RelockableMutexLock scope(&mu, DeferTraits{});
2931 if (b)
2932 scope.Lock();
2933 else
2934 mu.AssertHeld();
2935 x = 2;
2938 void assertSharedJoin() {
2939 RelockableMutexLock scope(&mu, DeferTraits{});
2940 if (b)
2941 scope.ReaderLock();
2942 else
2943 mu.AssertReaderHeld();
2944 print(x);
2945 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2948 void assertStrongerJoin() {
2949 RelockableMutexLock scope(&mu, DeferTraits{});
2950 if (b)
2951 scope.ReaderLock();
2952 else
2953 mu.AssertHeld();
2954 print(x);
2955 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2958 void assertWeakerJoin() {
2959 RelockableMutexLock scope(&mu, DeferTraits{});
2960 if (b)
2961 scope.Lock();
2962 else
2963 mu.AssertReaderHeld();
2964 print(x);
2965 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2968 void directUnlock() {
2969 RelockableExclusiveMutexLock scope(&mu);
2970 mu.Unlock();
2971 // Debatable that there is no warning. Currently we don't track in the scoped
2972 // object whether it is active, but just check if the contained locks can be
2973 // reacquired. Here they can, because mu has been unlocked manually.
2974 scope.Lock();
2977 void directRelock() {
2978 RelockableExclusiveMutexLock scope(&mu);
2979 scope.Unlock();
2980 mu.Lock();
2981 // Similarly debatable that there is no warning.
2982 scope.Unlock();
2985 // Doesn't make a lot of sense, just making sure there is no crash.
2986 void destructLock() {
2987 RelockableExclusiveMutexLock scope(&mu);
2988 scope.~RelockableExclusiveMutexLock();
2989 scope.Lock(); // Should be UB, so we don't really care.
2992 class SCOPED_LOCKABLE MemberLock {
2993 public:
2994 MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2995 ~MemberLock() UNLOCK_FUNCTION(mutex);
2996 void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2997 Mutex mutex;
3000 void relockShared2() {
3001 MemberLock lock; // expected-note{{mutex acquired here}}
3002 lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}}
3005 class SCOPED_LOCKABLE WeirdScope {
3006 private:
3007 Mutex *other;
3009 public:
3010 WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
3011 void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other);
3012 void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other);
3013 ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION();
3015 void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other);
3018 void relockWeird() {
3019 WeirdScope scope(&mu);
3020 x = 1;
3021 scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}}
3022 x = 2; // \
3023 // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3024 scope.requireOther(); // \
3025 // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}}
3026 scope.lock(); // expected-note {{mutex acquired here}}
3027 x = 3;
3028 scope.requireOther();
3029 } // expected-warning {{mutex 'scope.other' is still held at the end of function}}
3031 } // end namespace RelockableScopedLock
3034 namespace ScopedUnlock {
3036 class SCOPED_LOCKABLE MutexUnlock {
3037 public:
3038 MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu);
3039 ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3041 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
3042 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
3045 class SCOPED_LOCKABLE ReaderMutexUnlock {
3046 public:
3047 ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu);
3048 ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3050 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
3051 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
3054 Mutex mu;
3055 int x GUARDED_BY(mu);
3056 bool c;
3057 void print(int);
3059 void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3060 x = 1;
3061 MutexUnlock scope(&mu);
3062 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3065 void simpleShared() SHARED_LOCKS_REQUIRED(mu) {
3066 print(x);
3067 ReaderMutexUnlock scope(&mu);
3068 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3071 void innerUnlock() {
3072 MutexLock outer(&mu);
3073 if (x == 0) {
3074 MutexUnlock inner(&mu);
3075 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3077 x = 2;
3080 void innerUnlockShared() {
3081 ReaderMutexLock outer(&mu);
3082 if (x == 0) {
3083 ReaderMutexUnlock inner(&mu);
3084 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3086 print(x);
3089 void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3090 MutexUnlock scope(&mu);
3091 scope.Lock();
3092 x = 2;
3093 scope.Unlock();
3094 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3097 void join() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3098 MutexUnlock scope(&mu);
3099 if (c)
3100 scope.Lock();
3101 // No warning on join point because the lock will be released by the scope object anyway.
3102 scope.Lock();
3105 void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3106 MutexUnlock scope(&mu);
3107 scope.Lock(); // expected-note{{mutex acquired here}}
3108 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
3111 void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3112 MutexUnlock scope(&mu); // expected-note{{mutex released here}}
3113 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
3116 class SCOPED_LOCKABLE MutexLockUnlock {
3117 public:
3118 MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2);
3119 ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3121 void Release() EXCLUSIVE_UNLOCK_FUNCTION();
3122 void Acquire() EXCLUSIVE_LOCK_FUNCTION();
3125 Mutex other;
3126 void fn() EXCLUSIVE_LOCKS_REQUIRED(other);
3128 void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3129 MutexLockUnlock scope(&mu, &other);
3130 fn();
3131 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3134 } // end namespace ScopedUnlock
3137 namespace TrylockFunctionTest {
3139 class Foo {
3140 public:
3141 Mutex mu1_;
3142 Mutex mu2_;
3143 bool c;
3145 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
3148 bool Foo::lockBoth() {
3149 if (!mu1_.TryLock())
3150 return false;
3152 mu2_.Lock();
3153 if (!c) {
3154 mu1_.Unlock();
3155 mu2_.Unlock();
3156 return false;
3159 return true;
3163 } // end namespace TrylockFunctionTest
3167 namespace DoubleLockBug {
3169 class Foo {
3170 public:
3171 Mutex mu_;
3172 int a GUARDED_BY(mu_);
3174 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3175 int foo2() SHARED_LOCKS_REQUIRED(mu_);
3179 void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
3180 a = 0;
3183 int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
3184 return a;
3191 namespace UnlockBug {
3193 class Foo {
3194 public:
3195 Mutex mutex_;
3197 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3198 mutex_.Unlock();
3199 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3202 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3203 mutex_.Unlock();
3204 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3207 } // end namespace UnlockBug
3211 namespace FoolishScopedLockableBug {
3213 class SCOPED_LOCKABLE WTF_ScopedLockable {
3214 public:
3215 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
3217 // have to call release() manually;
3218 ~WTF_ScopedLockable();
3220 void release() UNLOCK_FUNCTION();
3224 class Foo {
3225 Mutex mu_;
3226 int a GUARDED_BY(mu_);
3227 bool c;
3229 void doSomething();
3231 void test1() {
3232 WTF_ScopedLockable wtf(&mu_);
3233 wtf.release();
3236 void test2() {
3237 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3238 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
3240 void test3() {
3241 if (c) {
3242 WTF_ScopedLockable wtf(&mu_);
3243 wtf.release();
3247 void test4() {
3248 if (c) {
3249 doSomething();
3251 else {
3252 WTF_ScopedLockable wtf(&mu_);
3253 wtf.release();
3257 void test5() {
3258 if (c) {
3259 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3261 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3263 void test6() {
3264 if (c) {
3265 doSomething();
3267 else {
3268 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3270 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3274 } // end namespace FoolishScopedLockableBug
3278 namespace TemporaryCleanupExpr {
3280 class Foo {
3281 int a GUARDED_BY(getMutexPtr().get());
3283 SmartPtr<Mutex> getMutexPtr();
3285 void test();
3289 void Foo::test() {
3291 ReaderMutexLock lock(getMutexPtr().get());
3292 int b = a;
3294 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}
3297 #ifdef __cpp_guaranteed_copy_elision
3299 void guaranteed_copy_elision() {
3300 MutexLock lock = MutexLock{&sls_mu};
3301 sls_guard_var = 0;
3304 void guaranteed_copy_elision_const() {
3305 const MutexLock lock = MutexLock{&sls_mu};
3306 sls_guard_var = 0;
3309 #endif
3311 } // end namespace TemporaryCleanupExpr
3315 namespace SmartPointerTests {
3317 class Foo {
3318 public:
3319 SmartPtr<Mutex> mu_;
3320 int a GUARDED_BY(mu_);
3321 int b GUARDED_BY(mu_.get());
3322 int c GUARDED_BY(*mu_);
3324 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3325 void Unlock() UNLOCK_FUNCTION(mu_);
3327 void test0();
3328 void test1();
3329 void test2();
3330 void test3();
3331 void test4();
3332 void test5();
3333 void test6();
3334 void test7();
3335 void test8();
3338 void Foo::test0() {
3339 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3340 b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
3341 c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
3344 void Foo::test1() {
3345 mu_->Lock();
3346 a = 0;
3347 b = 0;
3348 c = 0;
3349 mu_->Unlock();
3352 void Foo::test2() {
3353 (*mu_).Lock();
3354 a = 0;
3355 b = 0;
3356 c = 0;
3357 (*mu_).Unlock();
3361 void Foo::test3() {
3362 mu_.get()->Lock();
3363 a = 0;
3364 b = 0;
3365 c = 0;
3366 mu_.get()->Unlock();
3370 void Foo::test4() {
3371 MutexLock lock(mu_.get());
3372 a = 0;
3373 b = 0;
3374 c = 0;
3378 void Foo::test5() {
3379 MutexLock lock(&(*mu_));
3380 a = 0;
3381 b = 0;
3382 c = 0;
3386 void Foo::test6() {
3387 Lock();
3388 a = 0;
3389 b = 0;
3390 c = 0;
3391 Unlock();
3395 void Foo::test7() {
3397 Lock();
3398 mu_->Unlock();
3401 mu_->Lock();
3402 Unlock();
3405 mu_.get()->Lock();
3406 mu_->Unlock();
3409 mu_->Lock();
3410 mu_.get()->Unlock();
3413 mu_.get()->Lock();
3414 (*mu_).Unlock();
3417 (*mu_).Lock();
3418 mu_->Unlock();
3423 void Foo::test8() {
3424 mu_->Lock(); // expected-note 2 {{mutex acquired here}}
3425 mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3426 (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3427 mu_.get()->Unlock(); // expected-note {{mutex released here}}
3428 Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}
3432 class Bar {
3433 SmartPtr<Foo> foo;
3435 void test0();
3436 void test1();
3437 void test2();
3438 void test3();
3442 void Bar::test0() {
3443 foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
3444 (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
3445 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
3449 void Bar::test1() {
3450 foo->mu_->Lock();
3451 foo->a = 0;
3452 (*foo).b = 0;
3453 foo.get()->c = 0;
3454 foo->mu_->Unlock();
3458 void Bar::test2() {
3459 (*foo).mu_->Lock();
3460 foo->a = 0;
3461 (*foo).b = 0;
3462 foo.get()->c = 0;
3463 foo.get()->mu_->Unlock();
3467 void Bar::test3() {
3468 MutexLock lock(foo->mu_.get());
3469 foo->a = 0;
3470 (*foo).b = 0;
3471 foo.get()->c = 0;
3474 } // end namespace SmartPointerTests
3478 namespace DuplicateAttributeTest {
3480 class LOCKABLE Foo {
3481 public:
3482 Mutex mu1_;
3483 Mutex mu2_;
3484 Mutex mu3_;
3485 int a GUARDED_BY(mu1_);
3486 int b GUARDED_BY(mu2_);
3487 int c GUARDED_BY(mu3_);
3489 void lock() EXCLUSIVE_LOCK_FUNCTION();
3490 void unlock() UNLOCK_FUNCTION();
3492 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
3493 void slock1() SHARED_LOCK_FUNCTION(mu1_);
3494 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3495 void locklots()
3496 EXCLUSIVE_LOCK_FUNCTION(mu1_)
3497 EXCLUSIVE_LOCK_FUNCTION(mu2_)
3498 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3500 void unlock1() UNLOCK_FUNCTION(mu1_);
3501 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3502 void unlocklots()
3503 UNLOCK_FUNCTION(mu1_)
3504 UNLOCK_FUNCTION(mu2_)
3505 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3509 void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
3510 void Foo::unlock() UNLOCK_FUNCTION() { }
3512 void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
3513 mu1_.Lock();
3516 void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
3517 mu1_.ReaderLock();
3520 void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
3521 mu1_.Lock();
3522 mu2_.Lock();
3523 mu3_.Lock();
3526 void Foo::locklots()
3527 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
3528 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
3529 mu1_.Lock();
3530 mu2_.Lock();
3531 mu3_.Lock();
3534 void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
3535 mu1_.Unlock();
3538 void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
3539 mu1_.Unlock();
3540 mu2_.Unlock();
3541 mu3_.Unlock();
3544 void Foo::unlocklots()
3545 UNLOCK_FUNCTION(mu1_, mu2_)
3546 UNLOCK_FUNCTION(mu2_, mu3_) {
3547 mu1_.Unlock();
3548 mu2_.Unlock();
3549 mu3_.Unlock();
3553 void test0() {
3554 Foo foo;
3555 foo.lock();
3556 foo.unlock();
3558 foo.lock(); // expected-note{{mutex acquired here}}
3559 foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}
3560 foo.unlock(); // expected-note{{mutex released here}}
3561 foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}
3565 void test1() {
3566 Foo foo;
3567 foo.lock1();
3568 foo.a = 0;
3569 foo.unlock1();
3571 foo.lock1(); // expected-note{{mutex acquired here}}
3572 foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3573 foo.a = 0;
3574 foo.unlock1(); // expected-note{{mutex released here}}
3575 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3579 int test2() {
3580 Foo foo;
3581 foo.slock1();
3582 int d1 = foo.a;
3583 foo.unlock1();
3585 foo.slock1(); // expected-note{{mutex acquired here}}
3586 foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3587 int d2 = foo.a;
3588 foo.unlock1(); // expected-note{{mutex released here}}
3589 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3590 return d1 + d2;
3594 void test3() {
3595 Foo foo;
3596 foo.lock3();
3597 foo.a = 0;
3598 foo.b = 0;
3599 foo.c = 0;
3600 foo.unlock3();
3602 foo.lock3(); // expected-note 3 {{mutex acquired here}}
3603 foo.lock3(); // \
3604 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3605 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3606 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3607 foo.a = 0;
3608 foo.b = 0;
3609 foo.c = 0;
3610 foo.unlock3(); // expected-note 3 {{mutex released here}}
3611 foo.unlock3(); // \
3612 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3613 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3614 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3618 void testlots() {
3619 Foo foo;
3620 foo.locklots();
3621 foo.a = 0;
3622 foo.b = 0;
3623 foo.c = 0;
3624 foo.unlocklots();
3626 foo.locklots(); // expected-note 3 {{mutex acquired here}}
3627 foo.locklots(); // \
3628 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3629 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3630 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3631 foo.a = 0;
3632 foo.b = 0;
3633 foo.c = 0;
3634 foo.unlocklots(); // expected-note 3 {{mutex released here}}
3635 foo.unlocklots(); // \
3636 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3637 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3638 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3641 } // end namespace DuplicateAttributeTest
3645 namespace TryLockEqTest {
3647 class Foo {
3648 Mutex mu_;
3649 int a GUARDED_BY(mu_);
3650 bool c;
3652 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3653 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3654 void unlock() UNLOCK_FUNCTION(mu_);
3656 void test1();
3657 void test2();
3661 void Foo::test1() {
3662 if (tryLockMutexP() == 0) {
3663 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3664 return;
3666 a = 0;
3667 unlock();
3669 if (tryLockMutexP() != 0) {
3670 a = 0;
3671 unlock();
3674 if (0 != tryLockMutexP()) {
3675 a = 0;
3676 unlock();
3679 if (!(tryLockMutexP() == 0)) {
3680 a = 0;
3681 unlock();
3684 if (tryLockMutexI() == 0) {
3685 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3686 return;
3688 a = 0;
3689 unlock();
3691 if (0 == tryLockMutexI()) {
3692 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3693 return;
3695 a = 0;
3696 unlock();
3698 if (tryLockMutexI() == 1) {
3699 a = 0;
3700 unlock();
3703 if (mu_.TryLock() == false) {
3704 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3705 return;
3707 a = 0;
3708 unlock();
3710 if (mu_.TryLock() == true) {
3711 a = 0;
3712 unlock();
3714 else {
3715 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3718 #if __has_feature(cxx_nullptr)
3719 if (tryLockMutexP() == nullptr) {
3720 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3721 return;
3723 a = 0;
3724 unlock();
3725 #endif
3728 } // end namespace TryLockEqTest
3731 namespace ExistentialPatternMatching {
3733 class Graph {
3734 public:
3735 Mutex mu_;
3738 void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3739 void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3741 class Node {
3742 public:
3743 int a GUARDED_BY(&Graph::mu_);
3745 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3746 a = 0;
3748 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3751 void test() {
3752 Graph g1;
3753 Graph g2;
3754 Node n1;
3756 n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3757 n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3758 n1.foo2();
3760 g1.mu_.Lock();
3761 n1.a = 0;
3762 n1.foo();
3763 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3764 g1.mu_.Unlock();
3766 g2.mu_.Lock();
3767 n1.a = 0;
3768 n1.foo();
3769 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3770 g2.mu_.Unlock();
3772 LockAllGraphs();
3773 n1.a = 0;
3774 n1.foo();
3775 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3776 UnlockAllGraphs();
3778 LockAllGraphs();
3779 g1.mu_.Unlock();
3781 LockAllGraphs();
3782 g2.mu_.Unlock();
3784 LockAllGraphs(); // expected-note{{mutex acquired here}}
3785 g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}
3786 g1.mu_.Unlock();
3789 } // end namespace ExistentialPatternMatching
3792 namespace StringIgnoreTest {
3794 class Foo {
3795 public:
3796 Mutex mu_;
3797 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3798 void unlock() UNLOCK_FUNCTION("");
3799 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3800 void roober() SHARED_LOCKS_REQUIRED("");
3804 class Bar : public Foo {
3805 public:
3806 void bar(Foo* f) {
3807 f->unlock();
3808 f->goober();
3809 f->roober();
3810 f->lock();
3814 } // end namespace StringIgnoreTest
3817 namespace LockReturnedScopeFix {
3819 class Base {
3820 protected:
3821 struct Inner;
3822 bool c;
3824 const Mutex& getLock(const Inner* i);
3826 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3827 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3828 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3830 void bar(Inner* i);
3834 struct Base::Inner {
3835 Mutex lock_;
3836 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3840 const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3841 return i->lock_;
3845 void Base::foo(Inner* i) {
3846 i->doSomething();
3849 void Base::bar(Inner* i) {
3850 if (c) {
3851 i->lock_.Lock();
3852 unlockInner(i);
3854 else {
3855 lockInner(i);
3856 i->lock_.Unlock();
3860 } // end namespace LockReturnedScopeFix
3863 namespace TrylockWithCleanups {
3865 struct Foo {
3866 Mutex mu_;
3867 int a GUARDED_BY(mu_);
3870 Foo* GetAndLockFoo(const MyString& s)
3871 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3873 static void test() {
3874 Foo* lt = GetAndLockFoo("foo");
3875 if (!lt) return;
3876 int a = lt->a;
3877 lt->mu_.Unlock();
3880 } // end namespace TrylockWithCleanups
3883 namespace UniversalLock {
3885 class Foo {
3886 Mutex mu_;
3887 bool c;
3889 int a GUARDED_BY(mu_);
3890 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3891 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3893 void test1() {
3894 int b;
3896 beginNoWarnOnReads();
3897 b = a;
3898 r_foo();
3899 endNoWarnOnReads();
3901 beginNoWarnOnWrites();
3902 a = 0;
3903 w_foo();
3904 endNoWarnOnWrites();
3907 // don't warn on joins with universal lock
3908 void test2() {
3909 if (c) {
3910 beginNoWarnOnWrites();
3912 a = 0; // \
3913 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3914 endNoWarnOnWrites(); // \
3915 // expected-warning {{releasing wildcard '*' that was not held}}
3919 // make sure the universal lock joins properly
3920 void test3() {
3921 if (c) {
3922 mu_.Lock();
3923 beginNoWarnOnWrites();
3925 else {
3926 beginNoWarnOnWrites();
3927 mu_.Lock();
3929 a = 0;
3930 endNoWarnOnWrites();
3931 mu_.Unlock();
3935 // combine universal lock with other locks
3936 void test4() {
3937 beginNoWarnOnWrites();
3938 mu_.Lock();
3939 mu_.Unlock();
3940 endNoWarnOnWrites();
3942 mu_.Lock();
3943 beginNoWarnOnWrites();
3944 endNoWarnOnWrites();
3945 mu_.Unlock();
3947 mu_.Lock();
3948 beginNoWarnOnWrites();
3949 mu_.Unlock();
3950 endNoWarnOnWrites();
3954 } // end namespace UniversalLock
3957 namespace TemplateLockReturned {
3959 template<class T>
3960 class BaseT {
3961 public:
3962 virtual void baseMethod() = 0;
3963 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3965 Mutex mutex_;
3966 int a GUARDED_BY(mutex_);
3970 class Derived : public BaseT<int> {
3971 public:
3972 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3973 a = 0;
3977 } // end namespace TemplateLockReturned
3980 namespace ExprMatchingBugFix {
3982 class Foo {
3983 public:
3984 Mutex mu_;
3988 class Bar {
3989 public:
3990 bool c;
3991 Foo* foo;
3992 Bar(Foo* f) : foo(f) { }
3994 struct Nested {
3995 Foo* foo;
3996 Nested(Foo* f) : foo(f) { }
3998 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
4001 void test();
4005 void Bar::test() {
4006 foo->mu_.Lock();
4007 if (c) {
4008 Nested *n = new Nested(foo);
4009 n->unlockFoo();
4011 else {
4012 foo->mu_.Unlock();
4016 }; // end namespace ExprMatchingBugfix
4019 namespace ComplexNameTest {
4021 class Foo {
4022 public:
4023 static Mutex mu_;
4025 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
4026 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
4028 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
4031 class Bar {
4032 public:
4033 static Mutex mu_;
4035 Bar() LOCKS_EXCLUDED(mu_) { }
4036 ~Bar() LOCKS_EXCLUDED(mu_) { }
4038 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
4042 void test1() {
4043 Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}
4044 int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}
4045 } // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}
4048 void test2() {
4049 Bar::mu_.Lock();
4051 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}
4052 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}
4053 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}
4054 Bar::mu_.Unlock();
4057 }; // end namespace ComplexNameTest
4060 namespace UnreachableExitTest {
4062 class FemmeFatale {
4063 public:
4064 FemmeFatale();
4065 ~FemmeFatale() __attribute__((noreturn));
4068 void exitNow() __attribute__((noreturn));
4069 void exitDestruct(const MyString& ms) __attribute__((noreturn));
4071 Mutex fatalmu_;
4073 void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4074 exitNow();
4077 void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4078 FemmeFatale femme;
4081 bool c;
4083 void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4084 if (c) {
4085 exitNow();
4087 else {
4088 FemmeFatale femme;
4092 void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4093 exitDestruct("foo");
4096 } // end namespace UnreachableExitTest
4099 namespace VirtualMethodCanonicalizationTest {
4101 class Base {
4102 public:
4103 virtual Mutex* getMutex() = 0;
4106 class Base2 : public Base {
4107 public:
4108 Mutex* getMutex();
4111 class Base3 : public Base2 {
4112 public:
4113 Mutex* getMutex();
4116 class Derived : public Base3 {
4117 public:
4118 Mutex* getMutex(); // overrides Base::getMutex()
4121 void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
4123 void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
4124 baseFun(d);
4127 } // end namespace VirtualMethodCanonicalizationTest
4130 namespace TemplateFunctionParamRemapTest {
4132 template <class T>
4133 struct Cell {
4134 T dummy_;
4135 Mutex* mu_;
4138 class Foo {
4139 public:
4140 template <class T>
4141 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4143 void test();
4146 template<class T>
4147 void Foo::elr(Cell<T>* c1) { }
4149 void Foo::test() {
4150 Cell<int> cell;
4151 elr(&cell); // \
4152 // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}
4156 template<class T>
4157 void globalELR(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4159 template<class T>
4160 void globalELR(Cell<T>* c1) { }
4162 void globalTest() {
4163 Cell<int> cell;
4164 globalELR(&cell); // \
4165 // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}
4169 template<class T>
4170 void globalELR2(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4172 // second declaration
4173 template<class T>
4174 void globalELR2(Cell<T>* c2);
4176 template<class T>
4177 void globalELR2(Cell<T>* c3) { }
4179 // re-declaration after definition
4180 template<class T>
4181 void globalELR2(Cell<T>* c4);
4183 void globalTest2() {
4184 Cell<int> cell;
4185 globalELR2(&cell); // \
4186 // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}
4190 template<class T>
4191 class FooT {
4192 public:
4193 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4196 template<class T>
4197 void FooT<T>::elr(Cell<T>* c1) { }
4199 void testFooT() {
4200 Cell<int> cell;
4201 FooT<int> foo;
4202 foo.elr(&cell); // \
4203 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
4206 } // end namespace TemplateFunctionParamRemapTest
4209 namespace SelfConstructorTest {
4211 class SelfLock {
4212 public:
4213 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
4214 ~SelfLock() UNLOCK_FUNCTION(mu_);
4216 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
4218 Mutex mu_;
4221 class LOCKABLE SelfLock2 {
4222 public:
4223 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
4224 ~SelfLock2() UNLOCK_FUNCTION();
4226 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
4229 class SelfLockDeferred {
4230 public:
4231 SelfLockDeferred() LOCKS_EXCLUDED(mu_);
4232 ~SelfLockDeferred() UNLOCK_FUNCTION(mu_);
4234 Mutex mu_;
4237 class LOCKABLE SelfLockDeferred2 {
4238 public:
4239 SelfLockDeferred2() LOCKS_EXCLUDED(this);
4240 ~SelfLockDeferred2() UNLOCK_FUNCTION();
4244 void test() {
4245 SelfLock s;
4246 s.foo();
4249 void test2() {
4250 SelfLock2 s2;
4251 s2.foo();
4254 void testDeferredTemporary() {
4255 SelfLockDeferred(); // expected-warning {{releasing mutex '<temporary>.mu_' that was not held}}
4258 void testDeferredTemporary2() {
4259 SelfLockDeferred2(); // expected-warning {{releasing mutex '<temporary>' that was not held}}
4262 } // end namespace SelfConstructorTest
4265 namespace MultipleAttributeTest {
4267 class Foo {
4268 Mutex mu1_;
4269 Mutex mu2_;
4270 int a GUARDED_BY(mu1_);
4271 int b GUARDED_BY(mu2_);
4272 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
4273 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
4275 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
4276 EXCLUSIVE_LOCKS_REQUIRED(mu2_);
4277 void foo2() SHARED_LOCKS_REQUIRED(mu1_)
4278 SHARED_LOCKS_REQUIRED(mu2_);
4279 void foo3() LOCKS_EXCLUDED(mu1_)
4280 LOCKS_EXCLUDED(mu2_);
4281 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
4282 EXCLUSIVE_LOCK_FUNCTION(mu2_);
4283 void readerlock() SHARED_LOCK_FUNCTION(mu1_)
4284 SHARED_LOCK_FUNCTION(mu2_);
4285 void unlock() UNLOCK_FUNCTION(mu1_)
4286 UNLOCK_FUNCTION(mu2_);
4287 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
4288 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
4289 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
4290 SHARED_TRYLOCK_FUNCTION(true, mu2_);
4291 void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
4292 ASSERT_EXCLUSIVE_LOCK(mu2_);
4294 void alsoAssertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_, mu2_);
4296 void assertShared() ASSERT_SHARED_LOCK(mu1_)
4297 ASSERT_SHARED_LOCK(mu2_);
4299 void alsoAssertShared() ASSERT_SHARED_LOCK(mu1_, mu2_);
4301 void test();
4302 void testAssert();
4303 void testAssertShared();
4307 void Foo::foo1() {
4308 a = 1;
4309 b = 2;
4312 void Foo::foo2() {
4313 int result = a + b;
4316 void Foo::foo3() { }
4317 void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
4318 void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
4319 void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
4320 bool Foo::trylock() { return true; }
4321 bool Foo::readertrylock() { return true; }
4324 void Foo::test() {
4325 mu1_.Lock();
4326 foo1(); // expected-warning {{}}
4327 c = 0; // expected-warning {{}}
4328 *d = 0; // expected-warning {{}}
4329 mu1_.Unlock();
4331 mu1_.ReaderLock();
4332 foo2(); // expected-warning {{}}
4333 int x = c; // expected-warning {{}}
4334 int y = *d; // expected-warning {{}}
4335 mu1_.Unlock();
4337 mu2_.Lock();
4338 foo3(); // expected-warning {{}}
4339 mu2_.Unlock();
4341 lock();
4342 a = 0;
4343 b = 0;
4344 unlock();
4346 readerlock();
4347 int z = a + b;
4348 unlock();
4350 if (trylock()) {
4351 a = 0;
4352 b = 0;
4353 unlock();
4356 if (readertrylock()) {
4357 int zz = a + b;
4358 unlock();
4362 // Force duplication of attributes
4363 void Foo::assertBoth() { }
4364 void Foo::alsoAssertBoth() { }
4365 void Foo::assertShared() { }
4366 void Foo::alsoAssertShared() { }
4368 void Foo::testAssert() {
4370 assertBoth();
4371 a = 0;
4372 b = 0;
4375 alsoAssertBoth();
4376 a = 0;
4377 b = 0;
4381 void Foo::testAssertShared() {
4383 assertShared();
4384 int zz = a + b;
4388 alsoAssertShared();
4389 int zz = a + b;
4394 } // end namespace MultipleAttributeTest
4397 namespace GuardedNonPrimitiveTypeTest {
4400 class Data {
4401 public:
4402 Data(int i) : dat(i) { }
4404 int getValue() const { return dat; }
4405 void setValue(int i) { dat = i; }
4407 int operator[](int i) const { return dat; }
4408 int& operator[](int i) { return dat; }
4410 void operator()() { }
4412 Data& operator+=(int);
4413 Data& operator-=(int);
4414 Data& operator*=(int);
4415 Data& operator/=(int);
4416 Data& operator%=(int);
4417 Data& operator^=(int);
4418 Data& operator&=(int);
4419 Data& operator|=(int);
4420 Data& operator<<=(int);
4421 Data& operator>>=(int);
4422 Data& operator++();
4423 Data& operator++(int);
4424 Data& operator--();
4425 Data& operator--(int);
4427 private:
4428 int dat;
4432 class DataCell {
4433 public:
4434 DataCell(const Data& d) : dat(d) { }
4436 private:
4437 Data dat;
4441 void showDataCell(const DataCell& dc);
4444 class Foo {
4445 public:
4446 // method call tests
4447 void test() {
4448 data_.setValue(0); // FIXME -- should be writing \
4449 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4450 int a = data_.getValue(); // \
4451 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4453 datap1_->setValue(0); // FIXME -- should be writing \
4454 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4455 a = datap1_->getValue(); // \
4456 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4458 datap2_->setValue(0); // FIXME -- should be writing \
4459 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4460 a = datap2_->getValue(); // \
4461 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4463 (*datap2_).setValue(0); // FIXME -- should be writing \
4464 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4465 a = (*datap2_).getValue(); // \
4466 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4468 mu_.Lock();
4469 data_.setValue(1);
4470 datap1_->setValue(1);
4471 datap2_->setValue(1);
4472 mu_.Unlock();
4474 mu_.ReaderLock();
4475 a = data_.getValue();
4476 datap1_->setValue(0); // reads datap1_, writes *datap1_
4477 a = datap1_->getValue();
4478 a = datap2_->getValue();
4479 mu_.Unlock();
4482 // operator tests
4483 void test2() {
4484 data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4485 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \
4486 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4487 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \
4488 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4489 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4490 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4491 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4492 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4493 data_ += 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4494 data_ -= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4495 data_ *= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4496 data_ /= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4497 data_ %= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4498 data_ ^= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4499 data_ &= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4500 data_ |= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4501 data_ <<= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4502 data_ >>= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4503 ++data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4504 data_++; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4505 --data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4506 data_--; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4508 data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4509 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4511 data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4514 // const operator tests
4515 void test3() const {
4516 Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4518 //FIXME
4519 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4520 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4522 int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4525 private:
4526 Mutex mu_;
4527 Data data_ GUARDED_BY(mu_);
4528 Data* datap1_ GUARDED_BY(mu_);
4529 Data* datap2_ PT_GUARDED_BY(mu_);
4532 } // end namespace GuardedNonPrimitiveTypeTest
4535 namespace GuardedNonPrimitive_MemberAccess {
4537 class Cell {
4538 public:
4539 Cell(int i);
4541 void cellMethod();
4543 int a;
4547 class Foo {
4548 public:
4549 int a;
4550 Cell c GUARDED_BY(cell_mu_);
4551 Cell* cp PT_GUARDED_BY(cell_mu_);
4553 void myMethod();
4555 Mutex cell_mu_;
4559 class Bar {
4560 private:
4561 Mutex mu_;
4562 Foo foo GUARDED_BY(mu_);
4563 Foo* foop PT_GUARDED_BY(mu_);
4565 void test() {
4566 foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4568 int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4569 foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}
4571 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4572 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4574 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4575 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4577 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \
4578 // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}
4579 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \
4580 // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}
4582 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4583 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4584 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4585 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4587 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4588 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4589 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4590 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4594 } // namespace GuardedNonPrimitive_MemberAccess
4597 namespace TestThrowExpr {
4599 class Foo {
4600 Mutex mu_;
4602 bool hasError();
4604 void test() {
4605 mu_.Lock();
4606 if (hasError()) {
4607 throw "ugly";
4609 mu_.Unlock();
4613 } // end namespace TestThrowExpr
4616 namespace UnevaluatedContextTest {
4618 // parse attribute expressions in an unevaluated context.
4620 static inline Mutex* getMutex1();
4621 static inline Mutex* getMutex2();
4623 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());
4625 void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
4627 } // end namespace UnevaluatedContextTest
4630 namespace LockUnlockFunctionTest {
4632 // Check built-in lock functions
4633 class LOCKABLE MyLockable {
4634 public:
4635 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
4636 void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
4637 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
4639 private:
4640 Mutex mu_;
4644 class Foo {
4645 public:
4646 // Correct lock/unlock functions
4647 void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
4648 mu_.Lock();
4651 void readerLock() SHARED_LOCK_FUNCTION(mu_) {
4652 mu_.ReaderLock();
4655 void unlock() UNLOCK_FUNCTION(mu_) {
4656 mu_.Unlock();
4659 void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) {
4660 mu_.Unlock();
4663 void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) {
4664 mu_.ReaderUnlock();
4667 // Check failure to lock.
4668 void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4669 mu2_.Lock();
4670 mu2_.Unlock();
4671 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4673 void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4674 mu2_.Lock();
4675 mu2_.Unlock();
4676 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4678 void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4679 mu2_.Lock();
4680 mu2_.Unlock();
4681 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4683 // Check locking the wrong thing.
4684 void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4685 mu2_.Lock(); // expected-note {{mutex acquired here}}
4686 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4687 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4690 void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4691 mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
4692 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4693 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4696 void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4697 mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}
4698 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4700 private:
4701 Mutex mu_;
4702 Mutex mu2_;
4705 } // end namespace LockUnlockFunctionTest
4708 namespace AssertHeldTest {
4710 class Foo {
4711 public:
4712 int c;
4713 int a GUARDED_BY(mu_);
4714 Mutex mu_;
4716 void test1() {
4717 mu_.AssertHeld();
4718 int b = a;
4719 a = 0;
4722 void test2() {
4723 mu_.AssertReaderHeld();
4724 int b = a;
4725 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
4728 void test3() {
4729 if (c) {
4730 mu_.AssertHeld();
4732 else {
4733 mu_.AssertHeld();
4735 int b = a;
4736 a = 0;
4739 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4740 mu_.AssertHeld();
4741 int b = a;
4742 a = 0;
4745 void test5() UNLOCK_FUNCTION(mu_) {
4746 mu_.AssertHeld();
4747 mu_.Unlock();
4750 void test6() {
4751 mu_.AssertHeld();
4752 mu_.Unlock(); // should this be a warning?
4755 void test7() {
4756 if (c) {
4757 mu_.AssertHeld();
4759 else {
4760 mu_.Lock();
4762 int b = a;
4763 a = 0;
4764 mu_.Unlock();
4767 void test8() {
4768 if (c) {
4769 mu_.Lock();
4771 else {
4772 mu_.AssertHeld();
4774 // FIXME: should warn, because it's unclear whether we need to release or not.
4775 int b = a;
4776 a = 0;
4777 mu_.Unlock(); // should this be a warning?
4780 void test9() {
4781 if (c) {
4782 mu_.AssertHeld();
4784 else {
4785 mu_.Lock(); // expected-note {{mutex acquired here}}
4787 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4789 void test10() {
4790 if (c) {
4791 mu_.Lock(); // expected-note {{mutex acquired here}}
4793 else {
4794 mu_.AssertHeld();
4796 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4798 void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
4800 void test11() {
4801 assertMu();
4802 int b = a;
4803 a = 0;
4806 void test12() {
4807 if (c)
4808 mu_.ReaderLock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4809 else
4810 mu_.AssertHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4811 // FIXME: should instead warn because it's unclear whether we need to release or not.
4812 int b = a;
4813 a = 0;
4814 mu_.Unlock();
4817 void test13() {
4818 if (c)
4819 mu_.Lock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4820 else
4821 mu_.AssertReaderHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4822 // FIXME: should instead warn because it's unclear whether we need to release or not.
4823 int b = a;
4824 a = 0;
4825 mu_.Unlock();
4829 } // end namespace AssertHeldTest
4832 namespace LogicalConditionalTryLock {
4834 class Foo {
4835 public:
4836 Mutex mu;
4837 int a GUARDED_BY(mu);
4838 bool c;
4840 bool newc();
4842 void test1() {
4843 if (c && mu.TryLock()) {
4844 a = 0;
4845 mu.Unlock();
4849 void test2() {
4850 bool b = mu.TryLock();
4851 if (c && b) {
4852 a = 0;
4853 mu.Unlock();
4857 void test3() {
4858 if (c || !mu.TryLock())
4859 return;
4860 a = 0;
4861 mu.Unlock();
4864 void test4() {
4865 while (c && mu.TryLock()) {
4866 a = 0;
4867 c = newc();
4868 mu.Unlock();
4872 void test5() {
4873 while (c) {
4874 if (newc() || !mu.TryLock())
4875 break;
4876 a = 0;
4877 mu.Unlock();
4881 void test6() {
4882 mu.Lock();
4883 do {
4884 a = 0;
4885 mu.Unlock();
4886 } while (newc() && mu.TryLock());
4889 void test7() {
4890 for (bool b = mu.TryLock(); c && b;) {
4891 a = 0;
4892 mu.Unlock();
4896 void test8() {
4897 if (c && newc() && mu.TryLock()) {
4898 a = 0;
4899 mu.Unlock();
4903 void test9() {
4904 if (!(c && newc() && mu.TryLock()))
4905 return;
4906 a = 0;
4907 mu.Unlock();
4910 void test10() {
4911 if (!(c || !mu.TryLock())) {
4912 a = 0;
4913 mu.Unlock();
4918 } // end namespace LogicalConditionalTryLock
4922 namespace PtGuardedByTest {
4924 void doSomething();
4926 class Cell {
4927 public:
4928 int a;
4932 // This mainly duplicates earlier tests, but just to make sure...
4933 class PtGuardedByCorrectnessTest {
4934 Mutex mu1;
4935 Mutex mu2;
4936 int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4937 Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4938 int sa[10] GUARDED_BY(mu1);
4939 Cell sc[10] GUARDED_BY(mu1);
4941 static constexpr int Cell::*pa = &Cell::a;
4943 void test1() {
4944 mu1.Lock();
4945 if (a == 0) doSomething(); // OK, we don't dereference.
4946 a = 0;
4947 c = 0;
4948 if (sa[0] == 42) doSomething();
4949 sa[0] = 57;
4950 if (sc[0].a == 42) doSomething();
4951 sc[0].a = 57;
4952 mu1.Unlock();
4955 void test2() {
4956 mu1.ReaderLock();
4957 if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4958 *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4960 if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4961 c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4962 c->*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4964 if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4965 (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4966 (*c).*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4968 if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4969 a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4970 if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4971 c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4972 mu1.Unlock();
4975 void test3() {
4976 mu2.Lock();
4977 if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4978 *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4980 if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4981 c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4983 if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4984 (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4986 if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4987 a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4988 if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4989 c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4990 mu2.Unlock();
4993 void test4() { // Literal arrays
4994 if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4995 sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4996 if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4997 sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4998 sc[0].*pa = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
5000 if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
5001 *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
5002 if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
5003 (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
5004 if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
5005 sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
5008 void test5() {
5009 mu1.ReaderLock(); // OK -- correct use.
5010 mu2.Lock();
5011 if (*a == 0) doSomething();
5012 *a = 0;
5014 if (c->a == 0) doSomething();
5015 c->a = 0;
5017 if ((*c).a == 0) doSomething();
5018 (*c).a = 0;
5019 mu2.Unlock();
5020 mu1.Unlock();
5025 class SmartPtr_PtGuardedBy_Test {
5026 Mutex mu1;
5027 Mutex mu2;
5028 SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
5029 SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
5031 static constexpr int Cell::*pa = &Cell::a;
5033 void test1() {
5034 mu1.ReaderLock();
5035 mu2.Lock();
5037 sp.get();
5038 if (*sp == 0) doSomething();
5039 *sp = 0;
5040 sq->a = 0;
5041 sq->*pa = 0;
5043 if (sp[0] == 0) doSomething();
5044 sp[0] = 0;
5046 mu2.Unlock();
5047 mu1.Unlock();
5050 void test2() {
5051 mu2.Lock();
5053 sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
5054 if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
5055 *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
5056 sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
5057 sq->*pa = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
5059 if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
5060 sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
5061 if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
5062 sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
5064 mu2.Unlock();
5067 void test3() {
5068 mu1.Lock();
5070 sp.get();
5071 if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5072 *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5073 sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5074 sq->*pa = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5076 if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5077 sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5078 if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5079 sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5081 mu1.Unlock();
5085 } // end namespace PtGuardedByTest
5088 namespace NonMemberCalleeICETest {
5090 class A {
5091 void Run() {
5092 (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
5095 void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M);
5096 Mutex M;
5099 } // end namespace NonMemberCalleeICETest
5102 namespace pt_guard_attribute_type {
5103 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
5104 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
5106 void test() {
5107 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to non-static data members and global variables}}
5108 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to non-static data members and global variables}}
5110 typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to}}
5111 typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to}}
5113 } // end namespace pt_guard_attribute_type
5116 namespace ThreadAttributesOnLambdas {
5118 class Foo {
5119 Mutex mu_;
5121 void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);
5123 void test() {
5124 auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
5125 LockedFunction();
5128 auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {
5129 LockedFunction();
5132 auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {
5133 mu_.Lock();
5136 func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}
5137 func2();
5138 func3();
5139 mu_.Unlock();
5143 } // end namespace ThreadAttributesOnLambdas
5147 namespace AttributeExpressionCornerCases {
5149 class Foo {
5150 int a GUARDED_BY(getMu());
5152 Mutex* getMu() LOCK_RETURNED("");
5153 Mutex* getUniv() LOCK_RETURNED("*");
5155 void test1() {
5156 a = 0;
5159 void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
5160 a = 0;
5163 void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
5165 void test3() {
5166 foo(nullptr);
5171 class MapTest {
5172 struct MuCell { Mutex* mu; };
5174 MyMap<MyString, Mutex*> map;
5175 MyMap<MyString, MuCell> mapCell;
5177 int a GUARDED_BY(map["foo"]);
5178 int b GUARDED_BY(mapCell["foo"].mu);
5180 void test() {
5181 map["foo"]->Lock();
5182 a = 0;
5183 map["foo"]->Unlock();
5186 void test2() {
5187 mapCell["foo"].mu->Lock();
5188 b = 0;
5189 mapCell["foo"].mu->Unlock();
5194 class PreciseSmartPtr {
5195 SmartPtr<Mutex> mu;
5196 int val GUARDED_BY(mu);
5198 static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
5199 a.mu->Lock();
5200 bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
5201 // expected-note {{found near match 'a.mu'}}
5202 a.mu->Unlock();
5203 return result;
5208 class SmartRedeclare {
5209 SmartPtr<Mutex> mu;
5210 int val GUARDED_BY(mu);
5212 void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
5213 void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5214 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5218 void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
5219 val = 0;
5222 void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5223 val = 0;
5226 void SmartRedeclare::test3() {
5227 val = 0;
5231 namespace CustomMutex {
5234 class LOCKABLE BaseMutex { };
5235 class DerivedMutex : public BaseMutex { };
5237 void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
5238 void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
5240 static struct DerivedMutex custMu;
5242 static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
5244 void customTest() {
5245 customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
5246 doSomethingRequiringLock();
5247 customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
5250 } // end namespace CustomMutex
5252 } // end AttributeExpressionCornerCases
5255 namespace ScopedLockReturnedInvalid {
5257 class Opaque;
5259 Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
5261 void test(Opaque* o) {
5262 MutexLock lock(getMutex(o));
5265 } // end namespace ScopedLockReturnedInvalid
5268 namespace NegativeRequirements {
5270 class Bar {
5271 Mutex mu;
5272 int a GUARDED_BY(mu);
5274 public:
5275 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5276 mu.Lock();
5277 a = 0;
5278 mu.Unlock();
5283 class Foo {
5284 Mutex mu;
5285 int a GUARDED_BY(mu);
5287 public:
5288 void foo() {
5289 mu.Lock(); // warning? needs !mu?
5290 baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
5291 bar();
5292 mu.Unlock();
5295 void bar() {
5296 bar2(); // expected-warning {{calling function 'bar2' requires negative capability '!mu'}}
5299 void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5300 baz();
5303 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5304 mu.Lock();
5305 a = 0;
5306 mu.Unlock();
5309 void test() {
5310 Bar b;
5311 b.baz(); // no warning -- in different class.
5315 } // end namespace NegativeRequirements
5318 namespace NegativeThreadRoles {
5320 typedef int __attribute__((capability("role"))) ThreadRole;
5322 void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
5323 void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
5325 ThreadRole FlightControl, Logger;
5327 extern void enque_log_msg(const char *msg);
5328 void log_msg(const char *msg) {
5329 enque_log_msg(msg);
5332 void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
5333 void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
5335 void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
5336 dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
5337 dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
5340 void spawn_fake_flight_control_thread(void) {
5341 acquire(FlightControl);
5342 flight_control_entry();
5343 release(FlightControl);
5346 extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
5347 void logger_entry(void) __attribute__((requires_capability(Logger)))
5348 __attribute__((requires_capability(!FlightControl))) {
5349 const char *msg;
5351 while ((msg = deque_log_msg())) {
5352 dispatch_log(msg);
5356 void spawn_fake_logger_thread(void) __attribute__((requires_capability(!FlightControl))) {
5357 acquire(Logger);
5358 logger_entry();
5359 release(Logger);
5362 int main(void) __attribute__((requires_capability(!FlightControl))) {
5363 spawn_fake_flight_control_thread();
5364 spawn_fake_logger_thread();
5366 for (;;)
5367 ; /* Pretend to dispatch things. */
5369 return 0;
5372 } // end namespace NegativeThreadRoles
5375 namespace AssertSharedExclusive {
5377 void doSomething();
5379 class Foo {
5380 Mutex mu;
5381 int a GUARDED_BY(mu);
5383 void test() SHARED_LOCKS_REQUIRED(mu) {
5384 mu.AssertHeld();
5385 if (a > 0)
5386 doSomething();
5390 } // end namespace AssertSharedExclusive
5393 namespace RangeBasedForAndReferences {
5395 class Foo {
5396 struct MyStruct {
5397 int a;
5400 Mutex mu;
5401 int a GUARDED_BY(mu);
5402 MyContainer<int> cntr GUARDED_BY(mu);
5403 MyStruct s GUARDED_BY(mu);
5404 int arr[10] GUARDED_BY(mu);
5406 void nonref_test() {
5407 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5408 b = 0; // no warning
5411 void auto_test() {
5412 auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5413 b = 0; // no warning
5414 auto &c = a; // no warning
5415 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5418 void ref_test() {
5419 int &b = a;
5420 int &c = b;
5421 int &d = c;
5422 b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5423 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5424 d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5426 MyStruct &rs = s;
5427 rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
5429 int (&rarr)[10] = arr;
5430 rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
5433 void ptr_test() {
5434 int *b = &a;
5435 *b = 0; // no expected warning yet
5438 void for_test() {
5439 int total = 0;
5440 for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
5441 total += i;
5447 } // end namespace RangeBasedForAndReferences
5451 namespace PassByRefTest {
5453 class Foo {
5454 public:
5455 Foo() : a(0), b(0) { }
5457 int a;
5458 int b;
5460 void operator+(const Foo& f);
5462 void operator[](const Foo& g);
5464 void operator()();
5467 template<class T>
5468 T&& mymove(T& f);
5471 // test top-level functions
5472 void copy(Foo f);
5473 void write1(Foo& f);
5474 void write2(int a, Foo& f);
5475 void read1(const Foo& f);
5476 void read2(int a, const Foo& f);
5477 void destroy(Foo&& f);
5479 void operator/(const Foo& f, const Foo& g);
5480 void operator*(const Foo& f, const Foo& g);
5482 // Test constructors.
5483 struct FooRead {
5484 FooRead(const Foo &);
5486 struct FooWrite {
5487 FooWrite(Foo &);
5490 // Test variadic functions
5491 template<typename... T>
5492 void copyVariadic(T...) {}
5493 template<typename... T>
5494 void writeVariadic(T&...) {}
5495 template<typename... T>
5496 void readVariadic(const T&...) {}
5498 void copyVariadicC(int, ...);
5500 class Bar {
5501 public:
5502 Mutex mu;
5503 Foo foo GUARDED_BY(mu);
5504 Foo foo2 GUARDED_BY(mu);
5505 Foo* foop PT_GUARDED_BY(mu);
5506 SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
5508 // test methods.
5509 void mwrite1(Foo& f);
5510 void mwrite2(int a, Foo& f);
5511 void mread1(const Foo& f);
5512 void mread2(int a, const Foo& f);
5514 // static methods
5515 static void smwrite1(Foo& f);
5516 static void smwrite2(int a, Foo& f);
5517 static void smread1(const Foo& f);
5518 static void smread2(int a, const Foo& f);
5520 void operator<<(const Foo& f);
5522 void test1() {
5523 copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5524 write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5525 write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5526 read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5527 read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5528 destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5530 copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5531 readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5532 writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5533 copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5535 FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5536 FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5538 mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5539 mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5540 mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5541 mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5543 smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5544 smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5545 smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5546 smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5548 foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5549 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5550 foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5551 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5552 foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5553 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5554 foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5555 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5556 foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5557 (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5559 copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
5560 write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5561 write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5562 read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5563 read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5564 destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5566 copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5567 write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5568 write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5569 read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5570 read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5571 destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5573 // TODO -- these require better smart pointer handling.
5574 copy(*foosp.get());
5575 write1(*foosp.get());
5576 write2(10, *foosp.get());
5577 read1(*foosp.get());
5578 read2(10, *foosp.get());
5579 destroy(mymove(*foosp.get()));
5583 class Return {
5584 Mutex mu;
5585 Foo foo GUARDED_BY(mu);
5586 Foo* foo_ptr PT_GUARDED_BY(mu);
5588 Foo returns_value_locked() {
5589 MutexLock lock(&mu);
5590 return foo;
5593 Foo returns_value_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5594 return foo;
5597 Foo returns_value_releases_lock_after_return() UNLOCK_FUNCTION(mu) {
5598 MutexLock lock(&mu, true);
5599 return foo;
5602 Foo returns_value_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {
5603 mu.Lock();
5604 return foo;
5607 Foo returns_value_not_locked() {
5608 return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5611 Foo returns_value_releases_lock_before_return() UNLOCK_FUNCTION(mu) {
5612 mu.Unlock();
5613 return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5616 Foo &returns_ref_not_locked() {
5617 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}
5620 Foo &returns_ref_locked() {
5621 MutexLock lock(&mu);
5622 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}
5625 Foo &returns_ref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {
5626 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5629 Foo &returns_ref_exclusive_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5630 return foo;
5633 Foo &returns_ref_releases_lock_after_return() UNLOCK_FUNCTION(mu) {
5634 MutexLock lock(&mu, true);
5635 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5638 Foo& returns_ref_releases_lock_before_return() UNLOCK_FUNCTION(mu) {
5639 mu.Unlock();
5640 return foo; // // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5643 Foo &returns_ref_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {
5644 mu.Lock();
5645 return foo;
5648 const Foo &returns_constref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {
5649 return foo;
5652 Foo *returns_ptr() {
5653 return &foo; // FIXME -- Do we want to warn on this ?
5656 Foo &returns_ref2() {
5657 return *foo_ptr; // expected-warning {{returning the value that 'foo_ptr' points to by reference requires holding mutex 'mu' exclusively}}
5663 } // end namespace PassByRefTest
5666 namespace AcquiredBeforeAfterText {
5668 class Foo {
5669 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5670 Mutex mu2;
5671 Mutex mu3;
5673 void test1() {
5674 mu1.Lock();
5675 mu2.Lock();
5676 mu3.Lock();
5678 mu3.Unlock();
5679 mu2.Unlock();
5680 mu1.Unlock();
5683 void test2() {
5684 mu2.Lock();
5685 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5686 mu1.Unlock();
5687 mu2.Unlock();
5690 void test3() {
5691 mu3.Lock();
5692 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5693 mu1.Unlock();
5694 mu3.Unlock();
5697 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {
5698 mu2.Lock();
5699 mu2.Unlock();
5702 void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5703 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5704 mu1.Unlock();
5707 void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5708 mu1.AssertHeld();
5711 void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }
5713 void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }
5717 class Foo2 {
5718 Mutex mu1;
5719 Mutex mu2 ACQUIRED_AFTER(mu1);
5720 Mutex mu3 ACQUIRED_AFTER(mu1);
5722 void test1() {
5723 mu1.Lock();
5724 mu2.Lock();
5725 mu3.Lock();
5727 mu3.Unlock();
5728 mu2.Unlock();
5729 mu1.Unlock();
5732 void test2() {
5733 mu2.Lock();
5734 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5735 mu1.Unlock();
5736 mu2.Unlock();
5739 void test3() {
5740 mu3.Lock();
5741 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5742 mu1.Unlock();
5743 mu3.Unlock();
5748 class Foo3 {
5749 Mutex mu1 ACQUIRED_BEFORE(mu2);
5750 Mutex mu2;
5751 Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);
5752 Mutex mu4;
5754 void test1() {
5755 mu1.Lock();
5756 mu2.Lock();
5757 mu3.Lock();
5758 mu4.Lock();
5760 mu4.Unlock();
5761 mu3.Unlock();
5762 mu2.Unlock();
5763 mu1.Unlock();
5766 void test2() {
5767 mu4.Lock();
5768 mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}
5770 mu2.Unlock();
5771 mu4.Unlock();
5774 void test3() {
5775 mu4.Lock();
5776 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}
5778 mu1.Unlock();
5779 mu4.Unlock();
5782 void test4() {
5783 mu3.Lock();
5784 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5786 mu1.Unlock();
5787 mu3.Unlock();
5792 // Test transitive DAG traversal with AFTER
5793 class Foo4 {
5794 Mutex mu1;
5795 Mutex mu2 ACQUIRED_AFTER(mu1);
5796 Mutex mu3 ACQUIRED_AFTER(mu1);
5797 Mutex mu4 ACQUIRED_AFTER(mu2, mu3);
5798 Mutex mu5 ACQUIRED_AFTER(mu4);
5799 Mutex mu6 ACQUIRED_AFTER(mu4);
5800 Mutex mu7 ACQUIRED_AFTER(mu5, mu6);
5801 Mutex mu8 ACQUIRED_AFTER(mu7);
5803 void test() {
5804 mu8.Lock();
5805 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5806 mu1.Unlock();
5807 mu8.Unlock();
5812 // Test transitive DAG traversal with BEFORE
5813 class Foo5 {
5814 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5815 Mutex mu2 ACQUIRED_BEFORE(mu4);
5816 Mutex mu3 ACQUIRED_BEFORE(mu4);
5817 Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);
5818 Mutex mu5 ACQUIRED_BEFORE(mu7);
5819 Mutex mu6 ACQUIRED_BEFORE(mu7);
5820 Mutex mu7 ACQUIRED_BEFORE(mu8);
5821 Mutex mu8;
5823 void test() {
5824 mu8.Lock();
5825 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5826 mu1.Unlock();
5827 mu8.Unlock();
5832 class Foo6 {
5833 Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}}
5834 Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}}
5835 Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}}
5837 Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}}
5838 Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}}
5840 void test0() {
5841 mu_a.Lock();
5842 mu_b.Lock();
5843 mu_b.Unlock();
5844 mu_a.Unlock();
5847 void test1a() {
5848 mu1.Lock();
5849 mu1.Unlock();
5852 void test1b() {
5853 mu1.Lock();
5854 mu_a.Lock();
5855 mu_b.Lock();
5856 mu_b.Unlock();
5857 mu_a.Unlock();
5858 mu1.Unlock();
5861 void test() {
5862 mu2.Lock();
5863 mu2.Unlock();
5866 void test3() {
5867 mu3.Lock();
5868 mu3.Unlock();
5872 } // end namespace AcquiredBeforeAfterTest
5875 namespace ScopedAdoptTest {
5877 class Foo {
5878 Mutex mu;
5879 int a GUARDED_BY(mu);
5880 int b;
5882 void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {
5883 MutexLock slock(&mu, true);
5884 a = 0;
5887 void test2() SHARED_UNLOCK_FUNCTION(mu) {
5888 ReaderMutexLock slock(&mu, true);
5889 b = a;
5892 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5893 MutexLock slock(&mu, true);
5894 a = 0;
5895 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5897 void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5898 ReaderMutexLock slock(&mu, true);
5899 b = a;
5900 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5904 } // end namespace ScopedAdoptTest
5907 namespace TestReferenceNoThreadSafetyAnalysis {
5909 #define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
5911 // Takes a reference to a guarded data member, and returns an unguarded
5912 // reference.
5913 template <class T>
5914 inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
5915 return v;
5918 template <class T>
5919 inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
5920 return v;
5924 class Foo {
5925 public:
5926 Foo(): a(0) { }
5928 int a;
5932 class Bar {
5933 public:
5934 Bar() : a(0) { }
5936 Mutex mu;
5937 int a GUARDED_BY(mu);
5938 Foo foo GUARDED_BY(mu);
5942 void test() {
5943 Bar bar;
5944 const Bar cbar;
5946 int a = TS_UNCHECKED_READ(bar.a); // nowarn
5947 TS_UNCHECKED_READ(bar.a) = 1; // nowarn
5949 int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
5950 TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
5952 int c = TS_UNCHECKED_READ(cbar.a); // nowarn
5955 #undef TS_UNCHECKED_READ
5957 } // end namespace TestReferenceNoThreadSafetyAnalysis
5960 namespace GlobalAcquiredBeforeAfterTest {
5962 Mutex mu1;
5963 Mutex mu2 ACQUIRED_AFTER(mu1);
5965 void test3() {
5966 mu2.Lock();
5967 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5968 mu1.Unlock();
5969 mu2.Unlock();
5972 } // end namespace GlobalAcquiredBeforeAfterTest
5975 namespace LifetimeExtensionText {
5977 struct Holder {
5978 virtual ~Holder() throw() {}
5979 int i = 0;
5982 void test() {
5983 // Should not crash.
5984 const auto &value = Holder().i;
5987 } // end namespace LifetimeExtensionTest
5990 namespace LockableUnions {
5992 union LOCKABLE MutexUnion {
5993 int a;
5994 char* b;
5996 void Lock() EXCLUSIVE_LOCK_FUNCTION();
5997 void Unlock() UNLOCK_FUNCTION();
6000 MutexUnion muun2;
6001 MutexUnion muun1 ACQUIRED_BEFORE(muun2);
6003 void test() {
6004 muun2.Lock();
6005 muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
6006 muun1.Unlock();
6007 muun2.Unlock();
6010 } // end namespace LockableUnions
6012 // This used to crash.
6013 class acquired_before_empty_str {
6014 void WaitUntilSpaceAvailable() {
6015 lock_.ReaderLock(); // expected-note {{acquired here}}
6016 } // expected-warning {{mutex 'lock_' is still held at the end of function}}
6017 Mutex lock_ ACQUIRED_BEFORE("");
6020 namespace PR34800 {
6021 struct A {
6022 operator int() const;
6024 struct B {
6025 bool g() __attribute__((locks_excluded(h))); // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}}
6026 int h;
6028 struct C {
6029 B *operator[](int);
6031 C c;
6032 void f() { c[A()]->g(); }
6033 } // namespace PR34800
6035 #ifdef __cpp_guaranteed_copy_elision
6037 namespace ReturnScopedLockable {
6039 class Object {
6040 public:
6041 MutexLock lock() EXCLUSIVE_LOCK_FUNCTION(mutex) {
6042 // TODO: False positive because scoped lock isn't destructed.
6043 return MutexLock(&mutex); // expected-note {{mutex acquired here}}
6044 } // expected-warning {{mutex 'mutex' is still held at the end of function}}
6046 ReaderMutexLock lockShared() SHARED_LOCK_FUNCTION(mutex) {
6047 // TODO: False positive because scoped lock isn't destructed.
6048 return ReaderMutexLock(&mutex); // expected-note {{mutex acquired here}}
6049 } // expected-warning {{mutex 'mutex' is still held at the end of function}}
6051 MutexLock adopt() EXCLUSIVE_LOCKS_REQUIRED(mutex) {
6052 // TODO: False positive because scoped lock isn't destructed.
6053 return MutexLock(&mutex, true); // expected-note {{mutex acquired here}}
6054 } // expected-warning {{mutex 'mutex' is still held at the end of function}}
6056 ReaderMutexLock adoptShared() SHARED_LOCKS_REQUIRED(mutex) {
6057 // TODO: False positive because scoped lock isn't destructed.
6058 return ReaderMutexLock(&mutex, true); // expected-note {{mutex acquired here}}
6059 } // expected-warning {{mutex 'mutex' is still held at the end of function}}
6061 int x GUARDED_BY(mutex);
6062 void needsLock() EXCLUSIVE_LOCKS_REQUIRED(mutex);
6064 void testInside() {
6065 MutexLock scope = lock();
6066 x = 1;
6067 needsLock();
6070 Mutex mutex;
6073 Object obj;
6075 void testLock() {
6076 MutexLock scope = obj.lock();
6077 obj.x = 1;
6078 obj.needsLock();
6081 int testSharedLock() {
6082 ReaderMutexLock scope = obj.lockShared();
6083 obj.x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'obj.mutex' exclusively}}
6084 return obj.x;
6087 void testAdopt() {
6088 obj.mutex.Lock();
6089 MutexLock scope = obj.adopt();
6090 obj.x = 1;
6093 int testAdoptShared() {
6094 obj.mutex.Lock();
6095 ReaderMutexLock scope = obj.adoptShared();
6096 obj.x = 1;
6097 return obj.x;
6100 } // namespace ReturnScopedLockable
6102 #endif
6104 namespace PR38640 {
6105 void f() {
6106 // Self-referencing assignment previously caused an infinite loop when thread
6107 // safety analysis was enabled.
6108 int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}}
6112 namespace Derived_Smart_Pointer {
6113 template <class T>
6114 class SmartPtr_Derived : public SmartPtr<T> {};
6116 class Foo {
6117 public:
6118 SmartPtr_Derived<Mutex> mu_;
6119 int a GUARDED_BY(mu_);
6120 int b GUARDED_BY(mu_.get());
6121 int c GUARDED_BY(*mu_);
6123 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
6124 void Unlock() UNLOCK_FUNCTION(mu_);
6126 void test0() {
6127 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
6128 b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
6129 c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
6132 void test1() {
6133 Lock();
6134 a = 1;
6135 b = 1;
6136 c = 1;
6137 Unlock();
6141 class Bar {
6142 SmartPtr_Derived<Foo> foo;
6144 void test0() {
6145 foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
6146 (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
6147 foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
6150 void test1() {
6151 foo->Lock();
6152 foo->a = 1;
6153 foo->Unlock();
6155 foo->mu_->Lock();
6156 foo->b = 1;
6157 foo->mu_->Unlock();
6159 MutexLock lock(foo->mu_.get());
6160 foo->c = 1;
6164 class PointerGuard {
6165 Mutex mu1;
6166 Mutex mu2;
6167 SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
6169 void test0() {
6170 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
6171 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \
6172 // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
6176 void test1() {
6177 mu1.Lock();
6179 i.get();
6180 *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
6182 mu1.Unlock();
6185 void test2() {
6186 mu2.Lock();
6188 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
6189 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
6191 mu2.Unlock();
6194 void test3() {
6195 mu1.Lock();
6196 mu2.Lock();
6198 i.get();
6199 *i = 2;
6201 mu2.Unlock();
6202 mu1.Unlock();