1f4a2713aSLionel Sambuc // Test this without pch. 2f4a2713aSLionel Sambuc // RUN: %clang_cc1 -include %s -fsyntax-only -verify -Wthread-safety -std=c++11 %s 3f4a2713aSLionel Sambuc 4f4a2713aSLionel Sambuc // Test with pch. 5f4a2713aSLionel Sambuc // RUN: %clang_cc1 -emit-pch -o %t %s -std=c++11 6f4a2713aSLionel Sambuc // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -Wthread-safety -std=c++11 %s 7f4a2713aSLionel Sambuc 8f4a2713aSLionel Sambuc #ifndef HEADER 9f4a2713aSLionel Sambuc #define HEADER 10f4a2713aSLionel Sambuc 11f4a2713aSLionel Sambuc #define LOCKABLE __attribute__ ((lockable)) 12f4a2713aSLionel Sambuc #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) 13f4a2713aSLionel Sambuc #define GUARDED_BY(x) __attribute__ ((guarded_by(x))) 14f4a2713aSLionel Sambuc #define GUARDED_VAR __attribute__ ((guarded_var)) 15f4a2713aSLionel Sambuc #define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) 16f4a2713aSLionel Sambuc #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) 17f4a2713aSLionel Sambuc #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) 18f4a2713aSLionel Sambuc #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) 19f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) 20f4a2713aSLionel Sambuc #define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) 21f4a2713aSLionel Sambuc #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) 22f4a2713aSLionel Sambuc #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) 23f4a2713aSLionel Sambuc #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) 24f4a2713aSLionel Sambuc #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) 25f4a2713aSLionel Sambuc #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) 26f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCKS_REQUIRED(...) \ 27f4a2713aSLionel Sambuc __attribute__ ((exclusive_locks_required(__VA_ARGS__))) 28f4a2713aSLionel Sambuc #define SHARED_LOCKS_REQUIRED(...) \ 29f4a2713aSLionel Sambuc __attribute__ ((shared_locks_required(__VA_ARGS__))) 30f4a2713aSLionel Sambuc #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) 31f4a2713aSLionel Sambuc 32f4a2713aSLionel Sambuc 33f4a2713aSLionel Sambuc class __attribute__((lockable)) Mutex { 34f4a2713aSLionel Sambuc public: 35f4a2713aSLionel Sambuc void Lock() __attribute__((exclusive_lock_function)); 36f4a2713aSLionel Sambuc void ReaderLock() __attribute__((shared_lock_function)); 37f4a2713aSLionel Sambuc void Unlock() __attribute__((unlock_function)); 38f4a2713aSLionel Sambuc bool TryLock() __attribute__((exclusive_trylock_function(true))); 39f4a2713aSLionel Sambuc bool ReaderTryLock() __attribute__((shared_trylock_function(true))); 40f4a2713aSLionel Sambuc void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); 41f4a2713aSLionel Sambuc }; 42f4a2713aSLionel Sambuc 43f4a2713aSLionel Sambuc class __attribute__((scoped_lockable)) MutexLock { 44f4a2713aSLionel Sambuc public: 45f4a2713aSLionel Sambuc MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); 46f4a2713aSLionel Sambuc ~MutexLock() __attribute__((unlock_function)); 47f4a2713aSLionel Sambuc }; 48f4a2713aSLionel Sambuc 49f4a2713aSLionel Sambuc class __attribute__((scoped_lockable)) ReaderMutexLock { 50f4a2713aSLionel Sambuc public: 51f4a2713aSLionel Sambuc ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); 52f4a2713aSLionel Sambuc ~ReaderMutexLock() __attribute__((unlock_function)); 53f4a2713aSLionel Sambuc }; 54f4a2713aSLionel Sambuc 55f4a2713aSLionel Sambuc class SCOPED_LOCKABLE ReleasableMutexLock { 56f4a2713aSLionel Sambuc public: 57f4a2713aSLionel Sambuc ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu); 58f4a2713aSLionel Sambuc ~ReleasableMutexLock() UNLOCK_FUNCTION(); 59f4a2713aSLionel Sambuc 60f4a2713aSLionel Sambuc void Release() UNLOCK_FUNCTION(); 61f4a2713aSLionel Sambuc }; 62f4a2713aSLionel Sambuc 63f4a2713aSLionel Sambuc 64f4a2713aSLionel Sambuc // The universal lock, written "*", allows checking to be selectively turned 65f4a2713aSLionel Sambuc // off for a particular piece of code. 66f4a2713aSLionel Sambuc void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*"); 67f4a2713aSLionel Sambuc void endNoWarnOnReads() UNLOCK_FUNCTION("*"); 68f4a2713aSLionel Sambuc void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*"); 69f4a2713aSLionel Sambuc void endNoWarnOnWrites() UNLOCK_FUNCTION("*"); 70f4a2713aSLionel Sambuc 71f4a2713aSLionel Sambuc 72f4a2713aSLionel Sambuc // For testing handling of smart pointers. 73f4a2713aSLionel Sambuc template<class T> 74f4a2713aSLionel Sambuc class SmartPtr { 75f4a2713aSLionel Sambuc public: SmartPtr(T * p)76f4a2713aSLionel Sambuc SmartPtr(T* p) : ptr_(p) { } SmartPtr(const SmartPtr<T> & p)77f4a2713aSLionel Sambuc SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { } 78f4a2713aSLionel Sambuc ~SmartPtr(); 79f4a2713aSLionel Sambuc get() const80f4a2713aSLionel Sambuc T* get() const { return ptr_; } operator ->() const81f4a2713aSLionel Sambuc T* operator->() const { return ptr_; } operator *() const82f4a2713aSLionel Sambuc T& operator*() const { return *ptr_; } 83f4a2713aSLionel Sambuc 84f4a2713aSLionel Sambuc private: 85f4a2713aSLionel Sambuc T* ptr_; 86f4a2713aSLionel Sambuc }; 87f4a2713aSLionel Sambuc 88f4a2713aSLionel Sambuc 89f4a2713aSLionel Sambuc // For testing destructor calls and cleanup. 90f4a2713aSLionel Sambuc class MyString { 91f4a2713aSLionel Sambuc public: 92f4a2713aSLionel Sambuc MyString(const char* s); 93f4a2713aSLionel Sambuc ~MyString(); 94f4a2713aSLionel Sambuc }; 95f4a2713aSLionel Sambuc 96f4a2713aSLionel Sambuc 97f4a2713aSLionel Sambuc 98f4a2713aSLionel Sambuc Mutex sls_mu; 99f4a2713aSLionel Sambuc 100f4a2713aSLionel Sambuc Mutex sls_mu2 __attribute__((acquired_after(sls_mu))); 101f4a2713aSLionel Sambuc int sls_guard_var __attribute__((guarded_var)) = 0; 102f4a2713aSLionel Sambuc int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0; 103f4a2713aSLionel Sambuc 104f4a2713aSLionel Sambuc bool getBool(); 105f4a2713aSLionel Sambuc 106f4a2713aSLionel Sambuc class MutexWrapper { 107f4a2713aSLionel Sambuc public: 108f4a2713aSLionel Sambuc Mutex mu; 109f4a2713aSLionel Sambuc int x __attribute__((guarded_by(mu))); 110f4a2713aSLionel Sambuc void MyLock() __attribute__((exclusive_lock_function(mu))); 111f4a2713aSLionel Sambuc }; 112f4a2713aSLionel Sambuc 113f4a2713aSLionel Sambuc #else 114f4a2713aSLionel Sambuc 115f4a2713aSLionel Sambuc MutexWrapper sls_mw; 116f4a2713aSLionel Sambuc sls_fun_0()117f4a2713aSLionel Sambucvoid sls_fun_0() { 118f4a2713aSLionel Sambuc sls_mw.mu.Lock(); 119f4a2713aSLionel Sambuc sls_mw.x = 5; 120f4a2713aSLionel Sambuc sls_mw.mu.Unlock(); 121f4a2713aSLionel Sambuc } 122f4a2713aSLionel Sambuc sls_fun_2()123f4a2713aSLionel Sambucvoid sls_fun_2() { 124f4a2713aSLionel Sambuc sls_mu.Lock(); 125f4a2713aSLionel Sambuc int x = sls_guard_var; 126f4a2713aSLionel Sambuc sls_mu.Unlock(); 127f4a2713aSLionel Sambuc } 128f4a2713aSLionel Sambuc sls_fun_3()129f4a2713aSLionel Sambucvoid sls_fun_3() { 130f4a2713aSLionel Sambuc sls_mu.Lock(); 131f4a2713aSLionel Sambuc sls_guard_var = 2; 132f4a2713aSLionel Sambuc sls_mu.Unlock(); 133f4a2713aSLionel Sambuc } 134f4a2713aSLionel Sambuc sls_fun_4()135f4a2713aSLionel Sambucvoid sls_fun_4() { 136f4a2713aSLionel Sambuc sls_mu2.Lock(); 137f4a2713aSLionel Sambuc sls_guard_var = 2; 138f4a2713aSLionel Sambuc sls_mu2.Unlock(); 139f4a2713aSLionel Sambuc } 140f4a2713aSLionel Sambuc sls_fun_5()141f4a2713aSLionel Sambucvoid sls_fun_5() { 142f4a2713aSLionel Sambuc sls_mu.Lock(); 143f4a2713aSLionel Sambuc int x = sls_guardby_var; 144f4a2713aSLionel Sambuc sls_mu.Unlock(); 145f4a2713aSLionel Sambuc } 146f4a2713aSLionel Sambuc sls_fun_6()147f4a2713aSLionel Sambucvoid sls_fun_6() { 148f4a2713aSLionel Sambuc sls_mu.Lock(); 149f4a2713aSLionel Sambuc sls_guardby_var = 2; 150f4a2713aSLionel Sambuc sls_mu.Unlock(); 151f4a2713aSLionel Sambuc } 152f4a2713aSLionel Sambuc sls_fun_7()153f4a2713aSLionel Sambucvoid sls_fun_7() { 154f4a2713aSLionel Sambuc sls_mu.Lock(); 155f4a2713aSLionel Sambuc sls_mu2.Lock(); 156f4a2713aSLionel Sambuc sls_mu2.Unlock(); 157f4a2713aSLionel Sambuc sls_mu.Unlock(); 158f4a2713aSLionel Sambuc } 159f4a2713aSLionel Sambuc sls_fun_8()160f4a2713aSLionel Sambucvoid sls_fun_8() { 161f4a2713aSLionel Sambuc sls_mu.Lock(); 162f4a2713aSLionel Sambuc if (getBool()) 163f4a2713aSLionel Sambuc sls_mu.Unlock(); 164f4a2713aSLionel Sambuc else 165f4a2713aSLionel Sambuc sls_mu.Unlock(); 166f4a2713aSLionel Sambuc } 167f4a2713aSLionel Sambuc sls_fun_9()168f4a2713aSLionel Sambucvoid sls_fun_9() { 169f4a2713aSLionel Sambuc if (getBool()) 170f4a2713aSLionel Sambuc sls_mu.Lock(); 171f4a2713aSLionel Sambuc else 172f4a2713aSLionel Sambuc sls_mu.Lock(); 173f4a2713aSLionel Sambuc sls_mu.Unlock(); 174f4a2713aSLionel Sambuc } 175f4a2713aSLionel Sambuc sls_fun_good_6()176f4a2713aSLionel Sambucvoid sls_fun_good_6() { 177f4a2713aSLionel Sambuc if (getBool()) { 178f4a2713aSLionel Sambuc sls_mu.Lock(); 179f4a2713aSLionel Sambuc } else { 180f4a2713aSLionel Sambuc if (getBool()) { 181f4a2713aSLionel Sambuc getBool(); // EMPTY 182f4a2713aSLionel Sambuc } else { 183f4a2713aSLionel Sambuc getBool(); // EMPTY 184f4a2713aSLionel Sambuc } 185f4a2713aSLionel Sambuc sls_mu.Lock(); 186f4a2713aSLionel Sambuc } 187f4a2713aSLionel Sambuc sls_mu.Unlock(); 188f4a2713aSLionel Sambuc } 189f4a2713aSLionel Sambuc sls_fun_good_7()190f4a2713aSLionel Sambucvoid sls_fun_good_7() { 191f4a2713aSLionel Sambuc sls_mu.Lock(); 192f4a2713aSLionel Sambuc while (getBool()) { 193f4a2713aSLionel Sambuc sls_mu.Unlock(); 194f4a2713aSLionel Sambuc if (getBool()) { 195f4a2713aSLionel Sambuc if (getBool()) { 196f4a2713aSLionel Sambuc sls_mu.Lock(); 197f4a2713aSLionel Sambuc continue; 198f4a2713aSLionel Sambuc } 199f4a2713aSLionel Sambuc } 200f4a2713aSLionel Sambuc sls_mu.Lock(); 201f4a2713aSLionel Sambuc } 202f4a2713aSLionel Sambuc sls_mu.Unlock(); 203f4a2713aSLionel Sambuc } 204f4a2713aSLionel Sambuc sls_fun_good_8()205f4a2713aSLionel Sambucvoid sls_fun_good_8() { 206f4a2713aSLionel Sambuc sls_mw.MyLock(); 207f4a2713aSLionel Sambuc sls_mw.mu.Unlock(); 208f4a2713aSLionel Sambuc } 209f4a2713aSLionel Sambuc sls_fun_bad_1()210f4a2713aSLionel Sambucvoid sls_fun_bad_1() { 211f4a2713aSLionel Sambuc sls_mu.Unlock(); // \ 212*0a6a1f1dSLionel Sambuc // expected-warning{{releasing mutex 'sls_mu' that was not held}} 213f4a2713aSLionel Sambuc } 214f4a2713aSLionel Sambuc sls_fun_bad_2()215f4a2713aSLionel Sambucvoid sls_fun_bad_2() { 216f4a2713aSLionel Sambuc sls_mu.Lock(); 217f4a2713aSLionel Sambuc sls_mu.Lock(); // \ 218*0a6a1f1dSLionel Sambuc // expected-warning{{acquiring mutex 'sls_mu' that is already held}} 219f4a2713aSLionel Sambuc sls_mu.Unlock(); 220f4a2713aSLionel Sambuc } 221f4a2713aSLionel Sambuc sls_fun_bad_3()222f4a2713aSLionel Sambucvoid sls_fun_bad_3() { 223f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 224*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is still held at the end of function}} 225f4a2713aSLionel Sambuc sls_fun_bad_4()226f4a2713aSLionel Sambucvoid sls_fun_bad_4() { 227f4a2713aSLionel Sambuc if (getBool()) 228f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note{{mutex acquired here}} 229f4a2713aSLionel Sambuc else 230f4a2713aSLionel Sambuc sls_mu2.Lock(); // expected-note{{mutex acquired here}} 231*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \ 232*0a6a1f1dSLionel Sambuc // expected-warning{{mutex 'sls_mu2' is not held on every path through here}} 233f4a2713aSLionel Sambuc sls_fun_bad_5()234f4a2713aSLionel Sambucvoid sls_fun_bad_5() { 235f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 236f4a2713aSLionel Sambuc if (getBool()) 237f4a2713aSLionel Sambuc sls_mu.Unlock(); 238*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} 239f4a2713aSLionel Sambuc sls_fun_bad_6()240f4a2713aSLionel Sambucvoid sls_fun_bad_6() { 241f4a2713aSLionel Sambuc if (getBool()) { 242f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 243f4a2713aSLionel Sambuc } else { 244f4a2713aSLionel Sambuc if (getBool()) { 245f4a2713aSLionel Sambuc getBool(); // EMPTY 246f4a2713aSLionel Sambuc } else { 247f4a2713aSLionel Sambuc getBool(); // EMPTY 248f4a2713aSLionel Sambuc } 249f4a2713aSLionel Sambuc } 250f4a2713aSLionel Sambuc sls_mu.Unlock(); // \ 251*0a6a1f1dSLionel Sambuc expected-warning{{mutex 'sls_mu' is not held on every path through here}}\ 252*0a6a1f1dSLionel Sambuc expected-warning{{releasing mutex 'sls_mu' that was not held}} 253f4a2713aSLionel Sambuc } 254f4a2713aSLionel Sambuc sls_fun_bad_7()255f4a2713aSLionel Sambucvoid sls_fun_bad_7() { 256f4a2713aSLionel Sambuc sls_mu.Lock(); 257f4a2713aSLionel Sambuc while (getBool()) { 258f4a2713aSLionel Sambuc sls_mu.Unlock(); 259f4a2713aSLionel Sambuc if (getBool()) { 260f4a2713aSLionel Sambuc if (getBool()) { 261f4a2713aSLionel Sambuc continue; // \ 262*0a6a1f1dSLionel Sambuc expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} 263f4a2713aSLionel Sambuc } 264f4a2713aSLionel Sambuc } 265f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 266f4a2713aSLionel Sambuc } 267f4a2713aSLionel Sambuc sls_mu.Unlock(); 268f4a2713aSLionel Sambuc } 269f4a2713aSLionel Sambuc sls_fun_bad_8()270f4a2713aSLionel Sambucvoid sls_fun_bad_8() { 271f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note{{mutex acquired here}} 272f4a2713aSLionel Sambuc 273f4a2713aSLionel Sambuc do { 274*0a6a1f1dSLionel Sambuc sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} 275f4a2713aSLionel Sambuc } while (getBool()); 276f4a2713aSLionel Sambuc } 277f4a2713aSLionel Sambuc sls_fun_bad_9()278f4a2713aSLionel Sambucvoid sls_fun_bad_9() { 279f4a2713aSLionel Sambuc do { 280f4a2713aSLionel Sambuc sls_mu.Lock(); // \ 281*0a6a1f1dSLionel Sambuc // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \ 282f4a2713aSLionel Sambuc // expected-note{{mutex acquired here}} 283f4a2713aSLionel Sambuc } while (getBool()); 284f4a2713aSLionel Sambuc sls_mu.Unlock(); 285f4a2713aSLionel Sambuc } 286f4a2713aSLionel Sambuc sls_fun_bad_10()287f4a2713aSLionel Sambucvoid sls_fun_bad_10() { 288f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note 2{{mutex acquired here}} 289*0a6a1f1dSLionel Sambuc while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} 290f4a2713aSLionel Sambuc sls_mu.Unlock(); 291f4a2713aSLionel Sambuc } 292*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is still held at the end of function}} 293f4a2713aSLionel Sambuc sls_fun_bad_11()294f4a2713aSLionel Sambucvoid sls_fun_bad_11() { 295f4a2713aSLionel Sambuc while (getBool()) { // \ 296*0a6a1f1dSLionel Sambuc expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} 297f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 298f4a2713aSLionel Sambuc } 299f4a2713aSLionel Sambuc sls_mu.Unlock(); // \ 300*0a6a1f1dSLionel Sambuc // expected-warning{{releasing mutex 'sls_mu' that was not held}} 301f4a2713aSLionel Sambuc } 302f4a2713aSLionel Sambuc sls_fun_bad_12()303f4a2713aSLionel Sambucvoid sls_fun_bad_12() { 304f4a2713aSLionel Sambuc sls_mu.Lock(); // expected-note {{mutex acquired here}} 305f4a2713aSLionel Sambuc while (getBool()) { 306f4a2713aSLionel Sambuc sls_mu.Unlock(); 307f4a2713aSLionel Sambuc if (getBool()) { 308f4a2713aSLionel Sambuc if (getBool()) { 309*0a6a1f1dSLionel Sambuc break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}} 310f4a2713aSLionel Sambuc } 311f4a2713aSLionel Sambuc } 312f4a2713aSLionel Sambuc sls_mu.Lock(); 313f4a2713aSLionel Sambuc } 314f4a2713aSLionel Sambuc sls_mu.Unlock(); 315f4a2713aSLionel Sambuc } 316f4a2713aSLionel Sambuc 317f4a2713aSLionel Sambuc #endif 318