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 | |
24 | |
25 | namespace SimpleTest { |
26 | |
27 | class Bar { |
28 | Mutex mu; |
29 | int a GUARDED_BY(mu); |
30 | |
31 | public: |
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: |
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 | |
52 | void bar() { |
53 | baz(); // expected-warning {{calling function 'baz' requires holding '!mu'}} |
54 | } |
55 | |
56 | void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) { |
57 | mu.Lock(); |
58 | a = 0; |
59 | mu.Unlock(); |
60 | } |
61 | |
62 | void test() { |
63 | Bar b; |
64 | b.baz(); // no warning -- in different class. |
65 | } |
66 | |
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 | |
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> |
93 | static void Function(Foo *F) |
94 | EXCLUSIVE_LOCKS_REQUIRED(F->mutex()) UNLOCK_FUNCTION(F->mutex()) {} |
95 | }; |
96 | |
97 | void test() { TemplateClass<int> TC; } |
98 | |
99 | } // end namespace DoubleAttribute |
100 | |