7625 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s2// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s3// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s4// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s5 6// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s7// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s8 9#include "thread-safety-annotations.h"10 11class LOCKABLE Mutex {12 public:13 void Lock() EXCLUSIVE_LOCK_FUNCTION();14 void ReaderLock() SHARED_LOCK_FUNCTION();15 void Unlock() UNLOCK_FUNCTION();16 void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();17 void ReaderUnlock() SHARED_UNLOCK_FUNCTION();18 bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);19 bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);20 void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION();21 22 void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();23 void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();24 25 // for negative capabilities26 const Mutex& operator!() const { return *this; }27 28 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();29 void AssertReaderHeld() ASSERT_SHARED_LOCK();30};31 32class SCOPED_LOCKABLE MutexLock {33 public:34 MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);35 MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);36 ~MutexLock() UNLOCK_FUNCTION();37};38 39class SCOPED_LOCKABLE ReaderMutexLock {40 public:41 ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu);42 ReaderMutexLock(Mutex *mu, bool adopt) SHARED_LOCKS_REQUIRED(mu);43 ~ReaderMutexLock() UNLOCK_FUNCTION();44};45 46class SCOPED_LOCKABLE ReleasableMutexLock {47 public:48 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);49 ~ReleasableMutexLock() UNLOCK_FUNCTION();50 51 void Release() UNLOCK_FUNCTION();52};53 54class SCOPED_LOCKABLE DoubleMutexLock {55public:56 DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);57 ~DoubleMutexLock() UNLOCK_FUNCTION();58};59 60template<typename Mu>61class SCOPED_LOCKABLE TemplateMutexLock {62public:63 TemplateMutexLock(Mu *mu) EXCLUSIVE_LOCK_FUNCTION(mu);64 ~TemplateMutexLock() UNLOCK_FUNCTION();65};66 67template<typename... Mus>68class SCOPED_LOCKABLE VariadicMutexLock {69public:70 VariadicMutexLock(Mus *...mus) EXCLUSIVE_LOCK_FUNCTION(mus...);71 ~VariadicMutexLock() UNLOCK_FUNCTION();72};73 74// The universal lock, written "*", allows checking to be selectively turned75// off for a particular piece of code.76void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");77void endNoWarnOnReads() UNLOCK_FUNCTION("*");78void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");79void endNoWarnOnWrites() UNLOCK_FUNCTION("*");80 81 82// For testing handling of smart pointers.83template<class T>84class SmartPtr {85public:86 SmartPtr(T* p) : ptr_(p) { }87 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }88 ~SmartPtr();89 90 T* get() const { return ptr_; }91 T* operator->() const { return ptr_; }92 T& operator*() const { return *ptr_; }93 T& operator[](int i) const { return ptr_[i]; }94 95private:96 T* ptr_;97};98 99template<typename T, typename U>100U& operator->*(const SmartPtr<T>& ptr, U T::*p) { return ptr->*p; }101 102 103// For testing destructor calls and cleanup.104class MyString {105public:106 MyString(const char* s);107 ~MyString();108};109 110 111// For testing operator overloading112template <class K, class T>113class MyMap {114public:115 T& operator[](const K& k);116};117 118 119// For testing handling of containers.120template <class T>121class MyContainer {122public:123 MyContainer();124 125 typedef T* iterator;126 typedef const T* const_iterator;127 128 T* begin();129 T* end();130 131 const T* cbegin();132 const T* cend();133 134 T& operator[](int i);135 const T& operator[](int i) const;136 137private:138 T* ptr_;139};140 141 142 143Mutex sls_mu;144 145Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));146int sls_guard_var __attribute__((guarded_var)) = 0;147int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;148 149bool getBool();150 151class MutexWrapper {152public:153 Mutex mu;154 int x __attribute__((guarded_by(mu)));155 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);156};157 158struct TestingMoreComplexAttributes {159 Mutex lock;160 struct { Mutex lock; } strct;161 union {162 bool a __attribute__((guarded_by(lock)));163 bool b __attribute__((guarded_by(strct.lock)));164 bool *ptr_a __attribute__((pt_guarded_by(lock)));165 bool *ptr_b __attribute__((pt_guarded_by(strct.lock)));166 Mutex lock1 __attribute__((acquired_before(lock))) __attribute__((acquired_before(strct.lock)));167 Mutex lock2 __attribute__((acquired_after(lock))) __attribute__((acquired_after(strct.lock)));168 };169} more_complex_atttributes;170 171void more_complex_attributes() {172 more_complex_atttributes.a = true; // expected-warning{{writing variable 'a' requires holding mutex 'lock' exclusively}}173 more_complex_atttributes.b = true; // expected-warning{{writing variable 'b' requires holding mutex 'strct.lock' exclusively}}174 *more_complex_atttributes.ptr_a = true; // expected-warning{{writing the value pointed to by 'ptr_a' requires holding mutex 'lock' exclusively}}175 *more_complex_atttributes.ptr_b = true; // expected-warning{{writing the value pointed to by 'ptr_b' requires holding mutex 'strct.lock' exclusively}}176 177 more_complex_atttributes.lock.Lock();178 more_complex_atttributes.lock1.Lock(); // expected-warning{{mutex 'lock1' must be acquired before 'lock'}}179 more_complex_atttributes.lock1.Unlock();180 more_complex_atttributes.lock.Unlock();181 182 more_complex_atttributes.lock2.Lock();183 more_complex_atttributes.lock.Lock(); // expected-warning{{mutex 'lock' must be acquired before 'lock2'}}184 more_complex_atttributes.lock.Unlock();185 more_complex_atttributes.lock2.Unlock();186}187 188MutexWrapper sls_mw;189 190void sls_fun_0() {191 sls_mw.mu.Lock();192 sls_mw.x = 5;193 sls_mw.mu.Unlock();194}195 196void sls_fun_2() {197 sls_mu.Lock();198 int x = sls_guard_var;199 sls_mu.Unlock();200}201 202void sls_fun_3() {203 sls_mu.Lock();204 sls_guard_var = 2;205 sls_mu.Unlock();206}207 208void sls_fun_4() {209 sls_mu2.Lock();210 sls_guard_var = 2;211 sls_mu2.Unlock();212}213 214void sls_fun_5() {215 sls_mu.Lock();216 int x = sls_guardby_var;217 sls_mu.Unlock();218}219 220void sls_fun_6() {221 sls_mu.Lock();222 sls_guardby_var = 2;223 sls_mu.Unlock();224}225 226void sls_fun_7() {227 sls_mu.Lock();228 sls_mu2.Lock();229 sls_mu2.Unlock();230 sls_mu.Unlock();231}232 233void sls_fun_8() {234 sls_mu.Lock();235 if (getBool())236 sls_mu.Unlock();237 else238 sls_mu.Unlock();239}240 241void sls_fun_9() {242 if (getBool())243 sls_mu.Lock();244 else245 sls_mu.Lock();246 sls_mu.Unlock();247}248 249void sls_fun_good_6() {250 if (getBool()) {251 sls_mu.Lock();252 } else {253 if (getBool()) {254 getBool(); // EMPTY255 } else {256 getBool(); // EMPTY257 }258 sls_mu.Lock();259 }260 sls_mu.Unlock();261}262 263void sls_fun_good_7() {264 sls_mu.Lock();265 while (getBool()) {266 sls_mu.Unlock();267 if (getBool()) {268 if (getBool()) {269 sls_mu.Lock();270 continue;271 }272 }273 sls_mu.Lock();274 }275 sls_mu.Unlock();276}277 278void sls_fun_good_8() {279 sls_mw.MyLock();280 sls_mw.mu.Unlock();281}282 283void sls_fun_bad_1() {284 sls_mu.Unlock(); // \285 // expected-warning{{releasing mutex 'sls_mu' that was not held}}286}287 288void sls_fun_bad_2() {289 sls_mu.Lock(); // expected-note{{mutex acquired here}}290 sls_mu.Lock(); // \291 // expected-warning{{acquiring mutex 'sls_mu' that is already held}}292 sls_mu.Unlock();293}294 295void sls_fun_bad_3() {296 sls_mu.Lock(); // expected-note {{mutex acquired here}}297} // expected-warning{{mutex 'sls_mu' is still held at the end of function}}298 299void sls_fun_bad_4() {300 if (getBool())301 sls_mu.Lock(); // expected-note{{mutex acquired here}}302 else303 sls_mu2.Lock(); // expected-note{{mutex acquired here}}304} // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \305 // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}306 307void sls_fun_bad_5() {308 sls_mu.Lock(); // expected-note {{mutex acquired here}}309 if (getBool())310 sls_mu.Unlock();311} // expected-warning{{mutex 'sls_mu' is not held on every path through here}}312 313void sls_fun_bad_6() {314 if (getBool()) {315 sls_mu.Lock(); // expected-note {{mutex acquired here}}316 } else {317 if (getBool()) {318 getBool(); // EMPTY319 } else {320 getBool(); // EMPTY321 }322 }323 sls_mu.Unlock(); // \324 expected-warning{{mutex 'sls_mu' is not held on every path through here}}\325 expected-warning{{releasing mutex 'sls_mu' that was not held}}326}327 328void sls_fun_bad_7() {329 sls_mu.Lock();330 while (getBool()) { // \331 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}332 sls_mu.Unlock();333 if (getBool()) {334 if (getBool()) {335 continue;336 }337 }338 sls_mu.Lock(); // expected-note {{mutex acquired here}}339 }340 sls_mu.Unlock();341}342 343void sls_fun_bad_8() {344 sls_mu.Lock(); // expected-note{{mutex acquired here}}345 346 do {347 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}348 } while (getBool());349}350 351void sls_fun_bad_9() {352 do {353 sls_mu.Lock(); // \354 // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \355 // expected-note{{mutex acquired here}}356 } while (getBool());357 sls_mu.Unlock();358}359 360void sls_fun_bad_10() {361 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}362 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}363 sls_mu.Unlock();364 }365} // expected-warning{{mutex 'sls_mu' is still held at the end of function}}366 367void sls_fun_bad_11() {368 while (getBool()) { // \369 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}370 sls_mu.Lock(); // expected-note {{mutex acquired here}}371 }372 sls_mu.Unlock(); // \373 // expected-warning{{releasing mutex 'sls_mu' that was not held}}374}375 376void sls_fun_bad_12() {377 sls_mu.Lock(); // expected-note {{mutex acquired here}}378 while (getBool()) {379 sls_mu.Unlock();380 if (getBool()) {381 if (getBool()) {382 break;383 }384 }385 sls_mu.Lock();386 }387 sls_mu.Unlock(); // \388 expected-warning{{mutex 'sls_mu' is not held on every path through here}} \389 expected-warning{{releasing mutex 'sls_mu' that was not held}}390}391 392//-----------------------------------------//393// Handling lock expressions in attribute args394// -------------------------------------------//395 396Mutex aa_mu;397 398class GlobalLocker {399public:400 void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu);401 void globalUnlock() UNLOCK_FUNCTION(aa_mu);402};403 404GlobalLocker glock;405 406void aa_fun_1() {407 glock.globalLock();408 glock.globalUnlock();409}410 411void aa_fun_bad_1() {412 glock.globalUnlock(); // \413 // expected-warning{{releasing mutex 'aa_mu' that was not held}}414}415 416void aa_fun_bad_2() {417 glock.globalLock(); // expected-note{{mutex acquired here}}418 glock.globalLock(); // \419 // expected-warning{{acquiring mutex 'aa_mu' that is already held}}420 glock.globalUnlock();421}422 423void aa_fun_bad_3() {424 glock.globalLock(); // expected-note{{mutex acquired here}}425} // expected-warning{{mutex 'aa_mu' is still held at the end of function}}426 427//--------------------------------------------------//428// Regression tests for unusual method names429//--------------------------------------------------//430 431Mutex wmu;432 433// Test diagnostics for other method names.434class WeirdMethods {435 // FIXME: can't currently check inside constructors and destructors.436 WeirdMethods() {437 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}438 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}439 ~WeirdMethods() {440 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}441 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}442 void operator++() {443 wmu.Lock(); // expected-note {{mutex acquired here}}444 } // expected-warning {{mutex 'wmu' is still held at the end of function}}445 operator int*() {446 wmu.Lock(); // expected-note {{mutex acquired here}}447 return 0;448 } // expected-warning {{mutex 'wmu' is still held at the end of function}}449};450 451//-----------------------------------------------//452// Errors for guarded by or guarded var variables453// ----------------------------------------------//454 455int *pgb_gvar __attribute__((pt_guarded_var));456int *pgb_var __attribute__((pt_guarded_by(sls_mu)));457 458class PGBFoo {459 public:460 int x;461 int *pgb_field __attribute__((guarded_by(sls_mu2)))462 __attribute__((pt_guarded_by(sls_mu)));463 void testFoo() {464 pgb_field = &x; // \465 // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}466 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \467 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}468 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \469 // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}470 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \471 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}472 }473};474 475class GBFoo {476 public:477 int gb_field __attribute__((guarded_by(sls_mu)));478 479 void testFoo() {480 gb_field = 0; // \481 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}482 }483 484 void testNoAnal() NO_THREAD_SAFETY_ANALYSIS {485 gb_field = 0;486 }487};488 489GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));490 491void gb_fun_0() {492 sls_mu.Lock();493 int x = *pgb_var;494 sls_mu.Unlock();495}496 497void gb_fun_1() {498 sls_mu.Lock();499 *pgb_var = 2;500 sls_mu.Unlock();501}502 503void gb_fun_2() {504 int x;505 pgb_var = &x;506}507 508void gb_fun_3() {509 int *x = pgb_var;510}511 512void gb_bad_0() {513 sls_guard_var = 1; // \514 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}515}516 517void gb_bad_1() {518 int x = sls_guard_var; // \519 // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}520}521 522void gb_bad_2() {523 sls_guardby_var = 1; // \524 // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}525}526 527void gb_bad_3() {528 int x = sls_guardby_var; // \529 // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}530}531 532void gb_bad_4() {533 *pgb_gvar = 1; // \534 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}535}536 537void gb_bad_5() {538 int x = *pgb_gvar; // \539 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}540}541 542void gb_bad_6() {543 *pgb_var = 1; // \544 // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}545}546 547void gb_bad_7() {548 int x = *pgb_var; // \549 // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}550}551 552void gb_bad_8() {553 GBFoo G;554 G.gb_field = 0; // \555 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}556}557 558void gb_bad_9() {559 sls_guard_var++; // \560 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}561 sls_guard_var--; // \562 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}563 ++sls_guard_var; // \564 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}565 --sls_guard_var;// \566 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}567}568 569//-----------------------------------------------//570// Warnings on variables with late parsed attributes571// ----------------------------------------------//572 573class LateFoo {574public:575 int a __attribute__((guarded_by(mu)));576 int b;577 578 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { }579 580 void test() {581 a = 0; // \582 // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}583 b = a; // \584 // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}585 c = 0; // \586 // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}587 }588 589 int c __attribute__((guarded_by(mu)));590 591 Mutex mu;592};593 594class LateBar {595 public:596 int a_ __attribute__((guarded_by(mu1_)));597 int b_;598 int *q __attribute__((pt_guarded_by(mu)));599 Mutex mu1_;600 Mutex mu;601 LateFoo Foo;602 LateFoo Foo2;603 LateFoo *FooPointer;604};605 606LateBar b1, *b3;607 608void late_0() {609 LateFoo FooA;610 LateFoo FooB;611 FooA.mu.Lock();612 FooA.a = 5;613 FooA.mu.Unlock();614}615 616void late_1() {617 LateBar BarA;618 BarA.FooPointer->mu.Lock();619 BarA.FooPointer->a = 2;620 BarA.FooPointer->mu.Unlock();621}622 623void late_bad_0() {624 LateFoo fooA;625 LateFoo fooB;626 fooA.mu.Lock();627 fooB.a = 5; // \628 // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \629 // expected-note{{found near match 'fooA.mu'}}630 fooA.mu.Unlock();631}632 633void late_bad_1() {634 Mutex mu;635 mu.Lock();636 b1.mu1_.Lock();637 int res = b1.a_ + b3->b_;638 b3->b_ = *b1.q; // \639 // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}640 b1.mu1_.Unlock();641 b1.b_ = res;642 mu.Unlock();643}644 645void late_bad_2() {646 LateBar BarA;647 BarA.FooPointer->mu.Lock();648 BarA.Foo.a = 2; // \649 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \650 // expected-note{{found near match 'BarA.FooPointer->mu'}}651 BarA.FooPointer->mu.Unlock();652}653 654void late_bad_3() {655 LateBar BarA;656 BarA.Foo.mu.Lock();657 BarA.FooPointer->a = 2; // \658 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \659 // expected-note{{found near match 'BarA.Foo.mu'}}660 BarA.Foo.mu.Unlock();661}662 663void late_bad_4() {664 LateBar BarA;665 BarA.Foo.mu.Lock();666 BarA.Foo2.a = 2; // \667 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \668 // expected-note{{found near match 'BarA.Foo.mu'}}669 BarA.Foo.mu.Unlock();670}671 672//-----------------------------------------------//673// Extra warnings for shared vs. exclusive locks674// ----------------------------------------------//675 676void shared_fun_0() {677 sls_mu.Lock();678 do {679 sls_mu.Unlock();680 sls_mu.Lock();681 } while (getBool());682 sls_mu.Unlock();683}684 685void shared_fun_1() {686 sls_mu.ReaderLock(); // \687 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}688 do {689 sls_mu.Unlock();690 sls_mu.Lock(); // \691 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}692 } while (getBool());693 sls_mu.Unlock();694}695 696void shared_fun_3() {697 if (getBool())698 sls_mu.Lock();699 else700 sls_mu.Lock();701 *pgb_var = 1;702 sls_mu.Unlock();703}704 705void shared_fun_4() {706 if (getBool())707 sls_mu.ReaderLock();708 else709 sls_mu.ReaderLock();710 int x = sls_guardby_var;711 sls_mu.Unlock();712}713 714void shared_fun_8() {715 if (getBool())716 sls_mu.Lock(); // \717 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}718 else719 sls_mu.ReaderLock(); // \720 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}721 sls_mu.Unlock();722}723 724void shared_fun_9() {725 sls_mu.Lock();726 sls_mu.ExclusiveUnlock();727 728 sls_mu.ReaderLock();729 sls_mu.ReaderUnlock();730}731 732void shared_fun_10() {733 sls_mu.Lock();734 sls_mu.DemoteExclusive();735 sls_mu.ReaderUnlock();736}737 738void shared_fun_11() {739 sls_mu.ReaderLock();740 sls_mu.PromoteShared();741 sls_mu.Unlock();742}743 744void shared_bad_0() {745 sls_mu.Lock(); // \746 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}747 do {748 sls_mu.Unlock();749 sls_mu.ReaderLock(); // \750 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}751 } while (getBool());752 sls_mu.Unlock();753}754 755void shared_bad_1() {756 if (getBool())757 sls_mu.Lock(); // \758 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}759 else760 sls_mu.ReaderLock(); // \761 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}762 *pgb_var = 1;763 sls_mu.Unlock();764}765 766void shared_bad_2() {767 if (getBool())768 sls_mu.ReaderLock(); // \769 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}770 else771 sls_mu.Lock(); // \772 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}773 *pgb_var = 1;774 sls_mu.Unlock();775}776 777void shared_bad_3() {778 sls_mu.Lock(); // expected-note {{mutex acquired here}}779 sls_mu.ReaderUnlock(); // \780 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}781}782 783void shared_bad_4() {784 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}785 sls_mu.ExclusiveUnlock(); // \786 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}787}788 789void shared_bad_5() {790 sls_mu.Lock(); // expected-note {{mutex acquired here}}791 sls_mu.PromoteShared(); // \792 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}793 sls_mu.ExclusiveUnlock();794}795 796void shared_bad_6() {797 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}798 sls_mu.DemoteExclusive(); // \799 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}800 sls_mu.ReaderUnlock();801}802 803// FIXME: Add support for functions (not only methods)804class LRBar {805 public:806 void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);807 void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu);808 void le_fun() __attribute__((locks_excluded(sls_mu)));809};810 811class LRFoo {812 public:813 void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);814 void testShared() SHARED_LOCKS_REQUIRED(sls_mu2);815};816 817void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);818void elr_fun() {}819 820LRFoo MyLRFoo;821LRBar Bar;822 823void es_fun_0() {824 aa_mu.Lock();825 Bar.aa_elr_fun();826 aa_mu.Unlock();827}828 829void es_fun_1() {830 aa_mu.Lock();831 Bar.aa_elr_fun_s();832 aa_mu.Unlock();833}834 835void es_fun_2() {836 aa_mu.ReaderLock();837 Bar.aa_elr_fun_s();838 aa_mu.Unlock();839}840 841void es_fun_3() {842 sls_mu.Lock();843 MyLRFoo.test();844 sls_mu.Unlock();845}846 847void es_fun_4() {848 sls_mu2.Lock();849 MyLRFoo.testShared();850 sls_mu2.Unlock();851}852 853void es_fun_5() {854 sls_mu2.ReaderLock();855 MyLRFoo.testShared();856 sls_mu2.Unlock();857}858 859void es_fun_6() {860 Bar.le_fun();861}862 863void es_fun_7() {864 sls_mu.Lock();865 elr_fun();866 sls_mu.Unlock();867}868 869void es_fun_8() NO_THREAD_SAFETY_ANALYSIS;870 871void es_fun_8() {872 Bar.aa_elr_fun_s();873}874 875void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu);876void es_fun_9() {877 Bar.aa_elr_fun_s();878}879 880void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);881void es_fun_10() {882 Bar.aa_elr_fun_s();883}884 885void es_bad_0() {886 Bar.aa_elr_fun(); // \887 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}888}889 890void es_bad_1() {891 aa_mu.ReaderLock();892 Bar.aa_elr_fun(); // \893 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}894 aa_mu.Unlock();895}896 897void es_bad_2() {898 Bar.aa_elr_fun_s(); // \899 // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}900}901 902void es_bad_3() {903 MyLRFoo.test(); // \904 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}905}906 907void es_bad_4() {908 MyLRFoo.testShared(); // \909 // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}910}911 912void es_bad_5() {913 sls_mu.ReaderLock();914 MyLRFoo.test(); // \915 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}916 sls_mu.Unlock();917}918 919void es_bad_6() {920 sls_mu.Lock();921 Bar.le_fun(); // \922 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}923 sls_mu.Unlock();924}925 926void es_bad_7() {927 sls_mu.ReaderLock();928 Bar.le_fun(); // \929 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}930 sls_mu.Unlock();931}932 933 934//-----------------------------------------------//935// Unparseable lock expressions936// ----------------------------------------------//937 938// FIXME -- derive new tests for unhandled expressions939 940 941//----------------------------------------------------------------------------//942// The following test cases are ported from the gcc thread safety implementation943// They are each wrapped inside a namespace with the test number of the gcc test944//945// FIXME: add all the gcc tests, once this analysis passes them.946//----------------------------------------------------------------------------//947 948//-----------------------------------------//949// Good testcases (no errors)950//-----------------------------------------//951 952namespace thread_annot_lock_20 {953class Bar {954 public:955 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);956 static int b_ GUARDED_BY(mu1_);957 static Mutex mu1_;958 static int a_ GUARDED_BY(mu1_);959};960 961Bar b1;962 963int Bar::func1()964{965 int res = 5;966 967 if (a_ == 4)968 res = b_;969 return res;970}971} // end namespace thread_annot_lock_20972 973namespace thread_annot_lock_22 {974// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially975// uses in class definitions.976Mutex mu;977 978class Bar {979 public:980 int a_ GUARDED_BY(mu1_);981 int b_;982 int *q PT_GUARDED_BY(mu);983 Mutex mu1_ ACQUIRED_AFTER(mu);984};985 986Bar b1, *b3;987int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);988int res GUARDED_BY(mu) = 5;989 990int func(int i)991{992 int x;993 mu.Lock();994 b1.mu1_.Lock();995 res = b1.a_ + b3->b_;996 *p = i;997 b1.a_ = res + b3->b_;998 b3->b_ = *b1.q;999 b1.mu1_.Unlock();1000 b1.b_ = res;1001 x = res;1002 mu.Unlock();1003 return x;1004}1005} // end namespace thread_annot_lock_221006 1007namespace thread_annot_lock_27_modified {1008// test lock annotations applied to function definitions1009// Modified: applied annotations only to function declarations1010Mutex mu1;1011Mutex mu2 ACQUIRED_AFTER(mu1);1012 1013class Foo {1014 public:1015 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);1016};1017 1018int Foo::method1(int i) {1019 return i;1020}1021 1022 1023int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);1024int foo(int i) {1025 return i;1026}1027 1028static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);1029static int bar(int i) {1030 return i;1031}1032 1033void main() {1034 Foo a;1035 1036 mu1.Lock();1037 mu2.Lock();1038 a.method1(1);1039 foo(2);1040 mu2.Unlock();1041 bar(3);1042 mu1.Unlock();1043}1044} // end namespace thread_annot_lock_27_modified1045 1046 1047namespace thread_annot_lock_38 {1048// Test the case where a template member function is annotated with lock1049// attributes in a non-template class.1050class Foo {1051 public:1052 void func1(int y) LOCKS_EXCLUDED(mu_);1053 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);1054 private:1055 Mutex mu_;1056};1057 1058Foo *foo;1059 1060void main()1061{1062 foo->func1(5);1063 foo->func2(5);1064}1065} // end namespace thread_annot_lock_381066 1067namespace thread_annot_lock_43 {1068// Tests lock canonicalization1069class Foo {1070 public:1071 Mutex *mu_;1072};1073 1074class FooBar {1075 public:1076 Foo *foo_;1077 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }1078 int a_ GUARDED_BY(foo_->mu_);1079};1080 1081FooBar *fb;1082 1083void main()1084{1085 int x;1086 fb->foo_->mu_->Lock();1087 x = fb->GetA();1088 fb->foo_->mu_->Unlock();1089}1090} // end namespace thread_annot_lock_431091 1092namespace thread_annot_lock_49 {1093// Test the support for use of lock expression in the annotations1094class Foo {1095 public:1096 Mutex foo_mu_;1097};1098 1099class Bar {1100 private:1101 Foo *foo;1102 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);1103 1104 public:1105 void Test1() {1106 foo->foo_mu_.Lock();1107 bar_mu_.Lock();1108 bar_mu_.Unlock();1109 foo->foo_mu_.Unlock();1110 }1111};1112 1113void main() {1114 Bar bar;1115 bar.Test1();1116}1117} // end namespace thread_annot_lock_491118 1119namespace thread_annot_lock_61_modified {1120 // Modified to fix the compiler errors1121 // Test the fix for a bug introduced by the support of pass-by-reference1122 // parameters.1123 struct Foo { Foo &operator<< (bool) {return *this;} };1124 Foo &getFoo();1125 struct Bar { Foo &func () {return getFoo();} };1126 struct Bas { void operator& (Foo &) {} };1127 void mumble()1128 {1129 Bas() & Bar().func() << "" << "";1130 Bas() & Bar().func() << "";1131 }1132} // end namespace thread_annot_lock_61_modified1133 1134 1135namespace thread_annot_lock_65 {1136// Test the fix for a bug in the support of allowing reader locks for1137// non-const, non-modifying overload functions. (We didn't handle the builtin1138// properly.)1139enum MyFlags {1140 Zero,1141 One,1142 Two,1143 Three,1144 Four,1145 Five,1146 Six,1147 Seven,1148 Eight,1149 Nine1150};1151 1152inline MyFlags1153operator|(MyFlags a, MyFlags b)1154{1155 return MyFlags(static_cast<int>(a) | static_cast<int>(b));1156}1157 1158inline MyFlags&1159operator|=(MyFlags& a, MyFlags b)1160{1161 return a = a | b;1162}1163} // end namespace thread_annot_lock_651164 1165namespace thread_annot_lock_66_modified {1166// Modified: Moved annotation to function defn1167// Test annotations on out-of-line definitions of member functions where the1168// annotations refer to locks that are also data members in the class.1169Mutex mu;1170 1171class Foo {1172 public:1173 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);1174 int data GUARDED_BY(mu1);1175 Mutex *mu1;1176 Mutex *mu2;1177};1178 1179int Foo::method1(int i)1180{1181 return data + i;1182}1183 1184void main()1185{1186 Foo a;1187 1188 a.mu2->Lock();1189 a.mu1->Lock();1190 mu.Lock();1191 a.method1(1);1192 mu.Unlock();1193 a.mu1->Unlock();1194 a.mu2->Unlock();1195}1196} // end namespace thread_annot_lock_66_modified1197 1198namespace thread_annot_lock_68_modified {1199// Test a fix to a bug in the delayed name binding with nested template1200// instantiation. We use a stack to make sure a name is not resolved to an1201// inner context.1202template <typename T>1203class Bar {1204 Mutex mu_;1205};1206 1207template <typename T>1208class Foo {1209 public:1210 void func(T x) {1211 mu_.Lock();1212 count_ = x;1213 mu_.Unlock();1214 }1215 1216 private:1217 T count_ GUARDED_BY(mu_);1218 Bar<T> bar_;1219 Mutex mu_;1220};1221 1222void main()1223{1224 Foo<int> *foo;1225 foo->func(5);1226}1227} // end namespace thread_annot_lock_68_modified1228 1229namespace thread_annot_lock_30_modified {1230// Test delay parsing of lock attribute arguments with nested classes.1231// Modified: trylocks replaced with exclusive_lock_fun1232int a = 0;1233 1234class Bar {1235 struct Foo;1236 1237 public:1238 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);1239 1240 int func() {1241 MyLock();1242// if (foo == 0) {1243// return 0;1244// }1245 a = 5;1246 mu.Unlock();1247 return 1;1248 }1249 1250 class FooBar {1251 int x;1252 int y;1253 };1254 1255 private:1256 Mutex mu;1257};1258 1259Bar *bar;1260 1261void main()1262{1263 bar->func();1264}1265} // end namespace thread_annot_lock_30_modified1266 1267namespace thread_annot_lock_47 {1268// Test the support for annotations on virtual functions.1269// This is a good test case. (i.e. There should be no warning emitted by the1270// compiler.)1271class Base {1272 public:1273 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);1274 virtual void func2() LOCKS_EXCLUDED(mu_);1275 Mutex mu_;1276};1277 1278class Child : public Base {1279 public:1280 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);1281 virtual void func2() LOCKS_EXCLUDED(mu_);1282};1283 1284void main() {1285 Child *c;1286 Base *b = c;1287 1288 b->mu_.Lock();1289 b->func1();1290 b->mu_.Unlock();1291 b->func2();1292 1293 c->mu_.Lock();1294 c->func1();1295 c->mu_.Unlock();1296 c->func2();1297}1298} // end namespace thread_annot_lock_471299 1300//-----------------------------------------//1301// Tests which produce errors1302//-----------------------------------------//1303 1304namespace thread_annot_lock_13 {1305Mutex mu1;1306Mutex mu2;1307 1308int g GUARDED_BY(mu1);1309int w GUARDED_BY(mu2);1310 1311class Foo {1312 public:1313 void bar() LOCKS_EXCLUDED(mu_, mu1);1314 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);1315 1316 private:1317 int a_ GUARDED_BY(mu_);1318 public:1319 Mutex mu_ ACQUIRED_AFTER(mu1);1320};1321 1322int Foo::foo()1323{1324 int res;1325 w = 5;1326 res = a_ + 5;1327 return res;1328}1329 1330void Foo::bar()1331{1332 int x;1333 mu_.Lock();1334 x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}1335 a_ = x + 1;1336 mu_.Unlock();1337 if (x > 5) {1338 mu1.Lock();1339 g = 2;1340 mu1.Unlock();1341 }1342}1343 1344void main()1345{1346 Foo f1, *f2;1347 f1.mu_.Lock();1348 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}1349 mu2.Lock();1350 f1.foo();1351 mu2.Unlock();1352 f1.mu_.Unlock();1353 f2->mu_.Lock();1354 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}1355 f2->mu_.Unlock();1356 mu2.Lock();1357 w = 2;1358 mu2.Unlock();1359}1360} // end namespace thread_annot_lock_131361 1362namespace thread_annot_lock_18_modified {1363// Modified: Trylocks removed1364// Test the ability to distnguish between the same lock field of1365// different objects of a class.1366 class Bar {1367 public:1368 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);1369 void MyUnlock() UNLOCK_FUNCTION(mu1_);1370 int a_ GUARDED_BY(mu1_);1371 1372 private:1373 Mutex mu1_;1374};1375 1376Bar *b1, *b2;1377 1378void func()1379{1380 b1->MyLock();1381 b1->a_ = 5;1382 b2->a_ = 3; // \1383 // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \1384 // expected-note {{found near match 'b1->mu1_'}}1385 b2->MyLock();1386 b2->MyUnlock();1387 b1->MyUnlock();1388}1389} // end namespace thread_annot_lock_18_modified1390 1391namespace thread_annot_lock_21 {1392// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially1393// uses in class definitions.1394Mutex mu;1395 1396class Bar {1397 public:1398 int a_ GUARDED_BY(mu1_);1399 int b_;1400 int *q PT_GUARDED_BY(mu);1401 Mutex mu1_ ACQUIRED_AFTER(mu);1402};1403 1404Bar b1, *b3;1405int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);1406 1407int res GUARDED_BY(mu) = 5;1408 1409int func(int i)1410{1411 int x;1412 b3->mu1_.Lock();1413 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \1414 // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \1415 // expected-note {{found near match 'b3->mu1_'}}1416 *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \1417 // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}1418 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \1419 // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \1420 // expected-note {{found near match 'b3->mu1_'}}1421 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}1422 b3->mu1_.Unlock();1423 b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}1424 x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}1425 return x;1426}1427} // end namespace thread_annot_lock_211428 1429namespace thread_annot_lock_35_modified {1430// Test the analyzer's ability to distinguish the lock field of different1431// objects.1432class Foo {1433 private:1434 Mutex lock_;1435 int a_ GUARDED_BY(lock_);1436 1437 public:1438 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {1439 Foo *new_foo = new Foo;1440 1441 lock_.Lock();1442 1443 child->Func(new_foo); // There shouldn't be any warning here as the1444 // acquired lock is not in child.1445 child->bar(7); // \1446 // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \1447 // expected-note {{found near match 'lock_'}}1448 child->a_ = 5; // \1449 // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \1450 // expected-note {{found near match 'lock_'}}1451 lock_.Unlock();1452 }1453 1454 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {1455 a_ = y;1456 }1457};1458 1459Foo *x;1460 1461void main() {1462 Foo *child = new Foo;1463 x->Func(child);1464}1465} // end namespace thread_annot_lock_35_modified1466 1467namespace thread_annot_lock_36_modified {1468// Modified to move the annotations to function defns.1469// Test the analyzer's ability to distinguish the lock field of different1470// objects1471class Foo {1472 private:1473 Mutex lock_;1474 int a_ GUARDED_BY(lock_);1475 1476 public:1477 void Func(Foo* child) LOCKS_EXCLUDED(lock_);1478 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);1479};1480 1481void Foo::Func(Foo* child) {1482 Foo *new_foo = new Foo;1483 1484 lock_.Lock();1485 1486 child->lock_.Lock();1487 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}1488 child->bar(7);1489 child->a_ = 5;1490 child->lock_.Unlock();1491 1492 lock_.Unlock();1493}1494 1495void Foo::bar(int y) {1496 a_ = y;1497}1498 1499 1500Foo *x;1501 1502void main() {1503 Foo *child = new Foo;1504 x->Func(child);1505}1506} // end namespace thread_annot_lock_36_modified1507 1508 1509namespace thread_annot_lock_42 {1510// Test support of multiple lock attributes of the same kind on a decl.1511class Foo {1512 private:1513 Mutex mu1, mu2, mu3;1514 int x GUARDED_BY(mu1) GUARDED_BY(mu2);1515 int y GUARDED_BY(mu2);1516 1517 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {1518 mu2.Lock();1519 y = 2;1520 mu2.Unlock();1521 }1522 1523 public:1524 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {1525 x = 5;1526 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \1527 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}1528 }1529};1530 1531Foo *foo;1532 1533void func()1534{1535 foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \1536 // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}1537}1538} // end namespace thread_annot_lock_421539 1540namespace thread_annot_lock_46 {1541// Test the support for annotations on virtual functions.1542class Base {1543 public:1544 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);1545 virtual void func2() LOCKS_EXCLUDED(mu_);1546 Mutex mu_;1547};1548 1549class Child : public Base {1550 public:1551 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);1552 virtual void func2() LOCKS_EXCLUDED(mu_);1553};1554 1555void main() {1556 Child *c;1557 Base *b = c;1558 1559 b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}1560 b->mu_.Lock();1561 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}1562 b->mu_.Unlock();1563 1564 c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}1565 c->mu_.Lock();1566 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}1567 c->mu_.Unlock();1568}1569} // end namespace thread_annot_lock_461570 1571namespace thread_annot_lock_67_modified {1572// Modified: attributes on definitions moved to declarations1573// Test annotations on out-of-line definitions of member functions where the1574// annotations refer to locks that are also data members in the class.1575Mutex mu;1576Mutex mu3;1577 1578class Foo {1579 public:1580 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);1581 int data GUARDED_BY(mu1);1582 Mutex *mu1;1583 Mutex *mu2;1584};1585 1586int Foo::method1(int i) {1587 return data + i;1588}1589 1590void main()1591{1592 Foo a;1593 a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \1594 // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \1595 // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \1596 // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}1597}1598} // end namespace thread_annot_lock_67_modified1599 1600 1601namespace substitution_test {1602 class MyData {1603 public:1604 Mutex mu;1605 1606 void lockData() EXCLUSIVE_LOCK_FUNCTION(mu);1607 void unlockData() UNLOCK_FUNCTION(mu);1608 1609 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { }1610 void operator()() EXCLUSIVE_LOCKS_REQUIRED(mu) { }1611 1612 MyData operator+(const MyData& other) const SHARED_LOCKS_REQUIRED(mu, other.mu);1613 };1614 1615 MyData operator-(const MyData& a, const MyData& b) SHARED_LOCKS_REQUIRED(a.mu, b.mu);1616 1617 class DataLocker {1618 public:1619 void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu);1620 void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu);1621 };1622 1623 1624 class Foo {1625 public:1626 void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { }1627 1628 void subst(MyData& d) {1629 d.doSomething(); // expected-warning {{calling function 'doSomething' requires holding mutex 'd.mu' exclusively}}1630 d(); // expected-warning {{calling function 'operator()' requires holding mutex 'd.mu' exclusively}}1631 d.operator()(); // expected-warning {{calling function 'operator()' requires holding mutex 'd.mu' exclusively}}1632 1633 d.lockData();1634 d.doSomething();1635 d();1636 d.operator()();1637 d.unlockData();1638 }1639 1640 void binop(MyData& a, MyData& b) EXCLUSIVE_LOCKS_REQUIRED(a.mu) {1641 a + b; // expected-warning {{calling function 'operator+' requires holding mutex 'b.mu'}}1642 // expected-note@-1 {{found near match 'a.mu'}}1643 b + a; // expected-warning {{calling function 'operator+' requires holding mutex 'b.mu'}}1644 // expected-note@-1 {{found near match 'a.mu'}}1645 a - b; // expected-warning {{calling function 'operator-' requires holding mutex 'b.mu'}}1646 // expected-note@-1 {{found near match 'a.mu'}}1647 }1648 1649 void bar1(MyData* d) {1650 d->lockData();1651 foo(d);1652 d->unlockData();1653 }1654 1655 void bar2(MyData* d) {1656 DataLocker dlr;1657 dlr.lockData(d);1658 foo(d);1659 dlr.unlockData(d);1660 }1661 1662 void bar3(MyData* d1, MyData* d2) {1663 DataLocker dlr;1664 dlr.lockData(d1); // expected-note {{mutex acquired here}}1665 dlr.unlockData(d2); // \1666 // expected-warning {{releasing mutex 'd2->mu' that was not held}}1667 } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}1668 1669 void bar4(MyData* d1, MyData* d2) {1670 DataLocker dlr;1671 dlr.lockData(d1);1672 foo(d2); // \1673 // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \1674 // expected-note {{found near match 'd1->mu'}}1675 dlr.unlockData(d1);1676 }1677 };1678 1679 // Automatic object destructor calls don't appear as expressions in the CFG,1680 // so we have to handle them separately whenever substitutions are required.1681 struct DestructorRequires {1682 Mutex mu;1683 ~DestructorRequires() EXCLUSIVE_LOCKS_REQUIRED(mu);1684 };1685 1686 void destructorRequires() {1687 DestructorRequires rd;1688 rd.mu.AssertHeld();1689 }1690 1691 struct DestructorExcludes {1692 Mutex mu;1693 ~DestructorExcludes() LOCKS_EXCLUDED(mu);1694 };1695 1696 void destructorExcludes() {1697 DestructorExcludes ed;1698 ed.mu.Lock(); // expected-note {{mutex acquired here}}1699 } // expected-warning {{cannot call function '~DestructorExcludes' while mutex 'ed.mu' is held}}1700 // expected-warning@-1 {{mutex 'ed.mu' is still held at the end of function}}1701 1702} // end namespace substituation_test1703 1704 1705 1706namespace constructor_destructor_tests {1707 Mutex fooMu;1708 int myVar GUARDED_BY(fooMu);1709 1710 class Foo {1711 public:1712 Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { }1713 ~Foo() UNLOCK_FUNCTION(fooMu) { }1714 };1715 1716 void fooTest() {1717 Foo foo;1718 myVar = 0;1719 }1720}1721 1722 1723namespace template_member_test {1724 1725 struct S { int n; };1726 struct T {1727 Mutex m;1728 S *s GUARDED_BY(this->m);1729 };1730 Mutex m;1731 struct U {1732 union {1733 int n;1734 };1735 } *u GUARDED_BY(m);1736 1737 template<typename U>1738 struct IndirectLock {1739 int DoNaughtyThings(T *t) {1740 u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}1741 return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}1742 }1743 };1744 1745 template struct IndirectLock<int>; // expected-note {{here}}1746 1747 struct V {1748 void f(int);1749 void f(double);1750 1751 Mutex m;1752 V *p GUARDED_BY(this->m);1753 };1754 template<typename U> struct W {1755 V v;1756 void f(U u) {1757 v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}1758 }1759 };1760 template struct W<int>; // expected-note {{here}}1761 1762}1763 1764namespace test_scoped_lockable {1765 1766struct TestScopedLockable {1767 Mutex mu1;1768 Mutex mu2;1769 int a __attribute__((guarded_by(mu1)));1770 int b __attribute__((guarded_by(mu2)));1771 1772 bool getBool();1773 1774 bool lock2Bool(MutexLock);1775 1776 void foo1() {1777 MutexLock mulock(&mu1);1778 a = 5;1779 }1780 1781#ifdef __cpp_guaranteed_copy_elision1782 void const_lock() {1783 const MutexLock mulock = MutexLock(&mu1);1784 a = 5;1785 }1786#endif1787 1788 void temporary() {1789 MutexLock{&mu1}, a = 5;1790 }1791 1792 void temporary_cfg(int x) {1793 // test the case where a pair of temporary Ctor and Dtor is in different CFG blocks1794 lock2Bool(MutexLock{&mu1}) || x;1795 MutexLock{&mu1}; // no-warn1796 }1797 1798 void lifetime_extension() {1799 const MutexLock &mulock = MutexLock(&mu1);1800 a = 5;1801 }1802 1803 void foo2() {1804 ReaderMutexLock mulock1(&mu1);1805 if (getBool()) {1806 MutexLock mulock2a(&mu2);1807 b = a + 1;1808 }1809 else {1810 MutexLock mulock2b(&mu2);1811 b = a + 2;1812 }1813 }1814 1815 void foo3() {1816 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}1817 MutexLock mulock_b(&mu1); // \1818 // expected-warning {{acquiring mutex 'mu1' that is already held}}1819 }1820 1821 void temporary_double_lock() {1822 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}1823 MutexLock{&mu1}; // \1824 // expected-warning {{acquiring mutex 'mu1' that is already held}}1825 }1826 1827 void foo4() {1828 MutexLock mulock1(&mu1), mulock2(&mu2);1829 a = b+1;1830 b = a+1;1831 }1832 1833 void foo5() {1834 DoubleMutexLock mulock(&mu1, &mu2);1835 a = b + 1;1836 b = a + 1;1837 }1838 1839 void foo6() {1840 TemplateMutexLock<Mutex> mulock1(&mu1), mulock2(&mu2);1841 a = b + 1;1842 b = a + 1;1843 }1844 1845 void foo7() {1846 VariadicMutexLock<Mutex, Mutex> mulock(&mu1, &mu2);1847 a = b + 1;1848 b = a + 1;1849 }1850};1851 1852} // end namespace test_scoped_lockable1853 1854 1855namespace FunctionAttrTest {1856 1857class Foo {1858public:1859 Mutex mu_;1860 int a GUARDED_BY(mu_);1861};1862 1863Foo fooObj;1864 1865void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);1866 1867void bar() {1868 foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}1869 fooObj.mu_.Lock();1870 foo();1871 fooObj.mu_.Unlock();1872}1873 1874}; // end namespace FunctionAttrTest1875 1876 1877namespace TryLockTest {1878 1879struct TestTryLock {1880 Mutex mu;1881 int a GUARDED_BY(mu);1882 bool cond;1883 1884 void foo1() {1885 if (mu.TryLock()) {1886 a = 1;1887 mu.Unlock();1888 }1889 }1890 1891 void foo2() {1892 if (!mu.TryLock()) return;1893 a = 2;1894 mu.Unlock();1895 }1896 1897 void foo2_builtin_expect() {1898 if (__builtin_expect(!mu.TryLock(), false))1899 return;1900 a = 2;1901 mu.Unlock();1902 }1903 1904 void foo3() {1905 bool b = mu.TryLock();1906 if (b) {1907 a = 3;1908 mu.Unlock();1909 }1910 }1911 1912 void foo3_builtin_expect() {1913 bool b = mu.TryLock();1914 if (__builtin_expect(b, true)) {1915 a = 3;1916 mu.Unlock();1917 }1918 }1919 1920 void foo4() {1921 bool b = mu.TryLock();1922 if (!b) return;1923 a = 4;1924 mu.Unlock();1925 }1926 1927 void foo5() {1928 while (mu.TryLock()) {1929 a = a + 1;1930 mu.Unlock();1931 }1932 }1933 1934 void foo6() {1935 bool b = mu.TryLock();1936 b = !b;1937 if (b) return;1938 a = 6;1939 mu.Unlock();1940 }1941 1942 void foo7() {1943 bool b1 = mu.TryLock();1944 bool b2 = !b1;1945 bool b3 = !b2;1946 if (b3) {1947 a = 7;1948 mu.Unlock();1949 }1950 }1951 1952 // Test use-def chains: join points1953 void foo8() {1954 bool b = mu.TryLock();1955 bool b2 = b;1956 if (cond)1957 b = true;1958 if (b) { // b should be unknown at this point, because of the join point1959 a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}1960 }1961 if (b2) { // b2 should be known at this point.1962 a = 8;1963 mu.Unlock();1964 }1965 }1966 1967 // Test use-def-chains: back edges1968 void foo9() {1969 bool b = mu.TryLock();1970 1971 for (int i = 0; i < 10; ++i);1972 1973 if (b) { // b is still known, because the loop doesn't alter it1974 a = 9;1975 mu.Unlock();1976 }1977 }1978 1979 // Test use-def chains: back edges1980 void foo10() {1981 bool b = mu.TryLock();1982 1983 while (cond) {1984 if (b) { // b should be unknown at this point b/c of the loop1985 a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}1986 }1987 b = !b;1988 }1989 }1990 1991 // Test merge of exclusive trylock1992 void foo11() {1993 if (cond) {1994 if (!mu.TryLock())1995 return;1996 }1997 else {1998 mu.Lock();1999 }2000 a = 10;2001 mu.Unlock();2002 }2003 2004 // Test merge of shared trylock2005 void foo12() {2006 if (cond) {2007 if (!mu.ReaderTryLock())2008 return;2009 }2010 else {2011 mu.ReaderLock();2012 }2013 int i = a;2014 mu.Unlock();2015 }2016 2017 // Test with conditional operator2018 void foo13() {2019 if (mu.TryLock() ? 1 : 0)2020 mu.Unlock();2021 }2022 2023 void foo14() {2024 if (mu.TryLock() ? 0 : 1)2025 return;2026 mu.Unlock();2027 }2028 2029 void foo15() {2030 if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}2031 mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}2032 } // expected-warning{{mutex 'mu' is not held on every path through here}}2033}; // end TestTrylock2034 2035} // end namespace TrylockTest2036 2037 2038namespace TestTemplateAttributeInstantiation {2039 2040class Foo1 {2041public:2042 Mutex mu_;2043 int a GUARDED_BY(mu_);2044};2045 2046class Foo2 {2047public:2048 int a GUARDED_BY(mu_);2049 Mutex mu_;2050};2051 2052 2053class Bar {2054public:2055 // Test non-dependent expressions in attributes on template functions2056 template <class T>2057 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {2058 foo->a = 0;2059 }2060 2061 // Test dependent expressions in attributes on template functions2062 template <class T>2063 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {2064 fooT->a = 0;2065 }2066};2067 2068 2069template <class T>2070class BarT {2071public:2072 Foo1 fooBase;2073 T fooBaseT;2074 2075 // Test non-dependent expression in ordinary method on template class2076 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {2077 fooBase.a = 0;2078 }2079 2080 // Test dependent expressions in ordinary methods on template class2081 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {2082 fooBaseT.a = 0;2083 }2084 2085 // Test dependent expressions in template method in template class2086 template <class T2>2087 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {2088 fooBaseT.a = 0;2089 fooT->a = 0;2090 }2091};2092 2093template <class T>2094class Cell {2095public:2096 Mutex mu_;2097 // Test dependent guarded_by2098 T data GUARDED_BY(mu_);2099 2100 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {2101 data = 0;2102 }2103 2104 void foo() {2105 mu_.Lock();2106 data = 0;2107 mu_.Unlock();2108 }2109};2110 2111void test() {2112 Bar b;2113 BarT<Foo2> bt;2114 Foo1 f1;2115 Foo2 f2;2116 2117 f1.mu_.Lock();2118 f2.mu_.Lock();2119 bt.fooBase.mu_.Lock();2120 bt.fooBaseT.mu_.Lock();2121 2122 b.barND(&f1, &f2);2123 b.barD(&f1, &f2);2124 bt.barND();2125 bt.barD();2126 bt.barTD(&f2);2127 2128 f1.mu_.Unlock();2129 bt.barTD(&f1); // \2130 // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \2131 // expected-note {{found near match 'bt.fooBase.mu_'}}2132 2133 bt.fooBase.mu_.Unlock();2134 bt.fooBaseT.mu_.Unlock();2135 f2.mu_.Unlock();2136 2137 Cell<int> cell;2138 cell.data = 0; // \2139 // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}2140 cell.foo();2141 cell.mu_.Lock();2142 cell.fooEx();2143 cell.mu_.Unlock();2144}2145 2146 2147template <class T>2148class CellDelayed {2149public:2150 // Test dependent guarded_by2151 T data GUARDED_BY(mu_);2152 static T static_data GUARDED_BY(static_mu_);2153 2154 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {2155 this->data = other->data;2156 }2157 2158 template <class T2>2159 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {2160 this->data = otherT->data;2161 }2162 2163 void foo() {2164 mu_.Lock();2165 data = 0;2166 mu_.Unlock();2167 }2168 2169 Mutex mu_;2170 static Mutex static_mu_;2171};2172 2173void testDelayed() {2174 CellDelayed<int> celld;2175 CellDelayed<int> celld2;2176 celld.foo();2177 celld.mu_.Lock();2178 celld2.mu_.Lock();2179 2180 celld.fooEx(&celld2);2181 celld.fooExT(&celld2);2182 2183 celld2.mu_.Unlock();2184 celld.mu_.Unlock();2185}2186 2187}; // end namespace TestTemplateAttributeInstantiation2188 2189 2190namespace FunctionDeclDefTest {2191 2192class Foo {2193public:2194 Mutex mu_;2195 int a GUARDED_BY(mu_);2196 2197 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);2198};2199 2200// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_2201void Foo::foo1(Foo *f_defined) {2202 f_defined->a = 0;2203};2204 2205void test() {2206 Foo myfoo;2207 myfoo.foo1(&myfoo); // \2208 // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}2209 myfoo.mu_.Lock();2210 myfoo.foo1(&myfoo);2211 myfoo.mu_.Unlock();2212}2213 2214};2215 2216namespace GoingNative {2217 2218 struct LOCKABLE mutex {2219 void lock() EXCLUSIVE_LOCK_FUNCTION();2220 void unlock() UNLOCK_FUNCTION();2221 // ...2222 };2223 bool foo();2224 bool bar();2225 mutex m;2226 void test() {2227 m.lock();2228 while (foo()) { // expected-warning {{expecting mutex 'm' to be held at start of each loop}}2229 m.unlock();2230 // ...2231 if (bar()) {2232 // ...2233 if (foo())2234 continue;2235 //...2236 }2237 // ...2238 m.lock(); // expected-note {{mutex acquired here}}2239 }2240 m.unlock();2241 }2242 2243}2244 2245 2246 2247namespace FunctionDefinitionTest {2248 2249class Foo {2250public:2251 void foo1();2252 void foo2();2253 void foo3(Foo *other);2254 2255 template<class T>2256 void fooT1(const T& dummy1);2257 2258 template<class T>2259 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);2260 2261 Mutex mu_;2262 int a GUARDED_BY(mu_);2263};2264 2265template<class T>2266class FooT {2267public:2268 void foo();2269 2270 Mutex mu_;2271 T a GUARDED_BY(mu_);2272};2273 2274 2275void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {2276 a = 1;2277}2278 2279void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {2280 a = 2;2281}2282 2283void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {2284 other->a = 3;2285}2286 2287template<class T>2288void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {2289 a = dummy1;2290}2291 2292/* TODO -- uncomment with template instantiation of attributes.2293template<class T>2294void Foo::fooT2(const T& dummy2) {2295 a = dummy2;2296}2297*/2298 2299void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {2300 f->a = 1;2301}2302 2303void fooF2(Foo *f);2304void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {2305 f->a = 2;2306}2307 2308void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);2309void fooF3(Foo *f) {2310 f->a = 3;2311}2312 2313template<class T>2314void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {2315 a = 0;2316}2317 2318void test() {2319 int dummy = 0;2320 Foo myFoo;2321 2322 myFoo.foo2(); // \2323 // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}2324 myFoo.foo3(&myFoo); // \2325 // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}2326 myFoo.fooT1(dummy); // \2327 // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}2328 2329 myFoo.fooT2(dummy); // \2330 // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}2331 2332 fooF1(&myFoo); // \2333 // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}2334 fooF2(&myFoo); // \2335 // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}2336 fooF3(&myFoo); // \2337 // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}2338 2339 myFoo.mu_.Lock();2340 myFoo.foo2();2341 myFoo.foo3(&myFoo);2342 myFoo.fooT1(dummy);2343 2344 myFoo.fooT2(dummy);2345 2346 fooF1(&myFoo);2347 fooF2(&myFoo);2348 fooF3(&myFoo);2349 myFoo.mu_.Unlock();2350 2351 FooT<int> myFooT;2352 myFooT.foo(); // \2353 // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}2354}2355 2356} // end namespace FunctionDefinitionTest2357 2358 2359namespace SelfLockingTest {2360 2361class LOCKABLE MyLock {2362public:2363 int foo GUARDED_BY(this);2364 2365 void lock() EXCLUSIVE_LOCK_FUNCTION();2366 void unlock() UNLOCK_FUNCTION();2367 2368 void doSomething() {2369 this->lock(); // allow 'this' as a lock expression2370 foo = 0;2371 doSomethingElse();2372 this->unlock();2373 }2374 2375 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {2376 foo = 1;2377 };2378 2379 void test() {2380 foo = 2; // \2381 // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}2382 }2383};2384 2385 2386class LOCKABLE MyLock2 {2387public:2388 Mutex mu_;2389 int foo GUARDED_BY(this);2390 2391 // don't check inside lock and unlock functions2392 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }2393 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }2394 2395 // don't check inside constructors and destructors2396 MyLock2() { foo = 1; }2397 ~MyLock2() { foo = 0; }2398};2399 2400 2401} // end namespace SelfLockingTest2402 2403 2404namespace InvalidNonstatic {2405 2406// Forward decl here causes bogus "invalid use of non-static data member"2407// on reference to mutex_ in guarded_by attribute.2408class Foo;2409 2410class Foo {2411 Mutex* mutex_;2412 2413 int foo __attribute__((guarded_by(mutex_)));2414};2415 2416} // end namespace InvalidNonStatic2417 2418 2419namespace NoReturnTest {2420 2421bool condition();2422void fatal() __attribute__((noreturn));2423 2424Mutex mu_;2425 2426void test1() {2427 MutexLock lock(&mu_);2428 if (condition()) {2429 fatal();2430 return;2431 }2432}2433 2434} // end namespace NoReturnTest2435 2436 2437namespace TestMultiDecl {2438 2439class Foo {2440public:2441 int GUARDED_BY(mu_) a;2442 int GUARDED_BY(mu_) b, c;2443 2444 void foo() {2445 a = 0; // \2446 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}2447 b = 0; // \2448 // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}2449 c = 0; // \2450 // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}2451 }2452 2453private:2454 Mutex mu_;2455};2456 2457} // end namespace TestMultiDecl2458 2459 2460namespace WarnNoDecl {2461 2462class Foo {2463 void foo(int a); __attribute__(( // \2464 // expected-warning {{declaration does not declare anything}}2465 exclusive_locks_required(a))); // \2466 // expected-warning {{attribute exclusive_locks_required ignored}}2467 2468};2469 2470} // end namespace WarnNoDecl2471 2472 2473 2474namespace MoreLockExpressions {2475 2476class Foo {2477public:2478 Mutex mu_;2479 int a GUARDED_BY(mu_);2480};2481 2482class Bar {2483public:2484 int b;2485 Foo* f;2486 2487 Foo& getFoo() { return *f; }2488 Foo& getFoo2(int c) { return *f; }2489 Foo& getFoo3(int c, int d) { return *f; }2490 2491 Foo& getFooey() { return *f; }2492};2493 2494Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }2495 2496void test() {2497 Foo foo;2498 Foo *fooArray;2499 Foo &(*fooFuncPtr)();2500 Bar bar;2501 int a;2502 int b;2503 int c;2504 2505 bar.getFoo().mu_.Lock();2506 bar.getFoo().a = 0;2507 bar.getFoo().mu_.Unlock();2508 2509 (bar.getFoo().mu_).Lock(); // test parenthesis2510 bar.getFoo().a = 0;2511 (bar.getFoo().mu_).Unlock();2512 2513 bar.getFoo2(a).mu_.Lock();2514 bar.getFoo2(a).a = 0;2515 bar.getFoo2(a).mu_.Unlock();2516 2517 bar.getFoo3(a, b).mu_.Lock();2518 bar.getFoo3(a, b).a = 0;2519 bar.getFoo3(a, b).mu_.Unlock();2520 2521 getBarFoo(bar, a).mu_.Lock();2522 getBarFoo(bar, a).a = 0;2523 getBarFoo(bar, a).mu_.Unlock();2524 2525 bar.getFoo2(10).mu_.Lock();2526 bar.getFoo2(10).a = 0;2527 bar.getFoo2(10).mu_.Unlock();2528 2529 bar.getFoo2(a + 1).mu_.Lock();2530 bar.getFoo2(a + 1).a = 0;2531 bar.getFoo2(a + 1).mu_.Unlock();2532 2533 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();2534 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;2535 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();2536 2537 fooFuncPtr().mu_.Lock();2538 fooFuncPtr().a = 0;2539 fooFuncPtr().mu_.Unlock();2540}2541 2542 2543void test2() {2544 Foo *fooArray;2545 Bar bar;2546 int a;2547 int b;2548 int c;2549 2550 bar.getFoo().mu_.Lock();2551 bar.getFooey().a = 0; // \2552 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \2553 // expected-note {{found near match 'bar.getFoo().mu_'}}2554 bar.getFoo().mu_.Unlock();2555 2556 bar.getFoo2(a).mu_.Lock();2557 bar.getFoo2(b).a = 0; // \2558 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \2559 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}2560 bar.getFoo2(a).mu_.Unlock();2561 2562 bar.getFoo3(a, b).mu_.Lock();2563 bar.getFoo3(a, c).a = 0; // \2564 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \2565 // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}2566 bar.getFoo3(a, b).mu_.Unlock();2567 2568 getBarFoo(bar, a).mu_.Lock();2569 getBarFoo(bar, b).a = 0; // \2570 // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \2571 // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}2572 getBarFoo(bar, a).mu_.Unlock();2573 2574 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();2575 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \2576 // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \2577 // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}2578 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();2579}2580 2581 2582} // end namespace MoreLockExpressions2583 2584 2585namespace TrylockJoinPoint {2586 2587class Foo {2588 Mutex mu;2589 bool c;2590 2591 void foo() {2592 if (c) {2593 if (!mu.TryLock())2594 return;2595 } else {2596 mu.Lock();2597 }2598 mu.Unlock();2599 }2600};2601 2602} // end namespace TrylockJoinPoint2603 2604 2605namespace LockReturned {2606 2607class Foo {2608public:2609 int a GUARDED_BY(mu_);2610 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);2611 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);2612 2613 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);2614 2615 Mutex* getMu() LOCK_RETURNED(mu_);2616 2617 Mutex mu_;2618 2619 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);2620};2621 2622 2623// Calls getMu() directly to lock and unlock2624void test1(Foo* f1, Foo* f2) {2625 f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}2626 f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}2627 2628 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \2629 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}2630 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}2631 2632 f1->getMu()->Lock();2633 2634 f1->a = 0;2635 f1->foo();2636 f1->foo2(f2); // \2637 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \2638 // expected-note {{found near match 'f1->mu_'}}2639 2640 Foo::getMu(f2)->Lock();2641 f1->foo2(f2);2642 Foo::getMu(f2)->Unlock();2643 2644 Foo::sfoo(f1);2645 2646 f1->getMu()->Unlock();2647}2648 2649 2650Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));2651 2652class Bar : public Foo {2653public:2654 int b GUARDED_BY(getMu());2655 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());2656 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());2657 2658 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());2659 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));2660};2661 2662 2663 2664// Use getMu() within other attributes.2665// This requires at lest levels of substitution, more in the case of2666void test2(Bar* b1, Bar* b2) {2667 b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}2668 b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}2669 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \2670 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}2671 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}2672 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}2673 2674 b1->getMu()->Lock();2675 2676 b1->b = 0;2677 b1->bar();2678 b1->bar2(b2); // \2679 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \2680 // // expected-note {{found near match 'b1->mu_'}}2681 2682 b2->getMu()->Lock();2683 b1->bar2(b2);2684 2685 b2->getMu()->Unlock();2686 2687 Bar::sbar(b1);2688 Bar::sbar2(b1);2689 2690 b1->getMu()->Unlock();2691}2692 2693 2694// Lock the mutex directly, but use attributes that call getMu()2695// Also lock the mutex using getFooMu, which calls a lock_returned function.2696void test3(Bar* b1, Bar* b2) {2697 b1->mu_.Lock();2698 b1->b = 0;2699 b1->bar();2700 2701 getFooMu(b2)->Lock();2702 b1->bar2(b2);2703 getFooMu(b2)->Unlock();2704 2705 Bar::sbar(b1);2706 Bar::sbar2(b1);2707 2708 b1->mu_.Unlock();2709}2710 2711} // end namespace LockReturned2712 2713 2714namespace ReleasableScopedLock {2715 2716class Foo {2717 Mutex mu_;2718 bool c;2719 int a GUARDED_BY(mu_);2720 2721 void test1();2722 void test2();2723 void test3();2724 void test4();2725 void test5();2726 void test6();2727};2728 2729 2730void Foo::test1() {2731 ReleasableMutexLock rlock(&mu_);2732 rlock.Release();2733}2734 2735void Foo::test2() {2736 ReleasableMutexLock rlock(&mu_);2737 if (c) { // test join point -- held/not held during release2738 rlock.Release();2739 }2740 // No warning on join point because the lock will be released by the scope object anyway.2741}2742 2743void Foo::test3() {2744 ReleasableMutexLock rlock(&mu_);2745 a = 0;2746 rlock.Release();2747 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}2748}2749 2750void Foo::test4() {2751 ReleasableMutexLock rlock(&mu_);2752 rlock.Release(); // expected-note{{mutex released here}}2753 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}2754}2755 2756void Foo::test5() {2757 ReleasableMutexLock rlock(&mu_);2758 if (c) {2759 rlock.Release();2760 }2761 // No warning on join point because the lock will be released by the scope object anyway.2762 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}2763}2764 2765void Foo::test6() {2766 ReleasableMutexLock rlock(&mu_);2767 do {2768 if (c) {2769 rlock.Release();2770 break;2771 }2772 } while (c);2773 // No warning on join point because the lock will be released by the scope object anyway2774 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}2775}2776 2777 2778} // end namespace ReleasableScopedLock2779 2780 2781namespace RelockableScopedLock {2782 2783class DeferTraits {};2784 2785class SCOPED_LOCKABLE RelockableExclusiveMutexLock {2786public:2787 RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);2788 RelockableExclusiveMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);2789 ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();2790 2791 void Lock() EXCLUSIVE_LOCK_FUNCTION();2792 void Unlock() UNLOCK_FUNCTION();2793};2794 2795struct SharedTraits {};2796struct ExclusiveTraits {};2797 2798class SCOPED_LOCKABLE RelockableMutexLock {2799public:2800 RelockableMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);2801 RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu);2802 RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu);2803 ~RelockableMutexLock() UNLOCK_FUNCTION();2804 2805 void Lock() EXCLUSIVE_LOCK_FUNCTION();2806 void Unlock() UNLOCK_FUNCTION();2807 2808 void ReaderLock() SHARED_LOCK_FUNCTION();2809 void ReaderUnlock() UNLOCK_FUNCTION();2810 2811 void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();2812 void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();2813};2814 2815Mutex mu;2816int x GUARDED_BY(mu);2817bool b;2818 2819void print(int);2820 2821void relock() {2822 RelockableExclusiveMutexLock scope(&mu);2823 x = 2;2824 scope.Unlock();2825 2826 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2827 2828 scope.Lock();2829 x = 4;2830}2831 2832void deferLock() {2833 RelockableExclusiveMutexLock scope(&mu, DeferTraits{});2834 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2835 scope.Lock();2836 x = 3;2837}2838 2839void relockExclusive() {2840 RelockableMutexLock scope(&mu, SharedTraits{});2841 print(x);2842 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2843 scope.ReaderUnlock();2844 2845 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}2846 2847 scope.Lock();2848 print(x);2849 x = 4;2850 2851 scope.DemoteExclusive();2852 print(x);2853 x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2854}2855 2856void relockShared() {2857 RelockableMutexLock scope(&mu, ExclusiveTraits{});2858 print(x);2859 x = 2;2860 scope.Unlock();2861 2862 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}2863 2864 scope.ReaderLock();2865 print(x);2866 x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2867 2868 scope.PromoteShared();2869 print(x);2870 x = 5;2871}2872 2873void deferLockShared() {2874 RelockableMutexLock scope(&mu, DeferTraits{});2875 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}2876 scope.ReaderLock();2877 print(x);2878 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2879}2880 2881void doubleUnlock() {2882 RelockableExclusiveMutexLock scope(&mu);2883 scope.Unlock(); // expected-note{{mutex released here}}2884 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}2885}2886 2887void doubleLock1() {2888 RelockableExclusiveMutexLock scope(&mu); // expected-note{{mutex acquired here}}2889 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}2890}2891 2892void doubleLock2() {2893 RelockableExclusiveMutexLock scope(&mu);2894 scope.Unlock();2895 scope.Lock(); // expected-note{{mutex acquired here}}2896 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}2897}2898 2899void lockJoin() {2900 RelockableMutexLock scope(&mu, DeferTraits{});2901 if (b)2902 scope.Lock();2903 // No warning on join point because the lock will be released by the scope object anyway.2904 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2905}2906 2907void unlockJoin() {2908 RelockableMutexLock scope(&mu, DeferTraits{});2909 scope.Lock();2910 if (b)2911 scope.Unlock();2912 // No warning on join point because the lock will be released by the scope object anyway.2913 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2914}2915 2916void loopAcquire() {2917 RelockableMutexLock scope(&mu, DeferTraits{});2918 for (unsigned i = 1; i < 10; ++i)2919 scope.Lock(); // We could catch this double lock with negative capabilities.2920}2921 2922void loopRelease() {2923 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}2924 // We have to warn on this join point despite the lock being managed ...2925 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}2926 x = 1; // ... because we might miss that this doesn't always happen under lock.2927 if (i == 5)2928 scope.Unlock();2929 }2930}2931 2932void loopPromote() {2933 RelockableMutexLock scope(&mu, SharedTraits{});2934 for (unsigned i = 1; i < 10; ++i) {2935 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2936 if (i == 5)2937 scope.PromoteShared();2938 }2939}2940 2941void loopDemote() {2942 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}2943 // We have to warn on this join point despite the lock being managed ...2944 for (unsigned i = 1; i < 10; ++i) {2945 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.2946 if (i == 5)2947 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}2948 }2949}2950 2951void loopAcquireContinue() {2952 RelockableMutexLock scope(&mu, DeferTraits{});2953 for (unsigned i = 1; i < 10; ++i) {2954 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2955 if (i == 5) {2956 scope.Lock();2957 continue;2958 }2959 }2960}2961 2962void loopReleaseContinue() {2963 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}2964 // We have to warn on this join point despite the lock being managed ...2965 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}2966 x = 1; // ... because we might miss that this doesn't always happen under lock.2967 if (i == 5) {2968 scope.Unlock();2969 continue;2970 }2971 }2972}2973 2974void loopPromoteContinue() {2975 RelockableMutexLock scope(&mu, SharedTraits{});2976 for (unsigned i = 1; i < 10; ++i) {2977 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}2978 if (i == 5) {2979 scope.PromoteShared();2980 continue;2981 }2982 }2983}2984 2985void loopDemoteContinue() {2986 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}2987 // We have to warn on this join point despite the lock being managed ...2988 for (unsigned i = 1; i < 10; ++i) {2989 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.2990 if (i == 5) {2991 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}2992 continue;2993 }2994 }2995}2996 2997void exclusiveSharedJoin() {2998 RelockableMutexLock scope(&mu, DeferTraits{});2999 if (b)3000 scope.Lock();3001 else3002 scope.ReaderLock();3003 // No warning on join point because the lock will be released by the scope object anyway.3004 print(x);3005 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3006}3007 3008void sharedExclusiveJoin() {3009 RelockableMutexLock scope(&mu, DeferTraits{});3010 if (b)3011 scope.ReaderLock();3012 else3013 scope.Lock();3014 // No warning on join point because the lock will be released by the scope object anyway.3015 print(x);3016 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3017}3018 3019void assertJoin() {3020 RelockableMutexLock scope(&mu, DeferTraits{});3021 if (b)3022 scope.Lock();3023 else3024 mu.AssertHeld();3025 x = 2;3026}3027 3028void assertSharedJoin() {3029 RelockableMutexLock scope(&mu, DeferTraits{});3030 if (b)3031 scope.ReaderLock();3032 else3033 mu.AssertReaderHeld();3034 print(x);3035 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3036}3037 3038void assertStrongerJoin() {3039 RelockableMutexLock scope(&mu, DeferTraits{});3040 if (b)3041 scope.ReaderLock();3042 else3043 mu.AssertHeld();3044 print(x);3045 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3046}3047 3048void assertWeakerJoin() {3049 RelockableMutexLock scope(&mu, DeferTraits{});3050 if (b)3051 scope.Lock();3052 else3053 mu.AssertReaderHeld();3054 print(x);3055 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3056}3057 3058void directUnlock() {3059 RelockableExclusiveMutexLock scope(&mu);3060 mu.Unlock();3061 // Debatable that there is no warning. Currently we don't track in the scoped3062 // object whether it is active, but just check if the contained locks can be3063 // reacquired. Here they can, because mu has been unlocked manually.3064 scope.Lock();3065}3066 3067void directRelock() {3068 RelockableExclusiveMutexLock scope(&mu);3069 scope.Unlock();3070 mu.Lock();3071 // Similarly debatable that there is no warning.3072 scope.Unlock();3073}3074 3075// Doesn't make a lot of sense, just making sure there is no crash.3076void destructLock() {3077 RelockableExclusiveMutexLock scope(&mu);3078 scope.~RelockableExclusiveMutexLock();3079 scope.Lock(); // Should be UB, so we don't really care.3080}3081 3082class SCOPED_LOCKABLE MemberLock {3083public:3084 MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex);3085 ~MemberLock() UNLOCK_FUNCTION(mutex);3086 void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex);3087 Mutex mutex;3088};3089 3090void relockShared2() {3091 MemberLock lock; // expected-note{{mutex acquired here}}3092 lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}}3093}3094 3095class SCOPED_LOCKABLE WeirdScope {3096private:3097 Mutex *other;3098 3099public:3100 WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);3101 void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other);3102 void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other);3103 ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION();3104 3105 void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other);3106};3107 3108void relockWeird() {3109 WeirdScope scope(&mu);3110 x = 1;3111 scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}}3112 x = 2; // \3113 // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3114 scope.requireOther(); // \3115 // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}}3116 scope.lock(); // expected-note {{mutex acquired here}}3117 x = 3;3118 scope.requireOther();3119} // expected-warning {{mutex 'scope.other' is still held at the end of function}}3120 3121} // end namespace RelockableScopedLock3122 3123 3124namespace ScopedUnlock {3125 3126class SCOPED_LOCKABLE MutexUnlock {3127public:3128 MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu);3129 ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();3130 3131 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();3132 void Unlock() EXCLUSIVE_LOCK_FUNCTION();3133};3134 3135class SCOPED_LOCKABLE ReaderMutexUnlock {3136public:3137 ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu);3138 ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();3139 3140 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();3141 void Unlock() EXCLUSIVE_LOCK_FUNCTION();3142};3143 3144template<typename... Mus>3145class SCOPED_LOCKABLE VariadicMutexUnlock {3146public:3147 VariadicMutexUnlock(Mus *...mus) EXCLUSIVE_UNLOCK_FUNCTION(mus...);3148 ~VariadicMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();3149 3150 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();3151 void Unlock() EXCLUSIVE_LOCK_FUNCTION();3152};3153 3154Mutex mu;3155int x GUARDED_BY(mu);3156bool c;3157void print(int);3158 3159void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) {3160 x = 1;3161 MutexUnlock scope(&mu);3162 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3163}3164 3165void simpleShared() SHARED_LOCKS_REQUIRED(mu) {3166 print(x);3167 ReaderMutexUnlock scope(&mu);3168 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}3169}3170 3171void innerUnlock() {3172 MutexLock outer(&mu);3173 if (x == 0) {3174 MutexUnlock inner(&mu);3175 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3176 }3177 x = 2;3178}3179 3180void innerUnlockShared() {3181 ReaderMutexLock outer(&mu);3182 if (x == 0) {3183 ReaderMutexUnlock inner(&mu);3184 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}3185 }3186 print(x);3187}3188 3189void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) {3190 MutexUnlock scope(&mu);3191 scope.Lock();3192 x = 2;3193 scope.Unlock();3194 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3195}3196 3197void join() EXCLUSIVE_LOCKS_REQUIRED(mu) {3198 MutexUnlock scope(&mu);3199 if (c)3200 scope.Lock();3201 // No warning on join point because the lock will be released by the scope object anyway.3202 scope.Lock();3203}3204 3205void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) {3206 MutexUnlock scope(&mu);3207 scope.Lock(); // expected-note{{mutex acquired here}}3208 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}3209}3210 3211void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {3212 MutexUnlock scope(&mu); // expected-note{{mutex released here}}3213 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}3214}3215 3216Mutex mu2;3217int y GUARDED_BY(mu2);3218 3219void variadic() EXCLUSIVE_LOCKS_REQUIRED(mu, mu2) {3220 VariadicMutexUnlock<Mutex, Mutex> scope(&mu, &mu2);3221 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3222 y = 3; // expected-warning {{writing variable 'y' requires holding mutex 'mu2' exclusively}}3223 scope.Lock();3224 x = y = 4;3225}3226 3227class SCOPED_LOCKABLE MutexLockUnlock {3228public:3229 MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2);3230 ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION();3231 3232 void Release() EXCLUSIVE_UNLOCK_FUNCTION();3233 void Acquire() EXCLUSIVE_LOCK_FUNCTION();3234};3235 3236Mutex other;3237void fn() EXCLUSIVE_LOCKS_REQUIRED(other);3238 3239void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {3240 MutexLockUnlock scope(&mu, &other);3241 fn();3242 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}3243}3244 3245} // end namespace ScopedUnlock3246 3247namespace PassingScope {3248 3249class SCOPED_LOCKABLE RelockableScope {3250public:3251 RelockableScope(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);3252 void Release() UNLOCK_FUNCTION();3253 void Acquire() EXCLUSIVE_LOCK_FUNCTION();3254 ~RelockableScope() EXCLUSIVE_UNLOCK_FUNCTION();3255};3256 3257class SCOPED_LOCKABLE ReaderRelockableScope {3258public:3259 ReaderRelockableScope(Mutex *mu) SHARED_LOCK_FUNCTION(mu);3260 void Release() UNLOCK_FUNCTION();3261 void Acquire() SHARED_LOCK_FUNCTION();3262 ~ReaderRelockableScope() UNLOCK_FUNCTION();3263};3264 3265Mutex mu;3266Mutex mu1;3267Mutex mu2;3268int x GUARDED_BY(mu);3269int y GUARDED_BY(mu) GUARDED_BY(mu2);3270void print(int);3271 3272// Analysis inside the function with annotated parameters3273 3274void sharedRequired(ReleasableMutexLock& scope SHARED_LOCKS_REQUIRED(mu)) {3275 print(x); // OK.3276}3277 3278void sharedAcquire(ReaderRelockableScope& scope SHARED_LOCK_FUNCTION(mu)) {3279 scope.Acquire();3280 print(x);3281}3282 3283void sharedRelease(RelockableScope& scope SHARED_UNLOCK_FUNCTION(mu)) {3284 print(x);3285 scope.Release();3286 print(x); // expected-warning{{reading variable 'x' requires holding mutex 'mu'}}3287}3288 3289void requiredLock(ReleasableMutexLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu)) {3290 x = 1; // OK.3291}3292 3293void reacquireRequiredLock(RelockableScope& scope EXCLUSIVE_LOCKS_REQUIRED(mu)) {3294 scope.Release();3295 scope.Acquire();3296 x = 2; // OK.3297}3298 3299void releaseSingleMutex(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu)) {3300 x = 1; // OK.3301 scope.Release();3302 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3303}3304 3305void releaseMultipleMutexes(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu, mu2)) {3306 y = 1; // OK.3307 scope.Release();3308 y = 2; // expected-warning{{writing variable 'y' requires holding mutex 'mu' exclusively}}3309 // expected-warning@-1{{writing variable 'y' requires holding mutex 'mu2' exclusively}}3310}3311 3312void acquireLock(RelockableScope& scope EXCLUSIVE_LOCK_FUNCTION(mu)) {3313 x = 1; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3314 scope.Acquire();3315 x = 2; // OK.3316}3317 3318void acquireMultipleLocks(RelockableScope& scope EXCLUSIVE_LOCK_FUNCTION(mu, mu2)) {3319 y = 1; // expected-warning{{writing variable 'y' requires holding mutex 'mu' exclusively}}3320 // expected-warning@-1{{writing variable 'y' requires holding mutex 'mu2' exclusively}}3321 scope.Acquire();3322 y = 2; // OK.3323}3324 3325void excludedLock(ReleasableMutexLock& scope LOCKS_EXCLUDED(mu)) {3326 x = 1; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3327}3328 3329void acquireAndReleaseExcludedLocks(RelockableScope& scope LOCKS_EXCLUDED(mu)) {3330 scope.Acquire();3331 scope.Release();3332}3333 3334// expected-note@+1{{mutex acquired here}}3335void unreleasedMutex(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu)) {3336 x = 1; // OK.3337} // expected-warning{{mutex 'mu' is still held at the end of function}}3338 3339// expected-note@+1{{mutex acquired here}}3340void acquireAlreadyHeldMutex(RelockableScope& scope EXCLUSIVE_UNLOCK_FUNCTION(mu)) {3341 scope.Acquire(); // expected-warning{{acquiring mutex 'mu' that is already held}}3342 scope.Release();3343}3344 3345void reacquireMutex(RelockableScope& scope EXCLUSIVE_UNLOCK_FUNCTION(mu)) {3346 scope.Release();3347 scope.Acquire(); // expected-note{{mutex acquired here}}3348 x = 2; // OK.3349} // expected-warning{{mutex 'mu' is still held at the end of function}}3350 3351// expected-note@+1{{mutex acquired here}}3352void requireSingleMutex(ReleasableMutexLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu)) {3353 x = 1; // OK.3354 scope.Release();3355 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3356} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3357 3358// expected-note@+1 2{{mutex acquired here}}3359void requireMultipleMutexes(ReleasableMutexLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu, mu2)) {3360 y = 1; // OK.3361 scope.Release();3362 y = 2; // expected-warning{{writing variable 'y' requires holding mutex 'mu' exclusively}}3363 // expected-warning@-1{{writing variable 'y' requires holding mutex 'mu2' exclusively}}3364} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3365 // expected-warning@-1{{expecting mutex 'mu2' to be held at the end of function}}3366 3367// expected-note@+1{{mutex acquired here}}3368void acquireAlreadyHeldLock(RelockableScope& scope EXCLUSIVE_LOCKS_REQUIRED(mu)) {3369 scope.Acquire(); // expected-warning{{acquiring mutex 'mu' that is already held}}3370}3371 3372// expected-note@+1 {{mutex acquired here}}3373void releaseWithoutHoldingLock(ReleasableMutexLock& scope EXCLUSIVE_LOCK_FUNCTION(mu)) {3374 scope.Release(); // expected-warning{{releasing mutex 'mu' that was not held}}3375} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3376 3377// expected-note@+1 {{mutex acquired here}}3378void endWithReleasedMutex(RelockableScope& scope EXCLUSIVE_LOCK_FUNCTION(mu)) {3379 scope.Acquire();3380 scope.Release();3381} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3382 3383void acquireExcludedLock(RelockableScope& scope LOCKS_EXCLUDED(mu)) {3384 x = 1; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3385 scope.Acquire(); // expected-note {{mutex acquired here}}3386 x = 2; // OK.3387} // expected-warning{{mutex 'mu' is still held at the end of function}}3388 3389void acquireMultipleExcludedLocks(RelockableScope& scope LOCKS_EXCLUDED(mu, mu2)) {3390 y = 1; // expected-warning{{writing variable 'y' requires holding mutex 'mu' exclusively}}3391 // expected-warning@-1{{writing variable 'y' requires holding mutex 'mu2' exclusively}}3392 scope.Acquire(); // expected-note 2{{mutex acquired here}}3393 y = 2; // OK.3394} // expected-warning{{mutex 'mu' is still held at the end of function}}3395 // expected-warning@-1{{mutex 'mu2' is still held at the end of function}}3396 3397void reacquireExcludedLocks(RelockableScope& scope LOCKS_EXCLUDED(mu)) {3398 scope.Release(); // expected-warning{{releasing mutex 'mu' that was not held}}3399 scope.Acquire(); // expected-note {{mutex acquired here}}3400 x = 2; // OK.3401} // expected-warning{{mutex 'mu' is still held at the end of function}}3402 3403// expected-note@+1{{mutex acquired here}}3404void sharedRequired2(ReleasableMutexLock& scope SHARED_LOCKS_REQUIRED(mu)) {3405 print(x); // OK.3406 scope.Release();3407 print(x); // expected-warning{{reading variable 'x' requires holding mutex 'mu'}}3408} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3409 3410// expected-note@+1{{mutex acquired here}}3411void sharedAcquire2(RelockableScope& scope SHARED_LOCK_FUNCTION(mu)) {3412 print(x); // expected-warning{{reading variable 'x' requires holding mutex 'mu'}}3413 scope.Release(); // expected-warning{{releasing mutex 'mu' that was not held}}3414} // expected-warning{{expecting mutex 'mu' to be held at the end of function}}3415 3416// expected-note@+1 2{{mutex acquired here}}3417void sharedRelease2(RelockableScope& scope SHARED_UNLOCK_FUNCTION(mu)) {3418 scope.Acquire(); //expected-warning{{acquiring mutex 'mu' that is already held}}3419} //expected-warning{{mutex 'mu' is still held at the end of function}}3420 3421// Handling the call of the function with annotated parameters3422 3423// expected-note@+1{{see attribute on parameter here}}3424void release(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu));3425// expected-note@+1{{see attribute on parameter here}}3426void release_DoubleMutexLock(DoubleMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu));3427// expected-note@+1 2{{see attribute on parameter here}}3428void release_two(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu, mu2));3429// expected-note@+1{{see attribute on parameter here}}3430void release_double(DoubleMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu, mu2));3431void require(ReleasableMutexLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu));3432void acquire(RelockableScope& scope EXCLUSIVE_LOCK_FUNCTION(mu));3433void exclude(RelockableScope& scope LOCKS_EXCLUDED(mu));3434 3435void release_shared(ReaderRelockableScope& scope SHARED_UNLOCK_FUNCTION(mu));3436void require_shared(ReleasableMutexLock& scope SHARED_LOCKS_REQUIRED(mu));3437void acquire_shared(ReaderRelockableScope& scope SHARED_LOCK_FUNCTION(mu));3438 3439void unlockCall() {3440 ReleasableMutexLock scope(&mu);3441 x = 1; // OK.3442 release(scope);3443 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3444}3445 3446void unlockSharedCall() {3447 ReaderRelockableScope scope(&mu);3448 print(x); // OK.3449 release_shared(scope);3450 print(x); // expected-warning{{reading variable 'x' requires holding mutex 'mu'}}3451}3452 3453void requireCall() {3454 ReleasableMutexLock scope(&mu);3455 x = 1; // OK.3456 require(scope);3457 x = 2; // Ok.3458}3459 3460void requireSharedCall() {3461 ReleasableMutexLock scope(&mu);3462 print(x); // OK.3463 require_shared(scope);3464 print(x); // Ok.3465}3466 3467void acquireCall() {3468 RelockableScope scope(&mu);3469 scope.Release();3470 acquire(scope);3471 x = 2; // Ok.3472}3473 3474void acquireSharedCall() {3475 ReaderRelockableScope scope(&mu);3476 scope.Release();3477 acquire_shared(scope);3478 print(x); // Ok.3479}3480 3481void writeAfterExcludeCall() {3482 RelockableScope scope(&mu);3483 scope.Release();3484 exclude(scope);3485 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3486}3487 3488void unlockCallAfterExplicitRelease() {3489 ReleasableMutexLock scope(&mu);3490 x = 1; // OK.3491 scope.Release(); // expected-note{{mutex released here}}3492 release(scope); // expected-warning{{releasing mutex 'mu' that was not held}}3493 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3494}3495 3496void unmatchedMutexes() {3497 ReleasableMutexLock scope(&mu2);3498 release(scope); // expected-warning{{mutex managed by 'scope' is 'mu2' instead of 'mu'}}3499 // expected-warning@-1{{releasing mutex 'mu' that was not held}}3500}3501 3502void wrongOrder() {3503 DoubleMutexLock scope(&mu2, &mu);3504 release_double(scope); // expected-warning{{mutex managed by 'scope' is 'mu2' instead of 'mu'}}3505}3506 3507void differentNumberOfMutexes() {3508 ReleasableMutexLock scope(&mu);3509 release_two(scope); // expected-warning{{mutex 'mu2' not managed by 'scope'}}3510 // expected-warning@-1{{releasing mutex 'mu2' that was not held}}3511}3512 3513void differentNumberOfMutexes2() {3514 ReleasableMutexLock scope(&mu2);3515 release_two(scope); // expected-warning{{mutex managed by 'scope' is 'mu2' instead of 'mu'}}3516 // expected-warning@-1{{releasing mutex 'mu' that was not held}}3517}3518 3519void differentNumberOfMutexes3() {3520 DoubleMutexLock scope(&mu, &mu2);3521 release_DoubleMutexLock(scope); // expected-warning{{did not expect mutex 'mu2' to be managed by 'scope'}}3522}3523 3524void releaseDefault(ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(mu), int = 0);3525 3526void unlockFunctionDefault() {3527 ReleasableMutexLock scope(&mu);3528 x = 1; // OK.3529 releaseDefault(scope);3530 x = 2; // expected-warning{{writing variable 'x' requires holding mutex 'mu' exclusively}}3531}3532 3533void requireCallWithReleasedLock() {3534 ReleasableMutexLock scope(&mu);3535 scope.Release();3536 require(scope); // expected-warning{{calling function 'require' requires holding mutex 'mu' exclusively}}3537}3538 3539void acquireCallWithAlreadyHeldLock() {3540 RelockableScope scope(&mu); // expected-note{{mutex acquired here}}3541 acquire(scope); // expected-warning{{acquiring mutex 'mu' that is already held}}3542 x = 1;3543}3544 3545void excludeCallWithAlreadyHeldLock() {3546 RelockableScope scope(&mu);3547 exclude(scope); // expected-warning{{cannot call function 'exclude' while mutex 'mu' is held}}3548 x = 2; // OK.3549}3550 3551void requireConst(const ReleasableMutexLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu));3552void requireConstCall() {3553 requireConst(ReleasableMutexLock(&mu));3554}3555 3556void passScopeUndeclared(ReleasableMutexLock &scope) {3557 release(scope); // expected-warning{{calling function 'release' requires holding mutex 'scope' exclusively}}3558 // expected-warning@-1{{releasing mutex 'mu' that was not held}}3559}3560 3561class SCOPED_LOCKABLE ScopedWithoutLock {3562public:3563 ScopedWithoutLock();3564 3565 ~ScopedWithoutLock() EXCLUSIVE_UNLOCK_FUNCTION();3566};3567 3568void require(ScopedWithoutLock &scope EXCLUSIVE_LOCKS_REQUIRED(mu));3569 3570void constructWithoutLock() {3571 ScopedWithoutLock scope;3572 require(scope); // expected-warning{{calling function 'require' requires holding mutex 'mu' exclusively}}3573 // expected-warning@-1{{calling function 'require' requires holding mutex 'scope' exclusively}}3574} // expected-warning {{releasing mutex 'scope' that was not held}}3575 3576void requireConst(const ScopedWithoutLock& scope EXCLUSIVE_LOCKS_REQUIRED(mu));3577 3578void requireCallWithReleasedLock2() {3579 requireConst(ScopedWithoutLock());3580 // expected-warning@-1{{calling function 'requireConst' requires holding mutex '#undefined' exclusively}}3581 // expected-warning@-2{{calling function 'requireConst' requires holding mutex 'mu' exclusively}}3582}3583 3584void requireDecl(RelockableScope &scope EXCLUSIVE_LOCKS_REQUIRED(mu));3585void requireDecl(RelockableScope &scope) {3586 scope.Release();3587 scope.Acquire();3588}3589 3590struct foo3591{3592 Mutex mu;3593 // expected-note@+1{{see attribute on parameter here}}3594 void require(RelockableScope &scope EXCLUSIVE_LOCKS_REQUIRED(mu));3595 void callRequire(){3596 RelockableScope scope(&mu);3597 // TODO: False positive due to incorrect parsing of parameter attribute arguments.3598 require(scope);3599 // expected-warning@-1{{calling function 'require' requires holding mutex 'mu' exclusively}}3600 // expected-warning@-2{{mutex managed by 'scope' is 'mu' instead of 'mu'}}3601 }3602};3603 3604struct ObjectWithMutex {3605 Mutex mu;3606 int x GUARDED_BY(mu);3607};3608void releaseMember(ObjectWithMutex& object, ReleasableMutexLock& scope EXCLUSIVE_UNLOCK_FUNCTION(object.mu)) {3609 object.x = 1;3610 scope.Release();3611}3612void releaseMemberCall() {3613 ObjectWithMutex obj;3614 ReleasableMutexLock lock(&obj.mu);3615 releaseMember(obj, lock);3616}3617 3618} // end namespace PassingScope3619 3620namespace TrylockFunctionTest {3621 3622class Foo {3623public:3624 Mutex mu1_;3625 Mutex mu2_;3626 bool c;3627 3628 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);3629};3630 3631bool Foo::lockBoth() {3632 if (!mu1_.TryLock())3633 return false;3634 3635 mu2_.Lock();3636 if (!c) {3637 mu1_.Unlock();3638 mu2_.Unlock();3639 return false;3640 }3641 3642 return true;3643}3644 3645 3646} // end namespace TrylockFunctionTest3647 3648 3649 3650namespace DoubleLockBug {3651 3652class Foo {3653public:3654 Mutex mu_;3655 int a GUARDED_BY(mu_);3656 3657 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);3658 int foo2() SHARED_LOCKS_REQUIRED(mu_);3659};3660 3661 3662void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {3663 a = 0;3664}3665 3666int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {3667 return a;3668}3669 3670}3671 3672 3673 3674namespace UnlockBug {3675 3676class Foo {3677public:3678 Mutex mutex_;3679 3680 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}3681 mutex_.Unlock();3682 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}3683 3684 3685 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}3686 mutex_.Unlock();3687 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}3688};3689 3690} // end namespace UnlockBug3691 3692 3693 3694namespace FoolishScopedLockableBug {3695 3696class SCOPED_LOCKABLE WTF_ScopedLockable {3697public:3698 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);3699 3700 // have to call release() manually;3701 ~WTF_ScopedLockable();3702 3703 void release() UNLOCK_FUNCTION();3704};3705 3706 3707class Foo {3708 Mutex mu_;3709 int a GUARDED_BY(mu_);3710 bool c;3711 3712 void doSomething();3713 3714 void test1() {3715 WTF_ScopedLockable wtf(&mu_);3716 wtf.release();3717 }3718 3719 void test2() {3720 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}3721 } // expected-warning {{mutex 'mu_' is still held at the end of function}}3722 3723 void test3() {3724 if (c) {3725 WTF_ScopedLockable wtf(&mu_);3726 wtf.release();3727 }3728 }3729 3730 void test4() {3731 if (c) {3732 doSomething();3733 }3734 else {3735 WTF_ScopedLockable wtf(&mu_);3736 wtf.release();3737 }3738 }3739 3740 void test5() {3741 if (c) {3742 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}3743 }3744 } // expected-warning {{mutex 'mu_' is not held on every path through here}}3745 3746 void test6() {3747 if (c) {3748 doSomething();3749 }3750 else {3751 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}3752 }3753 } // expected-warning {{mutex 'mu_' is not held on every path through here}}3754};3755 3756 3757} // end namespace FoolishScopedLockableBug3758 3759 3760 3761namespace TemporaryCleanupExpr {3762 3763class Foo {3764 int a GUARDED_BY(getMutexPtr().get());3765 3766 SmartPtr<Mutex> getMutexPtr();3767 3768 void test();3769};3770 3771 3772void Foo::test() {3773 {3774 ReaderMutexLock lock(getMutexPtr().get());3775 int b = a;3776 }3777 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}3778}3779 3780#ifdef __cpp_guaranteed_copy_elision3781 3782void guaranteed_copy_elision() {3783 MutexLock lock = MutexLock{&sls_mu};3784 sls_guard_var = 0;3785}3786 3787void guaranteed_copy_elision_const() {3788 const MutexLock lock = MutexLock{&sls_mu};3789 sls_guard_var = 0;3790}3791 3792#endif3793 3794} // end namespace TemporaryCleanupExpr3795 3796 3797 3798namespace SmartPointerTests {3799 3800class Foo {3801public:3802 SmartPtr<Mutex> mu_;3803 int a GUARDED_BY(mu_);3804 int b GUARDED_BY(mu_.get());3805 int c GUARDED_BY(*mu_);3806 3807 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);3808 void Unlock() UNLOCK_FUNCTION(mu_);3809 3810 void test0();3811 void test1();3812 void test2();3813 void test3();3814 void test4();3815 void test5();3816 void test6();3817 void test7();3818 void test8();3819};3820 3821void Foo::test0() {3822 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}3823 b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}3824 c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}3825}3826 3827void Foo::test1() {3828 mu_->Lock();3829 a = 0;3830 b = 0;3831 c = 0;3832 mu_->Unlock();3833}3834 3835void Foo::test2() {3836 (*mu_).Lock();3837 a = 0;3838 b = 0;3839 c = 0;3840 (*mu_).Unlock();3841}3842 3843 3844void Foo::test3() {3845 mu_.get()->Lock();3846 a = 0;3847 b = 0;3848 c = 0;3849 mu_.get()->Unlock();3850}3851 3852 3853void Foo::test4() {3854 MutexLock lock(mu_.get());3855 a = 0;3856 b = 0;3857 c = 0;3858}3859 3860 3861void Foo::test5() {3862 MutexLock lock(&(*mu_));3863 a = 0;3864 b = 0;3865 c = 0;3866}3867 3868 3869void Foo::test6() {3870 Lock();3871 a = 0;3872 b = 0;3873 c = 0;3874 Unlock();3875}3876 3877 3878void Foo::test7() {3879 {3880 Lock();3881 mu_->Unlock();3882 }3883 {3884 mu_->Lock();3885 Unlock();3886 }3887 {3888 mu_.get()->Lock();3889 mu_->Unlock();3890 }3891 {3892 mu_->Lock();3893 mu_.get()->Unlock();3894 }3895 {3896 mu_.get()->Lock();3897 (*mu_).Unlock();3898 }3899 {3900 (*mu_).Lock();3901 mu_->Unlock();3902 }3903}3904 3905 3906void Foo::test8() {3907 mu_->Lock(); // expected-note 2 {{mutex acquired here}}3908 mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}3909 (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}3910 mu_.get()->Unlock(); // expected-note {{mutex released here}}3911 Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}3912}3913 3914 3915class Bar {3916 SmartPtr<Foo> foo;3917 3918 void test0();3919 void test1();3920 void test2();3921 void test3();3922};3923 3924 3925void Bar::test0() {3926 foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}3927 (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}3928 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}3929}3930 3931 3932void Bar::test1() {3933 foo->mu_->Lock();3934 foo->a = 0;3935 (*foo).b = 0;3936 foo.get()->c = 0;3937 foo->mu_->Unlock();3938}3939 3940 3941void Bar::test2() {3942 (*foo).mu_->Lock();3943 foo->a = 0;3944 (*foo).b = 0;3945 foo.get()->c = 0;3946 foo.get()->mu_->Unlock();3947}3948 3949 3950void Bar::test3() {3951 MutexLock lock(foo->mu_.get());3952 foo->a = 0;3953 (*foo).b = 0;3954 foo.get()->c = 0;3955}3956 3957} // end namespace SmartPointerTests3958 3959 3960 3961namespace DuplicateAttributeTest {3962 3963class LOCKABLE Foo {3964public:3965 Mutex mu1_;3966 Mutex mu2_;3967 Mutex mu3_;3968 int a GUARDED_BY(mu1_);3969 int b GUARDED_BY(mu2_);3970 int c GUARDED_BY(mu3_);3971 3972 void lock() EXCLUSIVE_LOCK_FUNCTION();3973 void unlock() UNLOCK_FUNCTION();3974 3975 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);3976 void slock1() SHARED_LOCK_FUNCTION(mu1_);3977 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);3978 void locklots()3979 EXCLUSIVE_LOCK_FUNCTION(mu1_)3980 EXCLUSIVE_LOCK_FUNCTION(mu2_)3981 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);3982 3983 void unlock1() UNLOCK_FUNCTION(mu1_);3984 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);3985 void unlocklots()3986 UNLOCK_FUNCTION(mu1_)3987 UNLOCK_FUNCTION(mu2_)3988 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);3989};3990 3991 3992void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }3993void Foo::unlock() UNLOCK_FUNCTION() { }3994 3995void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {3996 mu1_.Lock();3997}3998 3999void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {4000 mu1_.ReaderLock();4001}4002 4003void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {4004 mu1_.Lock();4005 mu2_.Lock();4006 mu3_.Lock();4007}4008 4009void Foo::locklots()4010 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)4011 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {4012 mu1_.Lock();4013 mu2_.Lock();4014 mu3_.Lock();4015}4016 4017void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {4018 mu1_.Unlock();4019}4020 4021void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {4022 mu1_.Unlock();4023 mu2_.Unlock();4024 mu3_.Unlock();4025}4026 4027void Foo::unlocklots()4028 UNLOCK_FUNCTION(mu1_, mu2_)4029 UNLOCK_FUNCTION(mu2_, mu3_) {4030 mu1_.Unlock();4031 mu2_.Unlock();4032 mu3_.Unlock();4033}4034 4035 4036void test0() {4037 Foo foo;4038 foo.lock();4039 foo.unlock();4040 4041 foo.lock(); // expected-note{{mutex acquired here}}4042 foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}4043 foo.unlock(); // expected-note{{mutex released here}}4044 foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}4045}4046 4047 4048void test1() {4049 Foo foo;4050 foo.lock1();4051 foo.a = 0;4052 foo.unlock1();4053 4054 foo.lock1(); // expected-note{{mutex acquired here}}4055 foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}4056 foo.a = 0;4057 foo.unlock1(); // expected-note{{mutex released here}}4058 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}4059}4060 4061 4062int test2() {4063 Foo foo;4064 foo.slock1();4065 int d1 = foo.a;4066 foo.unlock1();4067 4068 foo.slock1(); // expected-note{{mutex acquired here}}4069 foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}4070 int d2 = foo.a;4071 foo.unlock1(); // expected-note{{mutex released here}}4072 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}4073 return d1 + d2;4074}4075 4076 4077void test3() {4078 Foo foo;4079 foo.lock3();4080 foo.a = 0;4081 foo.b = 0;4082 foo.c = 0;4083 foo.unlock3();4084 4085 foo.lock3(); // expected-note 3 {{mutex acquired here}}4086 foo.lock3(); // \4087 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \4088 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \4089 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}4090 foo.a = 0;4091 foo.b = 0;4092 foo.c = 0;4093 foo.unlock3(); // expected-note 3 {{mutex released here}}4094 foo.unlock3(); // \4095 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \4096 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \4097 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}4098}4099 4100 4101void testlots() {4102 Foo foo;4103 foo.locklots();4104 foo.a = 0;4105 foo.b = 0;4106 foo.c = 0;4107 foo.unlocklots();4108 4109 foo.locklots(); // expected-note 3 {{mutex acquired here}}4110 foo.locklots(); // \4111 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \4112 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \4113 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}4114 foo.a = 0;4115 foo.b = 0;4116 foo.c = 0;4117 foo.unlocklots(); // expected-note 3 {{mutex released here}}4118 foo.unlocklots(); // \4119 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \4120 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \4121 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}4122}4123 4124} // end namespace DuplicateAttributeTest4125 4126 4127 4128namespace TryLockEqTest {4129 4130class Foo {4131 Mutex mu_;4132 int a GUARDED_BY(mu_);4133 bool c;4134 4135 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);4136 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);4137 void unlock() UNLOCK_FUNCTION(mu_);4138 4139 void test1();4140 void test2();4141};4142 4143 4144void Foo::test1() {4145 if (tryLockMutexP() == 0) {4146 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4147 return;4148 }4149 a = 0;4150 unlock();4151 4152 if (tryLockMutexP() != 0) {4153 a = 0;4154 unlock();4155 }4156 4157 if (0 != tryLockMutexP()) {4158 a = 0;4159 unlock();4160 }4161 4162 if (!(tryLockMutexP() == 0)) {4163 a = 0;4164 unlock();4165 }4166 4167 if (tryLockMutexI() == 0) {4168 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4169 return;4170 }4171 a = 0;4172 unlock();4173 4174 if (0 == tryLockMutexI()) {4175 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4176 return;4177 }4178 a = 0;4179 unlock();4180 4181 if (tryLockMutexI() == 1) {4182 a = 0;4183 unlock();4184 }4185 4186 if (mu_.TryLock() == false) {4187 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4188 return;4189 }4190 a = 0;4191 unlock();4192 4193 if (mu_.TryLock() == true) {4194 a = 0;4195 unlock();4196 }4197 else {4198 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4199 }4200 4201#if __has_feature(cxx_nullptr)4202 if (tryLockMutexP() == nullptr) {4203 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4204 return;4205 }4206 a = 0;4207 unlock();4208#endif4209}4210 4211} // end namespace TryLockEqTest4212 4213 4214namespace ExistentialPatternMatching {4215 4216class Graph {4217public:4218 Mutex mu_;4219};4220 4221void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);4222void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);4223 4224class Node {4225public:4226 int a GUARDED_BY(&Graph::mu_);4227 4228 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {4229 a = 0;4230 }4231 void foo2() LOCKS_EXCLUDED(&Graph::mu_);4232};4233 4234void test() {4235 Graph g1;4236 Graph g2;4237 Node n1;4238 4239 n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}4240 n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}4241 n1.foo2();4242 4243 g1.mu_.Lock();4244 n1.a = 0;4245 n1.foo();4246 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}4247 g1.mu_.Unlock();4248 4249 g2.mu_.Lock();4250 n1.a = 0;4251 n1.foo();4252 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}4253 g2.mu_.Unlock();4254 4255 LockAllGraphs();4256 n1.a = 0;4257 n1.foo();4258 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}4259 UnlockAllGraphs();4260 4261 LockAllGraphs();4262 g1.mu_.Unlock();4263 4264 LockAllGraphs();4265 g2.mu_.Unlock();4266 4267 LockAllGraphs(); // expected-note{{mutex acquired here}}4268 g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}4269 g1.mu_.Unlock();4270}4271 4272} // end namespace ExistentialPatternMatching4273 4274 4275namespace StringIgnoreTest {4276 4277class Foo {4278public:4279 Mutex mu_;4280 void lock() EXCLUSIVE_LOCK_FUNCTION("");4281 void unlock() UNLOCK_FUNCTION("");4282 void goober() EXCLUSIVE_LOCKS_REQUIRED("");4283 void roober() SHARED_LOCKS_REQUIRED("");4284};4285 4286 4287class Bar : public Foo {4288public:4289 void bar(Foo* f) {4290 f->unlock();4291 f->goober();4292 f->roober();4293 f->lock();4294 };4295};4296 4297} // end namespace StringIgnoreTest4298 4299 4300namespace LockReturnedScopeFix {4301 4302class Base {4303protected:4304 struct Inner;4305 bool c;4306 4307 const Mutex& getLock(const Inner* i);4308 4309 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));4310 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));4311 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));4312 4313 void bar(Inner* i);4314};4315 4316 4317struct Base::Inner {4318 Mutex lock_;4319 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);4320};4321 4322 4323const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {4324 return i->lock_;4325}4326 4327 4328void Base::foo(Inner* i) {4329 i->doSomething();4330}4331 4332void Base::bar(Inner* i) {4333 if (c) {4334 i->lock_.Lock();4335 unlockInner(i);4336 }4337 else {4338 lockInner(i);4339 i->lock_.Unlock();4340 }4341}4342 4343} // end namespace LockReturnedScopeFix4344 4345 4346namespace TrylockWithCleanups {4347 4348struct Foo {4349 Mutex mu_;4350 int a GUARDED_BY(mu_);4351};4352 4353Foo* GetAndLockFoo(const MyString& s)4354 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);4355 4356static void test() {4357 Foo* lt = GetAndLockFoo("foo");4358 if (!lt) return;4359 int a = lt->a;4360 lt->mu_.Unlock();4361}4362 4363} // end namespace TrylockWithCleanups4364 4365 4366namespace UniversalLock {4367 4368class Foo {4369 Mutex mu_;4370 bool c;4371 4372 int a GUARDED_BY(mu_);4373 void r_foo() SHARED_LOCKS_REQUIRED(mu_);4374 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);4375 4376 void test1() {4377 int b;4378 4379 beginNoWarnOnReads();4380 b = a;4381 r_foo();4382 endNoWarnOnReads();4383 4384 beginNoWarnOnWrites();4385 a = 0;4386 w_foo();4387 endNoWarnOnWrites();4388 }4389 4390 // don't warn on joins with universal lock4391 void test2() {4392 if (c) {4393 beginNoWarnOnWrites();4394 }4395 a = 0; // \4396 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}4397 endNoWarnOnWrites(); // \4398 // expected-warning {{releasing wildcard '*' that was not held}}4399 }4400 4401 4402 // make sure the universal lock joins properly4403 void test3() {4404 if (c) {4405 mu_.Lock();4406 beginNoWarnOnWrites();4407 }4408 else {4409 beginNoWarnOnWrites();4410 mu_.Lock();4411 }4412 a = 0;4413 endNoWarnOnWrites();4414 mu_.Unlock();4415 }4416 4417 4418 // combine universal lock with other locks4419 void test4() {4420 beginNoWarnOnWrites();4421 mu_.Lock();4422 mu_.Unlock();4423 endNoWarnOnWrites();4424 4425 mu_.Lock();4426 beginNoWarnOnWrites();4427 endNoWarnOnWrites();4428 mu_.Unlock();4429 4430 mu_.Lock();4431 beginNoWarnOnWrites();4432 mu_.Unlock();4433 endNoWarnOnWrites();4434 }4435};4436 4437} // end namespace UniversalLock4438 4439 4440namespace TemplateLockReturned {4441 4442template<class T>4443class BaseT {4444public:4445 virtual void baseMethod() = 0;4446 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }4447 4448 Mutex mutex_;4449 int a GUARDED_BY(mutex_);4450};4451 4452 4453class Derived : public BaseT<int> {4454public:4455 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {4456 a = 0;4457 }4458};4459 4460} // end namespace TemplateLockReturned4461 4462 4463namespace ExprMatchingBugFix {4464 4465class Foo {4466public:4467 Mutex mu_;4468};4469 4470 4471class Bar {4472public:4473 bool c;4474 Foo* foo;4475 Bar(Foo* f) : foo(f) { }4476 4477 struct Nested {4478 Foo* foo;4479 Nested(Foo* f) : foo(f) { }4480 4481 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);4482 };4483 4484 void test();4485};4486 4487 4488void Bar::test() {4489 foo->mu_.Lock();4490 if (c) {4491 Nested *n = new Nested(foo);4492 n->unlockFoo();4493 }4494 else {4495 foo->mu_.Unlock();4496 }4497}4498 4499}; // end namespace ExprMatchingBugfix4500 4501 4502namespace ComplexNameTest {4503 4504class Foo {4505public:4506 static Mutex mu_;4507 4508 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }4509 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }4510 4511 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }4512};4513 4514class Bar {4515public:4516 static Mutex mu_;4517 4518 Bar() LOCKS_EXCLUDED(mu_) { }4519 ~Bar() LOCKS_EXCLUDED(mu_) { }4520 4521 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }4522};4523 4524 4525void test1() {4526 Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}4527 int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}4528} // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}4529 4530 4531void test2() {4532 Bar::mu_.Lock();4533 {4534 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}4535 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}4536 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}4537 Bar::mu_.Unlock();4538}4539 4540}; // end namespace ComplexNameTest4541 4542 4543namespace UnreachableExitTest {4544 4545class FemmeFatale {4546public:4547 FemmeFatale();4548 ~FemmeFatale() __attribute__((noreturn));4549};4550 4551void exitNow() __attribute__((noreturn));4552void exitDestruct(const MyString& ms) __attribute__((noreturn));4553 4554Mutex fatalmu_;4555 4556void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {4557 exitNow();4558}4559 4560void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {4561 FemmeFatale femme;4562}4563 4564bool c;4565 4566void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {4567 if (c) {4568 exitNow();4569 }4570 else {4571 FemmeFatale femme;4572 }4573}4574 4575void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {4576 exitDestruct("foo");4577}4578 4579} // end namespace UnreachableExitTest4580 4581 4582namespace VirtualMethodCanonicalizationTest {4583 4584class Base {4585public:4586 virtual Mutex* getMutex() = 0;4587};4588 4589class Base2 : public Base {4590public:4591 Mutex* getMutex();4592};4593 4594class Base3 : public Base2 {4595public:4596 Mutex* getMutex();4597};4598 4599class Derived : public Base3 {4600public:4601 Mutex* getMutex(); // overrides Base::getMutex()4602};4603 4604void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }4605 4606void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {4607 baseFun(d);4608}4609 4610} // end namespace VirtualMethodCanonicalizationTest4611 4612 4613namespace TemplateFunctionParamRemapTest {4614 4615template <class T>4616struct Cell {4617 T dummy_;4618 Mutex* mu_;4619};4620 4621class Foo {4622public:4623 template <class T>4624 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);4625 4626 void test();4627};4628 4629template<class T>4630void Foo::elr(Cell<T>* c1) { }4631 4632void Foo::test() {4633 Cell<int> cell;4634 elr(&cell); // \4635 // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}4636}4637 4638 4639template<class T>4640void globalELR(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);4641 4642template<class T>4643void globalELR(Cell<T>* c1) { }4644 4645void globalTest() {4646 Cell<int> cell;4647 globalELR(&cell); // \4648 // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}4649}4650 4651 4652template<class T>4653void globalELR2(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);4654 4655// second declaration4656template<class T>4657void globalELR2(Cell<T>* c2);4658 4659template<class T>4660void globalELR2(Cell<T>* c3) { }4661 4662// re-declaration after definition4663template<class T>4664void globalELR2(Cell<T>* c4);4665 4666void globalTest2() {4667 Cell<int> cell;4668 globalELR2(&cell); // \4669 // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}4670}4671 4672 4673template<class T>4674class FooT {4675public:4676 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);4677};4678 4679template<class T>4680void FooT<T>::elr(Cell<T>* c1) { }4681 4682void testFooT() {4683 Cell<int> cell;4684 FooT<int> foo;4685 foo.elr(&cell); // \4686 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}4687}4688 4689} // end namespace TemplateFunctionParamRemapTest4690 4691 4692namespace SelfConstructorTest {4693 4694class SelfLock {4695public:4696 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);4697 ~SelfLock() UNLOCK_FUNCTION(mu_);4698 4699 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);4700 4701 Mutex mu_;4702};4703 4704class LOCKABLE SelfLock2 {4705public:4706 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();4707 ~SelfLock2() UNLOCK_FUNCTION();4708 4709 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);4710};4711 4712class SelfLockDeferred {4713public:4714 SelfLockDeferred() LOCKS_EXCLUDED(mu_);4715 ~SelfLockDeferred() UNLOCK_FUNCTION(mu_);4716 4717 Mutex mu_;4718};4719 4720class LOCKABLE SelfLockDeferred2 {4721public:4722 SelfLockDeferred2() LOCKS_EXCLUDED(this);4723 ~SelfLockDeferred2() UNLOCK_FUNCTION();4724};4725 4726 4727void test() {4728 SelfLock s;4729 s.foo();4730}4731 4732void test2() {4733 SelfLock2 s2;4734 s2.foo();4735}4736 4737void testDeferredTemporary() {4738 SelfLockDeferred(); // expected-warning {{releasing mutex '<temporary>.mu_' that was not held}}4739}4740 4741void testDeferredTemporary2() {4742 SelfLockDeferred2(); // expected-warning {{releasing mutex '<temporary>' that was not held}}4743}4744 4745} // end namespace SelfConstructorTest4746 4747 4748namespace MultipleAttributeTest {4749 4750class Foo {4751 Mutex mu1_;4752 Mutex mu2_;4753 int a GUARDED_BY(mu1_);4754 int b GUARDED_BY(mu2_);4755 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);4756 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);4757 4758 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)4759 EXCLUSIVE_LOCKS_REQUIRED(mu2_);4760 void foo2() SHARED_LOCKS_REQUIRED(mu1_)4761 SHARED_LOCKS_REQUIRED(mu2_);4762 void foo3() LOCKS_EXCLUDED(mu1_)4763 LOCKS_EXCLUDED(mu2_);4764 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)4765 EXCLUSIVE_LOCK_FUNCTION(mu2_);4766 void readerlock() SHARED_LOCK_FUNCTION(mu1_)4767 SHARED_LOCK_FUNCTION(mu2_);4768 void unlock() UNLOCK_FUNCTION(mu1_)4769 UNLOCK_FUNCTION(mu2_);4770 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)4771 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);4772 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)4773 SHARED_TRYLOCK_FUNCTION(true, mu2_);4774 void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)4775 ASSERT_EXCLUSIVE_LOCK(mu2_);4776 4777 void alsoAssertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_, mu2_);4778 4779 void assertShared() ASSERT_SHARED_LOCK(mu1_)4780 ASSERT_SHARED_LOCK(mu2_);4781 4782 void alsoAssertShared() ASSERT_SHARED_LOCK(mu1_, mu2_);4783 4784 void test();4785 void testAssert();4786 void testAssertShared();4787};4788 4789 4790void Foo::foo1() {4791 a = 1;4792 b = 2;4793}4794 4795void Foo::foo2() {4796 int result = a + b;4797}4798 4799void Foo::foo3() { }4800void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }4801void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }4802void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }4803bool Foo::trylock() { return true; }4804bool Foo::readertrylock() { return true; }4805 4806 4807void Foo::test() {4808 mu1_.Lock();4809 foo1(); // expected-warning {{}}4810 c = 0; // expected-warning {{}}4811 *d = 0; // expected-warning {{}}4812 mu1_.Unlock();4813 4814 mu1_.ReaderLock();4815 foo2(); // expected-warning {{}}4816 int x = c; // expected-warning {{}}4817 int y = *d; // expected-warning {{}}4818 mu1_.Unlock();4819 4820 mu2_.Lock();4821 foo3(); // expected-warning {{}}4822 mu2_.Unlock();4823 4824 lock();4825 a = 0;4826 b = 0;4827 unlock();4828 4829 readerlock();4830 int z = a + b;4831 unlock();4832 4833 if (trylock()) {4834 a = 0;4835 b = 0;4836 unlock();4837 }4838 4839 if (readertrylock()) {4840 int zz = a + b;4841 unlock();4842 }4843}4844 4845// Force duplication of attributes4846void Foo::assertBoth() { }4847void Foo::alsoAssertBoth() { }4848void Foo::assertShared() { }4849void Foo::alsoAssertShared() { }4850 4851void Foo::testAssert() {4852 {4853 assertBoth();4854 a = 0;4855 b = 0;4856 }4857 {4858 alsoAssertBoth();4859 a = 0;4860 b = 0;4861 }4862}4863 4864void Foo::testAssertShared() {4865 {4866 assertShared();4867 int zz = a + b;4868 }4869 4870 {4871 alsoAssertShared();4872 int zz = a + b;4873 }4874}4875 4876 4877} // end namespace MultipleAttributeTest4878 4879 4880namespace GuardedNonPrimitiveTypeTest {4881 4882 4883class Data {4884public:4885 Data(int i) : dat(i) { }4886 4887 int getValue() const { return dat; }4888 void setValue(int i) { dat = i; }4889 4890 int operator[](int i) const { return dat; }4891 int& operator[](int i) { return dat; }4892 4893 void operator()() { }4894 4895 Data& operator+=(int);4896 Data& operator-=(int);4897 Data& operator*=(int);4898 Data& operator/=(int);4899 Data& operator%=(int);4900 Data& operator^=(int);4901 Data& operator&=(int);4902 Data& operator|=(int);4903 Data& operator<<=(int);4904 Data& operator>>=(int);4905 Data& operator++();4906 Data& operator++(int);4907 Data& operator--();4908 Data& operator--(int);4909 4910private:4911 int dat;4912};4913 4914class DataWithAddrOf : public Data {4915public:4916 const Data* operator&();4917 const Data* operator&() const;4918};4919 4920class DataCell {4921public:4922 DataCell(const Data& d) : dat(d) { }4923 4924private:4925 Data dat;4926};4927 4928 4929void showData(const Data* d);4930void showDataCell(const DataCell& dc);4931 4932 4933class Foo {4934public:4935 // method call tests4936 void test() {4937 data_.setValue(0); // FIXME -- should be writing \4938 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}4939 int a = data_.getValue(); // \4940 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}4941 4942 datap1_->setValue(0); // FIXME -- should be writing \4943 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}4944 a = datap1_->getValue(); // \4945 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}4946 4947 datap2_->setValue(0); // FIXME -- should be writing \4948 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4949 a = datap2_->getValue(); // \4950 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4951 4952 (*datap2_).setValue(0); // FIXME -- should be writing \4953 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4954 a = (*datap2_).getValue(); // \4955 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4956 4957 mu_.Lock();4958 data_.setValue(1);4959 datap1_->setValue(1);4960 datap2_->setValue(1);4961 mu_.Unlock();4962 4963 mu_.ReaderLock();4964 a = data_.getValue();4965 datap1_->setValue(0); // reads datap1_, writes *datap1_4966 a = datap1_->getValue();4967 a = datap2_->getValue();4968 mu_.Unlock();4969 }4970 4971 // operator tests4972 void test2() {4973 data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4974 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \4975 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}4976 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \4977 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}4978 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \4979 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}4980 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \4981 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4982 data_ += 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4983 data_ -= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4984 data_ *= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4985 data_ /= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4986 data_ %= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4987 data_ ^= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4988 data_ &= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4989 data_ |= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4990 data_ <<= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4991 data_ >>= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4992 ++data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4993 data_++; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4994 --data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4995 data_--; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}4996 4997 data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}4998 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}4999 5000 data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}5001 5002 // Calls operator&, and does not take the address.5003 (void)&data_ao_; // expected-warning {{reading variable 'data_ao_' requires holding mutex 'mu_'}}5004 (void)__builtin_addressof(data_ao_); // expected-warning {{passing variable 'data_ao_' by reference requires holding mutex 'mu_'}}5005 showData(&data_ao_); // expected-warning {{reading variable 'data_ao_' requires holding mutex 'mu_'}}5006 }5007 5008 // const operator tests5009 void test3() const {5010 Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}5011 5012 //FIXME5013 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}5014 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}5015 5016 int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}5017 5018 (void)&data_ao_; // expected-warning {{reading variable 'data_ao_' requires holding mutex 'mu_'}}5019 showData(&data_ao_); // expected-warning {{reading variable 'data_ao_' requires holding mutex 'mu_'}}5020 }5021 5022private:5023 Mutex mu_;5024 Data data_ GUARDED_BY(mu_);5025 Data* datap1_ GUARDED_BY(mu_);5026 Data* datap2_ PT_GUARDED_BY(mu_);5027 DataWithAddrOf data_ao_ GUARDED_BY(mu_);5028};5029 5030} // end namespace GuardedNonPrimitiveTypeTest5031 5032 5033namespace GuardedNonPrimitive_MemberAccess {5034 5035class Cell {5036public:5037 Cell(int i);5038 5039 void cellMethod();5040 5041 int a;5042};5043 5044 5045class Foo {5046public:5047 int a;5048 Cell c GUARDED_BY(cell_mu_);5049 Cell* cp PT_GUARDED_BY(cell_mu_);5050 5051 void myMethod();5052 5053 Mutex cell_mu_;5054};5055 5056 5057class Bar {5058private:5059 Mutex mu_;5060 Foo foo GUARDED_BY(mu_);5061 Foo* foop PT_GUARDED_BY(mu_);5062 5063 void test() {5064 foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}5065 5066 int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}5067 foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}5068 5069 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}5070 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}5071 5072 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}5073 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}5074 5075 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \5076 // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}5077 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \5078 // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}5079 5080 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \5081 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}5082 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \5083 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}5084 5085 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \5086 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}5087 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \5088 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}5089 };5090};5091 5092} // namespace GuardedNonPrimitive_MemberAccess5093 5094 5095namespace TestThrowExpr {5096 5097class Foo {5098 Mutex mu_;5099 5100 bool hasError();5101 5102 void test() {5103 mu_.Lock();5104 if (hasError()) {5105 throw "ugly";5106 }5107 mu_.Unlock();5108 }5109};5110 5111} // end namespace TestThrowExpr5112 5113 5114namespace UnevaluatedContextTest {5115 5116// parse attribute expressions in an unevaluated context.5117 5118static inline Mutex* getMutex1();5119static inline Mutex* getMutex2();5120 5121void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());5122 5123void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());5124 5125} // end namespace UnevaluatedContextTest5126 5127 5128namespace LockUnlockFunctionTest {5129 5130// Check built-in lock functions5131class LOCKABLE MyLockable {5132public:5133 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }5134 void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }5135 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }5136 5137private:5138 Mutex mu_;5139};5140 5141 5142class Foo {5143public:5144 // Correct lock/unlock functions5145 void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {5146 mu_.Lock();5147 }5148 5149 void readerLock() SHARED_LOCK_FUNCTION(mu_) {5150 mu_.ReaderLock();5151 }5152 5153 void unlock() UNLOCK_FUNCTION(mu_) {5154 mu_.Unlock();5155 }5156 5157 void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) {5158 mu_.Unlock();5159 }5160 5161 void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) {5162 mu_.ReaderUnlock();5163 }5164 5165 // Check failure to lock.5166 void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5167 mu2_.Lock();5168 mu2_.Unlock();5169 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}5170 5171 void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5172 mu2_.Lock();5173 mu2_.Unlock();5174 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}5175 5176 void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5177 mu2_.Lock();5178 mu2_.Unlock();5179 } // expected-warning {{mutex 'mu_' is still held at the end of function}}5180 5181 // Check locking the wrong thing.5182 void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5183 mu2_.Lock(); // expected-note {{mutex acquired here}}5184 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \5185 // expected-warning {{mutex 'mu2_' is still held at the end of function}}5186 5187 5188 void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5189 mu2_.ReaderLock(); // expected-note {{mutex acquired here}}5190 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \5191 // expected-warning {{mutex 'mu2_' is still held at the end of function}}5192 5193 5194 void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}5195 mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}5196 } // expected-warning {{mutex 'mu_' is still held at the end of function}}5197 5198private:5199 Mutex mu_;5200 Mutex mu2_;5201};5202 5203} // end namespace LockUnlockFunctionTest5204 5205 5206namespace AssertHeldTest {5207 5208class Foo {5209public:5210 int c;5211 int a GUARDED_BY(mu_);5212 Mutex mu_;5213 5214 void test1() {5215 mu_.AssertHeld();5216 int b = a;5217 a = 0;5218 }5219 5220 void test2() {5221 mu_.AssertReaderHeld();5222 int b = a;5223 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}5224 }5225 5226 void test3() {5227 if (c) {5228 mu_.AssertHeld();5229 }5230 else {5231 mu_.AssertHeld();5232 }5233 int b = a;5234 a = 0;5235 }5236 5237 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {5238 mu_.AssertHeld();5239 int b = a;5240 a = 0;5241 }5242 5243 void test5() UNLOCK_FUNCTION(mu_) {5244 mu_.AssertHeld();5245 mu_.Unlock();5246 }5247 5248 void test6() {5249 mu_.AssertHeld();5250 mu_.Unlock(); // should this be a warning?5251 }5252 5253 void test7() {5254 if (c) {5255 mu_.AssertHeld();5256 }5257 else {5258 mu_.Lock();5259 }5260 int b = a;5261 a = 0;5262 mu_.Unlock();5263 }5264 5265 void test8() {5266 if (c) {5267 mu_.Lock();5268 }5269 else {5270 mu_.AssertHeld();5271 }5272 // FIXME: should warn, because it's unclear whether we need to release or not.5273 int b = a;5274 a = 0;5275 mu_.Unlock(); // should this be a warning?5276 }5277 5278 void test9() {5279 if (c) {5280 mu_.AssertHeld();5281 }5282 else {5283 mu_.Lock(); // expected-note {{mutex acquired here}}5284 }5285 } // expected-warning {{mutex 'mu_' is still held at the end of function}}5286 5287 void test10() {5288 if (c) {5289 mu_.Lock(); // expected-note {{mutex acquired here}}5290 }5291 else {5292 mu_.AssertHeld();5293 }5294 } // expected-warning {{mutex 'mu_' is still held at the end of function}}5295 5296 void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);5297 5298 void test11() {5299 assertMu();5300 int b = a;5301 a = 0;5302 }5303 5304 void test12() {5305 if (c)5306 mu_.ReaderLock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}5307 else5308 mu_.AssertHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}5309 // FIXME: should instead warn because it's unclear whether we need to release or not.5310 int b = a;5311 a = 0;5312 mu_.Unlock();5313 }5314 5315 void test13() {5316 if (c)5317 mu_.Lock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}5318 else5319 mu_.AssertReaderHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}5320 // FIXME: should instead warn because it's unclear whether we need to release or not.5321 int b = a;5322 a = 0;5323 mu_.Unlock();5324 }5325};5326 5327} // end namespace AssertHeldTest5328 5329 5330namespace LogicalConditionalTryLock {5331 5332class Foo {5333public:5334 Mutex mu;5335 int a GUARDED_BY(mu);5336 bool c;5337 5338 bool newc();5339 5340 void test1() {5341 if (c && mu.TryLock()) {5342 a = 0;5343 mu.Unlock();5344 }5345 }5346 5347 void test2() {5348 bool b = mu.TryLock();5349 if (c && b) {5350 a = 0;5351 mu.Unlock();5352 }5353 }5354 5355 void test3() {5356 if (c || !mu.TryLock())5357 return;5358 a = 0;5359 mu.Unlock();5360 }5361 5362 void test4() {5363 while (c && mu.TryLock()) {5364 a = 0;5365 c = newc();5366 mu.Unlock();5367 }5368 }5369 5370 void test5() {5371 while (c) {5372 if (newc() || !mu.TryLock())5373 break;5374 a = 0;5375 mu.Unlock();5376 }5377 }5378 5379 void test6() {5380 mu.Lock();5381 do {5382 a = 0;5383 mu.Unlock();5384 } while (newc() && mu.TryLock());5385 }5386 5387 void test7() {5388 for (bool b = mu.TryLock(); c && b;) {5389 a = 0;5390 mu.Unlock();5391 }5392 }5393 5394 void test8() {5395 if (c && newc() && mu.TryLock()) {5396 a = 0;5397 mu.Unlock();5398 }5399 }5400 5401 void test9() {5402 if (!(c && newc() && mu.TryLock()))5403 return;5404 a = 0;5405 mu.Unlock();5406 }5407 5408 void test10() {5409 if (!(c || !mu.TryLock())) {5410 a = 0;5411 mu.Unlock();5412 }5413 }5414};5415 5416} // end namespace LogicalConditionalTryLock5417 5418 5419 5420namespace PtGuardedByTest {5421 5422void doSomething();5423 5424class Cell {5425 public:5426 int a;5427};5428 5429 5430// This mainly duplicates earlier tests, but just to make sure...5431class PtGuardedByCorrectnessTest {5432 Mutex mu1;5433 Mutex mu2;5434 int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);5435 Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);5436 int sa[10] GUARDED_BY(mu1);5437 Cell sc[10] GUARDED_BY(mu1);5438 5439 static constexpr int Cell::*pa = &Cell::a;5440 5441 void test1() {5442 mu1.Lock();5443 if (a == 0) doSomething(); // OK, we don't dereference.5444 a = 0;5445 c = 0;5446 if (sa[0] == 42) doSomething();5447 sa[0] = 57;5448 if (sc[0].a == 42) doSomething();5449 sc[0].a = 57;5450 mu1.Unlock();5451 }5452 5453 void test2() {5454 mu1.ReaderLock();5455 if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}5456 *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}5457 5458 if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}5459 c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}5460 c->*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}5461 5462 if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}5463 (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}5464 (*c).*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}5465 5466 if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}5467 a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}5468 if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}5469 c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}5470 mu1.Unlock();5471 }5472 5473 void test3() {5474 mu2.Lock();5475 if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}5476 *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}5477 5478 if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5479 c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5480 5481 if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5482 (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5483 5484 if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}5485 a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}5486 if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5487 c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}5488 mu2.Unlock();5489 }5490 5491 void test4() { // Literal arrays5492 if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}5493 sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}5494 if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}5495 sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}5496 sc[0].*pa = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}5497 5498 if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}5499 *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}5500 if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}5501 (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}5502 if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}5503 sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}5504 }5505 5506 void test5() {5507 mu1.ReaderLock(); // OK -- correct use.5508 mu2.Lock();5509 if (*a == 0) doSomething();5510 *a = 0;5511 5512 if (c->a == 0) doSomething();5513 c->a = 0;5514 5515 if ((*c).a == 0) doSomething();5516 (*c).a = 0;5517 mu2.Unlock();5518 mu1.Unlock();5519 }5520};5521 5522 5523class SmartPtr_PtGuardedBy_Test {5524 Mutex mu1;5525 Mutex mu2;5526 SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);5527 SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);5528 5529 static constexpr int Cell::*pa = &Cell::a;5530 5531 void test1() {5532 mu1.ReaderLock();5533 mu2.Lock();5534 5535 sp.get();5536 if (*sp == 0) doSomething();5537 *sp = 0;5538 sq->a = 0;5539 sq->*pa = 0;5540 5541 if (sp[0] == 0) doSomething();5542 sp[0] = 0;5543 5544 mu2.Unlock();5545 mu1.Unlock();5546 }5547 5548 void test2() {5549 mu2.Lock();5550 5551 sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}5552 if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}5553 *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}5554 sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}5555 sq->*pa = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}5556 5557 if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}5558 sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}5559 if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}5560 sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}5561 5562 mu2.Unlock();5563 }5564 5565 void test3() {5566 mu1.Lock();5567 5568 sp.get();5569 if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}5570 *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}5571 sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}5572 sq->*pa = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}5573 5574 if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}5575 sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}5576 if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}5577 sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}5578 5579 mu1.Unlock();5580 }5581};5582 5583} // end namespace PtGuardedByTest5584 5585 5586namespace NonMemberCalleeICETest {5587 5588class A {5589 void Run() {5590 (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}5591 }5592 5593 void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M);5594 Mutex M;5595};5596 5597} // end namespace NonMemberCalleeICETest5598 5599 5600namespace pt_guard_attribute_type {5601 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}5602 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}5603 5604 void test() {5605 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to non-static data members and global variables}}5606 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to non-static data members and global variables}}5607 5608 typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to}}5609 typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to}}5610 }5611} // end namespace pt_guard_attribute_type5612 5613 5614namespace ThreadAttributesOnLambdas {5615 5616class Foo {5617 Mutex mu_;5618 5619 void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);5620 5621 void test() {5622 auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {5623 LockedFunction();5624 };5625 5626 auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {5627 LockedFunction();5628 };5629 5630 auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {5631 mu_.Lock();5632 };5633 5634 func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}5635 func1.operator()(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}5636 func2();5637 func2.operator()();5638 func3();5639 mu_.Unlock();5640 func3.operator()();5641 mu_.Unlock();5642 }5643};5644 5645} // end namespace ThreadAttributesOnLambdas5646 5647 5648 5649namespace AttributeExpressionCornerCases {5650 5651class Foo {5652 int a GUARDED_BY(getMu());5653 5654 Mutex* getMu() LOCK_RETURNED("");5655 Mutex* getUniv() LOCK_RETURNED("*");5656 5657 void test1() {5658 a = 0;5659 }5660 5661 void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {5662 a = 0;5663 }5664 5665 void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);5666 5667 void test3() {5668 foo(nullptr);5669 }5670};5671 5672 5673class MapTest {5674 struct MuCell { Mutex* mu; };5675 5676 MyMap<MyString, Mutex*> map;5677 MyMap<MyString, MuCell> mapCell;5678 5679 int a GUARDED_BY(map["foo"]);5680 int b GUARDED_BY(mapCell["foo"].mu);5681 5682 void test() {5683 map["foo"]->Lock();5684 a = 0;5685 map["foo"]->Unlock();5686 }5687 5688 void test2() {5689 mapCell["foo"].mu->Lock();5690 b = 0;5691 mapCell["foo"].mu->Unlock();5692 }5693};5694 5695 5696class PreciseSmartPtr {5697 SmartPtr<Mutex> mu;5698 int val GUARDED_BY(mu);5699 5700 static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {5701 a.mu->Lock();5702 bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \5703 // expected-note {{found near match 'a.mu'}}5704 a.mu->Unlock();5705 return result;5706 }5707};5708 5709 5710class SmartRedeclare {5711 SmartPtr<Mutex> mu;5712 int val GUARDED_BY(mu);5713 5714 void test() EXCLUSIVE_LOCKS_REQUIRED(mu);5715 void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());5716 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());5717};5718 5719 5720void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {5721 val = 0;5722}5723 5724void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {5725 val = 0;5726}5727 5728void SmartRedeclare::test3() {5729 val = 0;5730}5731 5732 5733namespace CustomMutex {5734 5735 5736class LOCKABLE BaseMutex { };5737class DerivedMutex : public BaseMutex { };5738 5739void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);5740void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);5741 5742static struct DerivedMutex custMu;5743 5744static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }5745 5746void customTest() {5747 customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts5748 doSomethingRequiringLock();5749 customUnlock(reinterpret_cast<BaseMutex*>(&custMu));5750}5751 5752} // end namespace CustomMutex5753 5754} // end AttributeExpressionCornerCases5755 5756 5757namespace ScopedLockReturnedInvalid {5758 5759class Opaque;5760 5761Mutex* getMutex(Opaque* o) LOCK_RETURNED("");5762 5763void test(Opaque* o) {5764 MutexLock lock(getMutex(o));5765}5766 5767} // end namespace ScopedLockReturnedInvalid5768 5769 5770namespace NegativeRequirements {5771 5772class Bar {5773 Mutex mu;5774 int a GUARDED_BY(mu);5775 5776public:5777 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {5778 mu.Lock();5779 a = 0;5780 mu.Unlock();5781 }5782};5783 5784 5785class Foo {5786 Mutex mu;5787 int a GUARDED_BY(mu);5788 5789public:5790 void foo() {5791 mu.Lock(); // warning? needs !mu?5792 baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}5793 bar();5794 mu.Unlock();5795 }5796 5797 void bar() {5798 bar2(); // expected-warning {{calling function 'bar2' requires negative capability '!mu'}}5799 }5800 5801 void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {5802 baz();5803 }5804 5805 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {5806 mu.Lock();5807 a = 0;5808 mu.Unlock();5809 }5810 5811 void test() {5812 Bar b;5813 b.baz(); // no warning -- in different class.5814 }5815};5816 5817} // end namespace NegativeRequirements5818 5819 5820namespace NegativeThreadRoles {5821 5822typedef int __attribute__((capability("role"))) ThreadRole;5823 5824void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}5825void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}5826 5827ThreadRole FlightControl, Logger;5828 5829extern void enque_log_msg(const char *msg);5830void log_msg(const char *msg) {5831 enque_log_msg(msg);5832}5833 5834void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}5835void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}5836 5837void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {5838 dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while role 'FlightControl' is held}} */5839 dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */5840}5841 5842void spawn_fake_flight_control_thread(void) {5843 acquire(FlightControl);5844 flight_control_entry();5845 release(FlightControl);5846}5847 5848extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));5849void logger_entry(void) __attribute__((requires_capability(Logger)))5850 __attribute__((requires_capability(!FlightControl))) {5851 const char *msg;5852 5853 while ((msg = deque_log_msg())) {5854 dispatch_log(msg);5855 }5856}5857 5858void spawn_fake_logger_thread(void) __attribute__((requires_capability(!FlightControl))) {5859 acquire(Logger);5860 logger_entry();5861 release(Logger);5862}5863 5864int main(void) __attribute__((requires_capability(!FlightControl))) {5865 spawn_fake_flight_control_thread();5866 spawn_fake_logger_thread();5867 5868 for (;;)5869 ; /* Pretend to dispatch things. */5870 5871 return 0;5872}5873 5874} // end namespace NegativeThreadRoles5875 5876 5877namespace AssertSharedExclusive {5878 5879void doSomething();5880 5881class Foo {5882 Mutex mu;5883 int a GUARDED_BY(mu);5884 5885 void test() SHARED_LOCKS_REQUIRED(mu) {5886 mu.AssertHeld();5887 if (a > 0)5888 doSomething();5889 }5890};5891 5892} // end namespace AssertSharedExclusive5893 5894 5895namespace RangeBasedForAndReferences {5896 5897class Foo {5898 struct MyStruct {5899 int a;5900 };5901 5902 Mutex mu;5903 int a GUARDED_BY(mu);5904 MyContainer<int> cntr GUARDED_BY(mu);5905 MyStruct s GUARDED_BY(mu);5906 int arr[10] GUARDED_BY(mu);5907 5908 void nonref_test() {5909 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}5910 b = 0; // no warning5911 }5912 5913 void auto_test() {5914 auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}5915 b = 0; // no warning5916 auto &c = a; // no warning5917 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}5918 }5919 5920 void ref_test() {5921 int &b = a;5922 int &c = b;5923 int &d = c;5924 b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}5925 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}5926 d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}5927 5928 MyStruct &rs = s;5929 rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}5930 5931 int (&rarr)[10] = arr;5932 rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}5933 }5934 5935 void ptr_test() {5936 int *b = &a;5937 *b = 0; // no expected warning yet5938 }5939 5940 void for_test() {5941 int total = 0;5942 for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}5943 total += i;5944 }5945 }5946};5947 5948 5949} // end namespace RangeBasedForAndReferences5950 5951 5952 5953namespace PassByRefTest {5954 5955class Foo {5956public:5957 Foo() : a(0), b(0) { }5958 5959 int a;5960 int b;5961 5962 void operator+(const Foo& f);5963 5964 void operator[](const Foo& g);5965 5966 void operator()();5967};5968 5969template<class T>5970T&& mymove(T& f);5971 5972 5973// test top-level functions5974void copy(Foo f);5975void write1(Foo& f);5976void write2(int a, Foo& f);5977void write3(Foo* f);5978void write4(Foo** f);5979void read1(const Foo& f);5980void read2(int a, const Foo& f);5981void read3(const Foo* f);5982void read4(Foo* const* f);5983void destroy(Foo&& f);5984 5985void operator/(const Foo& f, const Foo& g);5986void operator*(const Foo& f, const Foo& g);5987 5988// Test constructors.5989struct FooRead {5990 FooRead(const Foo &);5991};5992struct FooWrite {5993 FooWrite(Foo &);5994};5995 5996// Test variadic functions5997template<typename... T>5998void copyVariadic(T...) {}5999template<typename... T>6000void writeVariadic(T&...) {}6001template<typename... T>6002void readVariadic(const T&...) {}6003 6004void copyVariadicC(int, ...);6005 6006class Bar {6007public:6008 Mutex mu;6009 Foo foo GUARDED_BY(mu);6010 Foo foo2 GUARDED_BY(mu);6011 Foo* foop PT_GUARDED_BY(mu);6012 Foo* foop2 GUARDED_BY(mu);6013 SmartPtr<Foo> foosp PT_GUARDED_BY(mu);6014 6015 // test methods.6016 void mwrite1(Foo& f);6017 void mwrite2(int a, Foo& f);6018 void mwrite3(Foo* f);6019 void mread1(const Foo& f);6020 void mread2(int a, const Foo& f);6021 void mread3(const Foo* f);6022 6023 // static methods6024 static void smwrite1(Foo& f);6025 static void smwrite2(int a, Foo& f);6026 static void smwrite3(Foo* f);6027 static void smread1(const Foo& f);6028 static void smread2(int a, const Foo& f);6029 static void smread3(const Foo* f);6030 6031 void operator<<(const Foo& f);6032 6033 void test1() {6034 copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6035 write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6036 write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6037 read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6038 read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6039 destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6040 6041 copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6042 readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6043 writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6044 copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6045 6046 FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6047 FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6048 6049 mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6050 mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6051 mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6052 mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6053 6054 smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6055 smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6056 smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6057 smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6058 6059 foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \6060 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}6061 foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \6062 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}6063 foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \6064 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}6065 foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \6066 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}6067 foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6068 (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}6069 6070 copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}6071 write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}6072 write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}6073 read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}6074 read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}6075 destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}6076 6077 copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6078 write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6079 write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6080 read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6081 read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6082 destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}6083 6084 // TODO -- these require better smart pointer handling.6085 copy(*foosp.get());6086 write1(*foosp.get());6087 write2(10, *foosp.get());6088 read1(*foosp.get());6089 read2(10, *foosp.get());6090 destroy(mymove(*foosp.get()));6091 }6092 6093 void test_pass_pointer() {6094 (void)&foo; // no warning6095 (void)foop; // no warning6096 6097 write3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6098 write3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6099 write3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6100 write4((Foo **)&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6101 write4(&foop); // no warning6102 read3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6103 read3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6104 read3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6105 read4((Foo **)&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6106 read4(&foop); // no warning6107 mwrite3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6108 mwrite3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6109 mwrite3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6110 mread3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6111 mread3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6112 mread3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6113 smwrite3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6114 smwrite3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6115 smwrite3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6116 smread3(&foo); // expected-warning {{passing pointer to variable 'foo' requires holding mutex 'mu'}}6117 smread3(foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6118 smread3(&*foop); // expected-warning {{passing pointer 'foop' requires holding mutex 'mu'}}6119 6120 write3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6121 write3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6122 write4(&foop2); // expected-warning {{passing pointer to variable 'foop2' requires holding mutex 'mu'}}6123 read3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6124 read3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6125 read4(&foop2); // expected-warning {{passing pointer to variable 'foop2' requires holding mutex 'mu'}}6126 mwrite3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6127 mwrite3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6128 mread3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6129 mread3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6130 smwrite3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6131 smwrite3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6132 smread3(foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6133 smread3(&*foop2); // expected-warning {{reading variable 'foop2' requires holding mutex 'mu'}}6134 6135 mu.Lock();6136 write3(&foo);6137 write3(foop);6138 write3(&*foop);6139 write3(foop2);6140 write4(&foop2);6141 read3(&foo);6142 read3(foop);6143 read3(&*foop);6144 read3(foop2);6145 read4(&foop2);6146 mwrite3(&foo);6147 mwrite3(foop);6148 mwrite3(&*foop);6149 mwrite3(foop2);6150 mread3(&foo);6151 mread3(foop);6152 mread3(&*foop);6153 mread3(foop2);6154 smwrite3(&foo);6155 smwrite3(foop);6156 smwrite3(&*foop);6157 smwrite3(foop2);6158 smread3(&foo);6159 smread3(foop);6160 smread3(&*foop);6161 smread3(foop2);6162 mu.Unlock();6163 6164 mu.ReaderLock();6165 write3(&foo);6166 write3(foop);6167 write3(&*foop);6168 write3(foop2);6169 write4(&foop2);6170 read3(&foo);6171 read3(foop);6172 read3(&*foop);6173 read3(foop2);6174 read4(&foop2);6175 mwrite3(&foo);6176 mwrite3(foop);6177 mwrite3(&*foop);6178 mwrite3(foop2);6179 mread3(&foo);6180 mread3(foop);6181 mread3(&*foop);6182 mread3(foop2);6183 smwrite3(&foo);6184 smwrite3(foop);6185 smwrite3(&*foop);6186 smwrite3(foop2);6187 smread3(&foo);6188 smread3(foop);6189 smread3(&*foop);6190 smread3(foop2);6191 mu.ReaderUnlock();6192 }6193};6194 6195class Return {6196 Mutex mu;6197 Foo foo GUARDED_BY(mu);6198 Foo* foo_ptr PT_GUARDED_BY(mu);6199 Foo foo_depr GUARDED_VAR; // test deprecated attribute6200 Foo* foo_ptr_depr PT_GUARDED_VAR; // test deprecated attribute6201 6202 Foo returns_value_locked() {6203 MutexLock lock(&mu);6204 return foo;6205 }6206 6207 Foo returns_value_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {6208 return foo;6209 }6210 6211 Foo returns_value_releases_lock_after_return() UNLOCK_FUNCTION(mu) {6212 MutexLock lock(&mu, true);6213 return foo;6214 }6215 6216 Foo returns_value_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {6217 mu.Lock();6218 return foo;6219 }6220 6221 Foo returns_value_not_locked() {6222 return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6223 }6224 6225 Foo returns_value_releases_lock_before_return() UNLOCK_FUNCTION(mu) {6226 mu.Unlock();6227 return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}6228 }6229 6230 Foo &returns_ref_not_locked() {6231 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}6232 }6233 6234 Foo &returns_ref_locked() {6235 MutexLock lock(&mu);6236 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}6237 }6238 6239 Foo &returns_ref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6240 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}6241 }6242 6243 Foo &returns_ref_exclusive_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {6244 return foo;6245 }6246 6247 Foo &returns_ref_releases_lock_after_return() UNLOCK_FUNCTION(mu) {6248 MutexLock lock(&mu, true);6249 return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}6250 }6251 6252 Foo& returns_ref_releases_lock_before_return() UNLOCK_FUNCTION(mu) {6253 mu.Unlock();6254 return foo; // // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}6255 }6256 6257 Foo &returns_ref_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {6258 mu.Lock();6259 return foo;6260 }6261 6262 const Foo &returns_constref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6263 return foo;6264 }6265 6266 Foo *returns_ptr_exclusive_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {6267 return &foo;6268 }6269 6270 Foo *returns_pt_ptr_exclusive_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {6271 return foo_ptr;6272 }6273 6274 Foo *returns_ptr_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6275 return &foo; // expected-warning {{returning pointer to variable 'foo' requires holding mutex 'mu' exclusively}}6276 }6277 6278 Foo *returns_pt_ptr_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6279 return foo_ptr; // expected-warning {{returning pointer 'foo_ptr' requires holding mutex 'mu' exclusively}}6280 }6281 6282 const Foo *returns_constptr_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6283 return &foo;6284 }6285 6286 const Foo *returns_pt_constptr_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {6287 return foo_ptr;6288 }6289 6290 Foo *returns_ptr() {6291 return &foo; // expected-warning {{returning pointer to variable 'foo' requires holding mutex 'mu' exclusively}}6292 }6293 6294 Foo *returns_pt_ptr() {6295 return foo_ptr; // expected-warning {{returning pointer 'foo_ptr' requires holding mutex 'mu' exclusively}}6296 }6297 6298 Foo &returns_ref2() {6299 return *foo_ptr; // expected-warning {{returning the value that 'foo_ptr' points to by reference requires holding mutex 'mu' exclusively}}6300 }6301 6302 Foo *returns_ptr_deprecated() {6303 return &foo_depr; // expected-warning {{writing variable 'foo_depr' requires holding any mutex exclusively}}6304 }6305 6306 Foo *returns_pt_ptr_deprecated() {6307 return foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}}6308 }6309 6310 Foo &returns_ref_deprecated() {6311 return *foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}}6312 }6313 6314 // FIXME: Basic alias analysis would help catch cases like below.6315 Foo *returns_ptr_alias() {6316 mu.Lock();6317 Foo *ret = &foo;6318 mu.Unlock();6319 return ret; // no warning (false negative)6320 }6321 6322 Foo *returns_pt_ptr_alias() {6323 mu.Lock();6324 Foo *ret = foo_ptr;6325 mu.Unlock();6326 return ret; // no warning (false negative)6327 }6328 6329 Foo &returns_ref2_alias() {6330 mu.Lock();6331 Foo *ret = foo_ptr;6332 mu.Unlock();6333 return *ret; // no warning (false negative)6334 }6335};6336 6337 6338} // end namespace PassByRefTest6339 6340 6341namespace AcquiredBeforeAfterText {6342 6343class Foo {6344 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);6345 Mutex mu2;6346 Mutex mu3;6347 6348 void test1() {6349 mu1.Lock();6350 mu2.Lock();6351 mu3.Lock();6352 6353 mu3.Unlock();6354 mu2.Unlock();6355 mu1.Unlock();6356 }6357 6358 void test2() {6359 mu2.Lock();6360 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}6361 mu1.Unlock();6362 mu2.Unlock();6363 }6364 6365 void test3() {6366 mu3.Lock();6367 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}6368 mu1.Unlock();6369 mu3.Unlock();6370 }6371 6372 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {6373 mu2.Lock();6374 mu2.Unlock();6375 }6376 6377 void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {6378 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}6379 mu1.Unlock();6380 }6381 6382 void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {6383 mu1.AssertHeld();6384 }6385 6386 void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }6387 6388 void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }6389};6390 6391 6392class Foo2 {6393 Mutex mu1;6394 Mutex mu2 ACQUIRED_AFTER(mu1);6395 Mutex mu3 ACQUIRED_AFTER(mu1);6396 6397 void test1() {6398 mu1.Lock();6399 mu2.Lock();6400 mu3.Lock();6401 6402 mu3.Unlock();6403 mu2.Unlock();6404 mu1.Unlock();6405 }6406 6407 void test2() {6408 mu2.Lock();6409 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}6410 mu1.Unlock();6411 mu2.Unlock();6412 }6413 6414 void test3() {6415 mu3.Lock();6416 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}6417 mu1.Unlock();6418 mu3.Unlock();6419 }6420};6421 6422 6423class Foo3 {6424 Mutex mu1 ACQUIRED_BEFORE(mu2);6425 Mutex mu2;6426 Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);6427 Mutex mu4;6428 6429 void test1() {6430 mu1.Lock();6431 mu2.Lock();6432 mu3.Lock();6433 mu4.Lock();6434 6435 mu4.Unlock();6436 mu3.Unlock();6437 mu2.Unlock();6438 mu1.Unlock();6439 }6440 6441 void test2() {6442 mu4.Lock();6443 mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}6444 6445 mu2.Unlock();6446 mu4.Unlock();6447 }6448 6449 void test3() {6450 mu4.Lock();6451 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}6452 6453 mu1.Unlock();6454 mu4.Unlock();6455 }6456 6457 void test4() {6458 mu3.Lock();6459 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}6460 6461 mu1.Unlock();6462 mu3.Unlock();6463 }6464};6465 6466 6467// Test transitive DAG traversal with AFTER6468class Foo4 {6469 Mutex mu1;6470 Mutex mu2 ACQUIRED_AFTER(mu1);6471 Mutex mu3 ACQUIRED_AFTER(mu1);6472 Mutex mu4 ACQUIRED_AFTER(mu2, mu3);6473 Mutex mu5 ACQUIRED_AFTER(mu4);6474 Mutex mu6 ACQUIRED_AFTER(mu4);6475 Mutex mu7 ACQUIRED_AFTER(mu5, mu6);6476 Mutex mu8 ACQUIRED_AFTER(mu7);6477 6478 void test() {6479 mu8.Lock();6480 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}6481 mu1.Unlock();6482 mu8.Unlock();6483 }6484};6485 6486 6487// Test transitive DAG traversal with BEFORE6488class Foo5 {6489 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);6490 Mutex mu2 ACQUIRED_BEFORE(mu4);6491 Mutex mu3 ACQUIRED_BEFORE(mu4);6492 Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);6493 Mutex mu5 ACQUIRED_BEFORE(mu7);6494 Mutex mu6 ACQUIRED_BEFORE(mu7);6495 Mutex mu7 ACQUIRED_BEFORE(mu8);6496 Mutex mu8;6497 6498 void test() {6499 mu8.Lock();6500 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}6501 mu1.Unlock();6502 mu8.Unlock();6503 }6504};6505 6506 6507class Foo6 {6508 Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu1'}}6509 Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu2'}}6510 Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu3'}}6511 6512 Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu_b'}}6513 Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu_a'}}6514 6515 void test0() {6516 mu_a.Lock();6517 mu_b.Lock();6518 mu_b.Unlock();6519 mu_a.Unlock();6520 }6521 6522 void test1a() {6523 mu1.Lock();6524 mu1.Unlock();6525 }6526 6527 void test1b() {6528 mu1.Lock();6529 mu_a.Lock();6530 mu_b.Lock();6531 mu_b.Unlock();6532 mu_a.Unlock();6533 mu1.Unlock();6534 }6535 6536 void test() {6537 mu2.Lock();6538 mu2.Unlock();6539 }6540 6541 void test3() {6542 mu3.Lock();6543 mu3.Unlock();6544 }6545};6546 6547} // end namespace AcquiredBeforeAfterTest6548 6549 6550namespace ScopedAdoptTest {6551 6552class Foo {6553 Mutex mu;6554 int a GUARDED_BY(mu);6555 int b;6556 6557 void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {6558 MutexLock slock(&mu, true);6559 a = 0;6560 }6561 6562 void test2() SHARED_UNLOCK_FUNCTION(mu) {6563 ReaderMutexLock slock(&mu, true);6564 b = a;6565 }6566 6567 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}6568 MutexLock slock(&mu, true);6569 a = 0;6570 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}6571 6572 void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}6573 ReaderMutexLock slock(&mu, true);6574 b = a;6575 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}6576 6577};6578 6579} // end namespace ScopedAdoptTest6580 6581 6582namespace TestReferenceNoThreadSafetyAnalysis {6583 6584#define TS_UNCHECKED_READ(x) ts_unchecked_read(x)6585 6586// Takes a reference to a guarded data member, and returns an unguarded6587// reference.6588template <class T>6589inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {6590 return v;6591}6592 6593template <class T>6594inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {6595 return v;6596}6597 6598 6599class Foo {6600public:6601 Foo(): a(0) { }6602 6603 int a;6604};6605 6606 6607class Bar {6608public:6609 Bar() : a(0) { }6610 6611 Mutex mu;6612 int a GUARDED_BY(mu);6613 Foo foo GUARDED_BY(mu);6614};6615 6616 6617void test() {6618 Bar bar;6619 const Bar cbar;6620 6621 int a = TS_UNCHECKED_READ(bar.a); // nowarn6622 TS_UNCHECKED_READ(bar.a) = 1; // nowarn6623 6624 int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn6625 TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn6626 6627 int c = TS_UNCHECKED_READ(cbar.a); // nowarn6628}6629 6630#undef TS_UNCHECKED_READ6631 6632} // end namespace TestReferenceNoThreadSafetyAnalysis6633 6634 6635namespace GlobalAcquiredBeforeAfterTest {6636 6637Mutex mu1;6638Mutex mu2 ACQUIRED_AFTER(mu1);6639 6640void test3() {6641 mu2.Lock();6642 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}6643 mu1.Unlock();6644 mu2.Unlock();6645}6646 6647} // end namespace GlobalAcquiredBeforeAfterTest6648 6649 6650namespace LifetimeExtensionText {6651 6652struct Holder {6653 virtual ~Holder() throw() {}6654 int i = 0;6655};6656 6657void test() {6658 // Should not crash.6659 const auto &value = Holder().i;6660}6661 6662} // end namespace LifetimeExtensionTest6663 6664 6665namespace LockableUnions {6666 6667union LOCKABLE MutexUnion {6668 int a;6669 char* b;6670 6671 void Lock() EXCLUSIVE_LOCK_FUNCTION();6672 void Unlock() UNLOCK_FUNCTION();6673};6674 6675MutexUnion muun2;6676MutexUnion muun1 ACQUIRED_BEFORE(muun2);6677 6678void test() {6679 muun2.Lock();6680 muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}6681 muun1.Unlock();6682 muun2.Unlock();6683}6684 6685} // end namespace LockableUnions6686 6687// This used to crash.6688class acquired_before_empty_str {6689 void WaitUntilSpaceAvailable() {6690 lock_.ReaderLock(); // expected-note {{acquired here}}6691 } // expected-warning {{mutex 'lock_' is still held at the end of function}}6692 Mutex lock_ ACQUIRED_BEFORE("");6693};6694 6695namespace PR34800 {6696struct A {6697 operator int() const;6698};6699struct B {6700 bool g() __attribute__((locks_excluded(h))); // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}}6701 int h;6702};6703struct C {6704 B *operator[](int);6705};6706C c;6707void f() { c[A()]->g(); }6708} // namespace PR348006709 6710#ifdef __cpp_guaranteed_copy_elision6711 6712namespace ReturnScopedLockable {6713 6714class Object {6715public:6716 MutexLock lock() EXCLUSIVE_LOCK_FUNCTION(mutex) {6717 return MutexLock(&mutex);6718 }6719 6720 ReaderMutexLock lockShared() SHARED_LOCK_FUNCTION(mutex) {6721 return ReaderMutexLock(&mutex);6722 }6723 6724 MutexLock adopt() EXCLUSIVE_LOCKS_REQUIRED(mutex) {6725 return MutexLock(&mutex, true);6726 }6727 6728 ReaderMutexLock adoptShared() SHARED_LOCKS_REQUIRED(mutex) {6729 return ReaderMutexLock(&mutex, true);6730 }6731 6732 int x GUARDED_BY(mutex);6733 void needsLock() EXCLUSIVE_LOCKS_REQUIRED(mutex);6734 6735 void testInside() {6736 MutexLock scope = lock();6737 x = 1;6738 needsLock();6739 }6740 6741 Mutex mutex;6742};6743 6744Object obj;6745 6746void testLock() {6747 MutexLock scope = obj.lock();6748 obj.x = 1;6749 obj.needsLock();6750}6751 6752int testSharedLock() {6753 ReaderMutexLock scope = obj.lockShared();6754 obj.x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'obj.mutex' exclusively}}6755 return obj.x;6756}6757 6758void testAdopt() {6759 obj.mutex.Lock();6760 MutexLock scope = obj.adopt();6761 obj.x = 1;6762}6763 6764int testAdoptShared() {6765 obj.mutex.Lock();6766 ReaderMutexLock scope = obj.adoptShared();6767 obj.x = 1;6768 return obj.x;6769}6770 6771} // namespace ReturnScopedLockable6772 6773#endif // __cpp_guaranteed_copy_elision6774 6775namespace PR38640 {6776void f() {6777 // Self-referencing assignment previously caused an infinite loop when thread6778 // safety analysis was enabled.6779 int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}}6780}6781} // namespace PR386406782 6783namespace Derived_Smart_Pointer {6784template <class T>6785class SmartPtr_Derived : public SmartPtr<T> {};6786 6787class Foo {6788public:6789 SmartPtr_Derived<Mutex> mu_;6790 int a GUARDED_BY(mu_);6791 int b GUARDED_BY(mu_.get());6792 int c GUARDED_BY(*mu_);6793 6794 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);6795 void Unlock() UNLOCK_FUNCTION(mu_);6796 6797 void test0() {6798 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}6799 b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}6800 c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}6801 }6802 6803 void test1() {6804 Lock();6805 a = 1;6806 b = 1;6807 c = 1;6808 Unlock();6809 }6810};6811 6812class Bar {6813 SmartPtr_Derived<Foo> foo;6814 6815 void test0() {6816 foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}6817 (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}6818 foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}6819 }6820 6821 void test1() {6822 foo->Lock();6823 foo->a = 1;6824 foo->Unlock();6825 6826 foo->mu_->Lock();6827 foo->b = 1;6828 foo->mu_->Unlock();6829 6830 MutexLock lock(foo->mu_.get());6831 foo->c = 1;6832 }6833};6834 6835class PointerGuard {6836 Mutex mu1;6837 Mutex mu2;6838 SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2);6839 6840 void test0() {6841 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}6842 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \6843 // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}6844 6845 }6846 6847 void test1() {6848 mu1.Lock();6849 6850 i.get();6851 *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}6852 6853 mu1.Unlock();6854 }6855 6856 void test2() {6857 mu2.Lock();6858 6859 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}6860 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}6861 6862 mu2.Unlock();6863 }6864 6865 void test3() {6866 mu1.Lock();6867 mu2.Lock();6868 6869 i.get();6870 *i = 2;6871 6872 mu2.Unlock();6873 mu1.Unlock();6874 }6875};6876} // namespace Derived_Smart_Pointer6877 6878// Test for capabilities that are heap-allocated and stored in static variables.6879namespace FunctionStaticVariable {6880struct Data {6881 Mutex mu;6882 int x GUARDED_BY(mu);6883};6884 6885void testStaticVariable() {6886}6887 6888void testHeapAllocation() {6889 static Data *d = new Data;6890 d->mu.Lock();6891 d->x = 5;6892 d->mu.Unlock();6893}6894 6895void testHeapAllocationBug() {6896 static auto *d = new Data;6897 d->x = 10; // expected-warning{{writing variable 'x' requires holding mutex 'd->mu' exclusively}}6898}6899 6900void testHeapAllocationScopedLock() {6901 static Mutex *mu = new Mutex;6902 MutexLock lock(mu);6903}6904} // namespace FunctionStaticVariable6905 6906namespace Reentrancy {6907 6908class LOCKABLE REENTRANT_CAPABILITY ReentrantMutex {6909 public:6910 void Lock() EXCLUSIVE_LOCK_FUNCTION();6911 void ReaderLock() SHARED_LOCK_FUNCTION();6912 void Unlock() UNLOCK_FUNCTION();6913 void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();6914 void ReaderUnlock() SHARED_UNLOCK_FUNCTION();6915 bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);6916 bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);6917 6918 // for negative capabilities6919 const ReentrantMutex& operator!() const { return *this; }6920 6921 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();6922 void AssertReaderHeld() ASSERT_SHARED_LOCK();6923};6924 6925class SCOPED_LOCKABLE ReentrantMutexLock {6926 public:6927 ReentrantMutexLock(ReentrantMutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);6928 ~ReentrantMutexLock() UNLOCK_FUNCTION();6929};6930 6931class SCOPED_LOCKABLE ReentrantReaderMutexLock {6932 public:6933 ReentrantReaderMutexLock(ReentrantMutex *mu) SHARED_LOCK_FUNCTION(mu);6934 ~ReentrantReaderMutexLock() UNLOCK_FUNCTION();6935};6936 6937class SCOPED_LOCKABLE RelockableReentrantMutexLock {6938public:6939 RelockableReentrantMutexLock(ReentrantMutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);6940 ~RelockableReentrantMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();6941 6942 void Lock() EXCLUSIVE_LOCK_FUNCTION();6943 void Unlock() UNLOCK_FUNCTION();6944};6945 6946ReentrantMutex rmu;6947int guard_var __attribute__((guarded_var)) = 0;6948int guardby_var __attribute__((guarded_by(rmu))) = 0;6949 6950void testReentrantMany() {6951 rmu.Lock();6952 rmu.Lock();6953 rmu.Lock();6954 rmu.Lock();6955 rmu.Lock();6956 rmu.Lock();6957 rmu.Lock();6958 rmu.Lock();6959 rmu.Unlock();6960 rmu.Unlock();6961 rmu.Unlock();6962 rmu.Unlock();6963 rmu.Unlock();6964 rmu.Unlock();6965 rmu.Unlock();6966 rmu.Unlock();6967}6968 6969void testReentrantManyReader() {6970 rmu.ReaderLock();6971 rmu.ReaderLock();6972 rmu.ReaderLock();6973 rmu.ReaderLock();6974 rmu.ReaderLock();6975 rmu.ReaderLock();6976 rmu.ReaderLock();6977 rmu.ReaderLock();6978 rmu.ReaderUnlock();6979 rmu.ReaderUnlock();6980 rmu.ReaderUnlock();6981 rmu.ReaderUnlock();6982 rmu.ReaderUnlock();6983 rmu.ReaderUnlock();6984 rmu.ReaderUnlock();6985 rmu.ReaderUnlock();6986}6987 6988void testReentrantLock1() {6989 rmu.Lock();6990 guard_var = 2;6991 rmu.Lock();6992 guard_var = 2;6993 rmu.Unlock();6994 guard_var = 2;6995 rmu.Unlock();6996 guard_var = 2; // expected-warning{{writing variable 'guard_var' requires holding any mutex exclusively}}6997}6998 6999void testReentrantReaderLock1() {7000 rmu.ReaderLock();7001 int x = guard_var;7002 rmu.ReaderLock();7003 int y = guard_var;7004 rmu.ReaderUnlock();7005 int z = guard_var;7006 rmu.ReaderUnlock();7007 int a = guard_var; // expected-warning{{reading variable 'guard_var' requires holding any mutex}}7008}7009 7010void testReentrantLock2() {7011 rmu.Lock();7012 guardby_var = 2;7013 rmu.Lock();7014 guardby_var = 2;7015 rmu.Unlock();7016 guardby_var = 2;7017 rmu.Unlock();7018 guardby_var = 2; // expected-warning{{writing variable 'guardby_var' requires holding mutex 'rmu' exclusively}}7019}7020 7021void testReentrantReaderLock2() {7022 rmu.ReaderLock();7023 int x = guardby_var;7024 rmu.ReaderLock();7025 int y = guardby_var;7026 rmu.ReaderUnlock();7027 int z = guardby_var;7028 rmu.ReaderUnlock();7029 int a = guardby_var; // expected-warning{{reading variable 'guardby_var' requires holding mutex 'rmu'}}7030}7031 7032void testReentrantTryLock1() {7033 if (rmu.TryLock()) {7034 guardby_var = 1;7035 if (rmu.TryLock()) {7036 guardby_var = 1;7037 rmu.Unlock();7038 }7039 guardby_var = 1;7040 rmu.Unlock();7041 }7042 guardby_var = 1; // expected-warning{{writing variable 'guardby_var' requires holding mutex 'rmu' exclusively}}7043}7044 7045void testReentrantTryLock2() {7046 rmu.Lock();7047 guardby_var = 1;7048 if (rmu.TryLock()) {7049 guardby_var = 1;7050 rmu.Unlock();7051 }7052 guardby_var = 1;7053 rmu.Unlock();7054 guardby_var = 1; // expected-warning{{writing variable 'guardby_var' requires holding mutex 'rmu' exclusively}}7055}7056 7057void testReentrantNotHeld() {7058 rmu.Unlock(); // \7059 // expected-warning{{releasing mutex 'rmu' that was not held}}7060}7061 7062void testReentrantMissingUnlock() {7063 rmu.Lock(); // expected-note{{mutex acquired here}}7064 rmu.Lock(); // reenter7065 rmu.Unlock();7066} // expected-warning{{mutex 'rmu' is still held at the end of function}}7067 7068// Acquiring the same capability with different access privileges is not7069// considered reentrant.7070void testMixedSharedExclusive() {7071 rmu.ReaderLock(); // expected-note{{mutex acquired here}}7072 rmu.Lock(); // expected-warning{{acquiring mutex 'rmu' that is already held}}7073 rmu.Unlock(); // expected-note{{mutex released here}}7074 rmu.ReaderUnlock(); // expected-warning{{releasing mutex 'rmu' that was not held}}7075}7076 7077void testReentrantIntersection() {7078 rmu.Lock();7079 if (guardby_var) {7080 rmu.Lock();7081 rmu.Lock();7082 rmu.Unlock();7083 } else {7084 rmu.Lock();7085 guardby_var = 1;7086 }7087 guardby_var = 1;7088 rmu.Unlock();7089 guardby_var = 1;7090 rmu.Unlock();7091 guardby_var = 1; // expected-warning{{writing variable 'guardby_var' requires holding mutex 'rmu' exclusively}}7092}7093 7094void testReentrantIntersectionBad() {7095 rmu.Lock(); // expected-note{{mutex acquired here}}7096 if (guardby_var) {7097 rmu.Lock();7098 rmu.Lock();7099 } else {7100 rmu.Lock();7101 guardby_var = 1;7102 }7103 guardby_var = 1; // expected-warning{{mutex 'rmu' is not held on every path through here with equal reentrancy depth}}7104 rmu.Unlock();7105 guardby_var = 1;7106 rmu.Unlock();7107 guardby_var = 1;7108 rmu.Unlock();7109}7110 7111void testReentrantLoopBad() {7112 rmu.Lock(); // expected-note{{mutex acquired here}}7113 while (guardby_var) { // expected-warning{{expecting mutex 'rmu' to be held at start of each loop with equal reentrancy depth}}7114 rmu.Lock();7115 }7116 rmu.Unlock();7117}7118 7119void testLocksRequiredReentrant() EXCLUSIVE_LOCKS_REQUIRED(rmu) {7120 guardby_var = 1;7121 rmu.Lock();7122 rmu.Lock();7123 guardby_var = 1;7124 rmu.Unlock();7125 rmu.Unlock();7126 guardby_var = 1;7127}7128 7129void testAssertReentrant() {7130 rmu.AssertHeld();7131 guardby_var = 1;7132 rmu.Lock();7133 guardby_var = 1;7134 rmu.Unlock();7135 guardby_var = 1;7136}7137 7138void testAssertReaderReentrant() {7139 rmu.AssertReaderHeld();7140 int x = guardby_var;7141 rmu.ReaderLock();7142 int y = guardby_var;7143 rmu.ReaderUnlock();7144 int z = guardby_var;7145}7146 7147struct TestScopedReentrantLockable {7148 ReentrantMutex mu1;7149 ReentrantMutex mu2;7150 int a __attribute__((guarded_by(mu1)));7151 int b __attribute__((guarded_by(mu2)));7152 7153 bool getBool();7154 7155 void foo1() {7156 ReentrantMutexLock mulock1(&mu1);7157 a = 5;7158 ReentrantMutexLock mulock2(&mu1);7159 a = 5;7160 }7161 7162 void foo2() {7163 ReentrantMutexLock mulock1(&mu1);7164 a = 5;7165 mu1.Lock();7166 a = 5;7167 mu1.Unlock();7168 a = 5;7169 }7170 7171#ifdef __cpp_guaranteed_copy_elision7172 void const_lock() {7173 const ReentrantMutexLock mulock1 = ReentrantMutexLock(&mu1);7174 a = 5;7175 const ReentrantMutexLock mulock2 = ReentrantMutexLock(&mu1);7176 a = 3;7177 }7178#endif7179 7180 void temporary() {7181 ReentrantMutexLock{&mu1}, a = 1, ReentrantMutexLock{&mu1}, a = 5;7182 }7183 7184 void lifetime_extension() {7185 const ReentrantMutexLock &mulock1 = ReentrantMutexLock(&mu1);7186 a = 5;7187 const ReentrantMutexLock &mulock2 = ReentrantMutexLock(&mu1);7188 a = 5;7189 }7190 7191 void foo3() {7192 ReentrantReaderMutexLock mulock1(&mu1);7193 if (getBool()) {7194 ReentrantMutexLock mulock2a(&mu2);7195 b = a + 1;7196 }7197 else {7198 ReentrantMutexLock mulock2b(&mu2);7199 b = a + 2;7200 }7201 }7202 7203 void foo4() {7204 ReentrantMutexLock mulock_a(&mu1);7205 ReentrantMutexLock mulock_b(&mu1);7206 }7207 7208 void temporary_double_lock() {7209 ReentrantMutexLock mulock_a(&mu1);7210 ReentrantMutexLock{&mu1};7211 }7212 7213 void foo5() {7214 ReentrantMutexLock mulock1(&mu1), mulock2(&mu2);7215 {7216 ReentrantMutexLock mulock3(&mu1), mulock4(&mu2);7217 a = b+1;7218 }7219 b = a+1;7220 }7221};7222 7223void scopedDoubleUnlock() {7224 RelockableReentrantMutexLock scope(&rmu);7225 scope.Unlock(); // expected-note{{mutex released here}}7226 scope.Unlock(); // expected-warning {{releasing mutex 'rmu' that was not held}}7227}7228 7229void scopedDoubleLock1() {7230 RelockableReentrantMutexLock scope(&rmu);7231 scope.Lock();7232 scope.Unlock();7233}7234 7235void scopedDoubleLock2() {7236 RelockableReentrantMutexLock scope(&rmu);7237 scope.Unlock();7238 scope.Lock();7239 scope.Lock();7240 scope.Unlock();7241}7242 7243typedef int __attribute__((capability("bitlock"))) REENTRANT_CAPABILITY *bitlock_t;7244void bit_lock(bitlock_t l) EXCLUSIVE_LOCK_FUNCTION(l);7245void bit_unlock(bitlock_t l) UNLOCK_FUNCTION(l);7246bitlock_t bl;7247void testReentrantTypedef() {7248 bit_lock(bl);7249 bit_lock(bl);7250 bit_unlock(bl);7251 bit_unlock(bl);7252}7253 7254class TestNegativeWithReentrantMutex {7255 ReentrantMutex rmu;7256 int a GUARDED_BY(rmu);7257 7258public:7259 void baz() EXCLUSIVE_LOCKS_REQUIRED(!rmu) {7260 rmu.Lock();7261 rmu.Lock();7262 a = 0;7263 rmu.Unlock();7264 rmu.Unlock();7265 }7266};7267 7268} // namespace Reentrancy7269 7270// Tests for tracking aliases of capabilities.7271namespace CapabilityAliases {7272struct Foo {7273 Mutex mu;7274 int data GUARDED_BY(mu);7275};7276 7277Foo *returnsFoo();7278Foo *returnsFoo(Foo *foo);7279void locksRequired(Foo *foo) EXCLUSIVE_LOCKS_REQUIRED(foo->mu);7280void escapeAlias(int a, Foo *&ptr);7281void escapeAlias(int b, Foo **ptr);7282void passByConstRef(Foo* const& ptr);7283 7284void testBasicPointerAlias(Foo *f) {7285 Foo *ptr = f;7286 ptr->mu.Lock(); // lock through alias7287 f->data = 42; // access through original7288 ptr->mu.Unlock(); // unlock through alias7289}7290 7291void testBasicPointerAliasNoInit(Foo *f) {7292 Foo *ptr;7293 7294 ptr = nullptr;7295 ptr = f;7296 ptr->mu.Lock();7297 f->data = 42;7298 ptr->mu.Unlock();7299 ptr = nullptr;7300}7301 7302void testBasicPointerAliasLoop() {7303 for (;;) {7304 Foo *f = returnsFoo();7305 Foo *ptr = f;7306 if (!ptr)7307 break;7308 ptr->mu.Lock();7309 f->data = 42;7310 ptr->mu.Unlock();7311 }7312}7313 7314void testPointerAliasNoEscape1(Foo *f) {7315 Foo *ptr = f;7316 testBasicPointerAlias(ptr); // pass alias by value7317 7318 ptr->mu.Lock();7319 f->data = 42;7320 ptr->mu.Unlock();7321}7322 7323void testPointerAliasNoEscape2(Foo *f) {7324 Foo *ptr = f;7325 passByConstRef(ptr); // pass alias by const ref7326 7327 ptr->mu.Lock();7328 f->data = 42;7329 ptr->mu.Unlock();7330}7331 7332void testPointerAliasNoEscape3() {7333 Foo *ptr = returnsFoo();7334 ptr->mu.Lock();7335 locksRequired(ptr);7336 ptr->mu.Unlock();7337}7338 7339void testPointerAliasEscape1(Foo *f) {7340 Foo *ptr = f;7341 escapeAlias(0, ptr);7342 7343 ptr->mu.Lock();7344 f->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f->mu' exclusively}} \7345 // expected-note{{found near match 'ptr->mu'}}7346 ptr->mu.Unlock();7347}7348 7349void testPointerAliasEscape2(Foo *f) {7350 Foo *ptr = f;7351 escapeAlias(0, &ptr);7352 7353 ptr->mu.Lock();7354 f->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f->mu' exclusively}} \7355 // expected-note{{found near match 'ptr->mu'}}7356 ptr->mu.Unlock();7357}7358 7359void testPointerAliasEscape3(Foo *f) {7360 Foo *ptr;7361 7362 ptr = f;7363 escapeAlias(0, &ptr);7364 7365 ptr->mu.Lock();7366 f->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f->mu' exclusively}} \7367 // expected-note{{found near match 'ptr->mu'}}7368 ptr->mu.Unlock();7369}7370 7371void testPointerAliasEscapeAndReset(Foo *f) {7372 Foo *ptr;7373 7374 ptr = f;7375 escapeAlias(0, &ptr);7376 ptr = f;7377 7378 ptr->mu.Lock();7379 f->data = 42;7380 ptr->mu.Unlock();7381}7382 7383void testPointerAliasTryLock1() {7384 Foo *ptr = returnsFoo();7385 if (ptr->mu.TryLock()) {7386 locksRequired(ptr);7387 ptr->mu.Unlock();7388 }7389}7390 7391void testPointerAliasTryLock2() {7392 Foo *ptr;7393 ptr = returnsFoo();7394 Foo *ptr2 = ptr;7395 if (ptr->mu.TryLock()) {7396 locksRequired(ptr);7397 ptr2->mu.Unlock();7398 }7399}7400 7401// FIXME: This test demonstrates a dubious pattern that the analysis correctly7402// flags as unsafe, though the user might perceive it as a false positive. The7403// pattern combines a TryLock() failure path with a conditional reassignment of7404// the pointer being locked:7405//7406// 1. The conditional reassignment `ptr = returnsFoo(ptr);` forces `ptr` to7407// become a phi node in the CFG at the subsequent merge point. The alias7408// analysis correctly tracks that `ptr` could refer to one of two distinct7409// objects.7410//7411// 2. The lock acquired on the `!TryLock()` path should be (conceptually)7412// `phi(P1, P2)->mu`, while the lock on the successful path is on the7413// original `P1->mu`. When the paths merge the analysis currently discards7414// the alias as it cannot prove a single alias on that path.7415//7416// While this pattern is stylistically fragile and difficult to reason about, a7417// robust solution would require a more advanced symbolic representation of7418// capabilities within the analyzer. For now, we warn on such ambiguity.7419void testPointerAliasTryLockDubious(int x) {7420 Foo *ptr = returnsFoo();7421 if (!ptr->mu.TryLock()) { // expected-note{{mutex acquired here}}7422 if (x)7423 ptr = returnsFoo(ptr); // <-- this breaks the pattern7424 ptr->mu.Lock(); // expected-note{{mutex acquired here}}7425 }7426 ptr->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'ptr->mu' exclusively}} \7427 // expected-warning{{mutex 'ptr->mu' is not held on every path through here}} \7428 // expected-warning{{mutex 'returnsFoo().mu' is not held on every path through here}}7429 ptr->mu.Unlock(); // expected-warning{{releasing mutex 'ptr->mu' that was not held}}7430}7431 7432void testReassignment() {7433 Foo f1, f2;7434 Foo *ptr = &f1;7435 ptr->mu.Lock();7436 f1.data = 42;7437 ptr->mu.Unlock();7438 7439 ptr = &f2;7440 ptr->mu.Lock();7441 f2.data = 42;7442 f1.data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f1.mu'}} \7443 // expected-note{{found near match 'f2.mu'}}7444 ptr->mu.Unlock();7445}7446 7447// Nested field access through pointer7448struct Container {7449 Foo foo;7450};7451 7452void testNestedAccess(Container *c) {7453 Foo *ptr = &c->foo; // pointer to nested field7454 ptr->mu.Lock();7455 c->foo.data = 42;7456 ptr->mu.Unlock();7457}7458 7459void testNestedAcquire(Container *c) EXCLUSIVE_LOCK_FUNCTION(&c->foo.mu) {7460 Foo *buf = &c->foo;7461 buf->mu.Lock();7462}7463 7464struct ContainerOfPtr {7465 Foo *foo_ptr;7466 ContainerOfPtr *next;7467};7468 7469void testIndirectAccess(ContainerOfPtr *fc) {7470 Foo *ptr = fc->foo_ptr; // get pointer7471 ptr->mu.Lock();7472 fc->foo_ptr->data = 42; // access via original7473 ptr->mu.Unlock();7474}7475 7476void testAliasChainUnrelatedReassignment1(ContainerOfPtr *list) {7477 Foo *eb = list->foo_ptr;7478 eb->mu.Lock();7479 list = list->next;7480 eb->data = 42;7481 eb->mu.Unlock();7482}7483 7484void testAliasChainUnrelatedReassignment2(ContainerOfPtr *list) {7485 ContainerOfPtr *busyp = list;7486 Foo *eb = busyp->foo_ptr;7487 eb->mu.Lock();7488 busyp = busyp->next;7489 eb->data = 42;7490 eb->mu.Unlock();7491}7492 7493void testControlFlowDoWhile(Foo *f, int x) {7494 Foo *ptr = f;7495 7496 f->mu.Lock();7497 if (x) {7498 // complex merge7499 do { } while (x--);7500 }7501 ptr->data = 42;7502 ptr->mu.Unlock();7503}7504 7505// FIXME: No alias tracking through complex control flow.7506void testComplexControlFlow(Foo *f1, Foo *f2, bool cond) {7507 Foo *ptr;7508 if (cond) {7509 ptr = f1;7510 } else {7511 ptr = f2;7512 }7513 ptr->mu.Lock();7514 if (cond) {7515 f1->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f1->mu' exclusively}} \7516 // expected-note{{found near match 'ptr->mu'}}7517 } else {7518 f2->data = 42; // expected-warning{{writing variable 'data' requires holding mutex 'f2->mu' exclusively}} \7519 // expected-note{{found near match 'ptr->mu'}}7520 }7521 ptr->mu.Unlock();7522}7523 7524void testLockFunction(Foo *f) EXCLUSIVE_LOCK_FUNCTION(&f->mu) {7525 Mutex *mu = &f->mu;7526 mu->Lock();7527}7528 7529void testUnlockFunction(Foo *f) UNLOCK_FUNCTION(&f->mu) {7530 Mutex *mu = &f->mu;7531 mu->Unlock();7532}7533 7534// This is an idiom to deal with "pointer to returned object has a lock held,7535// but you must unlock it later" where the statement expression would be hidden7536// behind a macro.7537void lockWithinStatementExpr() {7538 Foo *f = ({ auto x = returnsFoo(); x->mu.Lock(); x; });7539 f->data = 42;7540 f->mu.Unlock();7541}7542 7543// Semantically UB, but let's not crash the compiler with this (should be7544// handled by -Wuninitialized).7545void testSelfInit() {7546 Mutex *mu = mu; // don't do this at home7547 mu->Lock();7548 mu->Unlock();7549}7550 7551void testSelfAssign() {7552 Foo *f = returnsFoo();7553 f = f;7554 f->mu.Lock();7555 f->data = 42;7556 f->mu.Unlock();7557}7558 7559void testRecursiveAssign() {7560 Foo *f = returnsFoo();7561 f = returnsFoo(f);7562 f->mu.Lock();7563 f->data = 42;7564 f->mu.Unlock();7565}7566 7567void testNew(Mutex *&out, int &x) {7568 Mutex *mu = new Mutex;7569 __atomic_store_n(&out, mu, __ATOMIC_RELEASE);7570 mu->Lock();7571 x = 42; // ... perhaps guarded by mu7572 mu->Unlock();7573}7574 7575void testNestedLoopInvariant(Container *c, int n) {7576 Foo *ptr = &c->foo;7577 ptr->mu.Lock();7578 7579 for (int i = 0; i < n; ++i) {7580 for (int j = 0; j < n; ++j) {7581 }7582 }7583 7584 c->foo.data = 42; // ok: alias still valid7585 ptr->mu.Unlock();7586}7587 7588void testLoopWithBreak(Foo *f, bool cond) {7589 Foo *ptr = f;7590 ptr->mu.Lock();7591 for (int i = 0; i < 10; ++i) {7592 if (cond) {7593 break; // merge point is after the loop7594 }7595 }7596 f->data = 42; // ok7597 ptr->mu.Unlock();7598}7599 7600void testLoopWithContinue(Foo *f, bool cond) {7601 Foo *ptr = f;7602 ptr->mu.Lock();7603 for (int i = 0; i < 10; ++i) {7604 if (cond) {7605 continue; // tests merge at the top of loop.7606 }7607 }7608 f->data = 42; // ok7609 ptr->mu.Unlock();7610}7611 7612void testLoopConditionalReassignment(Foo *f1, Foo *f2, bool cond) {7613 Foo *ptr = f1;7614 ptr->mu.Lock(); // expected-note{{mutex acquired here}}7615 7616 for (int i = 0; i < 10; ++i) {7617 if (cond) {7618 ptr = f2; // alias is reassigned on some path inside the loop.7619 }7620 }7621 f1->data = 42;7622 ptr->mu.Unlock(); // expected-warning{{releasing mutex 'ptr->mu' that was not held}}7623} // expected-warning{{mutex 'f1->mu' is still held at the end of function}}7624} // namespace CapabilityAliases7625