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 class SCOPED_LOCKABLE MutexLock {
25 public:
26   MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
27   MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);
28   ~MutexLock() UNLOCK_FUNCTION();
29 };
30 
31 namespace SimpleTest {
32 
33 class Bar {
34   Mutex mu;
35   int a GUARDED_BY(mu);
36 
37 public:
baz()38   void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
39     mu.Lock();
40     a = 0;
41     mu.Unlock();
42   }
43 };
44 
45 
46 class Foo {
47   Mutex mu;
48   int a GUARDED_BY(mu);
49 
50 public:
foo()51   void foo() {
52     mu.Lock();    // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
53     baz();        // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
54     bar();
55     mu.Unlock();
56   }
57 
bar()58   void bar() {
59     baz();        // expected-warning {{calling function 'baz' requires negative capability '!mu'}}
60   }
61 
baz()62   void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
63     mu.Lock();
64     a = 0;
65     mu.Unlock();
66   }
67 
test()68   void test() {
69     Bar b;
70     b.baz();     // no warning -- in different class.
71   }
72 
test2()73   void test2() {
74     mu.Lock();   // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
75     a = 0;
76     mu.Unlock();
77     baz();       // no warning -- !mu in set.
78   }
79 
test3()80   void test3() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
81     mu.Lock();
82     a = 0;
83     mu.Unlock();
84     baz();       // no warning -- !mu in set.
85   }
86 
test4()87   void test4() {
88     MutexLock lock(&mu); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
89   }
90 };
91 
92 }  // end namespace SimpleTest
93 
94 Mutex globalMutex;
95 
96 namespace ScopeTest {
97 
98 void f() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex);
99 void fq() EXCLUSIVE_LOCKS_REQUIRED(!::globalMutex);
100 
101 namespace ns {
102   Mutex globalMutex;
103   void f() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex);
104   void fq() EXCLUSIVE_LOCKS_REQUIRED(!ns::globalMutex);
105 }
106 
testGlobals()107 void testGlobals() EXCLUSIVE_LOCKS_REQUIRED(!ns::globalMutex) {
108   f();     // expected-warning {{calling function 'f' requires negative capability '!globalMutex'}}
109   fq();    // expected-warning {{calling function 'fq' requires negative capability '!globalMutex'}}
110   ns::f();
111   ns::fq();
112 }
113 
testNamespaceGlobals()114 void testNamespaceGlobals() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex) {
115   f();
116   fq();
117   ns::f();  // expected-warning {{calling function 'f' requires negative capability '!globalMutex'}}
118   ns::fq(); // expected-warning {{calling function 'fq' requires negative capability '!globalMutex'}}
119 }
120 
121 class StaticMembers {
122 public:
123   void pub() EXCLUSIVE_LOCKS_REQUIRED(!publicMutex);
124   void prot() EXCLUSIVE_LOCKS_REQUIRED(!protectedMutex);
125   void priv() EXCLUSIVE_LOCKS_REQUIRED(!privateMutex);
test()126   void test() {
127     pub();
128     prot();
129     priv();
130   }
131 
132   static Mutex publicMutex;
133 
134 protected:
135   static Mutex protectedMutex;
136 
137 private:
138   static Mutex privateMutex;
139 };
140 
testStaticMembers()141 void testStaticMembers() {
142   StaticMembers x;
143   x.pub();
144   x.prot();
145   x.priv();
146 }
147 
148 }  // end namespace ScopeTest
149 
150 namespace DoubleAttribute {
151 
152 struct Foo {
153   Mutex &mutex();
154 };
155 
156 template <typename A>
157 class TemplateClass {
158   template <typename B>
Function(Foo * F)159   static void Function(Foo *F)
160       EXCLUSIVE_LOCKS_REQUIRED(F->mutex()) UNLOCK_FUNCTION(F->mutex()) {}
161 };
162 
test()163 void test() { TemplateClass<int> TC; }
164 
165 }  // end namespace DoubleAttribute
166