1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
3 
4 // FIXME: should also run  %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
5 // FIXME: should also run  %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
6 
7 #include "thread-safety-annotations.h"
8 
9 class LOCKABLE Mutex {
10  public:
11   void Lock() EXCLUSIVE_LOCK_FUNCTION();
12   void ReaderLock() SHARED_LOCK_FUNCTION();
13   void Unlock() UNLOCK_FUNCTION();
14   bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
15   bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
16 
17   // for negative capabilities
operator !() const18   const Mutex& operator!() const { return *this; }
19 
20   void AssertHeld()       ASSERT_EXCLUSIVE_LOCK();
21   void AssertReaderHeld() ASSERT_SHARED_LOCK();
22 };
23 
24 
25 namespace SimpleTest {
26 
27 class Bar {
28   Mutex mu;
29   int a GUARDED_BY(mu);
30 
31 public:
baz()32   void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
33     mu.Lock();
34     a = 0;
35     mu.Unlock();
36   }
37 };
38 
39 
40 class Foo {
41   Mutex mu;
42   int a GUARDED_BY(mu);
43 
44 public:
foo()45   void foo() {
46     mu.Lock();    // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
47     baz();        // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
48     bar();
49     mu.Unlock();
50   }
51 
bar()52   void bar() {
53     baz();        // expected-warning {{calling function 'baz' requires holding  '!mu'}}
54   }
55 
baz()56   void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
57     mu.Lock();
58     a = 0;
59     mu.Unlock();
60   }
61 
test()62   void test() {
63     Bar b;
64     b.baz();     // no warning -- in different class.
65   }
66 
test2()67   void test2() {
68     mu.Lock();   // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
69     a = 0;
70     mu.Unlock();
71     baz();       // no warning -- !mu in set.
72   }
73 
test3()74   void test3() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
75     mu.Lock();
76     a = 0;
77     mu.Unlock();
78     baz();       // no warning -- !mu in set.
79   }
80 };
81 
82 }  // end namespace SimpleTest
83 
84 namespace DoubleAttribute {
85 
86 struct Foo {
87   Mutex &mutex();
88 };
89 
90 template <typename A>
91 class TemplateClass {
92   template <typename B>
Function(Foo * F)93   static void Function(Foo *F)
94       EXCLUSIVE_LOCKS_REQUIRED(F->mutex()) UNLOCK_FUNCTION(F->mutex()) {}
95 };
96 
test()97 void test() { TemplateClass<int> TC; }
98 
99 }  // end namespace DoubleAttribute
100