1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions %s 2*67e74705SXin Li 3*67e74705SXin Li // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s 4*67e74705SXin Li // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s 5*67e74705SXin Li 6*67e74705SXin Li #define LOCKABLE __attribute__ ((lockable)) 7*67e74705SXin Li #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) 8*67e74705SXin Li #define GUARDED_BY(x) __attribute__ ((guarded_by(x))) 9*67e74705SXin Li #define GUARDED_VAR __attribute__ ((guarded_var)) 10*67e74705SXin Li #define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) 11*67e74705SXin Li #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) 12*67e74705SXin Li #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) 13*67e74705SXin Li #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) 14*67e74705SXin Li #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) 15*67e74705SXin Li #define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) 16*67e74705SXin Li #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) 17*67e74705SXin Li #define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__))) 18*67e74705SXin Li #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) 19*67e74705SXin Li #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) 20*67e74705SXin Li #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) 21*67e74705SXin Li #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) 22*67e74705SXin Li #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) 23*67e74705SXin Li #define EXCLUSIVE_LOCKS_REQUIRED(...) \ 24*67e74705SXin Li __attribute__ ((exclusive_locks_required(__VA_ARGS__))) 25*67e74705SXin Li #define SHARED_LOCKS_REQUIRED(...) \ 26*67e74705SXin Li __attribute__ ((shared_locks_required(__VA_ARGS__))) 27*67e74705SXin Li #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) 28*67e74705SXin Li 29*67e74705SXin Li 30*67e74705SXin Li class __attribute__((lockable)) Mutex { 31*67e74705SXin Li public: 32*67e74705SXin Li void Lock() __attribute__((exclusive_lock_function)); 33*67e74705SXin Li void ReaderLock() __attribute__((shared_lock_function)); 34*67e74705SXin Li void Unlock() __attribute__((unlock_function)); 35*67e74705SXin Li bool TryLock() __attribute__((exclusive_trylock_function(true))); 36*67e74705SXin Li bool ReaderTryLock() __attribute__((shared_trylock_function(true))); 37*67e74705SXin Li void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); 38*67e74705SXin Li 39*67e74705SXin Li // for negative capabilities operator !() const40*67e74705SXin Li const Mutex& operator!() const { return *this; } 41*67e74705SXin Li 42*67e74705SXin Li void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); 43*67e74705SXin Li void AssertReaderHeld() ASSERT_SHARED_LOCK(); 44*67e74705SXin Li }; 45*67e74705SXin Li 46*67e74705SXin Li 47*67e74705SXin Li namespace SimpleTest { 48*67e74705SXin Li 49*67e74705SXin Li class Bar { 50*67e74705SXin Li Mutex mu; 51*67e74705SXin Li int a GUARDED_BY(mu); 52*67e74705SXin Li 53*67e74705SXin Li public: baz()54*67e74705SXin Li void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) { 55*67e74705SXin Li mu.Lock(); 56*67e74705SXin Li a = 0; 57*67e74705SXin Li mu.Unlock(); 58*67e74705SXin Li } 59*67e74705SXin Li }; 60*67e74705SXin Li 61*67e74705SXin Li 62*67e74705SXin Li class Foo { 63*67e74705SXin Li Mutex mu; 64*67e74705SXin Li int a GUARDED_BY(mu); 65*67e74705SXin Li 66*67e74705SXin Li public: foo()67*67e74705SXin Li void foo() { 68*67e74705SXin Li mu.Lock(); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}} 69*67e74705SXin Li baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}} 70*67e74705SXin Li bar(); 71*67e74705SXin Li mu.Unlock(); 72*67e74705SXin Li } 73*67e74705SXin Li bar()74*67e74705SXin Li void bar() { 75*67e74705SXin Li baz(); // expected-warning {{calling function 'baz' requires holding '!mu'}} 76*67e74705SXin Li } 77*67e74705SXin Li baz()78*67e74705SXin Li void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) { 79*67e74705SXin Li mu.Lock(); 80*67e74705SXin Li a = 0; 81*67e74705SXin Li mu.Unlock(); 82*67e74705SXin Li } 83*67e74705SXin Li test()84*67e74705SXin Li void test() { 85*67e74705SXin Li Bar b; 86*67e74705SXin Li b.baz(); // no warning -- in different class. 87*67e74705SXin Li } 88*67e74705SXin Li test2()89*67e74705SXin Li void test2() { 90*67e74705SXin Li mu.Lock(); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}} 91*67e74705SXin Li a = 0; 92*67e74705SXin Li mu.Unlock(); 93*67e74705SXin Li baz(); // no warning -- !mu in set. 94*67e74705SXin Li } 95*67e74705SXin Li test3()96*67e74705SXin Li void test3() EXCLUSIVE_LOCKS_REQUIRED(!mu) { 97*67e74705SXin Li mu.Lock(); 98*67e74705SXin Li a = 0; 99*67e74705SXin Li mu.Unlock(); 100*67e74705SXin Li baz(); // no warning -- !mu in set. 101*67e74705SXin Li } 102*67e74705SXin Li }; 103*67e74705SXin Li 104*67e74705SXin Li } // end namespace SimpleTest 105*67e74705SXin Li 106*67e74705SXin Li namespace DoubleAttribute { 107*67e74705SXin Li 108*67e74705SXin Li struct Foo { 109*67e74705SXin Li Mutex &mutex(); 110*67e74705SXin Li }; 111*67e74705SXin Li 112*67e74705SXin Li template <typename A> 113*67e74705SXin Li class TemplateClass { 114*67e74705SXin Li template <typename B> Function(Foo * F)115*67e74705SXin Li static void Function(Foo *F) 116*67e74705SXin Li EXCLUSIVE_LOCKS_REQUIRED(F->mutex()) UNLOCK_FUNCTION(F->mutex()) {} 117*67e74705SXin Li }; 118*67e74705SXin Li test()119*67e74705SXin Livoid test() { TemplateClass<int> TC; } 120*67e74705SXin Li 121*67e74705SXin Li } // end namespace DoubleAttribute 122