150
|
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
|
|
18 const Mutex& operator!() const { return *this; }
|
|
19
|
|
20 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
|
|
21 void AssertReaderHeld() ASSERT_SHARED_LOCK();
|
|
22 };
|
|
23
|
221
|
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 };
|
150
|
30
|
|
31 namespace SimpleTest {
|
|
32
|
|
33 class Bar {
|
|
34 Mutex mu;
|
|
35 int a GUARDED_BY(mu);
|
|
36
|
|
37 public:
|
|
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:
|
|
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
|
|
58 void bar() {
|
221
|
59 baz(); // expected-warning {{calling function 'baz' requires negative capability '!mu'}}
|
150
|
60 }
|
|
61
|
|
62 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
|
|
63 mu.Lock();
|
|
64 a = 0;
|
|
65 mu.Unlock();
|
|
66 }
|
|
67
|
|
68 void test() {
|
|
69 Bar b;
|
|
70 b.baz(); // no warning -- in different class.
|
|
71 }
|
|
72
|
|
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
|
|
80 void test3() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
|
|
81 mu.Lock();
|
|
82 a = 0;
|
|
83 mu.Unlock();
|
|
84 baz(); // no warning -- !mu in set.
|
|
85 }
|
221
|
86
|
|
87 void test4() {
|
|
88 MutexLock lock(&mu); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
|
|
89 }
|
150
|
90 };
|
|
91
|
|
92 } // end namespace SimpleTest
|
|
93
|
221
|
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
|
|
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
|
|
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);
|
|
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
|
|
141 void testStaticMembers() {
|
|
142 StaticMembers x;
|
|
143 x.pub();
|
|
144 x.prot();
|
|
145 x.priv();
|
|
146 }
|
|
147
|
|
148 } // end namespace ScopeTest
|
|
149
|
150
|
150 namespace DoubleAttribute {
|
|
151
|
|
152 struct Foo {
|
|
153 Mutex &mutex();
|
|
154 };
|
|
155
|
|
156 template <typename A>
|
|
157 class TemplateClass {
|
|
158 template <typename B>
|
|
159 static void Function(Foo *F)
|
|
160 EXCLUSIVE_LOCKS_REQUIRED(F->mutex()) UNLOCK_FUNCTION(F->mutex()) {}
|
|
161 };
|
|
162
|
|
163 void test() { TemplateClass<int> TC; }
|
|
164
|
|
165 } // end namespace DoubleAttribute
|