• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
2 
3 #define LOCKABLE            __attribute__ ((lockable))
4 #define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))
5 #define GUARDED_BY(x)       __attribute__ ((guarded_by(x)))
6 #define GUARDED_VAR         __attribute__ ((guarded_var))
7 #define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x)))
8 #define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var))
9 #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
10 #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
11 #define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
12 #define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__)))
13 #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
14 #define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__)))
15 #define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__)))
16 #define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x)))
17 #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
18 #define EXCLUSIVE_LOCKS_REQUIRED(...) \
19   __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
20 #define SHARED_LOCKS_REQUIRED(...) \
21   __attribute__ ((shared_locks_required(__VA_ARGS__)))
22 #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
23 
24 //-----------------------------------------//
25 //  Helper fields
26 //-----------------------------------------//
27 
28 
29 class  __attribute__((lockable)) Mutex {
30  public:
31   void Lock() __attribute__((exclusive_lock_function));
32   void ReaderLock() __attribute__((shared_lock_function));
33   void Unlock() __attribute__((unlock_function));
34   bool TryLock() __attribute__((exclusive_trylock_function(true)));
35   bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
36   void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
37 };
38 
39 class __attribute__((scoped_lockable)) MutexLock {
40  public:
41   MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
42   ~MutexLock() __attribute__((unlock_function));
43 };
44 
45 class __attribute__((scoped_lockable)) ReaderMutexLock {
46  public:
47   ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
48   ~ReaderMutexLock() __attribute__((unlock_function));
49 };
50 
51 
52 Mutex sls_mu;
53 
54 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
55 int sls_guard_var __attribute__((guarded_var)) = 0;
56 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
57 
58 bool getBool();
59 
60 class MutexWrapper {
61 public:
62    Mutex mu;
63    int x __attribute__((guarded_by(mu)));
64    void MyLock() __attribute__((exclusive_lock_function(mu)));
65 };
66 
67 MutexWrapper sls_mw;
68 
sls_fun_0()69 void sls_fun_0() {
70   sls_mw.mu.Lock();
71   sls_mw.x = 5;
72   sls_mw.mu.Unlock();
73 }
74 
sls_fun_2()75 void sls_fun_2() {
76   sls_mu.Lock();
77   int x = sls_guard_var;
78   sls_mu.Unlock();
79 }
80 
sls_fun_3()81 void sls_fun_3() {
82   sls_mu.Lock();
83   sls_guard_var = 2;
84   sls_mu.Unlock();
85 }
86 
sls_fun_4()87 void sls_fun_4() {
88   sls_mu2.Lock();
89   sls_guard_var = 2;
90   sls_mu2.Unlock();
91 }
92 
sls_fun_5()93 void sls_fun_5() {
94   sls_mu.Lock();
95   int x = sls_guardby_var;
96   sls_mu.Unlock();
97 }
98 
sls_fun_6()99 void sls_fun_6() {
100   sls_mu.Lock();
101   sls_guardby_var = 2;
102   sls_mu.Unlock();
103 }
104 
sls_fun_7()105 void sls_fun_7() {
106   sls_mu.Lock();
107   sls_mu2.Lock();
108   sls_mu2.Unlock();
109   sls_mu.Unlock();
110 }
111 
sls_fun_8()112 void sls_fun_8() {
113   sls_mu.Lock();
114   if (getBool())
115     sls_mu.Unlock();
116   else
117     sls_mu.Unlock();
118 }
119 
sls_fun_9()120 void sls_fun_9() {
121   if (getBool())
122     sls_mu.Lock();
123   else
124     sls_mu.Lock();
125   sls_mu.Unlock();
126 }
127 
sls_fun_good_6()128 void sls_fun_good_6() {
129   if (getBool()) {
130     sls_mu.Lock();
131   } else {
132     if (getBool()) {
133       getBool(); // EMPTY
134     } else {
135       getBool(); // EMPTY
136     }
137     sls_mu.Lock();
138   }
139   sls_mu.Unlock();
140 }
141 
sls_fun_good_7()142 void sls_fun_good_7() {
143   sls_mu.Lock();
144   while (getBool()) {
145     sls_mu.Unlock();
146     if (getBool()) {
147       if (getBool()) {
148         sls_mu.Lock();
149         continue;
150       }
151     }
152     sls_mu.Lock();
153   }
154   sls_mu.Unlock();
155 }
156 
sls_fun_good_8()157 void sls_fun_good_8() {
158   sls_mw.MyLock();
159   sls_mw.mu.Unlock();
160 }
161 
sls_fun_bad_1()162 void sls_fun_bad_1() {
163   sls_mu.Unlock(); // \
164     // expected-warning{{unlocking 'sls_mu' that was not locked}}
165 }
166 
sls_fun_bad_2()167 void sls_fun_bad_2() {
168   sls_mu.Lock();
169   sls_mu.Lock(); // \
170     // expected-warning{{locking 'sls_mu' that is already locked}}
171   sls_mu.Unlock();
172 }
173 
sls_fun_bad_3()174 void sls_fun_bad_3() {
175   sls_mu.Lock(); // expected-note {{mutex acquired here}}
176 } // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
177 
sls_fun_bad_4()178 void sls_fun_bad_4() {
179   if (getBool())
180     sls_mu.Lock(); // \
181   expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \
182   expected-note{{mutex acquired here}}
183 
184   else
185     sls_mu2.Lock(); // \
186   expected-note{{mutex acquired here}}
187 } // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
188 
sls_fun_bad_5()189 void sls_fun_bad_5() {
190   sls_mu.Lock(); // expected-note {{mutex acquired here}}
191   if (getBool())
192     sls_mu.Unlock();
193 } // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
194 
sls_fun_bad_6()195 void sls_fun_bad_6() {
196   if (getBool()) {
197     sls_mu.Lock(); // expected-note {{mutex acquired here}}
198   } else {
199     if (getBool()) {
200       getBool(); // EMPTY
201     } else {
202       getBool(); // EMPTY
203     }
204   }
205   sls_mu.Unlock(); // \
206     expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
207     expected-warning{{unlocking 'sls_mu' that was not locked}}
208 }
209 
sls_fun_bad_7()210 void sls_fun_bad_7() {
211   sls_mu.Lock();
212   while (getBool()) {
213     sls_mu.Unlock();
214     if (getBool()) {
215       if (getBool()) {
216         continue; // \
217         expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
218       }
219     }
220     sls_mu.Lock(); // expected-note {{mutex acquired here}}
221   }
222   sls_mu.Unlock();
223 }
224 
sls_fun_bad_8()225 void sls_fun_bad_8() {
226   sls_mu.Lock(); // expected-note{{mutex acquired here}}
227 
228   // FIXME: TERRIBLE SOURCE LOCATION!
229   do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
230     sls_mu.Unlock();
231   } while (getBool());
232 }
233 
sls_fun_bad_9()234 void sls_fun_bad_9() {
235   do {
236     sls_mu.Lock(); // \
237       // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
238       // expected-note{{mutex acquired here}}
239   } while (getBool());
240   sls_mu.Unlock();
241 }
242 
sls_fun_bad_10()243 void sls_fun_bad_10() {
244   sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
245   while(getBool()) {
246     sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
247   }
248 } // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
249 
sls_fun_bad_11()250 void sls_fun_bad_11() {
251   while (getBool()) { // \
252    expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
253     sls_mu.Lock(); // expected-note {{mutex acquired here}}
254   }
255   sls_mu.Unlock(); // \
256     // expected-warning{{unlocking 'sls_mu' that was not locked}}
257 }
258 
sls_fun_bad_12()259 void sls_fun_bad_12() {
260   sls_mu.Lock(); // expected-note {{mutex acquired here}}
261   while (getBool()) {
262     sls_mu.Unlock();
263     if (getBool()) {
264       if (getBool()) {
265         break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
266       }
267     }
268     sls_mu.Lock();
269   }
270   sls_mu.Unlock();
271 }
272 
273 //-----------------------------------------//
274 // Handling lock expressions in attribute args
275 // -------------------------------------------//
276 
277 Mutex aa_mu;
278 
279 class GlobalLocker {
280 public:
281   void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
282   void globalUnlock() __attribute__((unlock_function(aa_mu)));
283 };
284 
285 GlobalLocker glock;
286 
aa_fun_1()287 void aa_fun_1() {
288   glock.globalLock();
289   glock.globalUnlock();
290 }
291 
aa_fun_bad_1()292 void aa_fun_bad_1() {
293   glock.globalUnlock(); // \
294     // expected-warning{{unlocking 'aa_mu' that was not locked}}
295 }
296 
aa_fun_bad_2()297 void aa_fun_bad_2() {
298   glock.globalLock();
299   glock.globalLock(); // \
300     // expected-warning{{locking 'aa_mu' that is already locked}}
301   glock.globalUnlock();
302 }
303 
aa_fun_bad_3()304 void aa_fun_bad_3() {
305   glock.globalLock(); // expected-note{{mutex acquired here}}
306 } // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
307 
308 //--------------------------------------------------//
309 // Regression tests for unusual method names
310 //--------------------------------------------------//
311 
312 Mutex wmu;
313 
314 // Test diagnostics for other method names.
315 class WeirdMethods {
316   // FIXME: can't currently check inside constructors and destructors.
WeirdMethods()317   WeirdMethods() {
318     wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
319   } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
~WeirdMethods()320   ~WeirdMethods() {
321     wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
322   } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
operator ++()323   void operator++() {
324     wmu.Lock(); // expected-note {{mutex acquired here}}
325   } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
operator int*()326   operator int*() {
327     wmu.Lock(); // expected-note {{mutex acquired here}}
328     return 0;
329   } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
330 };
331 
332 //-----------------------------------------------//
333 // Errors for guarded by or guarded var variables
334 // ----------------------------------------------//
335 
336 int *pgb_gvar __attribute__((pt_guarded_var));
337 int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
338 
339 class PGBFoo {
340  public:
341   int x;
342   int *pgb_field __attribute__((guarded_by(sls_mu2)))
343                  __attribute__((pt_guarded_by(sls_mu)));
testFoo()344   void testFoo() {
345     pgb_field = &x; // \
346       // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
347     *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
348       // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
349     x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
350       // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
351     (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
352       // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
353   }
354 };
355 
356 class GBFoo {
357  public:
358   int gb_field __attribute__((guarded_by(sls_mu)));
359 
testFoo()360   void testFoo() {
361     gb_field = 0; // \
362       // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
363   }
364 
testNoAnal()365   void testNoAnal() __attribute__((no_thread_safety_analysis)) {
366     gb_field = 0;
367   }
368 };
369 
370 GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
371 
gb_fun_0()372 void gb_fun_0() {
373   sls_mu.Lock();
374   int x = *pgb_var;
375   sls_mu.Unlock();
376 }
377 
gb_fun_1()378 void gb_fun_1() {
379   sls_mu.Lock();
380   *pgb_var = 2;
381   sls_mu.Unlock();
382 }
383 
gb_fun_2()384 void gb_fun_2() {
385   int x;
386   pgb_var = &x;
387 }
388 
gb_fun_3()389 void gb_fun_3() {
390   int *x = pgb_var;
391 }
392 
gb_bad_0()393 void gb_bad_0() {
394   sls_guard_var = 1; // \
395     // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
396 }
397 
gb_bad_1()398 void gb_bad_1() {
399   int x = sls_guard_var; // \
400     // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
401 }
402 
gb_bad_2()403 void gb_bad_2() {
404   sls_guardby_var = 1; // \
405     // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
406 }
407 
gb_bad_3()408 void gb_bad_3() {
409   int x = sls_guardby_var; // \
410     // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
411 }
412 
gb_bad_4()413 void gb_bad_4() {
414   *pgb_gvar = 1; // \
415     // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
416 }
417 
gb_bad_5()418 void gb_bad_5() {
419   int x = *pgb_gvar; // \
420     // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
421 }
422 
gb_bad_6()423 void gb_bad_6() {
424   *pgb_var = 1; // \
425     // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
426 }
427 
gb_bad_7()428 void gb_bad_7() {
429   int x = *pgb_var; // \
430     // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
431 }
432 
gb_bad_8()433 void gb_bad_8() {
434   GBFoo G;
435   G.gb_field = 0; // \
436     // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
437 }
438 
gb_bad_9()439 void gb_bad_9() {
440   sls_guard_var++; // \
441     // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
442   sls_guard_var--; // \
443     // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
444   ++sls_guard_var; // \
445     // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
446   --sls_guard_var;// \
447     // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
448 }
449 
450 //-----------------------------------------------//
451 // Warnings on variables with late parsed attributes
452 // ----------------------------------------------//
453 
454 class LateFoo {
455 public:
456   int a __attribute__((guarded_by(mu)));
457   int b;
458 
foo()459   void foo() __attribute__((exclusive_locks_required(mu))) { }
460 
test()461   void test() {
462     a = 0; // \
463       // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
464     b = a; // \
465       // expected-warning {{reading variable 'a' requires locking 'mu'}}
466     c = 0; // \
467       // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
468   }
469 
470   int c __attribute__((guarded_by(mu)));
471 
472   Mutex mu;
473 };
474 
475 class LateBar {
476  public:
477   int a_ __attribute__((guarded_by(mu1_)));
478   int b_;
479   int *q __attribute__((pt_guarded_by(mu)));
480   Mutex mu1_;
481   Mutex mu;
482   LateFoo Foo;
483   LateFoo Foo2;
484   LateFoo *FooPointer;
485 };
486 
487 LateBar b1, *b3;
488 
late_0()489 void late_0() {
490   LateFoo FooA;
491   LateFoo FooB;
492   FooA.mu.Lock();
493   FooA.a = 5;
494   FooA.mu.Unlock();
495 }
496 
late_1()497 void late_1() {
498   LateBar BarA;
499   BarA.FooPointer->mu.Lock();
500   BarA.FooPointer->a = 2;
501   BarA.FooPointer->mu.Unlock();
502 }
503 
late_bad_0()504 void late_bad_0() {
505   LateFoo fooA;
506   LateFoo fooB;
507   fooA.mu.Lock();
508   fooB.a = 5; // \
509     // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
510   fooA.mu.Unlock();
511 }
512 
late_bad_1()513 void late_bad_1() {
514   Mutex mu;
515   mu.Lock();
516   b1.mu1_.Lock();
517   int res = b1.a_ + b3->b_;
518   b3->b_ = *b1.q; // \
519     // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
520   b1.mu1_.Unlock();
521   b1.b_ = res;
522   mu.Unlock();
523 }
524 
late_bad_2()525 void late_bad_2() {
526   LateBar BarA;
527   BarA.FooPointer->mu.Lock();
528   BarA.Foo.a = 2; // \
529     // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
530   BarA.FooPointer->mu.Unlock();
531 }
532 
late_bad_3()533 void late_bad_3() {
534   LateBar BarA;
535   BarA.Foo.mu.Lock();
536   BarA.FooPointer->a = 2; // \
537     // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
538   BarA.Foo.mu.Unlock();
539 }
540 
late_bad_4()541 void late_bad_4() {
542   LateBar BarA;
543   BarA.Foo.mu.Lock();
544   BarA.Foo2.a = 2; // \
545     // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
546   BarA.Foo.mu.Unlock();
547 }
548 
549 //-----------------------------------------------//
550 // Extra warnings for shared vs. exclusive locks
551 // ----------------------------------------------//
552 
shared_fun_0()553 void shared_fun_0() {
554   sls_mu.Lock();
555   do {
556     sls_mu.Unlock();
557     sls_mu.Lock();
558   } while (getBool());
559   sls_mu.Unlock();
560 }
561 
shared_fun_1()562 void shared_fun_1() {
563   sls_mu.ReaderLock(); // \
564     // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
565   do {
566     sls_mu.Unlock();
567     sls_mu.Lock();  // \
568       // expected-note {{the other lock of mutex 'sls_mu' is here}}
569   } while (getBool());
570   sls_mu.Unlock();
571 }
572 
shared_fun_3()573 void shared_fun_3() {
574   if (getBool())
575     sls_mu.Lock();
576   else
577     sls_mu.Lock();
578   *pgb_var = 1;
579   sls_mu.Unlock();
580 }
581 
shared_fun_4()582 void shared_fun_4() {
583   if (getBool())
584     sls_mu.ReaderLock();
585   else
586     sls_mu.ReaderLock();
587   int x = sls_guardby_var;
588   sls_mu.Unlock();
589 }
590 
shared_fun_8()591 void shared_fun_8() {
592   if (getBool())
593     sls_mu.Lock(); // \
594       // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
595   else
596     sls_mu.ReaderLock(); // \
597       // expected-note {{the other lock of mutex 'sls_mu' is here}}
598   sls_mu.Unlock();
599 }
600 
shared_bad_0()601 void shared_bad_0() {
602   sls_mu.Lock();  // \
603     // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
604   do {
605     sls_mu.Unlock();
606     sls_mu.ReaderLock();  // \
607       // expected-note {{the other lock of mutex 'sls_mu' is here}}
608   } while (getBool());
609   sls_mu.Unlock();
610 }
611 
shared_bad_1()612 void shared_bad_1() {
613   if (getBool())
614     sls_mu.Lock(); // \
615       // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
616   else
617     sls_mu.ReaderLock(); // \
618       // expected-note {{the other lock of mutex 'sls_mu' is here}}
619   *pgb_var = 1;
620   sls_mu.Unlock();
621 }
622 
shared_bad_2()623 void shared_bad_2() {
624   if (getBool())
625     sls_mu.ReaderLock(); // \
626       // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
627   else
628     sls_mu.Lock(); // \
629       // expected-note {{the other lock of mutex 'sls_mu' is here}}
630   *pgb_var = 1;
631   sls_mu.Unlock();
632 }
633 
634 // FIXME: Add support for functions (not only methods)
635 class LRBar {
636  public:
637   void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
638   void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
639   void le_fun() __attribute__((locks_excluded(sls_mu)));
640 };
641 
642 class LRFoo {
643  public:
644   void test() __attribute__((exclusive_locks_required(sls_mu)));
645   void testShared() __attribute__((shared_locks_required(sls_mu2)));
646 };
647 
648 void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
elr_fun()649 void elr_fun() {}
650 
651 LRFoo MyLRFoo;
652 LRBar Bar;
653 
es_fun_0()654 void es_fun_0() {
655   aa_mu.Lock();
656   Bar.aa_elr_fun();
657   aa_mu.Unlock();
658 }
659 
es_fun_1()660 void es_fun_1() {
661   aa_mu.Lock();
662   Bar.aa_elr_fun_s();
663   aa_mu.Unlock();
664 }
665 
es_fun_2()666 void es_fun_2() {
667   aa_mu.ReaderLock();
668   Bar.aa_elr_fun_s();
669   aa_mu.Unlock();
670 }
671 
es_fun_3()672 void es_fun_3() {
673   sls_mu.Lock();
674   MyLRFoo.test();
675   sls_mu.Unlock();
676 }
677 
es_fun_4()678 void es_fun_4() {
679   sls_mu2.Lock();
680   MyLRFoo.testShared();
681   sls_mu2.Unlock();
682 }
683 
es_fun_5()684 void es_fun_5() {
685   sls_mu2.ReaderLock();
686   MyLRFoo.testShared();
687   sls_mu2.Unlock();
688 }
689 
es_fun_6()690 void es_fun_6() {
691   Bar.le_fun();
692 }
693 
es_fun_7()694 void es_fun_7() {
695   sls_mu.Lock();
696   elr_fun();
697   sls_mu.Unlock();
698 }
699 
700 void es_fun_8() __attribute__((no_thread_safety_analysis));
701 
es_fun_8()702 void es_fun_8() {
703   Bar.aa_elr_fun_s();
704 }
705 
706 void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
es_fun_9()707 void es_fun_9() {
708   Bar.aa_elr_fun_s();
709 }
710 
711 void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
es_fun_10()712 void es_fun_10() {
713   Bar.aa_elr_fun_s();
714 }
715 
es_bad_0()716 void es_bad_0() {
717   Bar.aa_elr_fun(); // \
718     // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
719 }
720 
es_bad_1()721 void es_bad_1() {
722   aa_mu.ReaderLock();
723   Bar.aa_elr_fun(); // \
724     // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
725   aa_mu.Unlock();
726 }
727 
es_bad_2()728 void es_bad_2() {
729   Bar.aa_elr_fun_s(); // \
730     // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
731 }
732 
es_bad_3()733 void es_bad_3() {
734   MyLRFoo.test(); // \
735     // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
736 }
737 
es_bad_4()738 void es_bad_4() {
739   MyLRFoo.testShared(); // \
740     // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
741 }
742 
es_bad_5()743 void es_bad_5() {
744   sls_mu.ReaderLock();
745   MyLRFoo.test(); // \
746     // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
747   sls_mu.Unlock();
748 }
749 
es_bad_6()750 void es_bad_6() {
751   sls_mu.Lock();
752   Bar.le_fun(); // \
753     // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
754   sls_mu.Unlock();
755 }
756 
es_bad_7()757 void es_bad_7() {
758   sls_mu.ReaderLock();
759   Bar.le_fun(); // \
760     // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
761   sls_mu.Unlock();
762 }
763 
764 
765 //-----------------------------------------------//
766 // Unparseable lock expressions
767 // ----------------------------------------------//
768 
769 // FIXME -- derive new tests for unhandled expressions
770 
771 
772 //----------------------------------------------------------------------------//
773 // The following test cases are ported from the gcc thread safety implementation
774 // They are each wrapped inside a namespace with the test number of the gcc test
775 //
776 // FIXME: add all the gcc tests, once this analysis passes them.
777 //----------------------------------------------------------------------------//
778 
779 //-----------------------------------------//
780 // Good testcases (no errors)
781 //-----------------------------------------//
782 
783 namespace thread_annot_lock_20 {
784 class Bar {
785  public:
786   static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
787   static int b_ GUARDED_BY(mu1_);
788   static Mutex mu1_;
789   static int a_ GUARDED_BY(mu1_);
790 };
791 
792 Bar b1;
793 
func1()794 int Bar::func1()
795 {
796   int res = 5;
797 
798   if (a_ == 4)
799     res = b_;
800   return res;
801 }
802 } // end namespace thread_annot_lock_20
803 
804 namespace thread_annot_lock_22 {
805 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
806 // uses in class definitions.
807 Mutex mu;
808 
809 class Bar {
810  public:
811   int a_ GUARDED_BY(mu1_);
812   int b_;
813   int *q PT_GUARDED_BY(mu);
814   Mutex mu1_ ACQUIRED_AFTER(mu);
815 };
816 
817 Bar b1, *b3;
818 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
819 int res GUARDED_BY(mu) = 5;
820 
func(int i)821 int func(int i)
822 {
823   int x;
824   mu.Lock();
825   b1.mu1_.Lock();
826   res = b1.a_ + b3->b_;
827   *p = i;
828   b1.a_ = res + b3->b_;
829   b3->b_ = *b1.q;
830   b1.mu1_.Unlock();
831   b1.b_ = res;
832   x = res;
833   mu.Unlock();
834   return x;
835 }
836 } // end namespace thread_annot_lock_22
837 
838 namespace thread_annot_lock_27_modified {
839 // test lock annotations applied to function definitions
840 // Modified: applied annotations only to function declarations
841 Mutex mu1;
842 Mutex mu2 ACQUIRED_AFTER(mu1);
843 
844 class Foo {
845  public:
846   int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
847 };
848 
method1(int i)849 int Foo::method1(int i) {
850   return i;
851 }
852 
853 
854 int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
foo(int i)855 int foo(int i) {
856   return i;
857 }
858 
859 static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
bar(int i)860 static int bar(int i) {
861   return i;
862 }
863 
main()864 void main() {
865   Foo a;
866 
867   mu1.Lock();
868   mu2.Lock();
869   a.method1(1);
870   foo(2);
871   mu2.Unlock();
872   bar(3);
873   mu1.Unlock();
874 }
875 } // end namespace thread_annot_lock_27_modified
876 
877 
878 namespace thread_annot_lock_38 {
879 // Test the case where a template member function is annotated with lock
880 // attributes in a non-template class.
881 class Foo {
882  public:
883   void func1(int y) LOCKS_EXCLUDED(mu_);
884   template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
885  private:
886   Mutex mu_;
887 };
888 
889 Foo *foo;
890 
main()891 void main()
892 {
893   foo->func1(5);
894   foo->func2(5);
895 }
896 } // end namespace thread_annot_lock_38
897 
898 namespace thread_annot_lock_43 {
899 // Tests lock canonicalization
900 class Foo {
901  public:
902   Mutex *mu_;
903 };
904 
905 class FooBar {
906  public:
907   Foo *foo_;
GetA()908   int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
909   int a_ GUARDED_BY(foo_->mu_);
910 };
911 
912 FooBar *fb;
913 
main()914 void main()
915 {
916   int x;
917   fb->foo_->mu_->Lock();
918   x = fb->GetA();
919   fb->foo_->mu_->Unlock();
920 }
921 } // end namespace thread_annot_lock_43
922 
923 namespace thread_annot_lock_49 {
924 // Test the support for use of lock expression in the annotations
925 class Foo {
926  public:
927   Mutex foo_mu_;
928 };
929 
930 class Bar {
931  private:
932   Foo *foo;
933   Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
934 
935  public:
Test1()936   void Test1() {
937     foo->foo_mu_.Lock();
938     bar_mu_.Lock();
939     bar_mu_.Unlock();
940     foo->foo_mu_.Unlock();
941   }
942 };
943 
main()944 void main() {
945   Bar bar;
946   bar.Test1();
947 }
948 } // end namespace thread_annot_lock_49
949 
950 namespace thread_annot_lock_61_modified {
951   // Modified to fix the compiler errors
952   // Test the fix for a bug introduced by the support of pass-by-reference
953   // paramters.
operator <<thread_annot_lock_61_modified::Foo954   struct Foo { Foo &operator<< (bool) {return *this;} };
955   Foo &getFoo();
functhread_annot_lock_61_modified::Bar956   struct Bar { Foo &func () {return getFoo();} };
operator &thread_annot_lock_61_modified::Bas957   struct Bas { void operator& (Foo &) {} };
mumble()958   void mumble()
959   {
960     Bas() & Bar().func() << "" << "";
961     Bas() & Bar().func() << "";
962   }
963 } // end namespace thread_annot_lock_61_modified
964 
965 
966 namespace thread_annot_lock_65 {
967 // Test the fix for a bug in the support of allowing reader locks for
968 // non-const, non-modifying overload functions. (We didn't handle the builtin
969 // properly.)
970 enum MyFlags {
971   Zero,
972   One,
973   Two,
974   Three,
975   Four,
976   Five,
977   Six,
978   Seven,
979   Eight,
980   Nine
981 };
982 
983 inline MyFlags
operator |(MyFlags a,MyFlags b)984 operator|(MyFlags a, MyFlags b)
985 {
986   return MyFlags(static_cast<int>(a) | static_cast<int>(b));
987 }
988 
989 inline MyFlags&
operator |=(MyFlags & a,MyFlags b)990 operator|=(MyFlags& a, MyFlags b)
991 {
992     return a = a | b;
993 }
994 } // end namespace thread_annot_lock_65
995 
996 namespace thread_annot_lock_66_modified {
997 // Modified: Moved annotation to function defn
998 // Test annotations on out-of-line definitions of member functions where the
999 // annotations refer to locks that are also data members in the class.
1000 Mutex mu;
1001 
1002 class Foo {
1003  public:
1004   int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1005   int data GUARDED_BY(mu1);
1006   Mutex *mu1;
1007   Mutex *mu2;
1008 };
1009 
method1(int i)1010 int Foo::method1(int i)
1011 {
1012   return data + i;
1013 }
1014 
main()1015 void main()
1016 {
1017   Foo a;
1018 
1019   a.mu2->Lock();
1020   a.mu1->Lock();
1021   mu.Lock();
1022   a.method1(1);
1023   mu.Unlock();
1024   a.mu1->Unlock();
1025   a.mu2->Unlock();
1026 }
1027 } // end namespace thread_annot_lock_66_modified
1028 
1029 namespace thread_annot_lock_68_modified {
1030 // Test a fix to a bug in the delayed name binding with nested template
1031 // instantiation. We use a stack to make sure a name is not resolved to an
1032 // inner context.
1033 template <typename T>
1034 class Bar {
1035   Mutex mu_;
1036 };
1037 
1038 template <typename T>
1039 class Foo {
1040  public:
func(T x)1041   void func(T x) {
1042     mu_.Lock();
1043     count_ = x;
1044     mu_.Unlock();
1045   }
1046 
1047  private:
1048   T count_ GUARDED_BY(mu_);
1049   Bar<T> bar_;
1050   Mutex mu_;
1051 };
1052 
main()1053 void main()
1054 {
1055   Foo<int> *foo;
1056   foo->func(5);
1057 }
1058 } // end namespace thread_annot_lock_68_modified
1059 
1060 namespace thread_annot_lock_30_modified {
1061 // Test delay parsing of lock attribute arguments with nested classes.
1062 // Modified: trylocks replaced with exclusive_lock_fun
1063 int a = 0;
1064 
1065 class Bar {
1066   struct Foo;
1067 
1068  public:
1069   void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1070 
func()1071   int func() {
1072     MyLock();
1073 //    if (foo == 0) {
1074 //      return 0;
1075 //    }
1076     a = 5;
1077     mu.Unlock();
1078     return 1;
1079   }
1080 
1081   class FooBar {
1082     int x;
1083     int y;
1084   };
1085 
1086  private:
1087   Mutex mu;
1088 };
1089 
1090 Bar *bar;
1091 
main()1092 void main()
1093 {
1094   bar->func();
1095 }
1096 } // end namespace thread_annot_lock_30_modified
1097 
1098 namespace thread_annot_lock_47 {
1099 // Test the support for annotations on virtual functions.
1100 // This is a good test case. (i.e. There should be no warning emitted by the
1101 // compiler.)
1102 class Base {
1103  public:
1104   virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1105   virtual void func2() LOCKS_EXCLUDED(mu_);
1106   Mutex mu_;
1107 };
1108 
1109 class Child : public Base {
1110  public:
1111   virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1112   virtual void func2() LOCKS_EXCLUDED(mu_);
1113 };
1114 
main()1115 void main() {
1116   Child *c;
1117   Base *b = c;
1118 
1119   b->mu_.Lock();
1120   b->func1();
1121   b->mu_.Unlock();
1122   b->func2();
1123 
1124   c->mu_.Lock();
1125   c->func1();
1126   c->mu_.Unlock();
1127   c->func2();
1128 }
1129 } // end namespace thread_annot_lock_47
1130 
1131 //-----------------------------------------//
1132 // Tests which produce errors
1133 //-----------------------------------------//
1134 
1135 namespace thread_annot_lock_13 {
1136 Mutex mu1;
1137 Mutex mu2;
1138 
1139 int g GUARDED_BY(mu1);
1140 int w GUARDED_BY(mu2);
1141 
1142 class Foo {
1143  public:
1144   void bar() LOCKS_EXCLUDED(mu_, mu1);
1145   int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1146 
1147  private:
1148   int a_ GUARDED_BY(mu_);
1149  public:
1150   Mutex mu_ ACQUIRED_AFTER(mu1);
1151 };
1152 
foo()1153 int Foo::foo()
1154 {
1155   int res;
1156   w = 5;
1157   res = a_ + 5;
1158   return res;
1159 }
1160 
bar()1161 void Foo::bar()
1162 {
1163   int x;
1164   mu_.Lock();
1165   x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1166   a_ = x + 1;
1167   mu_.Unlock();
1168   if (x > 5) {
1169     mu1.Lock();
1170     g = 2;
1171     mu1.Unlock();
1172   }
1173 }
1174 
main()1175 void main()
1176 {
1177   Foo f1, *f2;
1178   f1.mu_.Lock();
1179   f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
1180   mu2.Lock();
1181   f1.foo();
1182   mu2.Unlock();
1183   f1.mu_.Unlock();
1184   f2->mu_.Lock();
1185   f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
1186   f2->mu_.Unlock();
1187   mu2.Lock();
1188   w = 2;
1189   mu2.Unlock();
1190 }
1191 } // end namespace thread_annot_lock_13
1192 
1193 namespace thread_annot_lock_18_modified {
1194 // Modified: Trylocks removed
1195 // Test the ability to distnguish between the same lock field of
1196 // different objects of a class.
1197   class Bar {
1198  public:
1199   bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1200   void MyUnlock() UNLOCK_FUNCTION(mu1_);
1201   int a_ GUARDED_BY(mu1_);
1202 
1203  private:
1204   Mutex mu1_;
1205 };
1206 
1207 Bar *b1, *b2;
1208 
func()1209 void func()
1210 {
1211   b1->MyLock();
1212   b1->a_ = 5;
1213   b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1214   b2->MyLock();
1215   b2->MyUnlock();
1216   b1->MyUnlock();
1217 }
1218 } // end namespace thread_annot_lock_18_modified
1219 
1220 namespace thread_annot_lock_21 {
1221 // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1222 // uses in class definitions.
1223 Mutex mu;
1224 
1225 class Bar {
1226  public:
1227   int a_ GUARDED_BY(mu1_);
1228   int b_;
1229   int *q PT_GUARDED_BY(mu);
1230   Mutex mu1_ ACQUIRED_AFTER(mu);
1231 };
1232 
1233 Bar b1, *b3;
1234 int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1235 
1236 int res GUARDED_BY(mu) = 5;
1237 
func(int i)1238 int func(int i)
1239 {
1240   int x;
1241   b3->mu1_.Lock();
1242   res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1243     // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1244   *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1245     // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1246   b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1247     // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1248   b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
1249   b3->mu1_.Unlock();
1250   b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1251   x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1252   return x;
1253 }
1254 } // end namespace thread_annot_lock_21
1255 
1256 namespace thread_annot_lock_35_modified {
1257 // Test the analyzer's ability to distinguish the lock field of different
1258 // objects.
1259 class Foo {
1260  private:
1261   Mutex lock_;
1262   int a_ GUARDED_BY(lock_);
1263 
1264  public:
Func(Foo * child)1265   void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1266      Foo *new_foo = new Foo;
1267 
1268      lock_.Lock();
1269 
1270      child->Func(new_foo); // There shouldn't be any warning here as the
1271                            // acquired lock is not in child.
1272      child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
1273      child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
1274      lock_.Unlock();
1275   }
1276 
bar(int y)1277   void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1278     a_ = y;
1279   }
1280 };
1281 
1282 Foo *x;
1283 
main()1284 void main() {
1285   Foo *child = new Foo;
1286   x->Func(child);
1287 }
1288 } // end namespace thread_annot_lock_35_modified
1289 
1290 namespace thread_annot_lock_36_modified {
1291 // Modified to move the annotations to function defns.
1292 // Test the analyzer's ability to distinguish the lock field of different
1293 // objects
1294 class Foo {
1295  private:
1296   Mutex lock_;
1297   int a_ GUARDED_BY(lock_);
1298 
1299  public:
1300   void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1301   void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1302 };
1303 
Func(Foo * child)1304 void Foo::Func(Foo* child) {
1305   Foo *new_foo = new Foo;
1306 
1307   lock_.Lock();
1308 
1309   child->lock_.Lock();
1310   child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
1311   child->bar(7);
1312   child->a_ = 5;
1313   child->lock_.Unlock();
1314 
1315   lock_.Unlock();
1316 }
1317 
bar(int y)1318 void Foo::bar(int y) {
1319   a_ = y;
1320 }
1321 
1322 
1323 Foo *x;
1324 
main()1325 void main() {
1326   Foo *child = new Foo;
1327   x->Func(child);
1328 }
1329 } // end namespace thread_annot_lock_36_modified
1330 
1331 
1332 namespace thread_annot_lock_42 {
1333 // Test support of multiple lock attributes of the same kind on a decl.
1334 class Foo {
1335  private:
1336   Mutex mu1, mu2, mu3;
1337   int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1338   int y GUARDED_BY(mu2);
1339 
f2()1340   void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1341     mu2.Lock();
1342     y = 2;
1343     mu2.Unlock();
1344   }
1345 
1346  public:
f1()1347   void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1348     x = 5;
1349     f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1350       // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
1351   }
1352 };
1353 
1354 Foo *foo;
1355 
func()1356 void func()
1357 {
1358   foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1359     // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1360 }
1361 } // end namespace thread_annot_lock_42
1362 
1363 namespace thread_annot_lock_46 {
1364 // Test the support for annotations on virtual functions.
1365 class Base {
1366  public:
1367   virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1368   virtual void func2() LOCKS_EXCLUDED(mu_);
1369   Mutex mu_;
1370 };
1371 
1372 class Child : public Base {
1373  public:
1374   virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1375   virtual void func2() LOCKS_EXCLUDED(mu_);
1376 };
1377 
main()1378 void main() {
1379   Child *c;
1380   Base *b = c;
1381 
1382   b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1383   b->mu_.Lock();
1384   b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
1385   b->mu_.Unlock();
1386 
1387   c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1388   c->mu_.Lock();
1389   c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
1390   c->mu_.Unlock();
1391 }
1392 } // end namespace thread_annot_lock_46
1393 
1394 namespace thread_annot_lock_67_modified {
1395 // Modified: attributes on definitions moved to declarations
1396 // Test annotations on out-of-line definitions of member functions where the
1397 // annotations refer to locks that are also data members in the class.
1398 Mutex mu;
1399 Mutex mu3;
1400 
1401 class Foo {
1402  public:
1403   int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1404   int data GUARDED_BY(mu1);
1405   Mutex *mu1;
1406   Mutex *mu2;
1407 };
1408 
method1(int i)1409 int Foo::method1(int i) {
1410   return data + i;
1411 }
1412 
main()1413 void main()
1414 {
1415   Foo a;
1416   a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1417     // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1418     // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1419     // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1420 }
1421 } // end namespace thread_annot_lock_67_modified
1422 
1423 
1424 namespace substitution_test {
1425   class MyData  {
1426   public:
1427     Mutex mu;
1428 
lockData()1429     void lockData()    __attribute__((exclusive_lock_function(mu)))   { }
unlockData()1430     void unlockData()  __attribute__((unlock_function(mu)))           { }
1431 
doSomething()1432     void doSomething() __attribute__((exclusive_locks_required(mu)))  { }
1433   };
1434 
1435 
1436   class DataLocker {
1437   public:
lockData(MyData * d)1438     void lockData  (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
unlockData(MyData * d)1439     void unlockData(MyData *d) __attribute__((unlock_function(d->mu)))         { }
1440   };
1441 
1442 
1443   class Foo {
1444   public:
foo(MyData * d)1445     void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1446 
bar1(MyData * d)1447     void bar1(MyData* d) {
1448       d->lockData();
1449       foo(d);
1450       d->unlockData();
1451     }
1452 
bar2(MyData * d)1453     void bar2(MyData* d) {
1454       DataLocker dlr;
1455       dlr.lockData(d);
1456       foo(d);
1457       dlr.unlockData(d);
1458     }
1459 
bar3(MyData * d1,MyData * d2)1460     void bar3(MyData* d1, MyData* d2) {
1461       DataLocker dlr;
1462       dlr.lockData(d1);   // expected-note {{mutex acquired here}}
1463       dlr.unlockData(d2); // \
1464         // expected-warning {{unlocking 'mu' that was not locked}}
1465     } // expected-warning {{mutex 'mu' is still locked at the end of function}}
1466 
bar4(MyData * d1,MyData * d2)1467     void bar4(MyData* d1, MyData* d2) {
1468       DataLocker dlr;
1469       dlr.lockData(d1);
1470       foo(d2); // \
1471         // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1472       dlr.unlockData(d1);
1473     }
1474   };
1475 } // end namespace substituation_test
1476 
1477 
1478 
1479 namespace constructor_destructor_tests {
1480   Mutex fooMu;
1481   int myVar GUARDED_BY(fooMu);
1482 
1483   class Foo {
1484   public:
Foo()1485     Foo()  __attribute__((exclusive_lock_function(fooMu))) { }
~Foo()1486     ~Foo() __attribute__((unlock_function(fooMu))) { }
1487   };
1488 
fooTest()1489   void fooTest() {
1490     Foo foo;
1491     myVar = 0;
1492   }
1493 }
1494 
1495 
1496 namespace invalid_lock_expression_test {
1497 
1498 class LOCKABLE MyLockable {
1499 public:
MyLockable()1500   MyLockable() __attribute__((exclusive_lock_function)) { }
~MyLockable()1501   ~MyLockable() { }
1502 };
1503 
1504 // create an empty lock expression
foo()1505 void foo() {
1506   MyLockable lock;  // \
1507     // expected-warning {{cannot resolve lock expression}}
1508 }
1509 
1510 } // end namespace invalid_lock_expression_test
1511 
1512 namespace template_member_test {
1513 
1514   struct S { int n; };
1515   struct T {
1516     Mutex m;
1517     S *s GUARDED_BY(this->m);
1518   };
1519   Mutex m;
1520   struct U {
1521     union {
1522       int n;
1523     };
1524   } *u GUARDED_BY(m);
1525 
1526   template<typename U>
1527   struct IndirectLock {
DoNaughtyThingstemplate_member_test::IndirectLock1528     int DoNaughtyThings(T *t) {
1529       u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
1530       return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1531     }
1532   };
1533 
1534   template struct IndirectLock<int>; // expected-note {{here}}
1535 
1536   struct V {
1537     void f(int);
1538     void f(double);
1539 
1540     Mutex m;
1541     V *p GUARDED_BY(this->m);
1542   };
1543   template<typename U> struct W {
1544     V v;
ftemplate_member_test::W1545     void f(U u) {
1546       v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1547     }
1548   };
1549   template struct W<int>; // expected-note {{here}}
1550 
1551 }
1552 
1553 namespace test_scoped_lockable {
1554 
1555 struct TestScopedLockable {
1556   Mutex mu1;
1557   Mutex mu2;
1558   int a __attribute__((guarded_by(mu1)));
1559   int b __attribute__((guarded_by(mu2)));
1560 
1561   bool getBool();
1562 
foo1test_scoped_lockable::TestScopedLockable1563   void foo1() {
1564     MutexLock mulock(&mu1);
1565     a = 5;
1566   }
1567 
foo2test_scoped_lockable::TestScopedLockable1568   void foo2() {
1569     ReaderMutexLock mulock1(&mu1);
1570     if (getBool()) {
1571       MutexLock mulock2a(&mu2);
1572       b = a + 1;
1573     }
1574     else {
1575       MutexLock mulock2b(&mu2);
1576       b = a + 2;
1577     }
1578   }
1579 
foo3test_scoped_lockable::TestScopedLockable1580   void foo3() {
1581     MutexLock mulock_a(&mu1);
1582     MutexLock mulock_b(&mu1); // \
1583       // expected-warning {{locking 'mu1' that is already locked}}
1584   }   // expected-warning {{unlocking 'mu1' that was not locked}}
1585 
foo4test_scoped_lockable::TestScopedLockable1586   void foo4() {
1587     MutexLock mulock1(&mu1), mulock2(&mu2);
1588     a = b+1;
1589     b = a+1;
1590   }
1591 };
1592 
1593 } // end namespace test_scoped_lockable
1594 
1595 
1596 namespace FunctionAttrTest {
1597 
1598 class Foo {
1599 public:
1600   Mutex mu_;
1601   int a GUARDED_BY(mu_);
1602 };
1603 
1604 Foo fooObj;
1605 
1606 void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1607 
bar()1608 void bar() {
1609   foo();  // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1610   fooObj.mu_.Lock();
1611   foo();
1612   fooObj.mu_.Unlock();
1613 }
1614 
1615 };  // end namespace FunctionAttrTest
1616 
1617 
1618 struct TestTryLock {
1619   Mutex mu;
1620   int a GUARDED_BY(mu);
1621   bool cond;
1622 
foo1TestTryLock1623   void foo1() {
1624     if (mu.TryLock()) {
1625       a = 1;
1626       mu.Unlock();
1627     }
1628   }
1629 
foo2TestTryLock1630   void foo2() {
1631     if (!mu.TryLock()) return;
1632     a = 2;
1633     mu.Unlock();
1634   }
1635 
foo3TestTryLock1636   void foo3() {
1637     bool b = mu.TryLock();
1638     if (b) {
1639       a = 3;
1640       mu.Unlock();
1641     }
1642   }
1643 
foo4TestTryLock1644   void foo4() {
1645     bool b = mu.TryLock();
1646     if (!b) return;
1647     a = 4;
1648     mu.Unlock();
1649   }
1650 
foo5TestTryLock1651   void foo5() {
1652     while (mu.TryLock()) {
1653       a = a + 1;
1654       mu.Unlock();
1655     }
1656   }
1657 
foo6TestTryLock1658   void foo6() {
1659     bool b = mu.TryLock();
1660     b = !b;
1661     if (b) return;
1662     a = 6;
1663     mu.Unlock();
1664   }
1665 
foo7TestTryLock1666   void foo7() {
1667     bool b1 = mu.TryLock();
1668     bool b2 = !b1;
1669     bool b3 = !b2;
1670     if (b3) {
1671       a = 7;
1672       mu.Unlock();
1673     }
1674   }
1675 
1676   // Test use-def chains: join points
foo8TestTryLock1677   void foo8() {
1678     bool b  = mu.TryLock();
1679     bool b2 = b;
1680     if (cond)
1681       b = true;
1682     if (b) {    // b should be unknown at this point, becuase of the join point
1683       a = 8;    // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1684     }
1685     if (b2) {   // b2 should be known at this point.
1686       a = 8;
1687       mu.Unlock();
1688     }
1689   }
1690 
1691   // Test use-def-chains: back edges
foo9TestTryLock1692   void foo9() {
1693     bool b = mu.TryLock();
1694 
1695     for (int i = 0; i < 10; ++i);
1696 
1697     if (b) {  // b is still known, because the loop doesn't alter it
1698       a = 9;
1699       mu.Unlock();
1700     }
1701   }
1702 
1703   // Test use-def chains: back edges
foo10TestTryLock1704   void foo10() {
1705     bool b = mu.TryLock();
1706 
1707     while (cond) {
1708       if (b) {   // b should be uknown at this point b/c of the loop
1709         a = 10;  // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1710       }
1711       b = !b;
1712     }
1713   }
1714 };  // end TestTrylock
1715 
1716 
1717 namespace TestTemplateAttributeInstantiation {
1718 
1719 class Foo1 {
1720 public:
1721   Mutex mu_;
1722   int a GUARDED_BY(mu_);
1723 };
1724 
1725 class Foo2 {
1726 public:
1727   int a GUARDED_BY(mu_);
1728   Mutex mu_;
1729 };
1730 
1731 
1732 class Bar {
1733 public:
1734   // Test non-dependent expressions in attributes on template functions
1735   template <class T>
barND(Foo1 * foo,T * fooT)1736   void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1737     foo->a = 0;
1738   }
1739 
1740   // Test dependent expressions in attributes on template functions
1741   template <class T>
barD(Foo1 * foo,T * fooT)1742   void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1743     fooT->a = 0;
1744   }
1745 };
1746 
1747 
1748 template <class T>
1749 class BarT {
1750 public:
1751   Foo1 fooBase;
1752   T    fooBaseT;
1753 
1754   // Test non-dependent expression in ordinary method on template class
barND()1755   void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1756     fooBase.a = 0;
1757   }
1758 
1759   // Test dependent expressions in ordinary methods on template class
barD()1760   void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1761     fooBaseT.a = 0;
1762   }
1763 
1764   // Test dependent expressions in template method in template class
1765   template <class T2>
barTD(T2 * fooT)1766   void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1767     fooBaseT.a = 0;
1768     fooT->a = 0;
1769   }
1770 };
1771 
1772 template <class T>
1773 class Cell {
1774 public:
1775   Mutex mu_;
1776   // Test dependent guarded_by
1777   T data GUARDED_BY(mu_);
1778 
fooEx()1779   void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1780     data = 0;
1781   }
1782 
foo()1783   void foo() {
1784     mu_.Lock();
1785     data = 0;
1786     mu_.Unlock();
1787   }
1788 };
1789 
test()1790 void test() {
1791   Bar b;
1792   BarT<Foo2> bt;
1793   Foo1 f1;
1794   Foo2 f2;
1795 
1796   f1.mu_.Lock();
1797   f2.mu_.Lock();
1798   bt.fooBase.mu_.Lock();
1799   bt.fooBaseT.mu_.Lock();
1800 
1801   b.barND(&f1, &f2);
1802   b.barD(&f1, &f2);
1803   bt.barND();
1804   bt.barD();
1805   bt.barTD(&f2);
1806 
1807   f1.mu_.Unlock();
1808   bt.barTD(&f1);  // \
1809     // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1810 
1811   bt.fooBase.mu_.Unlock();
1812   bt.fooBaseT.mu_.Unlock();
1813   f2.mu_.Unlock();
1814 
1815   Cell<int> cell;
1816   cell.data = 0; // \
1817     // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1818   cell.foo();
1819   cell.mu_.Lock();
1820   cell.fooEx();
1821   cell.mu_.Unlock();
1822 }
1823 
1824 
1825 template <class T>
1826 class CellDelayed {
1827 public:
1828   // Test dependent guarded_by
1829   T data GUARDED_BY(mu_);
1830   static T static_data GUARDED_BY(static_mu_);
1831 
fooEx(CellDelayed<T> * other)1832   void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1833     this->data = other->data;
1834   }
1835 
1836   template <class T2>
fooExT(CellDelayed<T2> * otherT)1837   void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1838     this->data = otherT->data;
1839   }
1840 
foo()1841   void foo() {
1842     mu_.Lock();
1843     data = 0;
1844     mu_.Unlock();
1845   }
1846 
1847   Mutex mu_;
1848   static Mutex static_mu_;
1849 };
1850 
testDelayed()1851 void testDelayed() {
1852   CellDelayed<int> celld;
1853   CellDelayed<int> celld2;
1854   celld.foo();
1855   celld.mu_.Lock();
1856   celld2.mu_.Lock();
1857 
1858   celld.fooEx(&celld2);
1859   celld.fooExT(&celld2);
1860 
1861   celld2.mu_.Unlock();
1862   celld.mu_.Unlock();
1863 }
1864 
1865 };  // end namespace TestTemplateAttributeInstantiation
1866 
1867 
1868 namespace FunctionDeclDefTest {
1869 
1870 class Foo {
1871 public:
1872   Mutex mu_;
1873   int a GUARDED_BY(mu_);
1874 
1875   virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1876 };
1877 
1878 // EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
foo1(Foo * f_defined)1879 void Foo::foo1(Foo *f_defined) {
1880   f_defined->a = 0;
1881 };
1882 
test()1883 void test() {
1884   Foo myfoo;
1885   myfoo.foo1(&myfoo);  // \
1886     // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1887   myfoo.mu_.Lock();
1888   myfoo.foo1(&myfoo);
1889   myfoo.mu_.Unlock();
1890 }
1891 
1892 };
1893 
1894 namespace GoingNative {
1895 
1896   struct __attribute__((lockable)) mutex {
1897     void lock() __attribute__((exclusive_lock_function));
1898     void unlock() __attribute__((unlock_function));
1899     // ...
1900   };
1901   bool foo();
1902   bool bar();
1903   mutex m;
test()1904   void test() {
1905     m.lock();
1906     while (foo()) {
1907       m.unlock();
1908       // ...
1909       if (bar()) {
1910         // ...
1911         if (foo())
1912           continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1913         //...
1914       }
1915       // ...
1916       m.lock(); // expected-note {{mutex acquired here}}
1917     }
1918     m.unlock();
1919   }
1920 
1921 }
1922 
1923 
1924 
1925 namespace FunctionDefinitionTest {
1926 
1927 class Foo {
1928 public:
1929   void foo1();
1930   void foo2();
1931   void foo3(Foo *other);
1932 
1933   template<class T>
1934   void fooT1(const T& dummy1);
1935 
1936   template<class T>
1937   void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1938 
1939   Mutex mu_;
1940   int a GUARDED_BY(mu_);
1941 };
1942 
1943 template<class T>
1944 class FooT {
1945 public:
1946   void foo();
1947 
1948   Mutex mu_;
1949   T a GUARDED_BY(mu_);
1950 };
1951 
1952 
foo1()1953 void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1954   a = 1;
1955 }
1956 
foo2()1957 void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1958   a = 2;
1959 }
1960 
foo3(Foo * other)1961 void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1962   other->a = 3;
1963 }
1964 
1965 template<class T>
fooT1(const T & dummy1)1966 void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1967   a = dummy1;
1968 }
1969 
1970 /* TODO -- uncomment with template instantiation of attributes.
1971 template<class T>
1972 void Foo::fooT2(const T& dummy2) {
1973   a = dummy2;
1974 }
1975 */
1976 
fooF1(Foo * f)1977 void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1978   f->a = 1;
1979 }
1980 
1981 void fooF2(Foo *f);
fooF2(Foo * f)1982 void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1983   f->a = 2;
1984 }
1985 
1986 void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
fooF3(Foo * f)1987 void fooF3(Foo *f) {
1988   f->a = 3;
1989 }
1990 
1991 template<class T>
foo()1992 void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1993   a = 0;
1994 }
1995 
test()1996 void test() {
1997   int dummy = 0;
1998   Foo myFoo;
1999 
2000   myFoo.foo2();        // \
2001     // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2002   myFoo.foo3(&myFoo);  // \
2003     // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2004   myFoo.fooT1(dummy);  // \
2005     // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2006 
2007   // FIXME: uncomment with template instantiation of attributes patch
2008   // myFoo.fooT2(dummy);  // expected warning
2009 
2010   fooF1(&myFoo);  // \
2011     // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2012   fooF2(&myFoo);  // \
2013     // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2014   fooF3(&myFoo);  // \
2015     // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2016 
2017   myFoo.mu_.Lock();
2018   myFoo.foo2();
2019   myFoo.foo3(&myFoo);
2020   myFoo.fooT1(dummy);
2021 
2022   // FIXME: uncomment with template instantiation of attributes patch
2023   // myFoo.fooT2(dummy);
2024 
2025   fooF1(&myFoo);
2026   fooF2(&myFoo);
2027   fooF3(&myFoo);
2028   myFoo.mu_.Unlock();
2029 
2030   FooT<int> myFooT;
2031   myFooT.foo();  // \
2032     // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2033 }
2034 
2035 } // end namespace FunctionDefinitionTest
2036 
2037 
2038 namespace SelfLockingTest {
2039 
2040 class LOCKABLE MyLock {
2041 public:
2042   int foo GUARDED_BY(this);
2043 
2044   void lock()   EXCLUSIVE_LOCK_FUNCTION();
2045   void unlock() UNLOCK_FUNCTION();
2046 
doSomething()2047   void doSomething() {
2048     this->lock();  // allow 'this' as a lock expression
2049     foo = 0;
2050     doSomethingElse();
2051     this->unlock();
2052   }
2053 
doSomethingElse()2054   void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2055     foo = 1;
2056   };
2057 
test()2058   void test() {
2059     foo = 2;  // \
2060       // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2061   }
2062 };
2063 
2064 
2065 class LOCKABLE MyLock2 {
2066 public:
2067   Mutex mu_;
2068   int foo GUARDED_BY(this);
2069 
2070   // don't check inside lock and unlock functions
lock()2071   void lock()   EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock();   }
unlock()2072   void unlock() UNLOCK_FUNCTION()         { mu_.Unlock(); }
2073 
2074   // don't check inside constructors and destructors
MyLock2()2075   MyLock2()  { foo = 1; }
~MyLock2()2076   ~MyLock2() { foo = 0; }
2077 };
2078 
2079 
2080 } // end namespace SelfLockingTest
2081 
2082 
2083 namespace InvalidNonstatic {
2084 
2085 // Forward decl here causes bogus "invalid use of non-static data member"
2086 // on reference to mutex_ in guarded_by attribute.
2087 class Foo;
2088 
2089 class Foo {
2090   Mutex* mutex_;
2091 
2092   int foo __attribute__((guarded_by(mutex_)));
2093 };
2094 
2095 }  // end namespace InvalidNonStatic
2096 
2097 
2098 namespace NoReturnTest {
2099 
2100 bool condition();
2101 void fatal() __attribute__((noreturn));
2102 
2103 Mutex mu_;
2104 
test1()2105 void test1() {
2106   MutexLock lock(&mu_);
2107   if (condition()) {
2108     fatal();
2109     return;
2110   }
2111 }
2112 
2113 } // end namespace NoReturnTest
2114 
2115 
2116 namespace TestMultiDecl {
2117 
2118 class Foo {
2119 public:
2120   int GUARDED_BY(mu_) a;
2121   int GUARDED_BY(mu_) b, c;
2122 
foo()2123   void foo() {
2124     a = 0; // \
2125       // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2126     b = 0; // \
2127       // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2128     c = 0; // \
2129       // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2130   }
2131 
2132 private:
2133   Mutex mu_;
2134 };
2135 
2136 } // end namespace TestMultiDecl
2137 
2138 
2139 namespace WarnNoDecl {
2140 
2141 class Foo {
2142   void foo(int a);  __attribute__(( // \
2143     // expected-warning {{declaration does not declare anything}}
2144     exclusive_locks_required(a))); // \
2145     // expected-warning {{attribute exclusive_locks_required ignored}}
2146 };
2147 
2148 } // end namespace WarnNoDecl
2149 
2150 
2151 
2152 namespace MoreLockExpressions {
2153 
2154 class Foo {
2155 public:
2156   Mutex mu_;
2157   int a GUARDED_BY(mu_);
2158 };
2159 
2160 class Bar {
2161 public:
2162   int b;
2163   Foo* f;
2164 
getFoo()2165   Foo& getFoo()              { return *f; }
getFoo2(int c)2166   Foo& getFoo2(int c)        { return *f; }
getFoo3(int c,int d)2167   Foo& getFoo3(int c, int d) { return *f; }
2168 
getFooey()2169   Foo& getFooey() { return *f; }
2170 };
2171 
getBarFoo(Bar & bar,int c)2172 Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2173 
test()2174 void test() {
2175   Foo foo;
2176   Foo *fooArray;
2177   Bar bar;
2178   int a;
2179   int b;
2180   int c;
2181 
2182   bar.getFoo().mu_.Lock();
2183   bar.getFoo().a = 0;
2184   bar.getFoo().mu_.Unlock();
2185 
2186   (bar.getFoo().mu_).Lock();   // test parenthesis
2187   bar.getFoo().a = 0;
2188   (bar.getFoo().mu_).Unlock();
2189 
2190   bar.getFoo2(a).mu_.Lock();
2191   bar.getFoo2(a).a = 0;
2192   bar.getFoo2(a).mu_.Unlock();
2193 
2194   bar.getFoo3(a, b).mu_.Lock();
2195   bar.getFoo3(a, b).a = 0;
2196   bar.getFoo3(a, b).mu_.Unlock();
2197 
2198   getBarFoo(bar, a).mu_.Lock();
2199   getBarFoo(bar, a).a = 0;
2200   getBarFoo(bar, a).mu_.Unlock();
2201 
2202   bar.getFoo2(10).mu_.Lock();
2203   bar.getFoo2(10).a = 0;
2204   bar.getFoo2(10).mu_.Unlock();
2205 
2206   bar.getFoo2(a + 1).mu_.Lock();
2207   bar.getFoo2(a + 1).a = 0;
2208   bar.getFoo2(a + 1).mu_.Unlock();
2209 
2210   (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2211   (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2212   (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2213 
2214   bar.getFoo().mu_.Lock();
2215   bar.getFooey().a = 0; // \
2216     // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2217   bar.getFoo().mu_.Unlock();
2218 
2219   bar.getFoo2(a).mu_.Lock();
2220   bar.getFoo2(b).a = 0; // \
2221     // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2222   bar.getFoo2(a).mu_.Unlock();
2223 
2224   bar.getFoo3(a, b).mu_.Lock();
2225   bar.getFoo3(a, c).a = 0;  // \
2226     // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2227   bar.getFoo3(a, b).mu_.Unlock();
2228 
2229   getBarFoo(bar, a).mu_.Lock();
2230   getBarFoo(bar, b).a = 0;  // \
2231     // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2232   getBarFoo(bar, a).mu_.Unlock();
2233 
2234   (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2235   (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2236     // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2237   (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2238 }
2239 
2240 
2241 } // end namespace
2242 
2243 
2244