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