thread-safety-attrs.cpp 8.0 KB

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