Index: test/SemaCXX/warn-thread-safety-analysis.cpp =================================================================== --- test/SemaCXX/warn-thread-safety-analysis.cpp +++ test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1,12 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 -DUSE_TRY_ACQUIRE_CAPABILITY %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s -#define LOCKABLE __attribute__((lockable)) #define SCOPED_LOCKABLE __attribute__((scoped_lockable)) #define GUARDED_BY(x) __attribute__((guarded_by(x))) #define GUARDED_VAR __attribute__((guarded_var)) @@ -14,42 +13,46 @@ #define PT_GUARDED_VAR __attribute__((pt_guarded_var)) #define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) #define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) -#if USE_ASSERT_CAPABILITY +#if USE_CAPABILITY +#define LOCKABLE __attribute__((capability("mutex"))) #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__))) #define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__))) -#else -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) -#endif - -#ifdef USE_TRY_ACQUIRE_CAPABILITY +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) #else +#define LOCKABLE __attribute__((lockable)) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) #endif #define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) -#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) -#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) #define LOCK_RETURNED(x) __attribute__((lock_returned(x))) #define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) #define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) class LOCKABLE Mutex { public: - void Lock() __attribute__((exclusive_lock_function)); - void ReaderLock() __attribute__((shared_lock_function)); - void Unlock() __attribute__((unlock_function)); + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void ReaderLock() SHARED_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); - void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); + void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION(); // for negative capabilities const Mutex& operator!() const { return *this; } @@ -80,11 +83,10 @@ void Release() UNLOCK_FUNCTION(); }; -class __attribute__((scoped_lockable)) DoubleMutexLock { +class SCOPED_LOCKABLE DoubleMutexLock { public: - DoubleMutexLock(Mutex *mu1, Mutex *mu2) - __attribute__((exclusive_lock_function(mu1, mu2))); - ~DoubleMutexLock() __attribute__((unlock_function)); + DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); + ~DoubleMutexLock() UNLOCK_FUNCTION(); }; // The universal lock, written "*", allows checking to be selectively turned @@ -165,7 +167,7 @@ public: Mutex mu; int x __attribute__((guarded_by(mu))); - void MyLock() __attribute__((exclusive_lock_function(mu))); + void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu); }; MutexWrapper sls_mw; @@ -378,8 +380,8 @@ class GlobalLocker { public: - void globalLock() __attribute__((exclusive_lock_function(aa_mu))); - void globalUnlock() __attribute__((unlock_function(aa_mu))); + void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu); + void globalUnlock() UNLOCK_FUNCTION(aa_mu); }; GlobalLocker glock; @@ -462,7 +464,7 @@ // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}} } - void testNoAnal() __attribute__((no_thread_safety_analysis)) { + void testNoAnal() NO_THREAD_SAFETY_ANALYSIS { gb_field = 0; } }; @@ -556,7 +558,7 @@ int a __attribute__((guarded_by(mu))); int b; - void foo() __attribute__((exclusive_locks_required(mu))) { } + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { } void test() { a = 0; // \ @@ -738,18 +740,18 @@ // FIXME: Add support for functions (not only methods) class LRBar { public: - void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu))); - void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu))); + void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu); + void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu); void le_fun() __attribute__((locks_excluded(sls_mu))); }; class LRFoo { public: - void test() __attribute__((exclusive_locks_required(sls_mu))); - void testShared() __attribute__((shared_locks_required(sls_mu2))); + void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu); + void testShared() SHARED_LOCKS_REQUIRED(sls_mu2); }; -void elr_fun() __attribute__((exclusive_locks_required(sls_mu))); +void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu); void elr_fun() {} LRFoo MyLRFoo; @@ -801,18 +803,18 @@ sls_mu.Unlock(); } -void es_fun_8() __attribute__((no_thread_safety_analysis)); +void es_fun_8() NO_THREAD_SAFETY_ANALYSIS; void es_fun_8() { Bar.aa_elr_fun_s(); } -void es_fun_9() __attribute__((shared_locks_required(aa_mu))); +void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu); void es_fun_9() { Bar.aa_elr_fun_s(); } -void es_fun_10() __attribute__((exclusive_locks_required(aa_mu))); +void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu); void es_fun_10() { Bar.aa_elr_fun_s(); } @@ -1538,23 +1540,23 @@ public: Mutex mu; - void lockData() __attribute__((exclusive_lock_function(mu))); - void unlockData() __attribute__((unlock_function(mu))); + void lockData() EXCLUSIVE_LOCK_FUNCTION(mu); + void unlockData() UNLOCK_FUNCTION(mu); - void doSomething() __attribute__((exclusive_locks_required(mu))) { } + void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { } }; class DataLocker { public: - void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))); - void unlockData(MyData *d) __attribute__((unlock_function(d->mu))); + void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu); + void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu); }; class Foo { public: - void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { } + void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { } void bar1(MyData* d) { d->lockData(); @@ -1595,8 +1597,8 @@ class Foo { public: - Foo() __attribute__((exclusive_lock_function(fooMu))) { } - ~Foo() __attribute__((unlock_function(fooMu))) { } + Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { } + ~Foo() UNLOCK_FUNCTION(fooMu) { } }; void fooTest() { @@ -2027,9 +2029,9 @@ namespace GoingNative { - struct __attribute__((lockable)) mutex { - void lock() __attribute__((exclusive_lock_function)); - void unlock() __attribute__((unlock_function)); + struct LOCKABLE mutex { + void lock() EXCLUSIVE_LOCK_FUNCTION(); + void unlock() UNLOCK_FUNCTION(); // ... }; bool foo(); @@ -3560,7 +3562,7 @@ class Foo { public: template - void elr(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); + void elr(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); void test(); }; @@ -3576,7 +3578,7 @@ template -void globalELR(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); +void globalELR(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); template void globalELR(Cell* c1) { } @@ -3589,7 +3591,7 @@ template -void globalELR2(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); +void globalELR2(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); // second declaration template @@ -3612,7 +3614,7 @@ template class FooT { public: - void elr(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); + void elr(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); }; template @@ -4422,7 +4424,7 @@ (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}} } - void RunHelper() __attribute__((exclusive_locks_required(M))); + void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M); Mutex M; }; @@ -4649,8 +4651,8 @@ typedef int __attribute__((capability("role"))) ThreadRole; -void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {} -void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {} +void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {} +void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {} ThreadRole FlightControl, Logger;