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