1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
4 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
5
6 // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
7 // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
8
9 #include "thread-safety-annotations.h"
10
11 class LOCKABLE Mutex {
12 public:
13 void Lock() EXCLUSIVE_LOCK_FUNCTION();
14 void ReaderLock() SHARED_LOCK_FUNCTION();
15 void Unlock() UNLOCK_FUNCTION();
16 void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
17 void ReaderUnlock() SHARED_UNLOCK_FUNCTION();
18 bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
19 bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
20 void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION();
21
22 void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
23 void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
24
25 // for negative capabilities
operator !() const26 const Mutex& operator!() const { return *this; }
27
28 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
29 void AssertReaderHeld() ASSERT_SHARED_LOCK();
30 };
31
32 class SCOPED_LOCKABLE MutexLock {
33 public:
34 MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
35 MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);
36 ~MutexLock() UNLOCK_FUNCTION();
37 };
38
39 class SCOPED_LOCKABLE ReaderMutexLock {
40 public:
41 ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu);
42 ReaderMutexLock(Mutex *mu, bool adopt) SHARED_LOCKS_REQUIRED(mu);
43 ~ReaderMutexLock() UNLOCK_FUNCTION();
44 };
45
46 class SCOPED_LOCKABLE ReleasableMutexLock {
47 public:
48 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
49 ~ReleasableMutexLock() UNLOCK_FUNCTION();
50
51 void Release() UNLOCK_FUNCTION();
52 };
53
54 class SCOPED_LOCKABLE DoubleMutexLock {
55 public:
56 DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);
57 ~DoubleMutexLock() UNLOCK_FUNCTION();
58 };
59
60 // The universal lock, written "*", allows checking to be selectively turned
61 // off for a particular piece of code.
62 void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
63 void endNoWarnOnReads() UNLOCK_FUNCTION("*");
64 void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
65 void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
66
67
68 // For testing handling of smart pointers.
69 template<class T>
70 class SmartPtr {
71 public:
SmartPtr(T * p)72 SmartPtr(T* p) : ptr_(p) { }
SmartPtr(const SmartPtr<T> & p)73 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
74 ~SmartPtr();
75
get() const76 T* get() const { return ptr_; }
operator ->() const77 T* operator->() const { return ptr_; }
operator *() const78 T& operator*() const { return *ptr_; }
operator [](int i) const79 T& operator[](int i) const { return ptr_[i]; }
80
81 private:
82 T* ptr_;
83 };
84
85 template<typename T, typename U>
operator ->*(const SmartPtr<T> & ptr,U T::* p)86 U& operator->*(const SmartPtr<T>& ptr, U T::*p) { return ptr->*p; }
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 // For testing operator overloading
98 template <class K, class T>
99 class MyMap {
100 public:
101 T& operator[](const K& k);
102 };
103
104
105 // For testing handling of containers.
106 template <class T>
107 class MyContainer {
108 public:
109 MyContainer();
110
111 typedef T* iterator;
112 typedef const T* const_iterator;
113
114 T* begin();
115 T* end();
116
117 const T* cbegin();
118 const T* cend();
119
120 T& operator[](int i);
121 const T& operator[](int i) const;
122
123 private:
124 T* ptr_;
125 };
126
127
128
129 Mutex sls_mu;
130
131 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
132 int sls_guard_var __attribute__((guarded_var)) = 0;
133 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
134
135 bool getBool();
136
137 class MutexWrapper {
138 public:
139 Mutex mu;
140 int x __attribute__((guarded_by(mu)));
141 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
142 };
143
144 MutexWrapper sls_mw;
145
sls_fun_0()146 void sls_fun_0() {
147 sls_mw.mu.Lock();
148 sls_mw.x = 5;
149 sls_mw.mu.Unlock();
150 }
151
sls_fun_2()152 void sls_fun_2() {
153 sls_mu.Lock();
154 int x = sls_guard_var;
155 sls_mu.Unlock();
156 }
157
sls_fun_3()158 void sls_fun_3() {
159 sls_mu.Lock();
160 sls_guard_var = 2;
161 sls_mu.Unlock();
162 }
163
sls_fun_4()164 void sls_fun_4() {
165 sls_mu2.Lock();
166 sls_guard_var = 2;
167 sls_mu2.Unlock();
168 }
169
sls_fun_5()170 void sls_fun_5() {
171 sls_mu.Lock();
172 int x = sls_guardby_var;
173 sls_mu.Unlock();
174 }
175
sls_fun_6()176 void sls_fun_6() {
177 sls_mu.Lock();
178 sls_guardby_var = 2;
179 sls_mu.Unlock();
180 }
181
sls_fun_7()182 void sls_fun_7() {
183 sls_mu.Lock();
184 sls_mu2.Lock();
185 sls_mu2.Unlock();
186 sls_mu.Unlock();
187 }
188
sls_fun_8()189 void sls_fun_8() {
190 sls_mu.Lock();
191 if (getBool())
192 sls_mu.Unlock();
193 else
194 sls_mu.Unlock();
195 }
196
sls_fun_9()197 void sls_fun_9() {
198 if (getBool())
199 sls_mu.Lock();
200 else
201 sls_mu.Lock();
202 sls_mu.Unlock();
203 }
204
sls_fun_good_6()205 void sls_fun_good_6() {
206 if (getBool()) {
207 sls_mu.Lock();
208 } else {
209 if (getBool()) {
210 getBool(); // EMPTY
211 } else {
212 getBool(); // EMPTY
213 }
214 sls_mu.Lock();
215 }
216 sls_mu.Unlock();
217 }
218
sls_fun_good_7()219 void sls_fun_good_7() {
220 sls_mu.Lock();
221 while (getBool()) {
222 sls_mu.Unlock();
223 if (getBool()) {
224 if (getBool()) {
225 sls_mu.Lock();
226 continue;
227 }
228 }
229 sls_mu.Lock();
230 }
231 sls_mu.Unlock();
232 }
233
sls_fun_good_8()234 void sls_fun_good_8() {
235 sls_mw.MyLock();
236 sls_mw.mu.Unlock();
237 }
238
sls_fun_bad_1()239 void sls_fun_bad_1() {
240 sls_mu.Unlock(); // \
241 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
242 }
243
sls_fun_bad_2()244 void sls_fun_bad_2() {
245 sls_mu.Lock(); // expected-note{{mutex acquired here}}
246 sls_mu.Lock(); // \
247 // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
248 sls_mu.Unlock();
249 }
250
sls_fun_bad_3()251 void sls_fun_bad_3() {
252 sls_mu.Lock(); // expected-note {{mutex acquired here}}
253 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
254
sls_fun_bad_4()255 void sls_fun_bad_4() {
256 if (getBool())
257 sls_mu.Lock(); // expected-note{{mutex acquired here}}
258 else
259 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
260 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
261 // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
262
sls_fun_bad_5()263 void sls_fun_bad_5() {
264 sls_mu.Lock(); // expected-note {{mutex acquired here}}
265 if (getBool())
266 sls_mu.Unlock();
267 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
268
sls_fun_bad_6()269 void sls_fun_bad_6() {
270 if (getBool()) {
271 sls_mu.Lock(); // expected-note {{mutex acquired here}}
272 } else {
273 if (getBool()) {
274 getBool(); // EMPTY
275 } else {
276 getBool(); // EMPTY
277 }
278 }
279 sls_mu.Unlock(); // \
280 expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
281 expected-warning{{releasing mutex 'sls_mu' that was not held}}
282 }
283
sls_fun_bad_7()284 void sls_fun_bad_7() {
285 sls_mu.Lock();
286 while (getBool()) { // \
287 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
288 sls_mu.Unlock();
289 if (getBool()) {
290 if (getBool()) {
291 continue;
292 }
293 }
294 sls_mu.Lock(); // expected-note {{mutex acquired here}}
295 }
296 sls_mu.Unlock();
297 }
298
sls_fun_bad_8()299 void sls_fun_bad_8() {
300 sls_mu.Lock(); // expected-note{{mutex acquired here}}
301
302 do {
303 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
304 } while (getBool());
305 }
306
sls_fun_bad_9()307 void sls_fun_bad_9() {
308 do {
309 sls_mu.Lock(); // \
310 // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
311 // expected-note{{mutex acquired here}}
312 } while (getBool());
313 sls_mu.Unlock();
314 }
315
sls_fun_bad_10()316 void sls_fun_bad_10() {
317 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
318 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
319 sls_mu.Unlock();
320 }
321 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
322
sls_fun_bad_11()323 void sls_fun_bad_11() {
324 while (getBool()) { // \
325 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
326 sls_mu.Lock(); // expected-note {{mutex acquired here}}
327 }
328 sls_mu.Unlock(); // \
329 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
330 }
331
sls_fun_bad_12()332 void sls_fun_bad_12() {
333 sls_mu.Lock(); // expected-note {{mutex acquired here}}
334 while (getBool()) {
335 sls_mu.Unlock();
336 if (getBool()) {
337 if (getBool()) {
338 break;
339 }
340 }
341 sls_mu.Lock();
342 }
343 sls_mu.Unlock(); // \
344 expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
345 expected-warning{{releasing mutex 'sls_mu' that was not held}}
346 }
347
348 //-----------------------------------------//
349 // Handling lock expressions in attribute args
350 // -------------------------------------------//
351
352 Mutex aa_mu;
353
354 class GlobalLocker {
355 public:
356 void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu);
357 void globalUnlock() UNLOCK_FUNCTION(aa_mu);
358 };
359
360 GlobalLocker glock;
361
aa_fun_1()362 void aa_fun_1() {
363 glock.globalLock();
364 glock.globalUnlock();
365 }
366
aa_fun_bad_1()367 void aa_fun_bad_1() {
368 glock.globalUnlock(); // \
369 // expected-warning{{releasing mutex 'aa_mu' that was not held}}
370 }
371
aa_fun_bad_2()372 void aa_fun_bad_2() {
373 glock.globalLock(); // expected-note{{mutex acquired here}}
374 glock.globalLock(); // \
375 // expected-warning{{acquiring mutex 'aa_mu' that is already held}}
376 glock.globalUnlock();
377 }
378
aa_fun_bad_3()379 void aa_fun_bad_3() {
380 glock.globalLock(); // expected-note{{mutex acquired here}}
381 } // expected-warning{{mutex 'aa_mu' is still held at the end of function}}
382
383 //--------------------------------------------------//
384 // Regression tests for unusual method names
385 //--------------------------------------------------//
386
387 Mutex wmu;
388
389 // Test diagnostics for other method names.
390 class WeirdMethods {
391 // FIXME: can't currently check inside constructors and destructors.
WeirdMethods()392 WeirdMethods() {
393 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
394 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
~WeirdMethods()395 ~WeirdMethods() {
396 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
397 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
operator ++()398 void operator++() {
399 wmu.Lock(); // expected-note {{mutex acquired here}}
400 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
operator int*()401 operator int*() {
402 wmu.Lock(); // expected-note {{mutex acquired here}}
403 return 0;
404 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
405 };
406
407 //-----------------------------------------------//
408 // Errors for guarded by or guarded var variables
409 // ----------------------------------------------//
410
411 int *pgb_gvar __attribute__((pt_guarded_var));
412 int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
413
414 class PGBFoo {
415 public:
416 int x;
417 int *pgb_field __attribute__((guarded_by(sls_mu2)))
418 __attribute__((pt_guarded_by(sls_mu)));
testFoo()419 void testFoo() {
420 pgb_field = &x; // \
421 // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}
422 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
423 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
424 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
425 // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}
426 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
427 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
428 }
429 };
430
431 class GBFoo {
432 public:
433 int gb_field __attribute__((guarded_by(sls_mu)));
434
testFoo()435 void testFoo() {
436 gb_field = 0; // \
437 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
438 }
439
testNoAnal()440 void testNoAnal() NO_THREAD_SAFETY_ANALYSIS {
441 gb_field = 0;
442 }
443 };
444
445 GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
446
gb_fun_0()447 void gb_fun_0() {
448 sls_mu.Lock();
449 int x = *pgb_var;
450 sls_mu.Unlock();
451 }
452
gb_fun_1()453 void gb_fun_1() {
454 sls_mu.Lock();
455 *pgb_var = 2;
456 sls_mu.Unlock();
457 }
458
gb_fun_2()459 void gb_fun_2() {
460 int x;
461 pgb_var = &x;
462 }
463
gb_fun_3()464 void gb_fun_3() {
465 int *x = pgb_var;
466 }
467
gb_bad_0()468 void gb_bad_0() {
469 sls_guard_var = 1; // \
470 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
471 }
472
gb_bad_1()473 void gb_bad_1() {
474 int x = sls_guard_var; // \
475 // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}
476 }
477
gb_bad_2()478 void gb_bad_2() {
479 sls_guardby_var = 1; // \
480 // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}
481 }
482
gb_bad_3()483 void gb_bad_3() {
484 int x = sls_guardby_var; // \
485 // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}
486 }
487
gb_bad_4()488 void gb_bad_4() {
489 *pgb_gvar = 1; // \
490 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}
491 }
492
gb_bad_5()493 void gb_bad_5() {
494 int x = *pgb_gvar; // \
495 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}
496 }
497
gb_bad_6()498 void gb_bad_6() {
499 *pgb_var = 1; // \
500 // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}
501 }
502
gb_bad_7()503 void gb_bad_7() {
504 int x = *pgb_var; // \
505 // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}
506 }
507
gb_bad_8()508 void gb_bad_8() {
509 GBFoo G;
510 G.gb_field = 0; // \
511 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}
512 }
513
gb_bad_9()514 void gb_bad_9() {
515 sls_guard_var++; // \
516 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
517 sls_guard_var--; // \
518 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
519 ++sls_guard_var; // \
520 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
521 --sls_guard_var;// \
522 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
523 }
524
525 //-----------------------------------------------//
526 // Warnings on variables with late parsed attributes
527 // ----------------------------------------------//
528
529 class LateFoo {
530 public:
531 int a __attribute__((guarded_by(mu)));
532 int b;
533
foo()534 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
535
test()536 void test() {
537 a = 0; // \
538 // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}
539 b = a; // \
540 // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
541 c = 0; // \
542 // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}
543 }
544
545 int c __attribute__((guarded_by(mu)));
546
547 Mutex mu;
548 };
549
550 class LateBar {
551 public:
552 int a_ __attribute__((guarded_by(mu1_)));
553 int b_;
554 int *q __attribute__((pt_guarded_by(mu)));
555 Mutex mu1_;
556 Mutex mu;
557 LateFoo Foo;
558 LateFoo Foo2;
559 LateFoo *FooPointer;
560 };
561
562 LateBar b1, *b3;
563
late_0()564 void late_0() {
565 LateFoo FooA;
566 LateFoo FooB;
567 FooA.mu.Lock();
568 FooA.a = 5;
569 FooA.mu.Unlock();
570 }
571
late_1()572 void late_1() {
573 LateBar BarA;
574 BarA.FooPointer->mu.Lock();
575 BarA.FooPointer->a = 2;
576 BarA.FooPointer->mu.Unlock();
577 }
578
late_bad_0()579 void late_bad_0() {
580 LateFoo fooA;
581 LateFoo fooB;
582 fooA.mu.Lock();
583 fooB.a = 5; // \
584 // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \
585 // expected-note{{found near match 'fooA.mu'}}
586 fooA.mu.Unlock();
587 }
588
late_bad_1()589 void late_bad_1() {
590 Mutex mu;
591 mu.Lock();
592 b1.mu1_.Lock();
593 int res = b1.a_ + b3->b_;
594 b3->b_ = *b1.q; // \
595 // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}
596 b1.mu1_.Unlock();
597 b1.b_ = res;
598 mu.Unlock();
599 }
600
late_bad_2()601 void late_bad_2() {
602 LateBar BarA;
603 BarA.FooPointer->mu.Lock();
604 BarA.Foo.a = 2; // \
605 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \
606 // expected-note{{found near match 'BarA.FooPointer->mu'}}
607 BarA.FooPointer->mu.Unlock();
608 }
609
late_bad_3()610 void late_bad_3() {
611 LateBar BarA;
612 BarA.Foo.mu.Lock();
613 BarA.FooPointer->a = 2; // \
614 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \
615 // expected-note{{found near match 'BarA.Foo.mu'}}
616 BarA.Foo.mu.Unlock();
617 }
618
late_bad_4()619 void late_bad_4() {
620 LateBar BarA;
621 BarA.Foo.mu.Lock();
622 BarA.Foo2.a = 2; // \
623 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \
624 // expected-note{{found near match 'BarA.Foo.mu'}}
625 BarA.Foo.mu.Unlock();
626 }
627
628 //-----------------------------------------------//
629 // Extra warnings for shared vs. exclusive locks
630 // ----------------------------------------------//
631
shared_fun_0()632 void shared_fun_0() {
633 sls_mu.Lock();
634 do {
635 sls_mu.Unlock();
636 sls_mu.Lock();
637 } while (getBool());
638 sls_mu.Unlock();
639 }
640
shared_fun_1()641 void shared_fun_1() {
642 sls_mu.ReaderLock(); // \
643 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
644 do {
645 sls_mu.Unlock();
646 sls_mu.Lock(); // \
647 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
648 } while (getBool());
649 sls_mu.Unlock();
650 }
651
shared_fun_3()652 void shared_fun_3() {
653 if (getBool())
654 sls_mu.Lock();
655 else
656 sls_mu.Lock();
657 *pgb_var = 1;
658 sls_mu.Unlock();
659 }
660
shared_fun_4()661 void shared_fun_4() {
662 if (getBool())
663 sls_mu.ReaderLock();
664 else
665 sls_mu.ReaderLock();
666 int x = sls_guardby_var;
667 sls_mu.Unlock();
668 }
669
shared_fun_8()670 void shared_fun_8() {
671 if (getBool())
672 sls_mu.Lock(); // \
673 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
674 else
675 sls_mu.ReaderLock(); // \
676 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
677 sls_mu.Unlock();
678 }
679
shared_fun_9()680 void shared_fun_9() {
681 sls_mu.Lock();
682 sls_mu.ExclusiveUnlock();
683
684 sls_mu.ReaderLock();
685 sls_mu.ReaderUnlock();
686 }
687
shared_fun_10()688 void shared_fun_10() {
689 sls_mu.Lock();
690 sls_mu.DemoteExclusive();
691 sls_mu.ReaderUnlock();
692 }
693
shared_fun_11()694 void shared_fun_11() {
695 sls_mu.ReaderLock();
696 sls_mu.PromoteShared();
697 sls_mu.Unlock();
698 }
699
shared_bad_0()700 void shared_bad_0() {
701 sls_mu.Lock(); // \
702 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
703 do {
704 sls_mu.Unlock();
705 sls_mu.ReaderLock(); // \
706 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
707 } while (getBool());
708 sls_mu.Unlock();
709 }
710
shared_bad_1()711 void shared_bad_1() {
712 if (getBool())
713 sls_mu.Lock(); // \
714 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
715 else
716 sls_mu.ReaderLock(); // \
717 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
718 *pgb_var = 1;
719 sls_mu.Unlock();
720 }
721
shared_bad_2()722 void shared_bad_2() {
723 if (getBool())
724 sls_mu.ReaderLock(); // \
725 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
726 else
727 sls_mu.Lock(); // \
728 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
729 *pgb_var = 1;
730 sls_mu.Unlock();
731 }
732
shared_bad_3()733 void shared_bad_3() {
734 sls_mu.Lock(); // expected-note {{mutex acquired here}}
735 sls_mu.ReaderUnlock(); // \
736 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
737 }
738
shared_bad_4()739 void shared_bad_4() {
740 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
741 sls_mu.ExclusiveUnlock(); // \
742 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
743 }
744
shared_bad_5()745 void shared_bad_5() {
746 sls_mu.Lock(); // expected-note {{mutex acquired here}}
747 sls_mu.PromoteShared(); // \
748 // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
749 sls_mu.ExclusiveUnlock();
750 }
751
shared_bad_6()752 void shared_bad_6() {
753 sls_mu.ReaderLock(); // expected-note {{mutex acquired here}}
754 sls_mu.DemoteExclusive(); // \
755 // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
756 sls_mu.ReaderUnlock();
757 }
758
759 // FIXME: Add support for functions (not only methods)
760 class LRBar {
761 public:
762 void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
763 void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu);
764 void le_fun() __attribute__((locks_excluded(sls_mu)));
765 };
766
767 class LRFoo {
768 public:
769 void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
770 void testShared() SHARED_LOCKS_REQUIRED(sls_mu2);
771 };
772
773 void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
elr_fun()774 void elr_fun() {}
775
776 LRFoo MyLRFoo;
777 LRBar Bar;
778
es_fun_0()779 void es_fun_0() {
780 aa_mu.Lock();
781 Bar.aa_elr_fun();
782 aa_mu.Unlock();
783 }
784
es_fun_1()785 void es_fun_1() {
786 aa_mu.Lock();
787 Bar.aa_elr_fun_s();
788 aa_mu.Unlock();
789 }
790
es_fun_2()791 void es_fun_2() {
792 aa_mu.ReaderLock();
793 Bar.aa_elr_fun_s();
794 aa_mu.Unlock();
795 }
796
es_fun_3()797 void es_fun_3() {
798 sls_mu.Lock();
799 MyLRFoo.test();
800 sls_mu.Unlock();
801 }
802
es_fun_4()803 void es_fun_4() {
804 sls_mu2.Lock();
805 MyLRFoo.testShared();
806 sls_mu2.Unlock();
807 }
808
es_fun_5()809 void es_fun_5() {
810 sls_mu2.ReaderLock();
811 MyLRFoo.testShared();
812 sls_mu2.Unlock();
813 }
814
es_fun_6()815 void es_fun_6() {
816 Bar.le_fun();
817 }
818
es_fun_7()819 void es_fun_7() {
820 sls_mu.Lock();
821 elr_fun();
822 sls_mu.Unlock();
823 }
824
825 void es_fun_8() NO_THREAD_SAFETY_ANALYSIS;
826
es_fun_8()827 void es_fun_8() {
828 Bar.aa_elr_fun_s();
829 }
830
831 void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu);
es_fun_9()832 void es_fun_9() {
833 Bar.aa_elr_fun_s();
834 }
835
836 void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
es_fun_10()837 void es_fun_10() {
838 Bar.aa_elr_fun_s();
839 }
840
es_bad_0()841 void es_bad_0() {
842 Bar.aa_elr_fun(); // \
843 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
844 }
845
es_bad_1()846 void es_bad_1() {
847 aa_mu.ReaderLock();
848 Bar.aa_elr_fun(); // \
849 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
850 aa_mu.Unlock();
851 }
852
es_bad_2()853 void es_bad_2() {
854 Bar.aa_elr_fun_s(); // \
855 // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}
856 }
857
es_bad_3()858 void es_bad_3() {
859 MyLRFoo.test(); // \
860 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
861 }
862
es_bad_4()863 void es_bad_4() {
864 MyLRFoo.testShared(); // \
865 // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}
866 }
867
es_bad_5()868 void es_bad_5() {
869 sls_mu.ReaderLock();
870 MyLRFoo.test(); // \
871 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
872 sls_mu.Unlock();
873 }
874
es_bad_6()875 void es_bad_6() {
876 sls_mu.Lock();
877 Bar.le_fun(); // \
878 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
879 sls_mu.Unlock();
880 }
881
es_bad_7()882 void es_bad_7() {
883 sls_mu.ReaderLock();
884 Bar.le_fun(); // \
885 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
886 sls_mu.Unlock();
887 }
888
889
890 //-----------------------------------------------//
891 // Unparseable lock expressions
892 // ----------------------------------------------//
893
894 // FIXME -- derive new tests for unhandled expressions
895
896
897 //----------------------------------------------------------------------------//
898 // The following test cases are ported from the gcc thread safety implementation
899 // They are each wrapped inside a namespace with the test number of the gcc test
900 //
901 // FIXME: add all the gcc tests, once this analysis passes them.
902 //----------------------------------------------------------------------------//
903
904 //-----------------------------------------//
905 // Good testcases (no errors)
906 //-----------------------------------------//
907
908 namespace thread_annot_lock_20 {
909 class Bar {
910 public:
911 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
912 static int b_ GUARDED_BY(mu1_);
913 static Mutex mu1_;
914 static int a_ GUARDED_BY(mu1_);
915 };
916
917 Bar b1;
918
func1()919 int Bar::func1()
920 {
921 int res = 5;
922
923 if (a_ == 4)
924 res = b_;
925 return res;
926 }
927 } // end namespace thread_annot_lock_20
928
929 namespace thread_annot_lock_22 {
930 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
931 // uses in class definitions.
932 Mutex mu;
933
934 class Bar {
935 public:
936 int a_ GUARDED_BY(mu1_);
937 int b_;
938 int *q PT_GUARDED_BY(mu);
939 Mutex mu1_ ACQUIRED_AFTER(mu);
940 };
941
942 Bar b1, *b3;
943 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
944 int res GUARDED_BY(mu) = 5;
945
func(int i)946 int func(int i)
947 {
948 int x;
949 mu.Lock();
950 b1.mu1_.Lock();
951 res = b1.a_ + b3->b_;
952 *p = i;
953 b1.a_ = res + b3->b_;
954 b3->b_ = *b1.q;
955 b1.mu1_.Unlock();
956 b1.b_ = res;
957 x = res;
958 mu.Unlock();
959 return x;
960 }
961 } // end namespace thread_annot_lock_22
962
963 namespace thread_annot_lock_27_modified {
964 // test lock annotations applied to function definitions
965 // Modified: applied annotations only to function declarations
966 Mutex mu1;
967 Mutex mu2 ACQUIRED_AFTER(mu1);
968
969 class Foo {
970 public:
971 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
972 };
973
method1(int i)974 int Foo::method1(int i) {
975 return i;
976 }
977
978
979 int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
foo(int i)980 int foo(int i) {
981 return i;
982 }
983
984 static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
bar(int i)985 static int bar(int i) {
986 return i;
987 }
988
main()989 void main() {
990 Foo a;
991
992 mu1.Lock();
993 mu2.Lock();
994 a.method1(1);
995 foo(2);
996 mu2.Unlock();
997 bar(3);
998 mu1.Unlock();
999 }
1000 } // end namespace thread_annot_lock_27_modified
1001
1002
1003 namespace thread_annot_lock_38 {
1004 // Test the case where a template member function is annotated with lock
1005 // attributes in a non-template class.
1006 class Foo {
1007 public:
1008 void func1(int y) LOCKS_EXCLUDED(mu_);
1009 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
1010 private:
1011 Mutex mu_;
1012 };
1013
1014 Foo *foo;
1015
main()1016 void main()
1017 {
1018 foo->func1(5);
1019 foo->func2(5);
1020 }
1021 } // end namespace thread_annot_lock_38
1022
1023 namespace thread_annot_lock_43 {
1024 // Tests lock canonicalization
1025 class Foo {
1026 public:
1027 Mutex *mu_;
1028 };
1029
1030 class FooBar {
1031 public:
1032 Foo *foo_;
GetA()1033 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
1034 int a_ GUARDED_BY(foo_->mu_);
1035 };
1036
1037 FooBar *fb;
1038
main()1039 void main()
1040 {
1041 int x;
1042 fb->foo_->mu_->Lock();
1043 x = fb->GetA();
1044 fb->foo_->mu_->Unlock();
1045 }
1046 } // end namespace thread_annot_lock_43
1047
1048 namespace thread_annot_lock_49 {
1049 // Test the support for use of lock expression in the annotations
1050 class Foo {
1051 public:
1052 Mutex foo_mu_;
1053 };
1054
1055 class Bar {
1056 private:
1057 Foo *foo;
1058 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
1059
1060 public:
Test1()1061 void Test1() {
1062 foo->foo_mu_.Lock();
1063 bar_mu_.Lock();
1064 bar_mu_.Unlock();
1065 foo->foo_mu_.Unlock();
1066 }
1067 };
1068
main()1069 void main() {
1070 Bar bar;
1071 bar.Test1();
1072 }
1073 } // end namespace thread_annot_lock_49
1074
1075 namespace thread_annot_lock_61_modified {
1076 // Modified to fix the compiler errors
1077 // Test the fix for a bug introduced by the support of pass-by-reference
1078 // parameters.
operator <<thread_annot_lock_61_modified::Foo1079 struct Foo { Foo &operator<< (bool) {return *this;} };
1080 Foo &getFoo();
functhread_annot_lock_61_modified::Bar1081 struct Bar { Foo &func () {return getFoo();} };
operator &thread_annot_lock_61_modified::Bas1082 struct Bas { void operator& (Foo &) {} };
mumble()1083 void mumble()
1084 {
1085 Bas() & Bar().func() << "" << "";
1086 Bas() & Bar().func() << "";
1087 }
1088 } // end namespace thread_annot_lock_61_modified
1089
1090
1091 namespace thread_annot_lock_65 {
1092 // Test the fix for a bug in the support of allowing reader locks for
1093 // non-const, non-modifying overload functions. (We didn't handle the builtin
1094 // properly.)
1095 enum MyFlags {
1096 Zero,
1097 One,
1098 Two,
1099 Three,
1100 Four,
1101 Five,
1102 Six,
1103 Seven,
1104 Eight,
1105 Nine
1106 };
1107
1108 inline MyFlags
operator |(MyFlags a,MyFlags b)1109 operator|(MyFlags a, MyFlags b)
1110 {
1111 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1112 }
1113
1114 inline MyFlags&
operator |=(MyFlags & a,MyFlags b)1115 operator|=(MyFlags& a, MyFlags b)
1116 {
1117 return a = a | b;
1118 }
1119 } // end namespace thread_annot_lock_65
1120
1121 namespace thread_annot_lock_66_modified {
1122 // Modified: Moved annotation to function defn
1123 // Test annotations on out-of-line definitions of member functions where the
1124 // annotations refer to locks that are also data members in the class.
1125 Mutex mu;
1126
1127 class Foo {
1128 public:
1129 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1130 int data GUARDED_BY(mu1);
1131 Mutex *mu1;
1132 Mutex *mu2;
1133 };
1134
method1(int i)1135 int Foo::method1(int i)
1136 {
1137 return data + i;
1138 }
1139
main()1140 void main()
1141 {
1142 Foo a;
1143
1144 a.mu2->Lock();
1145 a.mu1->Lock();
1146 mu.Lock();
1147 a.method1(1);
1148 mu.Unlock();
1149 a.mu1->Unlock();
1150 a.mu2->Unlock();
1151 }
1152 } // end namespace thread_annot_lock_66_modified
1153
1154 namespace thread_annot_lock_68_modified {
1155 // Test a fix to a bug in the delayed name binding with nested template
1156 // instantiation. We use a stack to make sure a name is not resolved to an
1157 // inner context.
1158 template <typename T>
1159 class Bar {
1160 Mutex mu_;
1161 };
1162
1163 template <typename T>
1164 class Foo {
1165 public:
func(T x)1166 void func(T x) {
1167 mu_.Lock();
1168 count_ = x;
1169 mu_.Unlock();
1170 }
1171
1172 private:
1173 T count_ GUARDED_BY(mu_);
1174 Bar<T> bar_;
1175 Mutex mu_;
1176 };
1177
main()1178 void main()
1179 {
1180 Foo<int> *foo;
1181 foo->func(5);
1182 }
1183 } // end namespace thread_annot_lock_68_modified
1184
1185 namespace thread_annot_lock_30_modified {
1186 // Test delay parsing of lock attribute arguments with nested classes.
1187 // Modified: trylocks replaced with exclusive_lock_fun
1188 int a = 0;
1189
1190 class Bar {
1191 struct Foo;
1192
1193 public:
1194 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1195
func()1196 int func() {
1197 MyLock();
1198 // if (foo == 0) {
1199 // return 0;
1200 // }
1201 a = 5;
1202 mu.Unlock();
1203 return 1;
1204 }
1205
1206 class FooBar {
1207 int x;
1208 int y;
1209 };
1210
1211 private:
1212 Mutex mu;
1213 };
1214
1215 Bar *bar;
1216
main()1217 void main()
1218 {
1219 bar->func();
1220 }
1221 } // end namespace thread_annot_lock_30_modified
1222
1223 namespace thread_annot_lock_47 {
1224 // Test the support for annotations on virtual functions.
1225 // This is a good test case. (i.e. There should be no warning emitted by the
1226 // compiler.)
1227 class Base {
1228 public:
1229 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1230 virtual void func2() LOCKS_EXCLUDED(mu_);
1231 Mutex mu_;
1232 };
1233
1234 class Child : public Base {
1235 public:
1236 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1237 virtual void func2() LOCKS_EXCLUDED(mu_);
1238 };
1239
main()1240 void main() {
1241 Child *c;
1242 Base *b = c;
1243
1244 b->mu_.Lock();
1245 b->func1();
1246 b->mu_.Unlock();
1247 b->func2();
1248
1249 c->mu_.Lock();
1250 c->func1();
1251 c->mu_.Unlock();
1252 c->func2();
1253 }
1254 } // end namespace thread_annot_lock_47
1255
1256 //-----------------------------------------//
1257 // Tests which produce errors
1258 //-----------------------------------------//
1259
1260 namespace thread_annot_lock_13 {
1261 Mutex mu1;
1262 Mutex mu2;
1263
1264 int g GUARDED_BY(mu1);
1265 int w GUARDED_BY(mu2);
1266
1267 class Foo {
1268 public:
1269 void bar() LOCKS_EXCLUDED(mu_, mu1);
1270 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1271
1272 private:
1273 int a_ GUARDED_BY(mu_);
1274 public:
1275 Mutex mu_ ACQUIRED_AFTER(mu1);
1276 };
1277
foo()1278 int Foo::foo()
1279 {
1280 int res;
1281 w = 5;
1282 res = a_ + 5;
1283 return res;
1284 }
1285
bar()1286 void Foo::bar()
1287 {
1288 int x;
1289 mu_.Lock();
1290 x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}
1291 a_ = x + 1;
1292 mu_.Unlock();
1293 if (x > 5) {
1294 mu1.Lock();
1295 g = 2;
1296 mu1.Unlock();
1297 }
1298 }
1299
main()1300 void main()
1301 {
1302 Foo f1, *f2;
1303 f1.mu_.Lock();
1304 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}
1305 mu2.Lock();
1306 f1.foo();
1307 mu2.Unlock();
1308 f1.mu_.Unlock();
1309 f2->mu_.Lock();
1310 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}
1311 f2->mu_.Unlock();
1312 mu2.Lock();
1313 w = 2;
1314 mu2.Unlock();
1315 }
1316 } // end namespace thread_annot_lock_13
1317
1318 namespace thread_annot_lock_18_modified {
1319 // Modified: Trylocks removed
1320 // Test the ability to distnguish between the same lock field of
1321 // different objects of a class.
1322 class Bar {
1323 public:
1324 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1325 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1326 int a_ GUARDED_BY(mu1_);
1327
1328 private:
1329 Mutex mu1_;
1330 };
1331
1332 Bar *b1, *b2;
1333
func()1334 void func()
1335 {
1336 b1->MyLock();
1337 b1->a_ = 5;
1338 b2->a_ = 3; // \
1339 // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \
1340 // expected-note {{found near match 'b1->mu1_'}}
1341 b2->MyLock();
1342 b2->MyUnlock();
1343 b1->MyUnlock();
1344 }
1345 } // end namespace thread_annot_lock_18_modified
1346
1347 namespace thread_annot_lock_21 {
1348 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1349 // uses in class definitions.
1350 Mutex mu;
1351
1352 class Bar {
1353 public:
1354 int a_ GUARDED_BY(mu1_);
1355 int b_;
1356 int *q PT_GUARDED_BY(mu);
1357 Mutex mu1_ ACQUIRED_AFTER(mu);
1358 };
1359
1360 Bar b1, *b3;
1361 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1362
1363 int res GUARDED_BY(mu) = 5;
1364
func(int i)1365 int func(int i)
1366 {
1367 int x;
1368 b3->mu1_.Lock();
1369 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \
1370 // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \
1371 // expected-note {{found near match 'b3->mu1_'}}
1372 *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \
1373 // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}
1374 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \
1375 // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \
1376 // expected-note {{found near match 'b3->mu1_'}}
1377 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}
1378 b3->mu1_.Unlock();
1379 b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1380 x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1381 return x;
1382 }
1383 } // end namespace thread_annot_lock_21
1384
1385 namespace thread_annot_lock_35_modified {
1386 // Test the analyzer's ability to distinguish the lock field of different
1387 // objects.
1388 class Foo {
1389 private:
1390 Mutex lock_;
1391 int a_ GUARDED_BY(lock_);
1392
1393 public:
Func(Foo * child)1394 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1395 Foo *new_foo = new Foo;
1396
1397 lock_.Lock();
1398
1399 child->Func(new_foo); // There shouldn't be any warning here as the
1400 // acquired lock is not in child.
1401 child->bar(7); // \
1402 // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \
1403 // expected-note {{found near match 'lock_'}}
1404 child->a_ = 5; // \
1405 // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \
1406 // expected-note {{found near match 'lock_'}}
1407 lock_.Unlock();
1408 }
1409
bar(int y)1410 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1411 a_ = y;
1412 }
1413 };
1414
1415 Foo *x;
1416
main()1417 void main() {
1418 Foo *child = new Foo;
1419 x->Func(child);
1420 }
1421 } // end namespace thread_annot_lock_35_modified
1422
1423 namespace thread_annot_lock_36_modified {
1424 // Modified to move the annotations to function defns.
1425 // Test the analyzer's ability to distinguish the lock field of different
1426 // objects
1427 class Foo {
1428 private:
1429 Mutex lock_;
1430 int a_ GUARDED_BY(lock_);
1431
1432 public:
1433 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1434 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1435 };
1436
Func(Foo * child)1437 void Foo::Func(Foo* child) {
1438 Foo *new_foo = new Foo;
1439
1440 lock_.Lock();
1441
1442 child->lock_.Lock();
1443 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}
1444 child->bar(7);
1445 child->a_ = 5;
1446 child->lock_.Unlock();
1447
1448 lock_.Unlock();
1449 }
1450
bar(int y)1451 void Foo::bar(int y) {
1452 a_ = y;
1453 }
1454
1455
1456 Foo *x;
1457
main()1458 void main() {
1459 Foo *child = new Foo;
1460 x->Func(child);
1461 }
1462 } // end namespace thread_annot_lock_36_modified
1463
1464
1465 namespace thread_annot_lock_42 {
1466 // Test support of multiple lock attributes of the same kind on a decl.
1467 class Foo {
1468 private:
1469 Mutex mu1, mu2, mu3;
1470 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1471 int y GUARDED_BY(mu2);
1472
f2()1473 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1474 mu2.Lock();
1475 y = 2;
1476 mu2.Unlock();
1477 }
1478
1479 public:
f1()1480 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1481 x = 5;
1482 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \
1483 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}
1484 }
1485 };
1486
1487 Foo *foo;
1488
func()1489 void func()
1490 {
1491 foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \
1492 // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}
1493 }
1494 } // end namespace thread_annot_lock_42
1495
1496 namespace thread_annot_lock_46 {
1497 // Test the support for annotations on virtual functions.
1498 class Base {
1499 public:
1500 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1501 virtual void func2() LOCKS_EXCLUDED(mu_);
1502 Mutex mu_;
1503 };
1504
1505 class Child : public Base {
1506 public:
1507 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1508 virtual void func2() LOCKS_EXCLUDED(mu_);
1509 };
1510
main()1511 void main() {
1512 Child *c;
1513 Base *b = c;
1514
1515 b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}}
1516 b->mu_.Lock();
1517 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}}
1518 b->mu_.Unlock();
1519
1520 c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}
1521 c->mu_.Lock();
1522 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}
1523 c->mu_.Unlock();
1524 }
1525 } // end namespace thread_annot_lock_46
1526
1527 namespace thread_annot_lock_67_modified {
1528 // Modified: attributes on definitions moved to declarations
1529 // Test annotations on out-of-line definitions of member functions where the
1530 // annotations refer to locks that are also data members in the class.
1531 Mutex mu;
1532 Mutex mu3;
1533
1534 class Foo {
1535 public:
1536 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1537 int data GUARDED_BY(mu1);
1538 Mutex *mu1;
1539 Mutex *mu2;
1540 };
1541
method1(int i)1542 int Foo::method1(int i) {
1543 return data + i;
1544 }
1545
main()1546 void main()
1547 {
1548 Foo a;
1549 a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \
1550 // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \
1551 // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \
1552 // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}
1553 }
1554 } // end namespace thread_annot_lock_67_modified
1555
1556
1557 namespace substitution_test {
1558 class MyData {
1559 public:
1560 Mutex mu;
1561
1562 void lockData() EXCLUSIVE_LOCK_FUNCTION(mu);
1563 void unlockData() UNLOCK_FUNCTION(mu);
1564
doSomething()1565 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
1566 };
1567
1568
1569 class DataLocker {
1570 public:
1571 void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu);
1572 void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu);
1573 };
1574
1575
1576 class Foo {
1577 public:
foo(MyData * d)1578 void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { }
1579
bar1(MyData * d)1580 void bar1(MyData* d) {
1581 d->lockData();
1582 foo(d);
1583 d->unlockData();
1584 }
1585
bar2(MyData * d)1586 void bar2(MyData* d) {
1587 DataLocker dlr;
1588 dlr.lockData(d);
1589 foo(d);
1590 dlr.unlockData(d);
1591 }
1592
bar3(MyData * d1,MyData * d2)1593 void bar3(MyData* d1, MyData* d2) {
1594 DataLocker dlr;
1595 dlr.lockData(d1); // expected-note {{mutex acquired here}}
1596 dlr.unlockData(d2); // \
1597 // expected-warning {{releasing mutex 'd2->mu' that was not held}}
1598 } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}
1599
bar4(MyData * d1,MyData * d2)1600 void bar4(MyData* d1, MyData* d2) {
1601 DataLocker dlr;
1602 dlr.lockData(d1);
1603 foo(d2); // \
1604 // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \
1605 // expected-note {{found near match 'd1->mu'}}
1606 dlr.unlockData(d1);
1607 }
1608 };
1609 } // end namespace substituation_test
1610
1611
1612
1613 namespace constructor_destructor_tests {
1614 Mutex fooMu;
1615 int myVar GUARDED_BY(fooMu);
1616
1617 class Foo {
1618 public:
EXCLUSIVE_LOCK_FUNCTION(fooMu)1619 Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { }
UNLOCK_FUNCTION(fooMu)1620 ~Foo() UNLOCK_FUNCTION(fooMu) { }
1621 };
1622
fooTest()1623 void fooTest() {
1624 Foo foo;
1625 myVar = 0;
1626 }
1627 }
1628
1629
1630 namespace template_member_test {
1631
1632 struct S { int n; };
1633 struct T {
1634 Mutex m;
1635 S *s GUARDED_BY(this->m);
1636 };
1637 Mutex m;
1638 struct U {
1639 union {
1640 int n;
1641 };
1642 } *u GUARDED_BY(m);
1643
1644 template<typename U>
1645 struct IndirectLock {
DoNaughtyThingstemplate_member_test::IndirectLock1646 int DoNaughtyThings(T *t) {
1647 u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}
1648 return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}
1649 }
1650 };
1651
1652 template struct IndirectLock<int>; // expected-note {{here}}
1653
1654 struct V {
1655 void f(int);
1656 void f(double);
1657
1658 Mutex m;
1659 V *p GUARDED_BY(this->m);
1660 };
1661 template<typename U> struct W {
1662 V v;
ftemplate_member_test::W1663 void f(U u) {
1664 v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}
1665 }
1666 };
1667 template struct W<int>; // expected-note {{here}}
1668
1669 }
1670
1671 namespace test_scoped_lockable {
1672
1673 struct TestScopedLockable {
1674 Mutex mu1;
1675 Mutex mu2;
1676 int a __attribute__((guarded_by(mu1)));
1677 int b __attribute__((guarded_by(mu2)));
1678
1679 bool getBool();
1680
foo1test_scoped_lockable::TestScopedLockable1681 void foo1() {
1682 MutexLock mulock(&mu1);
1683 a = 5;
1684 }
1685
foo2test_scoped_lockable::TestScopedLockable1686 void foo2() {
1687 ReaderMutexLock mulock1(&mu1);
1688 if (getBool()) {
1689 MutexLock mulock2a(&mu2);
1690 b = a + 1;
1691 }
1692 else {
1693 MutexLock mulock2b(&mu2);
1694 b = a + 2;
1695 }
1696 }
1697
foo3test_scoped_lockable::TestScopedLockable1698 void foo3() {
1699 MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}}
1700 MutexLock mulock_b(&mu1); // \
1701 // expected-warning {{acquiring mutex 'mu1' that is already held}}
1702 }
1703
foo4test_scoped_lockable::TestScopedLockable1704 void foo4() {
1705 MutexLock mulock1(&mu1), mulock2(&mu2);
1706 a = b+1;
1707 b = a+1;
1708 }
1709
foo5test_scoped_lockable::TestScopedLockable1710 void foo5() {
1711 DoubleMutexLock mulock(&mu1, &mu2);
1712 a = b + 1;
1713 b = a + 1;
1714 }
1715 };
1716
1717 } // end namespace test_scoped_lockable
1718
1719
1720 namespace FunctionAttrTest {
1721
1722 class Foo {
1723 public:
1724 Mutex mu_;
1725 int a GUARDED_BY(mu_);
1726 };
1727
1728 Foo fooObj;
1729
1730 void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1731
bar()1732 void bar() {
1733 foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}
1734 fooObj.mu_.Lock();
1735 foo();
1736 fooObj.mu_.Unlock();
1737 }
1738
1739 }; // end namespace FunctionAttrTest
1740
1741
1742 namespace TryLockTest {
1743
1744 struct TestTryLock {
1745 Mutex mu;
1746 int a GUARDED_BY(mu);
1747 bool cond;
1748
foo1TryLockTest::TestTryLock1749 void foo1() {
1750 if (mu.TryLock()) {
1751 a = 1;
1752 mu.Unlock();
1753 }
1754 }
1755
foo2TryLockTest::TestTryLock1756 void foo2() {
1757 if (!mu.TryLock()) return;
1758 a = 2;
1759 mu.Unlock();
1760 }
1761
foo2_builtin_expectTryLockTest::TestTryLock1762 void foo2_builtin_expect() {
1763 if (__builtin_expect(!mu.TryLock(), false))
1764 return;
1765 a = 2;
1766 mu.Unlock();
1767 }
1768
foo3TryLockTest::TestTryLock1769 void foo3() {
1770 bool b = mu.TryLock();
1771 if (b) {
1772 a = 3;
1773 mu.Unlock();
1774 }
1775 }
1776
foo3_builtin_expectTryLockTest::TestTryLock1777 void foo3_builtin_expect() {
1778 bool b = mu.TryLock();
1779 if (__builtin_expect(b, true)) {
1780 a = 3;
1781 mu.Unlock();
1782 }
1783 }
1784
foo4TryLockTest::TestTryLock1785 void foo4() {
1786 bool b = mu.TryLock();
1787 if (!b) return;
1788 a = 4;
1789 mu.Unlock();
1790 }
1791
foo5TryLockTest::TestTryLock1792 void foo5() {
1793 while (mu.TryLock()) {
1794 a = a + 1;
1795 mu.Unlock();
1796 }
1797 }
1798
foo6TryLockTest::TestTryLock1799 void foo6() {
1800 bool b = mu.TryLock();
1801 b = !b;
1802 if (b) return;
1803 a = 6;
1804 mu.Unlock();
1805 }
1806
foo7TryLockTest::TestTryLock1807 void foo7() {
1808 bool b1 = mu.TryLock();
1809 bool b2 = !b1;
1810 bool b3 = !b2;
1811 if (b3) {
1812 a = 7;
1813 mu.Unlock();
1814 }
1815 }
1816
1817 // Test use-def chains: join points
foo8TryLockTest::TestTryLock1818 void foo8() {
1819 bool b = mu.TryLock();
1820 bool b2 = b;
1821 if (cond)
1822 b = true;
1823 if (b) { // b should be unknown at this point, because of the join point
1824 a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1825 }
1826 if (b2) { // b2 should be known at this point.
1827 a = 8;
1828 mu.Unlock();
1829 }
1830 }
1831
1832 // Test use-def-chains: back edges
foo9TryLockTest::TestTryLock1833 void foo9() {
1834 bool b = mu.TryLock();
1835
1836 for (int i = 0; i < 10; ++i);
1837
1838 if (b) { // b is still known, because the loop doesn't alter it
1839 a = 9;
1840 mu.Unlock();
1841 }
1842 }
1843
1844 // Test use-def chains: back edges
foo10TryLockTest::TestTryLock1845 void foo10() {
1846 bool b = mu.TryLock();
1847
1848 while (cond) {
1849 if (b) { // b should be unknown at this point b/c of the loop
1850 a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1851 }
1852 b = !b;
1853 }
1854 }
1855
1856 // Test merge of exclusive trylock
foo11TryLockTest::TestTryLock1857 void foo11() {
1858 if (cond) {
1859 if (!mu.TryLock())
1860 return;
1861 }
1862 else {
1863 mu.Lock();
1864 }
1865 a = 10;
1866 mu.Unlock();
1867 }
1868
1869 // Test merge of shared trylock
foo12TryLockTest::TestTryLock1870 void foo12() {
1871 if (cond) {
1872 if (!mu.ReaderTryLock())
1873 return;
1874 }
1875 else {
1876 mu.ReaderLock();
1877 }
1878 int i = a;
1879 mu.Unlock();
1880 }
1881
1882 // Test with conditional operator
foo13TryLockTest::TestTryLock1883 void foo13() {
1884 if (mu.TryLock() ? 1 : 0)
1885 mu.Unlock();
1886 }
1887
foo14TryLockTest::TestTryLock1888 void foo14() {
1889 if (mu.TryLock() ? 0 : 1)
1890 return;
1891 mu.Unlock();
1892 }
1893
foo15TryLockTest::TestTryLock1894 void foo15() {
1895 if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
1896 mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}
1897 } // expected-warning{{mutex 'mu' is not held on every path through here}}
1898 }; // end TestTrylock
1899
1900 } // end namespace TrylockTest
1901
1902
1903 namespace TestTemplateAttributeInstantiation {
1904
1905 class Foo1 {
1906 public:
1907 Mutex mu_;
1908 int a GUARDED_BY(mu_);
1909 };
1910
1911 class Foo2 {
1912 public:
1913 int a GUARDED_BY(mu_);
1914 Mutex mu_;
1915 };
1916
1917
1918 class Bar {
1919 public:
1920 // Test non-dependent expressions in attributes on template functions
1921 template <class T>
barND(Foo1 * foo,T * fooT)1922 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1923 foo->a = 0;
1924 }
1925
1926 // Test dependent expressions in attributes on template functions
1927 template <class T>
barD(Foo1 * foo,T * fooT)1928 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1929 fooT->a = 0;
1930 }
1931 };
1932
1933
1934 template <class T>
1935 class BarT {
1936 public:
1937 Foo1 fooBase;
1938 T fooBaseT;
1939
1940 // Test non-dependent expression in ordinary method on template class
barND()1941 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1942 fooBase.a = 0;
1943 }
1944
1945 // Test dependent expressions in ordinary methods on template class
barD()1946 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1947 fooBaseT.a = 0;
1948 }
1949
1950 // Test dependent expressions in template method in template class
1951 template <class T2>
barTD(T2 * fooT)1952 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1953 fooBaseT.a = 0;
1954 fooT->a = 0;
1955 }
1956 };
1957
1958 template <class T>
1959 class Cell {
1960 public:
1961 Mutex mu_;
1962 // Test dependent guarded_by
1963 T data GUARDED_BY(mu_);
1964
fooEx()1965 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1966 data = 0;
1967 }
1968
foo()1969 void foo() {
1970 mu_.Lock();
1971 data = 0;
1972 mu_.Unlock();
1973 }
1974 };
1975
test()1976 void test() {
1977 Bar b;
1978 BarT<Foo2> bt;
1979 Foo1 f1;
1980 Foo2 f2;
1981
1982 f1.mu_.Lock();
1983 f2.mu_.Lock();
1984 bt.fooBase.mu_.Lock();
1985 bt.fooBaseT.mu_.Lock();
1986
1987 b.barND(&f1, &f2);
1988 b.barD(&f1, &f2);
1989 bt.barND();
1990 bt.barD();
1991 bt.barTD(&f2);
1992
1993 f1.mu_.Unlock();
1994 bt.barTD(&f1); // \
1995 // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \
1996 // expected-note {{found near match 'bt.fooBase.mu_'}}
1997
1998 bt.fooBase.mu_.Unlock();
1999 bt.fooBaseT.mu_.Unlock();
2000 f2.mu_.Unlock();
2001
2002 Cell<int> cell;
2003 cell.data = 0; // \
2004 // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}
2005 cell.foo();
2006 cell.mu_.Lock();
2007 cell.fooEx();
2008 cell.mu_.Unlock();
2009 }
2010
2011
2012 template <class T>
2013 class CellDelayed {
2014 public:
2015 // Test dependent guarded_by
2016 T data GUARDED_BY(mu_);
2017 static T static_data GUARDED_BY(static_mu_);
2018
fooEx(CellDelayed<T> * other)2019 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
2020 this->data = other->data;
2021 }
2022
2023 template <class T2>
fooExT(CellDelayed<T2> * otherT)2024 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
2025 this->data = otherT->data;
2026 }
2027
foo()2028 void foo() {
2029 mu_.Lock();
2030 data = 0;
2031 mu_.Unlock();
2032 }
2033
2034 Mutex mu_;
2035 static Mutex static_mu_;
2036 };
2037
testDelayed()2038 void testDelayed() {
2039 CellDelayed<int> celld;
2040 CellDelayed<int> celld2;
2041 celld.foo();
2042 celld.mu_.Lock();
2043 celld2.mu_.Lock();
2044
2045 celld.fooEx(&celld2);
2046 celld.fooExT(&celld2);
2047
2048 celld2.mu_.Unlock();
2049 celld.mu_.Unlock();
2050 }
2051
2052 }; // end namespace TestTemplateAttributeInstantiation
2053
2054
2055 namespace FunctionDeclDefTest {
2056
2057 class Foo {
2058 public:
2059 Mutex mu_;
2060 int a GUARDED_BY(mu_);
2061
2062 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
2063 };
2064
2065 // EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
foo1(Foo * f_defined)2066 void Foo::foo1(Foo *f_defined) {
2067 f_defined->a = 0;
2068 };
2069
test()2070 void test() {
2071 Foo myfoo;
2072 myfoo.foo1(&myfoo); // \
2073 // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}
2074 myfoo.mu_.Lock();
2075 myfoo.foo1(&myfoo);
2076 myfoo.mu_.Unlock();
2077 }
2078
2079 };
2080
2081 namespace GoingNative {
2082
2083 struct LOCKABLE mutex {
2084 void lock() EXCLUSIVE_LOCK_FUNCTION();
2085 void unlock() UNLOCK_FUNCTION();
2086 // ...
2087 };
2088 bool foo();
2089 bool bar();
2090 mutex m;
test()2091 void test() {
2092 m.lock();
2093 while (foo()) { // expected-warning {{expecting mutex 'm' to be held at start of each loop}}
2094 m.unlock();
2095 // ...
2096 if (bar()) {
2097 // ...
2098 if (foo())
2099 continue;
2100 //...
2101 }
2102 // ...
2103 m.lock(); // expected-note {{mutex acquired here}}
2104 }
2105 m.unlock();
2106 }
2107
2108 }
2109
2110
2111
2112 namespace FunctionDefinitionTest {
2113
2114 class Foo {
2115 public:
2116 void foo1();
2117 void foo2();
2118 void foo3(Foo *other);
2119
2120 template<class T>
2121 void fooT1(const T& dummy1);
2122
2123 template<class T>
2124 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2125
2126 Mutex mu_;
2127 int a GUARDED_BY(mu_);
2128 };
2129
2130 template<class T>
2131 class FooT {
2132 public:
2133 void foo();
2134
2135 Mutex mu_;
2136 T a GUARDED_BY(mu_);
2137 };
2138
2139
foo1()2140 void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2141 a = 1;
2142 }
2143
foo2()2144 void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2145 a = 2;
2146 }
2147
foo3(Foo * other)2148 void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2149 other->a = 3;
2150 }
2151
2152 template<class T>
fooT1(const T & dummy1)2153 void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2154 a = dummy1;
2155 }
2156
2157 /* TODO -- uncomment with template instantiation of attributes.
2158 template<class T>
2159 void Foo::fooT2(const T& dummy2) {
2160 a = dummy2;
2161 }
2162 */
2163
fooF1(Foo * f)2164 void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2165 f->a = 1;
2166 }
2167
2168 void fooF2(Foo *f);
fooF2(Foo * f)2169 void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2170 f->a = 2;
2171 }
2172
2173 void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
fooF3(Foo * f)2174 void fooF3(Foo *f) {
2175 f->a = 3;
2176 }
2177
2178 template<class T>
foo()2179 void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2180 a = 0;
2181 }
2182
test()2183 void test() {
2184 int dummy = 0;
2185 Foo myFoo;
2186
2187 myFoo.foo2(); // \
2188 // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}
2189 myFoo.foo3(&myFoo); // \
2190 // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
2191 myFoo.fooT1(dummy); // \
2192 // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2193
2194 myFoo.fooT2(dummy); // \
2195 // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}
2196
2197 fooF1(&myFoo); // \
2198 // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
2199 fooF2(&myFoo); // \
2200 // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}
2201 fooF3(&myFoo); // \
2202 // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}
2203
2204 myFoo.mu_.Lock();
2205 myFoo.foo2();
2206 myFoo.foo3(&myFoo);
2207 myFoo.fooT1(dummy);
2208
2209 myFoo.fooT2(dummy);
2210
2211 fooF1(&myFoo);
2212 fooF2(&myFoo);
2213 fooF3(&myFoo);
2214 myFoo.mu_.Unlock();
2215
2216 FooT<int> myFooT;
2217 myFooT.foo(); // \
2218 // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}
2219 }
2220
2221 } // end namespace FunctionDefinitionTest
2222
2223
2224 namespace SelfLockingTest {
2225
2226 class LOCKABLE MyLock {
2227 public:
2228 int foo GUARDED_BY(this);
2229
2230 void lock() EXCLUSIVE_LOCK_FUNCTION();
2231 void unlock() UNLOCK_FUNCTION();
2232
doSomething()2233 void doSomething() {
2234 this->lock(); // allow 'this' as a lock expression
2235 foo = 0;
2236 doSomethingElse();
2237 this->unlock();
2238 }
2239
doSomethingElse()2240 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2241 foo = 1;
2242 };
2243
test()2244 void test() {
2245 foo = 2; // \
2246 // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}
2247 }
2248 };
2249
2250
2251 class LOCKABLE MyLock2 {
2252 public:
2253 Mutex mu_;
2254 int foo GUARDED_BY(this);
2255
2256 // don't check inside lock and unlock functions
lock()2257 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
unlock()2258 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2259
2260 // don't check inside constructors and destructors
MyLock2()2261 MyLock2() { foo = 1; }
~MyLock2()2262 ~MyLock2() { foo = 0; }
2263 };
2264
2265
2266 } // end namespace SelfLockingTest
2267
2268
2269 namespace InvalidNonstatic {
2270
2271 // Forward decl here causes bogus "invalid use of non-static data member"
2272 // on reference to mutex_ in guarded_by attribute.
2273 class Foo;
2274
2275 class Foo {
2276 Mutex* mutex_;
2277
2278 int foo __attribute__((guarded_by(mutex_)));
2279 };
2280
2281 } // end namespace InvalidNonStatic
2282
2283
2284 namespace NoReturnTest {
2285
2286 bool condition();
2287 void fatal() __attribute__((noreturn));
2288
2289 Mutex mu_;
2290
test1()2291 void test1() {
2292 MutexLock lock(&mu_);
2293 if (condition()) {
2294 fatal();
2295 return;
2296 }
2297 }
2298
2299 } // end namespace NoReturnTest
2300
2301
2302 namespace TestMultiDecl {
2303
2304 class Foo {
2305 public:
2306 int GUARDED_BY(mu_) a;
2307 int GUARDED_BY(mu_) b, c;
2308
foo()2309 void foo() {
2310 a = 0; // \
2311 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2312 b = 0; // \
2313 // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2314 c = 0; // \
2315 // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
2316 }
2317
2318 private:
2319 Mutex mu_;
2320 };
2321
2322 } // end namespace TestMultiDecl
2323
2324
2325 namespace WarnNoDecl {
2326
2327 class Foo {
2328 void foo(int a); __attribute__(( // \
2329 // expected-warning {{declaration does not declare anything}}
2330 exclusive_locks_required(a))); // \
2331 // expected-warning {{attribute exclusive_locks_required ignored}}
2332 };
2333
2334 } // end namespace WarnNoDecl
2335
2336
2337
2338 namespace MoreLockExpressions {
2339
2340 class Foo {
2341 public:
2342 Mutex mu_;
2343 int a GUARDED_BY(mu_);
2344 };
2345
2346 class Bar {
2347 public:
2348 int b;
2349 Foo* f;
2350
getFoo()2351 Foo& getFoo() { return *f; }
getFoo2(int c)2352 Foo& getFoo2(int c) { return *f; }
getFoo3(int c,int d)2353 Foo& getFoo3(int c, int d) { return *f; }
2354
getFooey()2355 Foo& getFooey() { return *f; }
2356 };
2357
getBarFoo(Bar & bar,int c)2358 Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2359
test()2360 void test() {
2361 Foo foo;
2362 Foo *fooArray;
2363 Foo &(*fooFuncPtr)();
2364 Bar bar;
2365 int a;
2366 int b;
2367 int c;
2368
2369 bar.getFoo().mu_.Lock();
2370 bar.getFoo().a = 0;
2371 bar.getFoo().mu_.Unlock();
2372
2373 (bar.getFoo().mu_).Lock(); // test parenthesis
2374 bar.getFoo().a = 0;
2375 (bar.getFoo().mu_).Unlock();
2376
2377 bar.getFoo2(a).mu_.Lock();
2378 bar.getFoo2(a).a = 0;
2379 bar.getFoo2(a).mu_.Unlock();
2380
2381 bar.getFoo3(a, b).mu_.Lock();
2382 bar.getFoo3(a, b).a = 0;
2383 bar.getFoo3(a, b).mu_.Unlock();
2384
2385 getBarFoo(bar, a).mu_.Lock();
2386 getBarFoo(bar, a).a = 0;
2387 getBarFoo(bar, a).mu_.Unlock();
2388
2389 bar.getFoo2(10).mu_.Lock();
2390 bar.getFoo2(10).a = 0;
2391 bar.getFoo2(10).mu_.Unlock();
2392
2393 bar.getFoo2(a + 1).mu_.Lock();
2394 bar.getFoo2(a + 1).a = 0;
2395 bar.getFoo2(a + 1).mu_.Unlock();
2396
2397 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2398 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2399 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2400
2401 fooFuncPtr().mu_.Lock();
2402 fooFuncPtr().a = 0;
2403 fooFuncPtr().mu_.Unlock();
2404 }
2405
2406
test2()2407 void test2() {
2408 Foo *fooArray;
2409 Bar bar;
2410 int a;
2411 int b;
2412 int c;
2413
2414 bar.getFoo().mu_.Lock();
2415 bar.getFooey().a = 0; // \
2416 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \
2417 // expected-note {{found near match 'bar.getFoo().mu_'}}
2418 bar.getFoo().mu_.Unlock();
2419
2420 bar.getFoo2(a).mu_.Lock();
2421 bar.getFoo2(b).a = 0; // \
2422 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \
2423 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
2424 bar.getFoo2(a).mu_.Unlock();
2425
2426 bar.getFoo3(a, b).mu_.Lock();
2427 bar.getFoo3(a, c).a = 0; // \
2428 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
2429 // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
2430 bar.getFoo3(a, b).mu_.Unlock();
2431
2432 getBarFoo(bar, a).mu_.Lock();
2433 getBarFoo(bar, b).a = 0; // \
2434 // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
2435 // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
2436 getBarFoo(bar, a).mu_.Unlock();
2437
2438 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2439 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2440 // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
2441 // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
2442 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2443 }
2444
2445
2446 } // end namespace MoreLockExpressions
2447
2448
2449 namespace TrylockJoinPoint {
2450
2451 class Foo {
2452 Mutex mu;
2453 bool c;
2454
foo()2455 void foo() {
2456 if (c) {
2457 if (!mu.TryLock())
2458 return;
2459 } else {
2460 mu.Lock();
2461 }
2462 mu.Unlock();
2463 }
2464 };
2465
2466 } // end namespace TrylockJoinPoint
2467
2468
2469 namespace LockReturned {
2470
2471 class Foo {
2472 public:
2473 int a GUARDED_BY(mu_);
2474 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2475 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2476
2477 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2478
2479 Mutex* getMu() LOCK_RETURNED(mu_);
2480
2481 Mutex mu_;
2482
2483 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2484 };
2485
2486
2487 // Calls getMu() directly to lock and unlock
test1(Foo * f1,Foo * f2)2488 void test1(Foo* f1, Foo* f2) {
2489 f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}
2490 f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}
2491
2492 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \
2493 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}
2494 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}
2495
2496 f1->getMu()->Lock();
2497
2498 f1->a = 0;
2499 f1->foo();
2500 f1->foo2(f2); // \
2501 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \
2502 // expected-note {{found near match 'f1->mu_'}}
2503
2504 Foo::getMu(f2)->Lock();
2505 f1->foo2(f2);
2506 Foo::getMu(f2)->Unlock();
2507
2508 Foo::sfoo(f1);
2509
2510 f1->getMu()->Unlock();
2511 }
2512
2513
2514 Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2515
2516 class Bar : public Foo {
2517 public:
2518 int b GUARDED_BY(getMu());
2519 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2520 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2521
2522 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2523 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2524 };
2525
2526
2527
2528 // Use getMu() within other attributes.
2529 // This requires at lest levels of substitution, more in the case of
test2(Bar * b1,Bar * b2)2530 void test2(Bar* b1, Bar* b2) {
2531 b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}
2532 b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}
2533 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \
2534 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}
2535 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}
2536 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}
2537
2538 b1->getMu()->Lock();
2539
2540 b1->b = 0;
2541 b1->bar();
2542 b1->bar2(b2); // \
2543 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \
2544 // // expected-note {{found near match 'b1->mu_'}}
2545
2546 b2->getMu()->Lock();
2547 b1->bar2(b2);
2548
2549 b2->getMu()->Unlock();
2550
2551 Bar::sbar(b1);
2552 Bar::sbar2(b1);
2553
2554 b1->getMu()->Unlock();
2555 }
2556
2557
2558 // Lock the mutex directly, but use attributes that call getMu()
2559 // Also lock the mutex using getFooMu, which calls a lock_returned function.
test3(Bar * b1,Bar * b2)2560 void test3(Bar* b1, Bar* b2) {
2561 b1->mu_.Lock();
2562 b1->b = 0;
2563 b1->bar();
2564
2565 getFooMu(b2)->Lock();
2566 b1->bar2(b2);
2567 getFooMu(b2)->Unlock();
2568
2569 Bar::sbar(b1);
2570 Bar::sbar2(b1);
2571
2572 b1->mu_.Unlock();
2573 }
2574
2575 } // end namespace LockReturned
2576
2577
2578 namespace ReleasableScopedLock {
2579
2580 class Foo {
2581 Mutex mu_;
2582 bool c;
2583 int a GUARDED_BY(mu_);
2584
2585 void test1();
2586 void test2();
2587 void test3();
2588 void test4();
2589 void test5();
2590 void test6();
2591 };
2592
2593
test1()2594 void Foo::test1() {
2595 ReleasableMutexLock rlock(&mu_);
2596 rlock.Release();
2597 }
2598
test2()2599 void Foo::test2() {
2600 ReleasableMutexLock rlock(&mu_);
2601 if (c) { // test join point -- held/not held during release
2602 rlock.Release();
2603 }
2604 // No warning on join point because the lock will be released by the scope object anyway.
2605 }
2606
test3()2607 void Foo::test3() {
2608 ReleasableMutexLock rlock(&mu_);
2609 a = 0;
2610 rlock.Release();
2611 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2612 }
2613
test4()2614 void Foo::test4() {
2615 ReleasableMutexLock rlock(&mu_);
2616 rlock.Release(); // expected-note{{mutex released here}}
2617 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2618 }
2619
test5()2620 void Foo::test5() {
2621 ReleasableMutexLock rlock(&mu_);
2622 if (c) {
2623 rlock.Release();
2624 }
2625 // No warning on join point because the lock will be released by the scope object anyway.
2626 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2627 }
2628
test6()2629 void Foo::test6() {
2630 ReleasableMutexLock rlock(&mu_);
2631 do {
2632 if (c) {
2633 rlock.Release();
2634 break;
2635 }
2636 } while (c);
2637 // No warning on join point because the lock will be released by the scope object anyway
2638 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2639 }
2640
2641
2642 } // end namespace ReleasableScopedLock
2643
2644
2645 namespace RelockableScopedLock {
2646
2647 class DeferTraits {};
2648
2649 class SCOPED_LOCKABLE RelockableExclusiveMutexLock {
2650 public:
2651 RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2652 RelockableExclusiveMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2653 ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();
2654
2655 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2656 void Unlock() UNLOCK_FUNCTION();
2657 };
2658
2659 struct SharedTraits {};
2660 struct ExclusiveTraits {};
2661
2662 class SCOPED_LOCKABLE RelockableMutexLock {
2663 public:
2664 RelockableMutexLock(Mutex *mu, DeferTraits) LOCKS_EXCLUDED(mu);
2665 RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu);
2666 RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu);
2667 ~RelockableMutexLock() UNLOCK_FUNCTION();
2668
2669 void Lock() EXCLUSIVE_LOCK_FUNCTION();
2670 void Unlock() UNLOCK_FUNCTION();
2671
2672 void ReaderLock() SHARED_LOCK_FUNCTION();
2673 void ReaderUnlock() UNLOCK_FUNCTION();
2674
2675 void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
2676 void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
2677 };
2678
2679 Mutex mu;
2680 int x GUARDED_BY(mu);
2681 bool b;
2682
2683 void print(int);
2684
relock()2685 void relock() {
2686 RelockableExclusiveMutexLock scope(&mu);
2687 x = 2;
2688 scope.Unlock();
2689
2690 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2691
2692 scope.Lock();
2693 x = 4;
2694 }
2695
deferLock()2696 void deferLock() {
2697 RelockableExclusiveMutexLock scope(&mu, DeferTraits{});
2698 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2699 scope.Lock();
2700 x = 3;
2701 }
2702
relockExclusive()2703 void relockExclusive() {
2704 RelockableMutexLock scope(&mu, SharedTraits{});
2705 print(x);
2706 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2707 scope.ReaderUnlock();
2708
2709 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2710
2711 scope.Lock();
2712 print(x);
2713 x = 4;
2714
2715 scope.DemoteExclusive();
2716 print(x);
2717 x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2718 }
2719
relockShared()2720 void relockShared() {
2721 RelockableMutexLock scope(&mu, ExclusiveTraits{});
2722 print(x);
2723 x = 2;
2724 scope.Unlock();
2725
2726 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2727
2728 scope.ReaderLock();
2729 print(x);
2730 x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2731
2732 scope.PromoteShared();
2733 print(x);
2734 x = 5;
2735 }
2736
deferLockShared()2737 void deferLockShared() {
2738 RelockableMutexLock scope(&mu, DeferTraits{});
2739 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
2740 scope.ReaderLock();
2741 print(x);
2742 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2743 }
2744
doubleUnlock()2745 void doubleUnlock() {
2746 RelockableExclusiveMutexLock scope(&mu);
2747 scope.Unlock(); // expected-note{{mutex released here}}
2748 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
2749 }
2750
doubleLock1()2751 void doubleLock1() {
2752 RelockableExclusiveMutexLock scope(&mu); // expected-note{{mutex acquired here}}
2753 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2754 }
2755
doubleLock2()2756 void doubleLock2() {
2757 RelockableExclusiveMutexLock scope(&mu);
2758 scope.Unlock();
2759 scope.Lock(); // expected-note{{mutex acquired here}}
2760 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
2761 }
2762
lockJoin()2763 void lockJoin() {
2764 RelockableMutexLock scope(&mu, DeferTraits{});
2765 if (b)
2766 scope.Lock();
2767 // No warning on join point because the lock will be released by the scope object anyway.
2768 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2769 }
2770
unlockJoin()2771 void unlockJoin() {
2772 RelockableMutexLock scope(&mu, DeferTraits{});
2773 scope.Lock();
2774 if (b)
2775 scope.Unlock();
2776 // No warning on join point because the lock will be released by the scope object anyway.
2777 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2778 }
2779
loopAcquire()2780 void loopAcquire() {
2781 RelockableMutexLock scope(&mu, DeferTraits{});
2782 for (unsigned i = 1; i < 10; ++i)
2783 scope.Lock(); // We could catch this double lock with negative capabilities.
2784 }
2785
loopRelease()2786 void loopRelease() {
2787 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2788 // We have to warn on this join point despite the lock being managed ...
2789 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2790 x = 1; // ... because we might miss that this doesn't always happen under lock.
2791 if (i == 5)
2792 scope.Unlock();
2793 }
2794 }
2795
loopPromote()2796 void loopPromote() {
2797 RelockableMutexLock scope(&mu, SharedTraits{});
2798 for (unsigned i = 1; i < 10; ++i) {
2799 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2800 if (i == 5)
2801 scope.PromoteShared();
2802 }
2803 }
2804
loopDemote()2805 void loopDemote() {
2806 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2807 // We have to warn on this join point despite the lock being managed ...
2808 for (unsigned i = 1; i < 10; ++i) {
2809 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2810 if (i == 5)
2811 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2812 }
2813 }
2814
loopAcquireContinue()2815 void loopAcquireContinue() {
2816 RelockableMutexLock scope(&mu, DeferTraits{});
2817 for (unsigned i = 1; i < 10; ++i) {
2818 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2819 if (i == 5) {
2820 scope.Lock();
2821 continue;
2822 }
2823 }
2824 }
2825
loopReleaseContinue()2826 void loopReleaseContinue() {
2827 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
2828 // We have to warn on this join point despite the lock being managed ...
2829 for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
2830 x = 1; // ... because we might miss that this doesn't always happen under lock.
2831 if (i == 5) {
2832 scope.Unlock();
2833 continue;
2834 }
2835 }
2836 }
2837
loopPromoteContinue()2838 void loopPromoteContinue() {
2839 RelockableMutexLock scope(&mu, SharedTraits{});
2840 for (unsigned i = 1; i < 10; ++i) {
2841 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2842 if (i == 5) {
2843 scope.PromoteShared();
2844 continue;
2845 }
2846 }
2847 }
2848
loopDemoteContinue()2849 void loopDemoteContinue() {
2850 RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{the other acquisition of mutex 'mu' is here}}
2851 // We have to warn on this join point despite the lock being managed ...
2852 for (unsigned i = 1; i < 10; ++i) {
2853 x = 1; // ... because we might miss that this doesn't always happen under exclusive lock.
2854 if (i == 5) {
2855 scope.DemoteExclusive(); // expected-warning {{mutex 'mu' is acquired exclusively and shared in the same scope}}
2856 continue;
2857 }
2858 }
2859 }
2860
exclusiveSharedJoin()2861 void exclusiveSharedJoin() {
2862 RelockableMutexLock scope(&mu, DeferTraits{});
2863 if (b)
2864 scope.Lock();
2865 else
2866 scope.ReaderLock();
2867 // No warning on join point because the lock will be released by the scope object anyway.
2868 print(x);
2869 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2870 }
2871
sharedExclusiveJoin()2872 void sharedExclusiveJoin() {
2873 RelockableMutexLock scope(&mu, DeferTraits{});
2874 if (b)
2875 scope.ReaderLock();
2876 else
2877 scope.Lock();
2878 // No warning on join point because the lock will be released by the scope object anyway.
2879 print(x);
2880 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2881 }
2882
assertJoin()2883 void assertJoin() {
2884 RelockableMutexLock scope(&mu, DeferTraits{});
2885 if (b)
2886 scope.Lock();
2887 else
2888 mu.AssertHeld();
2889 x = 2;
2890 }
2891
assertSharedJoin()2892 void assertSharedJoin() {
2893 RelockableMutexLock scope(&mu, DeferTraits{});
2894 if (b)
2895 scope.ReaderLock();
2896 else
2897 mu.AssertReaderHeld();
2898 print(x);
2899 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2900 }
2901
assertStrongerJoin()2902 void assertStrongerJoin() {
2903 RelockableMutexLock scope(&mu, DeferTraits{});
2904 if (b)
2905 scope.ReaderLock();
2906 else
2907 mu.AssertHeld();
2908 print(x);
2909 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2910 }
2911
assertWeakerJoin()2912 void assertWeakerJoin() {
2913 RelockableMutexLock scope(&mu, DeferTraits{});
2914 if (b)
2915 scope.Lock();
2916 else
2917 mu.AssertReaderHeld();
2918 print(x);
2919 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2920 }
2921
directUnlock()2922 void directUnlock() {
2923 RelockableExclusiveMutexLock scope(&mu);
2924 mu.Unlock();
2925 // Debatable that there is no warning. Currently we don't track in the scoped
2926 // object whether it is active, but just check if the contained locks can be
2927 // reacquired. Here they can, because mu has been unlocked manually.
2928 scope.Lock();
2929 }
2930
directRelock()2931 void directRelock() {
2932 RelockableExclusiveMutexLock scope(&mu);
2933 scope.Unlock();
2934 mu.Lock();
2935 // Similarly debatable that there is no warning.
2936 scope.Unlock();
2937 }
2938
2939 // Doesn't make a lot of sense, just making sure there is no crash.
destructLock()2940 void destructLock() {
2941 RelockableExclusiveMutexLock scope(&mu);
2942 scope.~RelockableExclusiveMutexLock();
2943 scope.Lock(); // Should be UB, so we don't really care.
2944 }
2945
2946 class SCOPED_LOCKABLE MemberLock {
2947 public:
2948 MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2949 ~MemberLock() UNLOCK_FUNCTION(mutex);
2950 void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex);
2951 Mutex mutex;
2952 };
2953
relockShared2()2954 void relockShared2() {
2955 MemberLock lock; // expected-note{{mutex acquired here}}
2956 lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}}
2957 }
2958
2959 class SCOPED_LOCKABLE WeirdScope {
2960 private:
2961 Mutex *other;
2962
2963 public:
2964 WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
2965 void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other);
2966 void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other);
2967 ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION();
2968
2969 void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other);
2970 };
2971
relockWeird()2972 void relockWeird() {
2973 WeirdScope scope(&mu);
2974 x = 1;
2975 scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}}
2976 x = 2; // \
2977 // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
2978 scope.requireOther(); // \
2979 // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}}
2980 scope.lock(); // expected-note {{mutex acquired here}}
2981 x = 3;
2982 scope.requireOther();
2983 } // expected-warning {{mutex 'scope.other' is still held at the end of function}}
2984
2985 } // end namespace RelockableScopedLock
2986
2987
2988 namespace ScopedUnlock {
2989
2990 class SCOPED_LOCKABLE MutexUnlock {
2991 public:
2992 MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu);
2993 ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
2994
2995 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
2996 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
2997 };
2998
2999 class SCOPED_LOCKABLE ReaderMutexUnlock {
3000 public:
3001 ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu);
3002 ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3003
3004 void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
3005 void Unlock() EXCLUSIVE_LOCK_FUNCTION();
3006 };
3007
3008 Mutex mu;
3009 int x GUARDED_BY(mu);
3010 bool c;
3011 void print(int);
3012
simple()3013 void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3014 x = 1;
3015 MutexUnlock scope(&mu);
3016 x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3017 }
3018
simpleShared()3019 void simpleShared() SHARED_LOCKS_REQUIRED(mu) {
3020 print(x);
3021 ReaderMutexUnlock scope(&mu);
3022 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3023 }
3024
innerUnlock()3025 void innerUnlock() {
3026 MutexLock outer(&mu);
3027 if (x == 0) {
3028 MutexUnlock inner(&mu);
3029 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3030 }
3031 x = 2;
3032 }
3033
innerUnlockShared()3034 void innerUnlockShared() {
3035 ReaderMutexLock outer(&mu);
3036 if (x == 0) {
3037 ReaderMutexUnlock inner(&mu);
3038 print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
3039 }
3040 print(x);
3041 }
3042
manual()3043 void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3044 MutexUnlock scope(&mu);
3045 scope.Lock();
3046 x = 2;
3047 scope.Unlock();
3048 x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3049 }
3050
join()3051 void join() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3052 MutexUnlock scope(&mu);
3053 if (c)
3054 scope.Lock();
3055 // No warning on join point because the lock will be released by the scope object anyway.
3056 scope.Lock();
3057 }
3058
doubleLock()3059 void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3060 MutexUnlock scope(&mu);
3061 scope.Lock(); // expected-note{{mutex acquired here}}
3062 scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
3063 }
3064
doubleUnlock()3065 void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3066 MutexUnlock scope(&mu); // expected-note{{mutex released here}}
3067 scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
3068 }
3069
3070 class SCOPED_LOCKABLE MutexLockUnlock {
3071 public:
3072 MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2);
3073 ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
3074
3075 void Release() EXCLUSIVE_UNLOCK_FUNCTION();
3076 void Acquire() EXCLUSIVE_LOCK_FUNCTION();
3077 };
3078
3079 Mutex other;
3080 void fn() EXCLUSIVE_LOCKS_REQUIRED(other);
3081
lockUnlock()3082 void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
3083 MutexLockUnlock scope(&mu, &other);
3084 fn();
3085 x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
3086 }
3087
3088 } // end namespace ScopedUnlock
3089
3090
3091 namespace TrylockFunctionTest {
3092
3093 class Foo {
3094 public:
3095 Mutex mu1_;
3096 Mutex mu2_;
3097 bool c;
3098
3099 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
3100 };
3101
lockBoth()3102 bool Foo::lockBoth() {
3103 if (!mu1_.TryLock())
3104 return false;
3105
3106 mu2_.Lock();
3107 if (!c) {
3108 mu1_.Unlock();
3109 mu2_.Unlock();
3110 return false;
3111 }
3112
3113 return true;
3114 }
3115
3116
3117 } // end namespace TrylockFunctionTest
3118
3119
3120
3121 namespace DoubleLockBug {
3122
3123 class Foo {
3124 public:
3125 Mutex mu_;
3126 int a GUARDED_BY(mu_);
3127
3128 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3129 int foo2() SHARED_LOCKS_REQUIRED(mu_);
3130 };
3131
3132
foo1()3133 void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
3134 a = 0;
3135 }
3136
foo2()3137 int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
3138 return a;
3139 }
3140
3141 }
3142
3143
3144
3145 namespace UnlockBug {
3146
3147 class Foo {
3148 public:
3149 Mutex mutex_;
3150
foo1()3151 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3152 mutex_.Unlock();
3153 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3154
3155
foo2()3156 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
3157 mutex_.Unlock();
3158 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
3159 };
3160
3161 } // end namespace UnlockBug
3162
3163
3164
3165 namespace FoolishScopedLockableBug {
3166
3167 class SCOPED_LOCKABLE WTF_ScopedLockable {
3168 public:
3169 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
3170
3171 // have to call release() manually;
3172 ~WTF_ScopedLockable();
3173
3174 void release() UNLOCK_FUNCTION();
3175 };
3176
3177
3178 class Foo {
3179 Mutex mu_;
3180 int a GUARDED_BY(mu_);
3181 bool c;
3182
3183 void doSomething();
3184
test1()3185 void test1() {
3186 WTF_ScopedLockable wtf(&mu_);
3187 wtf.release();
3188 }
3189
test2()3190 void test2() {
3191 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3192 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
3193
test3()3194 void test3() {
3195 if (c) {
3196 WTF_ScopedLockable wtf(&mu_);
3197 wtf.release();
3198 }
3199 }
3200
test4()3201 void test4() {
3202 if (c) {
3203 doSomething();
3204 }
3205 else {
3206 WTF_ScopedLockable wtf(&mu_);
3207 wtf.release();
3208 }
3209 }
3210
test5()3211 void test5() {
3212 if (c) {
3213 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3214 }
3215 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3216
test6()3217 void test6() {
3218 if (c) {
3219 doSomething();
3220 }
3221 else {
3222 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
3223 }
3224 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
3225 };
3226
3227
3228 } // end namespace FoolishScopedLockableBug
3229
3230
3231
3232 namespace TemporaryCleanupExpr {
3233
3234 class Foo {
3235 int a GUARDED_BY(getMutexPtr().get());
3236
3237 SmartPtr<Mutex> getMutexPtr();
3238
3239 void test();
3240 };
3241
3242
test()3243 void Foo::test() {
3244 {
3245 ReaderMutexLock lock(getMutexPtr().get());
3246 int b = a;
3247 }
3248 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}
3249 }
3250
3251 #ifdef __cpp_guaranteed_copy_elision
3252
guaranteed_copy_elision()3253 void guaranteed_copy_elision() {
3254 MutexLock lock = MutexLock{&sls_mu};
3255 sls_guard_var = 0;
3256 }
3257
guaranteed_copy_elision_const()3258 void guaranteed_copy_elision_const() {
3259 const MutexLock lock = MutexLock{&sls_mu};
3260 sls_guard_var = 0;
3261 }
3262
3263 #endif
3264
3265 } // end namespace TemporaryCleanupExpr
3266
3267
3268
3269 namespace SmartPointerTests {
3270
3271 class Foo {
3272 public:
3273 SmartPtr<Mutex> mu_;
3274 int a GUARDED_BY(mu_);
3275 int b GUARDED_BY(mu_.get());
3276 int c GUARDED_BY(*mu_);
3277
3278 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3279 void Unlock() UNLOCK_FUNCTION(mu_);
3280
3281 void test0();
3282 void test1();
3283 void test2();
3284 void test3();
3285 void test4();
3286 void test5();
3287 void test6();
3288 void test7();
3289 void test8();
3290 };
3291
test0()3292 void Foo::test0() {
3293 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3294 b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
3295 c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
3296 }
3297
test1()3298 void Foo::test1() {
3299 mu_->Lock();
3300 a = 0;
3301 b = 0;
3302 c = 0;
3303 mu_->Unlock();
3304 }
3305
test2()3306 void Foo::test2() {
3307 (*mu_).Lock();
3308 a = 0;
3309 b = 0;
3310 c = 0;
3311 (*mu_).Unlock();
3312 }
3313
3314
test3()3315 void Foo::test3() {
3316 mu_.get()->Lock();
3317 a = 0;
3318 b = 0;
3319 c = 0;
3320 mu_.get()->Unlock();
3321 }
3322
3323
test4()3324 void Foo::test4() {
3325 MutexLock lock(mu_.get());
3326 a = 0;
3327 b = 0;
3328 c = 0;
3329 }
3330
3331
test5()3332 void Foo::test5() {
3333 MutexLock lock(&(*mu_));
3334 a = 0;
3335 b = 0;
3336 c = 0;
3337 }
3338
3339
test6()3340 void Foo::test6() {
3341 Lock();
3342 a = 0;
3343 b = 0;
3344 c = 0;
3345 Unlock();
3346 }
3347
3348
test7()3349 void Foo::test7() {
3350 {
3351 Lock();
3352 mu_->Unlock();
3353 }
3354 {
3355 mu_->Lock();
3356 Unlock();
3357 }
3358 {
3359 mu_.get()->Lock();
3360 mu_->Unlock();
3361 }
3362 {
3363 mu_->Lock();
3364 mu_.get()->Unlock();
3365 }
3366 {
3367 mu_.get()->Lock();
3368 (*mu_).Unlock();
3369 }
3370 {
3371 (*mu_).Lock();
3372 mu_->Unlock();
3373 }
3374 }
3375
3376
test8()3377 void Foo::test8() {
3378 mu_->Lock(); // expected-note 2 {{mutex acquired here}}
3379 mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3380 (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
3381 mu_.get()->Unlock(); // expected-note {{mutex released here}}
3382 Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}
3383 }
3384
3385
3386 class Bar {
3387 SmartPtr<Foo> foo;
3388
3389 void test0();
3390 void test1();
3391 void test2();
3392 void test3();
3393 };
3394
3395
test0()3396 void Bar::test0() {
3397 foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
3398 (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
3399 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
3400 }
3401
3402
test1()3403 void Bar::test1() {
3404 foo->mu_->Lock();
3405 foo->a = 0;
3406 (*foo).b = 0;
3407 foo.get()->c = 0;
3408 foo->mu_->Unlock();
3409 }
3410
3411
test2()3412 void Bar::test2() {
3413 (*foo).mu_->Lock();
3414 foo->a = 0;
3415 (*foo).b = 0;
3416 foo.get()->c = 0;
3417 foo.get()->mu_->Unlock();
3418 }
3419
3420
test3()3421 void Bar::test3() {
3422 MutexLock lock(foo->mu_.get());
3423 foo->a = 0;
3424 (*foo).b = 0;
3425 foo.get()->c = 0;
3426 }
3427
3428 } // end namespace SmartPointerTests
3429
3430
3431
3432 namespace DuplicateAttributeTest {
3433
3434 class LOCKABLE Foo {
3435 public:
3436 Mutex mu1_;
3437 Mutex mu2_;
3438 Mutex mu3_;
3439 int a GUARDED_BY(mu1_);
3440 int b GUARDED_BY(mu2_);
3441 int c GUARDED_BY(mu3_);
3442
3443 void lock() EXCLUSIVE_LOCK_FUNCTION();
3444 void unlock() UNLOCK_FUNCTION();
3445
3446 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
3447 void slock1() SHARED_LOCK_FUNCTION(mu1_);
3448 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3449 void locklots()
3450 EXCLUSIVE_LOCK_FUNCTION(mu1_)
3451 EXCLUSIVE_LOCK_FUNCTION(mu2_)
3452 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
3453
3454 void unlock1() UNLOCK_FUNCTION(mu1_);
3455 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3456 void unlocklots()
3457 UNLOCK_FUNCTION(mu1_)
3458 UNLOCK_FUNCTION(mu2_)
3459 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
3460 };
3461
3462
lock()3463 void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
unlock()3464 void Foo::unlock() UNLOCK_FUNCTION() { }
3465
lock1()3466 void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
3467 mu1_.Lock();
3468 }
3469
slock1()3470 void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
3471 mu1_.ReaderLock();
3472 }
3473
lock3()3474 void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
3475 mu1_.Lock();
3476 mu2_.Lock();
3477 mu3_.Lock();
3478 }
3479
locklots()3480 void Foo::locklots()
3481 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
3482 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
3483 mu1_.Lock();
3484 mu2_.Lock();
3485 mu3_.Lock();
3486 }
3487
unlock1()3488 void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
3489 mu1_.Unlock();
3490 }
3491
unlock3()3492 void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
3493 mu1_.Unlock();
3494 mu2_.Unlock();
3495 mu3_.Unlock();
3496 }
3497
unlocklots()3498 void Foo::unlocklots()
3499 UNLOCK_FUNCTION(mu1_, mu2_)
3500 UNLOCK_FUNCTION(mu2_, mu3_) {
3501 mu1_.Unlock();
3502 mu2_.Unlock();
3503 mu3_.Unlock();
3504 }
3505
3506
test0()3507 void test0() {
3508 Foo foo;
3509 foo.lock();
3510 foo.unlock();
3511
3512 foo.lock(); // expected-note{{mutex acquired here}}
3513 foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}
3514 foo.unlock(); // expected-note{{mutex released here}}
3515 foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}
3516 }
3517
3518
test1()3519 void test1() {
3520 Foo foo;
3521 foo.lock1();
3522 foo.a = 0;
3523 foo.unlock1();
3524
3525 foo.lock1(); // expected-note{{mutex acquired here}}
3526 foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3527 foo.a = 0;
3528 foo.unlock1(); // expected-note{{mutex released here}}
3529 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3530 }
3531
3532
test2()3533 int test2() {
3534 Foo foo;
3535 foo.slock1();
3536 int d1 = foo.a;
3537 foo.unlock1();
3538
3539 foo.slock1(); // expected-note{{mutex acquired here}}
3540 foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
3541 int d2 = foo.a;
3542 foo.unlock1(); // expected-note{{mutex released here}}
3543 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
3544 return d1 + d2;
3545 }
3546
3547
test3()3548 void test3() {
3549 Foo foo;
3550 foo.lock3();
3551 foo.a = 0;
3552 foo.b = 0;
3553 foo.c = 0;
3554 foo.unlock3();
3555
3556 foo.lock3(); // expected-note 3 {{mutex acquired here}}
3557 foo.lock3(); // \
3558 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3559 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3560 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3561 foo.a = 0;
3562 foo.b = 0;
3563 foo.c = 0;
3564 foo.unlock3(); // expected-note 3 {{mutex released here}}
3565 foo.unlock3(); // \
3566 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3567 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3568 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3569 }
3570
3571
testlots()3572 void testlots() {
3573 Foo foo;
3574 foo.locklots();
3575 foo.a = 0;
3576 foo.b = 0;
3577 foo.c = 0;
3578 foo.unlocklots();
3579
3580 foo.locklots(); // expected-note 3 {{mutex acquired here}}
3581 foo.locklots(); // \
3582 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3583 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3584 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3585 foo.a = 0;
3586 foo.b = 0;
3587 foo.c = 0;
3588 foo.unlocklots(); // expected-note 3 {{mutex released here}}
3589 foo.unlocklots(); // \
3590 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3591 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3592 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3593 }
3594
3595 } // end namespace DuplicateAttributeTest
3596
3597
3598
3599 namespace TryLockEqTest {
3600
3601 class Foo {
3602 Mutex mu_;
3603 int a GUARDED_BY(mu_);
3604 bool c;
3605
3606 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3607 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3608 void unlock() UNLOCK_FUNCTION(mu_);
3609
3610 void test1();
3611 void test2();
3612 };
3613
3614
test1()3615 void Foo::test1() {
3616 if (tryLockMutexP() == 0) {
3617 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3618 return;
3619 }
3620 a = 0;
3621 unlock();
3622
3623 if (tryLockMutexP() != 0) {
3624 a = 0;
3625 unlock();
3626 }
3627
3628 if (0 != tryLockMutexP()) {
3629 a = 0;
3630 unlock();
3631 }
3632
3633 if (!(tryLockMutexP() == 0)) {
3634 a = 0;
3635 unlock();
3636 }
3637
3638 if (tryLockMutexI() == 0) {
3639 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3640 return;
3641 }
3642 a = 0;
3643 unlock();
3644
3645 if (0 == tryLockMutexI()) {
3646 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3647 return;
3648 }
3649 a = 0;
3650 unlock();
3651
3652 if (tryLockMutexI() == 1) {
3653 a = 0;
3654 unlock();
3655 }
3656
3657 if (mu_.TryLock() == false) {
3658 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3659 return;
3660 }
3661 a = 0;
3662 unlock();
3663
3664 if (mu_.TryLock() == true) {
3665 a = 0;
3666 unlock();
3667 }
3668 else {
3669 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3670 }
3671
3672 #if __has_feature(cxx_nullptr)
3673 if (tryLockMutexP() == nullptr) {
3674 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3675 return;
3676 }
3677 a = 0;
3678 unlock();
3679 #endif
3680 }
3681
3682 } // end namespace TryLockEqTest
3683
3684
3685 namespace ExistentialPatternMatching {
3686
3687 class Graph {
3688 public:
3689 Mutex mu_;
3690 };
3691
3692 void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3693 void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3694
3695 class Node {
3696 public:
3697 int a GUARDED_BY(&Graph::mu_);
3698
foo()3699 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3700 a = 0;
3701 }
3702 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3703 };
3704
test()3705 void test() {
3706 Graph g1;
3707 Graph g2;
3708 Node n1;
3709
3710 n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3711 n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3712 n1.foo2();
3713
3714 g1.mu_.Lock();
3715 n1.a = 0;
3716 n1.foo();
3717 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3718 g1.mu_.Unlock();
3719
3720 g2.mu_.Lock();
3721 n1.a = 0;
3722 n1.foo();
3723 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3724 g2.mu_.Unlock();
3725
3726 LockAllGraphs();
3727 n1.a = 0;
3728 n1.foo();
3729 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3730 UnlockAllGraphs();
3731
3732 LockAllGraphs();
3733 g1.mu_.Unlock();
3734
3735 LockAllGraphs();
3736 g2.mu_.Unlock();
3737
3738 LockAllGraphs(); // expected-note{{mutex acquired here}}
3739 g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}
3740 g1.mu_.Unlock();
3741 }
3742
3743 } // end namespace ExistentialPatternMatching
3744
3745
3746 namespace StringIgnoreTest {
3747
3748 class Foo {
3749 public:
3750 Mutex mu_;
3751 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3752 void unlock() UNLOCK_FUNCTION("");
3753 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3754 void roober() SHARED_LOCKS_REQUIRED("");
3755 };
3756
3757
3758 class Bar : public Foo {
3759 public:
bar(Foo * f)3760 void bar(Foo* f) {
3761 f->unlock();
3762 f->goober();
3763 f->roober();
3764 f->lock();
3765 };
3766 };
3767
3768 } // end namespace StringIgnoreTest
3769
3770
3771 namespace LockReturnedScopeFix {
3772
3773 class Base {
3774 protected:
3775 struct Inner;
3776 bool c;
3777
3778 const Mutex& getLock(const Inner* i);
3779
3780 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3781 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3782 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3783
3784 void bar(Inner* i);
3785 };
3786
3787
3788 struct Base::Inner {
3789 Mutex lock_;
3790 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3791 };
3792
3793
getLock(const Inner * i)3794 const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3795 return i->lock_;
3796 }
3797
3798
foo(Inner * i)3799 void Base::foo(Inner* i) {
3800 i->doSomething();
3801 }
3802
bar(Inner * i)3803 void Base::bar(Inner* i) {
3804 if (c) {
3805 i->lock_.Lock();
3806 unlockInner(i);
3807 }
3808 else {
3809 lockInner(i);
3810 i->lock_.Unlock();
3811 }
3812 }
3813
3814 } // end namespace LockReturnedScopeFix
3815
3816
3817 namespace TrylockWithCleanups {
3818
3819 struct Foo {
3820 Mutex mu_;
3821 int a GUARDED_BY(mu_);
3822 };
3823
3824 Foo* GetAndLockFoo(const MyString& s)
3825 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3826
test()3827 static void test() {
3828 Foo* lt = GetAndLockFoo("foo");
3829 if (!lt) return;
3830 int a = lt->a;
3831 lt->mu_.Unlock();
3832 }
3833
3834 } // end namespace TrylockWithCleanups
3835
3836
3837 namespace UniversalLock {
3838
3839 class Foo {
3840 Mutex mu_;
3841 bool c;
3842
3843 int a GUARDED_BY(mu_);
3844 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3845 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3846
test1()3847 void test1() {
3848 int b;
3849
3850 beginNoWarnOnReads();
3851 b = a;
3852 r_foo();
3853 endNoWarnOnReads();
3854
3855 beginNoWarnOnWrites();
3856 a = 0;
3857 w_foo();
3858 endNoWarnOnWrites();
3859 }
3860
3861 // don't warn on joins with universal lock
test2()3862 void test2() {
3863 if (c) {
3864 beginNoWarnOnWrites();
3865 }
3866 a = 0; // \
3867 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3868 endNoWarnOnWrites(); // \
3869 // expected-warning {{releasing wildcard '*' that was not held}}
3870 }
3871
3872
3873 // make sure the universal lock joins properly
test3()3874 void test3() {
3875 if (c) {
3876 mu_.Lock();
3877 beginNoWarnOnWrites();
3878 }
3879 else {
3880 beginNoWarnOnWrites();
3881 mu_.Lock();
3882 }
3883 a = 0;
3884 endNoWarnOnWrites();
3885 mu_.Unlock();
3886 }
3887
3888
3889 // combine universal lock with other locks
test4()3890 void test4() {
3891 beginNoWarnOnWrites();
3892 mu_.Lock();
3893 mu_.Unlock();
3894 endNoWarnOnWrites();
3895
3896 mu_.Lock();
3897 beginNoWarnOnWrites();
3898 endNoWarnOnWrites();
3899 mu_.Unlock();
3900
3901 mu_.Lock();
3902 beginNoWarnOnWrites();
3903 mu_.Unlock();
3904 endNoWarnOnWrites();
3905 }
3906 };
3907
3908 } // end namespace UniversalLock
3909
3910
3911 namespace TemplateLockReturned {
3912
3913 template<class T>
3914 class BaseT {
3915 public:
3916 virtual void baseMethod() = 0;
get_mutex()3917 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3918
3919 Mutex mutex_;
3920 int a GUARDED_BY(mutex_);
3921 };
3922
3923
3924 class Derived : public BaseT<int> {
3925 public:
baseMethod()3926 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3927 a = 0;
3928 }
3929 };
3930
3931 } // end namespace TemplateLockReturned
3932
3933
3934 namespace ExprMatchingBugFix {
3935
3936 class Foo {
3937 public:
3938 Mutex mu_;
3939 };
3940
3941
3942 class Bar {
3943 public:
3944 bool c;
3945 Foo* foo;
Bar(Foo * f)3946 Bar(Foo* f) : foo(f) { }
3947
3948 struct Nested {
3949 Foo* foo;
NestedExprMatchingBugFix::Bar::Nested3950 Nested(Foo* f) : foo(f) { }
3951
3952 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3953 };
3954
3955 void test();
3956 };
3957
3958
test()3959 void Bar::test() {
3960 foo->mu_.Lock();
3961 if (c) {
3962 Nested *n = new Nested(foo);
3963 n->unlockFoo();
3964 }
3965 else {
3966 foo->mu_.Unlock();
3967 }
3968 }
3969
3970 }; // end namespace ExprMatchingBugfix
3971
3972
3973 namespace ComplexNameTest {
3974
3975 class Foo {
3976 public:
3977 static Mutex mu_;
3978
EXCLUSIVE_LOCKS_REQUIRED(mu_)3979 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
EXCLUSIVE_LOCKS_REQUIRED(mu_)3980 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3981
operator [](int i)3982 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3983 };
3984
3985 class Bar {
3986 public:
3987 static Mutex mu_;
3988
LOCKS_EXCLUDED(mu_)3989 Bar() LOCKS_EXCLUDED(mu_) { }
LOCKS_EXCLUDED(mu_)3990 ~Bar() LOCKS_EXCLUDED(mu_) { }
3991
operator [](int i)3992 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3993 };
3994
3995
test1()3996 void test1() {
3997 Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}
3998 int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}
3999 } // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}
4000
4001
test2()4002 void test2() {
4003 Bar::mu_.Lock();
4004 {
4005 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}
4006 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}
4007 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}
4008 Bar::mu_.Unlock();
4009 }
4010
4011 }; // end namespace ComplexNameTest
4012
4013
4014 namespace UnreachableExitTest {
4015
4016 class FemmeFatale {
4017 public:
4018 FemmeFatale();
4019 ~FemmeFatale() __attribute__((noreturn));
4020 };
4021
4022 void exitNow() __attribute__((noreturn));
4023 void exitDestruct(const MyString& ms) __attribute__((noreturn));
4024
4025 Mutex fatalmu_;
4026
test1()4027 void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4028 exitNow();
4029 }
4030
test2()4031 void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4032 FemmeFatale femme;
4033 }
4034
4035 bool c;
4036
test3()4037 void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4038 if (c) {
4039 exitNow();
4040 }
4041 else {
4042 FemmeFatale femme;
4043 }
4044 }
4045
test4()4046 void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
4047 exitDestruct("foo");
4048 }
4049
4050 } // end namespace UnreachableExitTest
4051
4052
4053 namespace VirtualMethodCanonicalizationTest {
4054
4055 class Base {
4056 public:
4057 virtual Mutex* getMutex() = 0;
4058 };
4059
4060 class Base2 : public Base {
4061 public:
4062 Mutex* getMutex();
4063 };
4064
4065 class Base3 : public Base2 {
4066 public:
4067 Mutex* getMutex();
4068 };
4069
4070 class Derived : public Base3 {
4071 public:
4072 Mutex* getMutex(); // overrides Base::getMutex()
4073 };
4074
baseFun(Base * b)4075 void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
4076
derivedFun(Derived * d)4077 void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
4078 baseFun(d);
4079 }
4080
4081 } // end namespace VirtualMethodCanonicalizationTest
4082
4083
4084 namespace TemplateFunctionParamRemapTest {
4085
4086 template <class T>
4087 struct Cell {
4088 T dummy_;
4089 Mutex* mu_;
4090 };
4091
4092 class Foo {
4093 public:
4094 template <class T>
4095 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4096
4097 void test();
4098 };
4099
4100 template<class T>
elr(Cell<T> * c1)4101 void Foo::elr(Cell<T>* c1) { }
4102
test()4103 void Foo::test() {
4104 Cell<int> cell;
4105 elr(&cell); // \
4106 // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}
4107 }
4108
4109
4110 template<class T>
4111 void globalELR(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4112
4113 template<class T>
globalELR(Cell<T> * c1)4114 void globalELR(Cell<T>* c1) { }
4115
globalTest()4116 void globalTest() {
4117 Cell<int> cell;
4118 globalELR(&cell); // \
4119 // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}
4120 }
4121
4122
4123 template<class T>
4124 void globalELR2(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4125
4126 // second declaration
4127 template<class T>
4128 void globalELR2(Cell<T>* c2);
4129
4130 template<class T>
globalELR2(Cell<T> * c3)4131 void globalELR2(Cell<T>* c3) { }
4132
4133 // re-declaration after definition
4134 template<class T>
4135 void globalELR2(Cell<T>* c4);
4136
globalTest2()4137 void globalTest2() {
4138 Cell<int> cell;
4139 globalELR2(&cell); // \
4140 // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}
4141 }
4142
4143
4144 template<class T>
4145 class FooT {
4146 public:
4147 void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
4148 };
4149
4150 template<class T>
elr(Cell<T> * c1)4151 void FooT<T>::elr(Cell<T>* c1) { }
4152
testFooT()4153 void testFooT() {
4154 Cell<int> cell;
4155 FooT<int> foo;
4156 foo.elr(&cell); // \
4157 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
4158 }
4159
4160 } // end namespace TemplateFunctionParamRemapTest
4161
4162
4163 namespace SelfConstructorTest {
4164
4165 class SelfLock {
4166 public:
4167 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
4168 ~SelfLock() UNLOCK_FUNCTION(mu_);
4169
4170 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
4171
4172 Mutex mu_;
4173 };
4174
4175 class LOCKABLE SelfLock2 {
4176 public:
4177 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
4178 ~SelfLock2() UNLOCK_FUNCTION();
4179
4180 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
4181 };
4182
4183
test()4184 void test() {
4185 SelfLock s;
4186 s.foo();
4187 }
4188
test2()4189 void test2() {
4190 SelfLock2 s2;
4191 s2.foo();
4192 }
4193
4194 } // end namespace SelfConstructorTest
4195
4196
4197 namespace MultipleAttributeTest {
4198
4199 class Foo {
4200 Mutex mu1_;
4201 Mutex mu2_;
4202 int a GUARDED_BY(mu1_);
4203 int b GUARDED_BY(mu2_);
4204 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
4205 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
4206
4207 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
4208 EXCLUSIVE_LOCKS_REQUIRED(mu2_);
4209 void foo2() SHARED_LOCKS_REQUIRED(mu1_)
4210 SHARED_LOCKS_REQUIRED(mu2_);
4211 void foo3() LOCKS_EXCLUDED(mu1_)
4212 LOCKS_EXCLUDED(mu2_);
4213 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
4214 EXCLUSIVE_LOCK_FUNCTION(mu2_);
4215 void readerlock() SHARED_LOCK_FUNCTION(mu1_)
4216 SHARED_LOCK_FUNCTION(mu2_);
4217 void unlock() UNLOCK_FUNCTION(mu1_)
4218 UNLOCK_FUNCTION(mu2_);
4219 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
4220 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
4221 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
4222 SHARED_TRYLOCK_FUNCTION(true, mu2_);
4223 void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
4224 ASSERT_EXCLUSIVE_LOCK(mu2_);
4225
4226 void alsoAssertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_, mu2_);
4227
4228 void assertShared() ASSERT_SHARED_LOCK(mu1_)
4229 ASSERT_SHARED_LOCK(mu2_);
4230
4231 void alsoAssertShared() ASSERT_SHARED_LOCK(mu1_, mu2_);
4232
4233 void test();
4234 void testAssert();
4235 void testAssertShared();
4236 };
4237
4238
foo1()4239 void Foo::foo1() {
4240 a = 1;
4241 b = 2;
4242 }
4243
foo2()4244 void Foo::foo2() {
4245 int result = a + b;
4246 }
4247
foo3()4248 void Foo::foo3() { }
lock()4249 void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
readerlock()4250 void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
unlock()4251 void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
trylock()4252 bool Foo::trylock() { return true; }
readertrylock()4253 bool Foo::readertrylock() { return true; }
4254
4255
test()4256 void Foo::test() {
4257 mu1_.Lock();
4258 foo1(); // expected-warning {{}}
4259 c = 0; // expected-warning {{}}
4260 *d = 0; // expected-warning {{}}
4261 mu1_.Unlock();
4262
4263 mu1_.ReaderLock();
4264 foo2(); // expected-warning {{}}
4265 int x = c; // expected-warning {{}}
4266 int y = *d; // expected-warning {{}}
4267 mu1_.Unlock();
4268
4269 mu2_.Lock();
4270 foo3(); // expected-warning {{}}
4271 mu2_.Unlock();
4272
4273 lock();
4274 a = 0;
4275 b = 0;
4276 unlock();
4277
4278 readerlock();
4279 int z = a + b;
4280 unlock();
4281
4282 if (trylock()) {
4283 a = 0;
4284 b = 0;
4285 unlock();
4286 }
4287
4288 if (readertrylock()) {
4289 int zz = a + b;
4290 unlock();
4291 }
4292 }
4293
4294 // Force duplication of attributes
assertBoth()4295 void Foo::assertBoth() { }
alsoAssertBoth()4296 void Foo::alsoAssertBoth() { }
assertShared()4297 void Foo::assertShared() { }
alsoAssertShared()4298 void Foo::alsoAssertShared() { }
4299
testAssert()4300 void Foo::testAssert() {
4301 {
4302 assertBoth();
4303 a = 0;
4304 b = 0;
4305 }
4306 {
4307 alsoAssertBoth();
4308 a = 0;
4309 b = 0;
4310 }
4311 }
4312
testAssertShared()4313 void Foo::testAssertShared() {
4314 {
4315 assertShared();
4316 int zz = a + b;
4317 }
4318
4319 {
4320 alsoAssertShared();
4321 int zz = a + b;
4322 }
4323 }
4324
4325
4326 } // end namespace MultipleAttributeTest
4327
4328
4329 namespace GuardedNonPrimitiveTypeTest {
4330
4331
4332 class Data {
4333 public:
Data(int i)4334 Data(int i) : dat(i) { }
4335
getValue() const4336 int getValue() const { return dat; }
setValue(int i)4337 void setValue(int i) { dat = i; }
4338
operator [](int i) const4339 int operator[](int i) const { return dat; }
operator [](int i)4340 int& operator[](int i) { return dat; }
4341
operator ()()4342 void operator()() { }
4343
4344 Data& operator+=(int);
4345 Data& operator-=(int);
4346 Data& operator*=(int);
4347 Data& operator/=(int);
4348 Data& operator%=(int);
4349 Data& operator^=(int);
4350 Data& operator&=(int);
4351 Data& operator|=(int);
4352 Data& operator<<=(int);
4353 Data& operator>>=(int);
4354 Data& operator++();
4355 Data& operator++(int);
4356 Data& operator--();
4357 Data& operator--(int);
4358
4359 private:
4360 int dat;
4361 };
4362
4363
4364 class DataCell {
4365 public:
DataCell(const Data & d)4366 DataCell(const Data& d) : dat(d) { }
4367
4368 private:
4369 Data dat;
4370 };
4371
4372
4373 void showDataCell(const DataCell& dc);
4374
4375
4376 class Foo {
4377 public:
4378 // method call tests
test()4379 void test() {
4380 data_.setValue(0); // FIXME -- should be writing \
4381 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4382 int a = data_.getValue(); // \
4383 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4384
4385 datap1_->setValue(0); // FIXME -- should be writing \
4386 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4387 a = datap1_->getValue(); // \
4388 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4389
4390 datap2_->setValue(0); // FIXME -- should be writing \
4391 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4392 a = datap2_->getValue(); // \
4393 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4394
4395 (*datap2_).setValue(0); // FIXME -- should be writing \
4396 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4397 a = (*datap2_).getValue(); // \
4398 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4399
4400 mu_.Lock();
4401 data_.setValue(1);
4402 datap1_->setValue(1);
4403 datap2_->setValue(1);
4404 mu_.Unlock();
4405
4406 mu_.ReaderLock();
4407 a = data_.getValue();
4408 datap1_->setValue(0); // reads datap1_, writes *datap1_
4409 a = datap1_->getValue();
4410 a = datap2_->getValue();
4411 mu_.Unlock();
4412 }
4413
4414 // operator tests
test2()4415 void test2() {
4416 data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4417 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \
4418 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4419 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \
4420 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4421 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4422 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
4423 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
4424 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4425 data_ += 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4426 data_ -= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4427 data_ *= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4428 data_ /= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4429 data_ %= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4430 data_ ^= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4431 data_ &= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4432 data_ |= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4433 data_ <<= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4434 data_ >>= 1; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4435 ++data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4436 data_++; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4437 --data_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4438 data_--; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
4439
4440 data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4441 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4442
4443 data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4444 }
4445
4446 // const operator tests
test3() const4447 void test3() const {
4448 Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4449
4450 //FIXME
4451 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4452 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
4453
4454 int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
4455 }
4456
4457 private:
4458 Mutex mu_;
4459 Data data_ GUARDED_BY(mu_);
4460 Data* datap1_ GUARDED_BY(mu_);
4461 Data* datap2_ PT_GUARDED_BY(mu_);
4462 };
4463
4464 } // end namespace GuardedNonPrimitiveTypeTest
4465
4466
4467 namespace GuardedNonPrimitive_MemberAccess {
4468
4469 class Cell {
4470 public:
4471 Cell(int i);
4472
4473 void cellMethod();
4474
4475 int a;
4476 };
4477
4478
4479 class Foo {
4480 public:
4481 int a;
4482 Cell c GUARDED_BY(cell_mu_);
4483 Cell* cp PT_GUARDED_BY(cell_mu_);
4484
4485 void myMethod();
4486
4487 Mutex cell_mu_;
4488 };
4489
4490
4491 class Bar {
4492 private:
4493 Mutex mu_;
4494 Foo foo GUARDED_BY(mu_);
4495 Foo* foop PT_GUARDED_BY(mu_);
4496
test()4497 void test() {
4498 foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4499
4500 int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
4501 foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}
4502
4503 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4504 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4505
4506 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
4507 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
4508
4509 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \
4510 // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}
4511 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \
4512 // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}
4513
4514 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4515 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4516 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4517 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4518
4519 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4520 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
4521 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
4522 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
4523 };
4524 };
4525
4526 } // namespace GuardedNonPrimitive_MemberAccess
4527
4528
4529 namespace TestThrowExpr {
4530
4531 class Foo {
4532 Mutex mu_;
4533
4534 bool hasError();
4535
test()4536 void test() {
4537 mu_.Lock();
4538 if (hasError()) {
4539 throw "ugly";
4540 }
4541 mu_.Unlock();
4542 }
4543 };
4544
4545 } // end namespace TestThrowExpr
4546
4547
4548 namespace UnevaluatedContextTest {
4549
4550 // parse attribute expressions in an unevaluated context.
4551
4552 static inline Mutex* getMutex1();
4553 static inline Mutex* getMutex2();
4554
4555 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());
4556
4557 void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
4558
4559 } // end namespace UnevaluatedContextTest
4560
4561
4562 namespace LockUnlockFunctionTest {
4563
4564 // Check built-in lock functions
4565 class LOCKABLE MyLockable {
4566 public:
lock()4567 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
readerLock()4568 void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
unlock()4569 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
4570
4571 private:
4572 Mutex mu_;
4573 };
4574
4575
4576 class Foo {
4577 public:
4578 // Correct lock/unlock functions
lock()4579 void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
4580 mu_.Lock();
4581 }
4582
readerLock()4583 void readerLock() SHARED_LOCK_FUNCTION(mu_) {
4584 mu_.ReaderLock();
4585 }
4586
unlock()4587 void unlock() UNLOCK_FUNCTION(mu_) {
4588 mu_.Unlock();
4589 }
4590
unlockExclusive()4591 void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) {
4592 mu_.Unlock();
4593 }
4594
unlockShared()4595 void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) {
4596 mu_.ReaderUnlock();
4597 }
4598
4599 // Check failure to lock.
lockBad()4600 void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4601 mu2_.Lock();
4602 mu2_.Unlock();
4603 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4604
readerLockBad()4605 void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4606 mu2_.Lock();
4607 mu2_.Unlock();
4608 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4609
unlockBad()4610 void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4611 mu2_.Lock();
4612 mu2_.Unlock();
4613 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4614
4615 // Check locking the wrong thing.
lockBad2()4616 void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4617 mu2_.Lock(); // expected-note {{mutex acquired here}}
4618 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4619 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4620
4621
readerLockBad2()4622 void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4623 mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
4624 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4625 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4626
4627
unlockBad2()4628 void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4629 mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}
4630 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4631
4632 private:
4633 Mutex mu_;
4634 Mutex mu2_;
4635 };
4636
4637 } // end namespace LockUnlockFunctionTest
4638
4639
4640 namespace AssertHeldTest {
4641
4642 class Foo {
4643 public:
4644 int c;
4645 int a GUARDED_BY(mu_);
4646 Mutex mu_;
4647
test1()4648 void test1() {
4649 mu_.AssertHeld();
4650 int b = a;
4651 a = 0;
4652 }
4653
test2()4654 void test2() {
4655 mu_.AssertReaderHeld();
4656 int b = a;
4657 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
4658 }
4659
test3()4660 void test3() {
4661 if (c) {
4662 mu_.AssertHeld();
4663 }
4664 else {
4665 mu_.AssertHeld();
4666 }
4667 int b = a;
4668 a = 0;
4669 }
4670
test4()4671 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4672 mu_.AssertHeld();
4673 int b = a;
4674 a = 0;
4675 }
4676
test5()4677 void test5() UNLOCK_FUNCTION(mu_) {
4678 mu_.AssertHeld();
4679 mu_.Unlock();
4680 }
4681
test6()4682 void test6() {
4683 mu_.AssertHeld();
4684 mu_.Unlock(); // should this be a warning?
4685 }
4686
test7()4687 void test7() {
4688 if (c) {
4689 mu_.AssertHeld();
4690 }
4691 else {
4692 mu_.Lock();
4693 }
4694 int b = a;
4695 a = 0;
4696 mu_.Unlock();
4697 }
4698
test8()4699 void test8() {
4700 if (c) {
4701 mu_.Lock();
4702 }
4703 else {
4704 mu_.AssertHeld();
4705 }
4706 // FIXME: should warn, because it's unclear whether we need to release or not.
4707 int b = a;
4708 a = 0;
4709 mu_.Unlock(); // should this be a warning?
4710 }
4711
test9()4712 void test9() {
4713 if (c) {
4714 mu_.AssertHeld();
4715 }
4716 else {
4717 mu_.Lock(); // expected-note {{mutex acquired here}}
4718 }
4719 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4720
test10()4721 void test10() {
4722 if (c) {
4723 mu_.Lock(); // expected-note {{mutex acquired here}}
4724 }
4725 else {
4726 mu_.AssertHeld();
4727 }
4728 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4729
4730 void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
4731
test11()4732 void test11() {
4733 assertMu();
4734 int b = a;
4735 a = 0;
4736 }
4737
test12()4738 void test12() {
4739 if (c)
4740 mu_.ReaderLock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4741 else
4742 mu_.AssertHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4743 // FIXME: should instead warn because it's unclear whether we need to release or not.
4744 int b = a;
4745 a = 0;
4746 mu_.Unlock();
4747 }
4748
test13()4749 void test13() {
4750 if (c)
4751 mu_.Lock(); // expected-warning {{mutex 'mu_' is acquired exclusively and shared in the same scope}}
4752 else
4753 mu_.AssertReaderHeld(); // expected-note {{the other acquisition of mutex 'mu_' is here}}
4754 // FIXME: should instead warn because it's unclear whether we need to release or not.
4755 int b = a;
4756 a = 0;
4757 mu_.Unlock();
4758 }
4759 };
4760
4761 } // end namespace AssertHeldTest
4762
4763
4764 namespace LogicalConditionalTryLock {
4765
4766 class Foo {
4767 public:
4768 Mutex mu;
4769 int a GUARDED_BY(mu);
4770 bool c;
4771
4772 bool newc();
4773
test1()4774 void test1() {
4775 if (c && mu.TryLock()) {
4776 a = 0;
4777 mu.Unlock();
4778 }
4779 }
4780
test2()4781 void test2() {
4782 bool b = mu.TryLock();
4783 if (c && b) {
4784 a = 0;
4785 mu.Unlock();
4786 }
4787 }
4788
test3()4789 void test3() {
4790 if (c || !mu.TryLock())
4791 return;
4792 a = 0;
4793 mu.Unlock();
4794 }
4795
test4()4796 void test4() {
4797 while (c && mu.TryLock()) {
4798 a = 0;
4799 c = newc();
4800 mu.Unlock();
4801 }
4802 }
4803
test5()4804 void test5() {
4805 while (c) {
4806 if (newc() || !mu.TryLock())
4807 break;
4808 a = 0;
4809 mu.Unlock();
4810 }
4811 }
4812
test6()4813 void test6() {
4814 mu.Lock();
4815 do {
4816 a = 0;
4817 mu.Unlock();
4818 } while (newc() && mu.TryLock());
4819 }
4820
test7()4821 void test7() {
4822 for (bool b = mu.TryLock(); c && b;) {
4823 a = 0;
4824 mu.Unlock();
4825 }
4826 }
4827
test8()4828 void test8() {
4829 if (c && newc() && mu.TryLock()) {
4830 a = 0;
4831 mu.Unlock();
4832 }
4833 }
4834
test9()4835 void test9() {
4836 if (!(c && newc() && mu.TryLock()))
4837 return;
4838 a = 0;
4839 mu.Unlock();
4840 }
4841
test10()4842 void test10() {
4843 if (!(c || !mu.TryLock())) {
4844 a = 0;
4845 mu.Unlock();
4846 }
4847 }
4848 };
4849
4850 } // end namespace LogicalConditionalTryLock
4851
4852
4853
4854 namespace PtGuardedByTest {
4855
4856 void doSomething();
4857
4858 class Cell {
4859 public:
4860 int a;
4861 };
4862
4863
4864 // This mainly duplicates earlier tests, but just to make sure...
4865 class PtGuardedByCorrectnessTest {
4866 Mutex mu1;
4867 Mutex mu2;
4868 int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4869 Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4870 int sa[10] GUARDED_BY(mu1);
4871 Cell sc[10] GUARDED_BY(mu1);
4872
4873 static constexpr int Cell::*pa = &Cell::a;
4874
test1()4875 void test1() {
4876 mu1.Lock();
4877 if (a == 0) doSomething(); // OK, we don't dereference.
4878 a = 0;
4879 c = 0;
4880 if (sa[0] == 42) doSomething();
4881 sa[0] = 57;
4882 if (sc[0].a == 42) doSomething();
4883 sc[0].a = 57;
4884 mu1.Unlock();
4885 }
4886
test2()4887 void test2() {
4888 mu1.ReaderLock();
4889 if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4890 *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4891
4892 if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4893 c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4894 c->*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4895
4896 if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4897 (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4898 (*c).*pa = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4899
4900 if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4901 a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4902 if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4903 c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4904 mu1.Unlock();
4905 }
4906
test3()4907 void test3() {
4908 mu2.Lock();
4909 if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4910 *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4911
4912 if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4913 c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4914
4915 if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4916 (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4917
4918 if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4919 a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4920 if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4921 c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4922 mu2.Unlock();
4923 }
4924
test4()4925 void test4() { // Literal arrays
4926 if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4927 sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4928 if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4929 sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4930 sc[0].*pa = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4931
4932 if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4933 *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4934 if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4935 (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4936 if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4937 sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4938 }
4939
test5()4940 void test5() {
4941 mu1.ReaderLock(); // OK -- correct use.
4942 mu2.Lock();
4943 if (*a == 0) doSomething();
4944 *a = 0;
4945
4946 if (c->a == 0) doSomething();
4947 c->a = 0;
4948
4949 if ((*c).a == 0) doSomething();
4950 (*c).a = 0;
4951 mu2.Unlock();
4952 mu1.Unlock();
4953 }
4954 };
4955
4956
4957 class SmartPtr_PtGuardedBy_Test {
4958 Mutex mu1;
4959 Mutex mu2;
4960 SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4961 SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4962
4963 static constexpr int Cell::*pa = &Cell::a;
4964
test1()4965 void test1() {
4966 mu1.ReaderLock();
4967 mu2.Lock();
4968
4969 sp.get();
4970 if (*sp == 0) doSomething();
4971 *sp = 0;
4972 sq->a = 0;
4973 sq->*pa = 0;
4974
4975 if (sp[0] == 0) doSomething();
4976 sp[0] = 0;
4977
4978 mu2.Unlock();
4979 mu1.Unlock();
4980 }
4981
test2()4982 void test2() {
4983 mu2.Lock();
4984
4985 sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4986 if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4987 *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4988 sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4989 sq->*pa = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4990
4991 if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4992 sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4993 if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4994 sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4995
4996 mu2.Unlock();
4997 }
4998
test3()4999 void test3() {
5000 mu1.Lock();
5001
5002 sp.get();
5003 if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5004 *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5005 sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5006 sq->*pa = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5007
5008 if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5009 sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
5010 if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5011 sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
5012
5013 mu1.Unlock();
5014 }
5015 };
5016
5017 } // end namespace PtGuardedByTest
5018
5019
5020 namespace NonMemberCalleeICETest {
5021
5022 class A {
Run()5023 void Run() {
5024 (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
5025 }
5026
5027 void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M);
5028 Mutex M;
5029 };
5030
5031 } // end namespace NonMemberCalleeICETest
5032
5033
5034 namespace pt_guard_attribute_type {
5035 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
5036 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
5037
test()5038 void test() {
5039 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to non-static data members and global variables}}
5040 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to non-static data members and global variables}}
5041
5042 typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to}}
5043 typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to}}
5044 }
5045 } // end namespace pt_guard_attribute_type
5046
5047
5048 namespace ThreadAttributesOnLambdas {
5049
5050 class Foo {
5051 Mutex mu_;
5052
5053 void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);
5054
test()5055 void test() {
5056 auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
5057 LockedFunction();
5058 };
5059
5060 auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {
5061 LockedFunction();
5062 };
5063
5064 auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {
5065 mu_.Lock();
5066 };
5067
5068 func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}
5069 func2();
5070 func3();
5071 mu_.Unlock();
5072 }
5073 };
5074
5075 } // end namespace ThreadAttributesOnLambdas
5076
5077
5078
5079 namespace AttributeExpressionCornerCases {
5080
5081 class Foo {
5082 int a GUARDED_BY(getMu());
5083
5084 Mutex* getMu() LOCK_RETURNED("");
5085 Mutex* getUniv() LOCK_RETURNED("*");
5086
test1()5087 void test1() {
5088 a = 0;
5089 }
5090
test2()5091 void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
5092 a = 0;
5093 }
5094
5095 void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
5096
test3()5097 void test3() {
5098 foo(nullptr);
5099 }
5100 };
5101
5102
5103 class MapTest {
5104 struct MuCell { Mutex* mu; };
5105
5106 MyMap<MyString, Mutex*> map;
5107 MyMap<MyString, MuCell> mapCell;
5108
5109 int a GUARDED_BY(map["foo"]);
5110 int b GUARDED_BY(mapCell["foo"].mu);
5111
test()5112 void test() {
5113 map["foo"]->Lock();
5114 a = 0;
5115 map["foo"]->Unlock();
5116 }
5117
test2()5118 void test2() {
5119 mapCell["foo"].mu->Lock();
5120 b = 0;
5121 mapCell["foo"].mu->Unlock();
5122 }
5123 };
5124
5125
5126 class PreciseSmartPtr {
5127 SmartPtr<Mutex> mu;
5128 int val GUARDED_BY(mu);
5129
compare(PreciseSmartPtr & a,PreciseSmartPtr & b)5130 static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
5131 a.mu->Lock();
5132 bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
5133 // expected-note {{found near match 'a.mu'}}
5134 a.mu->Unlock();
5135 return result;
5136 }
5137 };
5138
5139
5140 class SmartRedeclare {
5141 SmartPtr<Mutex> mu;
5142 int val GUARDED_BY(mu);
5143
5144 void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
5145 void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5146 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
5147 };
5148
5149
test()5150 void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
5151 val = 0;
5152 }
5153
test2()5154 void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5155 val = 0;
5156 }
5157
test3()5158 void SmartRedeclare::test3() {
5159 val = 0;
5160 }
5161
5162
5163 namespace CustomMutex {
5164
5165
5166 class LOCKABLE BaseMutex { };
5167 class DerivedMutex : public BaseMutex { };
5168
5169 void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
5170 void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
5171
5172 static struct DerivedMutex custMu;
5173
doSomethingRequiringLock()5174 static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
5175
customTest()5176 void customTest() {
5177 customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
5178 doSomethingRequiringLock();
5179 customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
5180 }
5181
5182 } // end namespace CustomMutex
5183
5184 } // end AttributeExpressionCornerCases
5185
5186
5187 namespace ScopedLockReturnedInvalid {
5188
5189 class Opaque;
5190
5191 Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
5192
test(Opaque * o)5193 void test(Opaque* o) {
5194 MutexLock lock(getMutex(o));
5195 }
5196
5197 } // end namespace ScopedLockReturnedInvalid
5198
5199
5200 namespace NegativeRequirements {
5201
5202 class Bar {
5203 Mutex mu;
5204 int a GUARDED_BY(mu);
5205
5206 public:
baz()5207 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5208 mu.Lock();
5209 a = 0;
5210 mu.Unlock();
5211 }
5212 };
5213
5214
5215 class Foo {
5216 Mutex mu;
5217 int a GUARDED_BY(mu);
5218
5219 public:
foo()5220 void foo() {
5221 mu.Lock(); // warning? needs !mu?
5222 baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
5223 bar();
5224 mu.Unlock();
5225 }
5226
bar()5227 void bar() {
5228 bar2(); // expected-warning {{calling function 'bar2' requires negative capability '!mu'}}
5229 }
5230
bar2()5231 void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5232 baz();
5233 }
5234
baz()5235 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
5236 mu.Lock();
5237 a = 0;
5238 mu.Unlock();
5239 }
5240
test()5241 void test() {
5242 Bar b;
5243 b.baz(); // no warning -- in different class.
5244 }
5245 };
5246
5247 } // end namespace NegativeRequirements
5248
5249
5250 namespace NegativeThreadRoles {
5251
5252 typedef int __attribute__((capability("role"))) ThreadRole;
5253
acquire(ThreadRole R)5254 void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
release(ThreadRole R)5255 void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
5256
5257 ThreadRole FlightControl, Logger;
5258
5259 extern void enque_log_msg(const char *msg);
log_msg(const char * msg)5260 void log_msg(const char *msg) {
5261 enque_log_msg(msg);
5262 }
5263
dispatch_log(const char * msg)5264 void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
dispatch_log2(const char * msg)5265 void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
5266
flight_control_entry(void)5267 void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
5268 dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
5269 dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
5270 }
5271
spawn_fake_flight_control_thread(void)5272 void spawn_fake_flight_control_thread(void) {
5273 acquire(FlightControl);
5274 flight_control_entry();
5275 release(FlightControl);
5276 }
5277
5278 extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
logger_entry(void)5279 void logger_entry(void) __attribute__((requires_capability(Logger)))
5280 __attribute__((requires_capability(!FlightControl))) {
5281 const char *msg;
5282
5283 while ((msg = deque_log_msg())) {
5284 dispatch_log(msg);
5285 }
5286 }
5287
spawn_fake_logger_thread(void)5288 void spawn_fake_logger_thread(void) __attribute__((requires_capability(!FlightControl))) {
5289 acquire(Logger);
5290 logger_entry();
5291 release(Logger);
5292 }
5293
main(void)5294 int main(void) __attribute__((requires_capability(!FlightControl))) {
5295 spawn_fake_flight_control_thread();
5296 spawn_fake_logger_thread();
5297
5298 for (;;)
5299 ; /* Pretend to dispatch things. */
5300
5301 return 0;
5302 }
5303
5304 } // end namespace NegativeThreadRoles
5305
5306
5307 namespace AssertSharedExclusive {
5308
5309 void doSomething();
5310
5311 class Foo {
5312 Mutex mu;
5313 int a GUARDED_BY(mu);
5314
test()5315 void test() SHARED_LOCKS_REQUIRED(mu) {
5316 mu.AssertHeld();
5317 if (a > 0)
5318 doSomething();
5319 }
5320 };
5321
5322 } // end namespace AssertSharedExclusive
5323
5324
5325 namespace RangeBasedForAndReferences {
5326
5327 class Foo {
5328 struct MyStruct {
5329 int a;
5330 };
5331
5332 Mutex mu;
5333 int a GUARDED_BY(mu);
5334 MyContainer<int> cntr GUARDED_BY(mu);
5335 MyStruct s GUARDED_BY(mu);
5336 int arr[10] GUARDED_BY(mu);
5337
nonref_test()5338 void nonref_test() {
5339 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5340 b = 0; // no warning
5341 }
5342
auto_test()5343 void auto_test() {
5344 auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
5345 b = 0; // no warning
5346 auto &c = a; // no warning
5347 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5348 }
5349
ref_test()5350 void ref_test() {
5351 int &b = a;
5352 int &c = b;
5353 int &d = c;
5354 b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5355 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5356 d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
5357
5358 MyStruct &rs = s;
5359 rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
5360
5361 int (&rarr)[10] = arr;
5362 rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
5363 }
5364
ptr_test()5365 void ptr_test() {
5366 int *b = &a;
5367 *b = 0; // no expected warning yet
5368 }
5369
for_test()5370 void for_test() {
5371 int total = 0;
5372 for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
5373 total += i;
5374 }
5375 }
5376 };
5377
5378
5379 } // end namespace RangeBasedForAndReferences
5380
5381
5382
5383 namespace PassByRefTest {
5384
5385 class Foo {
5386 public:
Foo()5387 Foo() : a(0), b(0) { }
5388
5389 int a;
5390 int b;
5391
5392 void operator+(const Foo& f);
5393
5394 void operator[](const Foo& g);
5395
5396 void operator()();
5397 };
5398
5399 template<class T>
5400 T&& mymove(T& f);
5401
5402
5403 // test top-level functions
5404 void copy(Foo f);
5405 void write1(Foo& f);
5406 void write2(int a, Foo& f);
5407 void read1(const Foo& f);
5408 void read2(int a, const Foo& f);
5409 void destroy(Foo&& f);
5410
5411 void operator/(const Foo& f, const Foo& g);
5412 void operator*(const Foo& f, const Foo& g);
5413
5414 // Test constructors.
5415 struct FooRead {
5416 FooRead(const Foo &);
5417 };
5418 struct FooWrite {
5419 FooWrite(Foo &);
5420 };
5421
5422 // Test variadic functions
5423 template<typename... T>
copyVariadic(T...)5424 void copyVariadic(T...) {}
5425 template<typename... T>
writeVariadic(T &...)5426 void writeVariadic(T&...) {}
5427 template<typename... T>
readVariadic(const T &...)5428 void readVariadic(const T&...) {}
5429
5430 void copyVariadicC(int, ...);
5431
5432 class Bar {
5433 public:
5434 Mutex mu;
5435 Foo foo GUARDED_BY(mu);
5436 Foo foo2 GUARDED_BY(mu);
5437 Foo* foop PT_GUARDED_BY(mu);
5438 SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
5439
5440 // test methods.
5441 void mwrite1(Foo& f);
5442 void mwrite2(int a, Foo& f);
5443 void mread1(const Foo& f);
5444 void mread2(int a, const Foo& f);
5445
5446 // static methods
5447 static void smwrite1(Foo& f);
5448 static void smwrite2(int a, Foo& f);
5449 static void smread1(const Foo& f);
5450 static void smread2(int a, const Foo& f);
5451
5452 void operator<<(const Foo& f);
5453
test1()5454 void test1() {
5455 copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5456 write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5457 write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5458 read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5459 read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5460 destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5461
5462 copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5463 readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5464 writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5465 copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5466
5467 FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5468 FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5469
5470 mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5471 mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5472 mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5473 mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5474
5475 smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5476 smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5477 smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5478 smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5479
5480 foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5481 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5482 foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5483 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5484 foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5485 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5486 foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
5487 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
5488 foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5489 (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
5490
5491 copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
5492 write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5493 write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5494 read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5495 read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5496 destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
5497
5498 copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5499 write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5500 write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5501 read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5502 read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5503 destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
5504
5505 // TODO -- these require better smart pointer handling.
5506 copy(*foosp.get());
5507 write1(*foosp.get());
5508 write2(10, *foosp.get());
5509 read1(*foosp.get());
5510 read2(10, *foosp.get());
5511 destroy(mymove(*foosp.get()));
5512 }
5513 };
5514
5515
5516 } // end namespace PassByRefTest
5517
5518
5519 namespace AcquiredBeforeAfterText {
5520
5521 class Foo {
5522 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5523 Mutex mu2;
5524 Mutex mu3;
5525
test1()5526 void test1() {
5527 mu1.Lock();
5528 mu2.Lock();
5529 mu3.Lock();
5530
5531 mu3.Unlock();
5532 mu2.Unlock();
5533 mu1.Unlock();
5534 }
5535
test2()5536 void test2() {
5537 mu2.Lock();
5538 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5539 mu1.Unlock();
5540 mu2.Unlock();
5541 }
5542
test3()5543 void test3() {
5544 mu3.Lock();
5545 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5546 mu1.Unlock();
5547 mu3.Unlock();
5548 }
5549
test4()5550 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {
5551 mu2.Lock();
5552 mu2.Unlock();
5553 }
5554
test5()5555 void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5556 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5557 mu1.Unlock();
5558 }
5559
test6()5560 void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
5561 mu1.AssertHeld();
5562 }
5563
test7()5564 void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }
5565
test8()5566 void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }
5567 };
5568
5569
5570 class Foo2 {
5571 Mutex mu1;
5572 Mutex mu2 ACQUIRED_AFTER(mu1);
5573 Mutex mu3 ACQUIRED_AFTER(mu1);
5574
test1()5575 void test1() {
5576 mu1.Lock();
5577 mu2.Lock();
5578 mu3.Lock();
5579
5580 mu3.Unlock();
5581 mu2.Unlock();
5582 mu1.Unlock();
5583 }
5584
test2()5585 void test2() {
5586 mu2.Lock();
5587 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5588 mu1.Unlock();
5589 mu2.Unlock();
5590 }
5591
test3()5592 void test3() {
5593 mu3.Lock();
5594 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5595 mu1.Unlock();
5596 mu3.Unlock();
5597 }
5598 };
5599
5600
5601 class Foo3 {
5602 Mutex mu1 ACQUIRED_BEFORE(mu2);
5603 Mutex mu2;
5604 Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);
5605 Mutex mu4;
5606
test1()5607 void test1() {
5608 mu1.Lock();
5609 mu2.Lock();
5610 mu3.Lock();
5611 mu4.Lock();
5612
5613 mu4.Unlock();
5614 mu3.Unlock();
5615 mu2.Unlock();
5616 mu1.Unlock();
5617 }
5618
test2()5619 void test2() {
5620 mu4.Lock();
5621 mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}
5622
5623 mu2.Unlock();
5624 mu4.Unlock();
5625 }
5626
test3()5627 void test3() {
5628 mu4.Lock();
5629 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}
5630
5631 mu1.Unlock();
5632 mu4.Unlock();
5633 }
5634
test4()5635 void test4() {
5636 mu3.Lock();
5637 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
5638
5639 mu1.Unlock();
5640 mu3.Unlock();
5641 }
5642 };
5643
5644
5645 // Test transitive DAG traversal with AFTER
5646 class Foo4 {
5647 Mutex mu1;
5648 Mutex mu2 ACQUIRED_AFTER(mu1);
5649 Mutex mu3 ACQUIRED_AFTER(mu1);
5650 Mutex mu4 ACQUIRED_AFTER(mu2, mu3);
5651 Mutex mu5 ACQUIRED_AFTER(mu4);
5652 Mutex mu6 ACQUIRED_AFTER(mu4);
5653 Mutex mu7 ACQUIRED_AFTER(mu5, mu6);
5654 Mutex mu8 ACQUIRED_AFTER(mu7);
5655
test()5656 void test() {
5657 mu8.Lock();
5658 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5659 mu1.Unlock();
5660 mu8.Unlock();
5661 }
5662 };
5663
5664
5665 // Test transitive DAG traversal with BEFORE
5666 class Foo5 {
5667 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5668 Mutex mu2 ACQUIRED_BEFORE(mu4);
5669 Mutex mu3 ACQUIRED_BEFORE(mu4);
5670 Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);
5671 Mutex mu5 ACQUIRED_BEFORE(mu7);
5672 Mutex mu6 ACQUIRED_BEFORE(mu7);
5673 Mutex mu7 ACQUIRED_BEFORE(mu8);
5674 Mutex mu8;
5675
test()5676 void test() {
5677 mu8.Lock();
5678 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5679 mu1.Unlock();
5680 mu8.Unlock();
5681 }
5682 };
5683
5684
5685 class Foo6 {
5686 Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}}
5687 Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}}
5688 Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}}
5689
5690 Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}}
5691 Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}}
5692
test0()5693 void test0() {
5694 mu_a.Lock();
5695 mu_b.Lock();
5696 mu_b.Unlock();
5697 mu_a.Unlock();
5698 }
5699
test1a()5700 void test1a() {
5701 mu1.Lock();
5702 mu1.Unlock();
5703 }
5704
test1b()5705 void test1b() {
5706 mu1.Lock();
5707 mu_a.Lock();
5708 mu_b.Lock();
5709 mu_b.Unlock();
5710 mu_a.Unlock();
5711 mu1.Unlock();
5712 }
5713
test()5714 void test() {
5715 mu2.Lock();
5716 mu2.Unlock();
5717 }
5718
test3()5719 void test3() {
5720 mu3.Lock();
5721 mu3.Unlock();
5722 }
5723 };
5724
5725 } // end namespace AcquiredBeforeAfterTest
5726
5727
5728 namespace ScopedAdoptTest {
5729
5730 class Foo {
5731 Mutex mu;
5732 int a GUARDED_BY(mu);
5733 int b;
5734
test1()5735 void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {
5736 MutexLock slock(&mu, true);
5737 a = 0;
5738 }
5739
test2()5740 void test2() SHARED_UNLOCK_FUNCTION(mu) {
5741 ReaderMutexLock slock(&mu, true);
5742 b = a;
5743 }
5744
test3()5745 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5746 MutexLock slock(&mu, true);
5747 a = 0;
5748 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5749
test4()5750 void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5751 ReaderMutexLock slock(&mu, true);
5752 b = a;
5753 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5754
5755 };
5756
5757 } // end namespace ScopedAdoptTest
5758
5759
5760 namespace TestReferenceNoThreadSafetyAnalysis {
5761
5762 #define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
5763
5764 // Takes a reference to a guarded data member, and returns an unguarded
5765 // reference.
5766 template <class T>
ts_unchecked_read(const T & v)5767 inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
5768 return v;
5769 }
5770
5771 template <class T>
ts_unchecked_read(T & v)5772 inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
5773 return v;
5774 }
5775
5776
5777 class Foo {
5778 public:
Foo()5779 Foo(): a(0) { }
5780
5781 int a;
5782 };
5783
5784
5785 class Bar {
5786 public:
Bar()5787 Bar() : a(0) { }
5788
5789 Mutex mu;
5790 int a GUARDED_BY(mu);
5791 Foo foo GUARDED_BY(mu);
5792 };
5793
5794
test()5795 void test() {
5796 Bar bar;
5797 const Bar cbar;
5798
5799 int a = TS_UNCHECKED_READ(bar.a); // nowarn
5800 TS_UNCHECKED_READ(bar.a) = 1; // nowarn
5801
5802 int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
5803 TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
5804
5805 int c = TS_UNCHECKED_READ(cbar.a); // nowarn
5806 }
5807
5808 #undef TS_UNCHECKED_READ
5809
5810 } // end namespace TestReferenceNoThreadSafetyAnalysis
5811
5812
5813 namespace GlobalAcquiredBeforeAfterTest {
5814
5815 Mutex mu1;
5816 Mutex mu2 ACQUIRED_AFTER(mu1);
5817
test3()5818 void test3() {
5819 mu2.Lock();
5820 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5821 mu1.Unlock();
5822 mu2.Unlock();
5823 }
5824
5825 } // end namespace GlobalAcquiredBeforeAfterTest
5826
5827
5828 namespace LifetimeExtensionText {
5829
5830 struct Holder {
~HolderLifetimeExtensionText::Holder5831 virtual ~Holder() throw() {}
5832 int i = 0;
5833 };
5834
test()5835 void test() {
5836 // Should not crash.
5837 const auto &value = Holder().i;
5838 }
5839
5840 } // end namespace LifetimeExtensionTest
5841
5842
5843 namespace LockableUnions {
5844
5845 union LOCKABLE MutexUnion {
5846 int a;
5847 char* b;
5848
5849 void Lock() EXCLUSIVE_LOCK_FUNCTION();
5850 void Unlock() UNLOCK_FUNCTION();
5851 };
5852
5853 MutexUnion muun2;
5854 MutexUnion muun1 ACQUIRED_BEFORE(muun2);
5855
test()5856 void test() {
5857 muun2.Lock();
5858 muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
5859 muun1.Unlock();
5860 muun2.Unlock();
5861 }
5862
5863 } // end namespace LockableUnions
5864
5865 // This used to crash.
5866 class acquired_before_empty_str {
WaitUntilSpaceAvailable()5867 void WaitUntilSpaceAvailable() {
5868 lock_.ReaderLock(); // expected-note {{acquired here}}
5869 } // expected-warning {{mutex 'lock_' is still held at the end of function}}
5870 Mutex lock_ ACQUIRED_BEFORE("");
5871 };
5872
5873 namespace PR34800 {
5874 struct A {
5875 operator int() const;
5876 };
5877 struct B {
5878 bool g() __attribute__((locks_excluded(h))); // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}}
5879 int h;
5880 };
5881 struct C {
5882 B *operator[](int);
5883 };
5884 C c;
f()5885 void f() { c[A()]->g(); }
5886 } // namespace PR34800
5887
5888 namespace ReturnScopedLockable {
5889 template<typename Object> class SCOPED_LOCKABLE ReadLockedPtr {
5890 public:
5891 ReadLockedPtr(Object *ptr) SHARED_LOCK_FUNCTION((*this)->mutex);
5892 ReadLockedPtr(ReadLockedPtr &&) SHARED_LOCK_FUNCTION((*this)->mutex);
5893 ~ReadLockedPtr() UNLOCK_FUNCTION();
5894
operator ->() const5895 Object *operator->() const { return object; }
5896
5897 private:
5898 Object *object;
5899 };
5900
5901 struct Object {
5902 int f() SHARED_LOCKS_REQUIRED(mutex);
5903 Mutex mutex;
5904 };
5905
5906 ReadLockedPtr<Object> get();
use()5907 int use() {
5908 auto ptr = get();
5909 return ptr->f();
5910 }
use_constructor()5911 void use_constructor() {
5912 auto ptr = ReadLockedPtr<Object>(nullptr);
5913 ptr->f();
5914 auto ptr2 = ReadLockedPtr<Object>{nullptr};
5915 ptr2->f();
5916 auto ptr3 = (ReadLockedPtr<Object>{nullptr});
5917 ptr3->f();
5918 }
5919 struct Convertible {
5920 Convertible();
5921 operator ReadLockedPtr<Object>();
5922 };
use_conversion()5923 void use_conversion() {
5924 ReadLockedPtr<Object> ptr = Convertible();
5925 ptr->f();
5926 }
5927 }
5928
5929 namespace PR38640 {
f()5930 void f() {
5931 // Self-referencing assignment previously caused an infinite loop when thread
5932 // safety analysis was enabled.
5933 int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}}
5934 }
5935 }
5936
5937 namespace Derived_Smart_Pointer {
5938 template <class T>
5939 class SmartPtr_Derived : public SmartPtr<T> {};
5940
5941 class Foo {
5942 public:
5943 SmartPtr_Derived<Mutex> mu_;
5944 int a GUARDED_BY(mu_);
5945 int b GUARDED_BY(mu_.get());
5946 int c GUARDED_BY(*mu_);
5947
5948 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
5949 void Unlock() UNLOCK_FUNCTION(mu_);
5950
test0()5951 void test0() {
5952 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
5953 b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
5954 c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
5955 }
5956
test1()5957 void test1() {
5958 Lock();
5959 a = 1;
5960 b = 1;
5961 c = 1;
5962 Unlock();
5963 }
5964 };
5965
5966 class Bar {
5967 SmartPtr_Derived<Foo> foo;
5968
test0()5969 void test0() {
5970 foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
5971 (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
5972 foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
5973 }
5974
test1()5975 void test1() {
5976 foo->Lock();
5977 foo->a = 1;
5978 foo->Unlock();
5979
5980 foo->mu_->Lock();
5981 foo->b = 1;
5982 foo->mu_->Unlock();
5983
5984 MutexLock lock(foo->mu_.get());
5985 foo->c = 1;
5986 }
5987 };
5988
5989 class PointerGuard {
5990 Mutex mu1;
5991 Mutex mu2;
5992 SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
5993
test0()5994 void test0() {
5995 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
5996 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \
5997 // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
5998
5999 }
6000
test1()6001 void test1() {
6002 mu1.Lock();
6003
6004 i.get();
6005 *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
6006
6007 mu1.Unlock();
6008 }
6009
test2()6010 void test2() {
6011 mu2.Lock();
6012
6013 i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
6014 *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
6015
6016 mu2.Unlock();
6017 }
6018
test3()6019 void test3() {
6020 mu1.Lock();
6021 mu2.Lock();
6022
6023 i.get();
6024 *i = 2;
6025
6026 mu2.Unlock();
6027 mu1.Unlock();
6028 }
6029 };
6030 }
6031