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 33 class __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 43 class __attribute__((scoped_lockable)) MutexLock { 44 public: 45 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); 46 ~MutexLock() __attribute__((unlock_function)); 47 }; 48 49 class __attribute__((scoped_lockable)) ReaderMutexLock { 50 public: 51 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); 52 ~ReaderMutexLock() __attribute__((unlock_function)); 53 }; 54 55 class 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. 66 void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*"); 67 void endNoWarnOnReads() UNLOCK_FUNCTION("*"); 68 void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*"); 69 void endNoWarnOnWrites() UNLOCK_FUNCTION("*"); 70 71 72 // For testing handling of smart pointers. 73 template<class T> 74 class SmartPtr { 75 public: 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 84 private: 85 T* ptr_; 86 }; 87 88 89 // For testing destructor calls and cleanup. 90 class MyString { 91 public: 92 MyString(const char* s); 93 ~MyString(); 94 }; 95 96 97 98 Mutex sls_mu; 99 100 Mutex sls_mu2 __attribute__((acquired_after(sls_mu))); 101 int sls_guard_var __attribute__((guarded_var)) = 0; 102 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0; 103 104 bool getBool(); 105 106 class MutexWrapper { 107 public: 108 Mutex mu; 109 int x __attribute__((guarded_by(mu))); 110 void MyLock() __attribute__((exclusive_lock_function(mu))); 111 }; 112 113 #else 114 115 MutexWrapper sls_mw; 116 117 void sls_fun_0() { 118 sls_mw.mu.Lock(); 119 sls_mw.x = 5; 120 sls_mw.mu.Unlock(); 121 } 122 123 void sls_fun_2() { 124 sls_mu.Lock(); 125 int x = sls_guard_var; 126 sls_mu.Unlock(); 127 } 128 129 void sls_fun_3() { 130 sls_mu.Lock(); 131 sls_guard_var = 2; 132 sls_mu.Unlock(); 133 } 134 135 void sls_fun_4() { 136 sls_mu2.Lock(); 137 sls_guard_var = 2; 138 sls_mu2.Unlock(); 139 } 140 141 void sls_fun_5() { 142 sls_mu.Lock(); 143 int x = sls_guardby_var; 144 sls_mu.Unlock(); 145 } 146 147 void sls_fun_6() { 148 sls_mu.Lock(); 149 sls_guardby_var = 2; 150 sls_mu.Unlock(); 151 } 152 153 void sls_fun_7() { 154 sls_mu.Lock(); 155 sls_mu2.Lock(); 156 sls_mu2.Unlock(); 157 sls_mu.Unlock(); 158 } 159 160 void sls_fun_8() { 161 sls_mu.Lock(); 162 if (getBool()) 163 sls_mu.Unlock(); 164 else 165 sls_mu.Unlock(); 166 } 167 168 void sls_fun_9() { 169 if (getBool()) 170 sls_mu.Lock(); 171 else 172 sls_mu.Lock(); 173 sls_mu.Unlock(); 174 } 175 176 void 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 190 void 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 205 void sls_fun_good_8() { 206 sls_mw.MyLock(); 207 sls_mw.mu.Unlock(); 208 } 209 210 void sls_fun_bad_1() { 211 sls_mu.Unlock(); // \ 212 // expected-warning{{releasing mutex 'sls_mu' that was not held}} 213 } 214 215 void 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 222 void 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 226 void 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 234 void 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 240 void 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 255 void 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 270 void 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 278 void 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 287 void 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 294 void 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 303 void 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