| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- // Test this without pch.
- // RUN: %clang_cc1 -include %s -fsyntax-only -verify -Wthread-safety -std=c++11 %s
- // Test with pch.
- // RUN: %clang_cc1 -emit-pch -o %t %s -std=c++11
- // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -Wthread-safety -std=c++11 %s
- #ifndef HEADER
- #define HEADER
- #define LOCKABLE __attribute__ ((lockable))
- #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
- #define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
- #define GUARDED_VAR __attribute__ ((guarded_var))
- #define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
- #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
- #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
- #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
- #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
- #define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
- #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
- #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
- #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
- #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
- #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
- #define EXCLUSIVE_LOCKS_REQUIRED(...) \
- __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
- #define SHARED_LOCKS_REQUIRED(...) \
- __attribute__ ((shared_locks_required(__VA_ARGS__)))
- #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
- class __attribute__((lockable)) Mutex {
- public:
- void Lock() __attribute__((exclusive_lock_function));
- void ReaderLock() __attribute__((shared_lock_function));
- void Unlock() __attribute__((unlock_function));
- bool TryLock() __attribute__((exclusive_trylock_function(true)));
- bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
- void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
- };
- class __attribute__((scoped_lockable)) MutexLock {
- public:
- MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
- ~MutexLock() __attribute__((unlock_function));
- };
- class __attribute__((scoped_lockable)) ReaderMutexLock {
- public:
- ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
- ~ReaderMutexLock() __attribute__((unlock_function));
- };
- class SCOPED_LOCKABLE ReleasableMutexLock {
- public:
- ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
- ~ReleasableMutexLock() UNLOCK_FUNCTION();
- void Release() UNLOCK_FUNCTION();
- };
- // The universal lock, written "*", allows checking to be selectively turned
- // off for a particular piece of code.
- void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
- void endNoWarnOnReads() UNLOCK_FUNCTION("*");
- void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
- void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
- // For testing handling of smart pointers.
- template<class T>
- class SmartPtr {
- public:
- SmartPtr(T* p) : ptr_(p) { }
- SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
- ~SmartPtr();
- T* get() const { return ptr_; }
- T* operator->() const { return ptr_; }
- T& operator*() const { return *ptr_; }
- private:
- T* ptr_;
- };
- // For testing destructor calls and cleanup.
- class MyString {
- public:
- MyString(const char* s);
- ~MyString();
- };
- Mutex sls_mu;
- Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
- int sls_guard_var __attribute__((guarded_var)) = 0;
- int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
- bool getBool();
- class MutexWrapper {
- public:
- Mutex mu;
- int x __attribute__((guarded_by(mu)));
- void MyLock() __attribute__((exclusive_lock_function(mu)));
- };
- #else
- MutexWrapper sls_mw;
- void sls_fun_0() {
- sls_mw.mu.Lock();
- sls_mw.x = 5;
- sls_mw.mu.Unlock();
- }
- void sls_fun_2() {
- sls_mu.Lock();
- int x = sls_guard_var;
- sls_mu.Unlock();
- }
- void sls_fun_3() {
- sls_mu.Lock();
- sls_guard_var = 2;
- sls_mu.Unlock();
- }
- void sls_fun_4() {
- sls_mu2.Lock();
- sls_guard_var = 2;
- sls_mu2.Unlock();
- }
- void sls_fun_5() {
- sls_mu.Lock();
- int x = sls_guardby_var;
- sls_mu.Unlock();
- }
- void sls_fun_6() {
- sls_mu.Lock();
- sls_guardby_var = 2;
- sls_mu.Unlock();
- }
- void sls_fun_7() {
- sls_mu.Lock();
- sls_mu2.Lock();
- sls_mu2.Unlock();
- sls_mu.Unlock();
- }
- void sls_fun_8() {
- sls_mu.Lock();
- if (getBool())
- sls_mu.Unlock();
- else
- sls_mu.Unlock();
- }
- void sls_fun_9() {
- if (getBool())
- sls_mu.Lock();
- else
- sls_mu.Lock();
- sls_mu.Unlock();
- }
- void sls_fun_good_6() {
- if (getBool()) {
- sls_mu.Lock();
- } else {
- if (getBool()) {
- getBool(); // EMPTY
- } else {
- getBool(); // EMPTY
- }
- sls_mu.Lock();
- }
- sls_mu.Unlock();
- }
- void sls_fun_good_7() {
- sls_mu.Lock();
- while (getBool()) {
- sls_mu.Unlock();
- if (getBool()) {
- if (getBool()) {
- sls_mu.Lock();
- continue;
- }
- }
- sls_mu.Lock();
- }
- sls_mu.Unlock();
- }
- void sls_fun_good_8() {
- sls_mw.MyLock();
- sls_mw.mu.Unlock();
- }
- void sls_fun_bad_1() {
- sls_mu.Unlock(); // \
- // expected-warning{{releasing mutex 'sls_mu' that was not held}}
- }
- void sls_fun_bad_2() {
- sls_mu.Lock();
- sls_mu.Lock(); // \
- // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
- sls_mu.Unlock();
- }
- void sls_fun_bad_3() {
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
- void sls_fun_bad_4() {
- if (getBool())
- sls_mu.Lock(); // expected-note{{mutex acquired here}}
- else
- sls_mu2.Lock(); // expected-note{{mutex acquired here}}
- } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
- // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
- void sls_fun_bad_5() {
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- if (getBool())
- sls_mu.Unlock();
- } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
- void sls_fun_bad_6() {
- if (getBool()) {
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- } else {
- if (getBool()) {
- getBool(); // EMPTY
- } else {
- getBool(); // EMPTY
- }
- }
- sls_mu.Unlock(); // \
- expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
- expected-warning{{releasing mutex 'sls_mu' that was not held}}
- }
- void sls_fun_bad_7() {
- sls_mu.Lock();
- while (getBool()) {
- sls_mu.Unlock();
- if (getBool()) {
- if (getBool()) {
- continue; // \
- expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
- }
- }
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- }
- sls_mu.Unlock();
- }
- void sls_fun_bad_8() {
- sls_mu.Lock(); // expected-note{{mutex acquired here}}
- do {
- sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
- } while (getBool());
- }
- void sls_fun_bad_9() {
- do {
- sls_mu.Lock(); // \
- // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
- // expected-note{{mutex acquired here}}
- } while (getBool());
- sls_mu.Unlock();
- }
- void sls_fun_bad_10() {
- sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
- while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
- sls_mu.Unlock();
- }
- } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
- void sls_fun_bad_11() {
- while (getBool()) { // \
- expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- }
- sls_mu.Unlock(); // \
- // expected-warning{{releasing mutex 'sls_mu' that was not held}}
- }
- void sls_fun_bad_12() {
- sls_mu.Lock(); // expected-note {{mutex acquired here}}
- while (getBool()) {
- sls_mu.Unlock();
- if (getBool()) {
- if (getBool()) {
- break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
- }
- }
- sls_mu.Lock();
- }
- sls_mu.Unlock();
- }
- #endif
|