2011-08-24 02:46:34 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------//
|
|
|
|
// Helper fields
|
|
|
|
//-----------------------------------------//
|
|
|
|
|
|
|
|
|
|
|
|
class __attribute__((lockable)) Mutex {
|
|
|
|
public:
|
|
|
|
void Lock() __attribute__((exclusive_lock_function));
|
|
|
|
void ReaderLock() __attribute__((shared_lock_function));
|
|
|
|
void Unlock() __attribute__((unlock_function));
|
|
|
|
bool TryLock() __attribute__((exclusive_trylock_function(true)));
|
|
|
|
bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
|
|
|
|
void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Mutex sls_mu;
|
|
|
|
|
|
|
|
Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
|
|
|
|
int sls_guard_var __attribute__((guarded_var)) = 0;
|
|
|
|
int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
|
|
|
|
|
|
|
|
bool getBool();
|
|
|
|
|
|
|
|
class MutexWrapper {
|
|
|
|
public:
|
|
|
|
Mutex mu;
|
|
|
|
// int x __attribute__((guarded_by(mu))); // FIXME: scoping error
|
|
|
|
};
|
|
|
|
|
|
|
|
MutexWrapper sls_mw;
|
|
|
|
|
|
|
|
void sls_fun_0() {
|
|
|
|
sls_mw.mu.Lock();
|
|
|
|
// sls_mw.x = 5; // FIXME: turn mu into sls_mw.mu
|
|
|
|
sls_mw.mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_2() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
int x = sls_guard_var;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_3() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
sls_guard_var = 2;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_4() {
|
|
|
|
sls_mu2.Lock();
|
|
|
|
sls_guard_var = 2;
|
|
|
|
sls_mu2.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_5() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
int x = sls_guardby_var;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_6() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
sls_guardby_var = 2;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_7() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
sls_mu2.Lock();
|
|
|
|
sls_mu2.Unlock();
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_8() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Unlock();
|
|
|
|
else
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_9() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Lock();
|
|
|
|
else
|
|
|
|
sls_mu.Lock();
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_good_6() {
|
|
|
|
if (getBool()) {
|
|
|
|
sls_mu.Lock();
|
|
|
|
} else {
|
|
|
|
if (getBool()) {
|
|
|
|
getBool(); // EMPTY
|
|
|
|
} else {
|
|
|
|
getBool(); // EMPTY
|
|
|
|
}
|
|
|
|
sls_mu.Lock();
|
|
|
|
}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_good_7() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
while (getBool()) {
|
|
|
|
sls_mu.Unlock();
|
|
|
|
if (getBool()) {
|
|
|
|
if (getBool()) {
|
|
|
|
sls_mu.Lock();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sls_mu.Lock();
|
|
|
|
}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_1() {
|
|
|
|
sls_mu.Unlock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{unlocking 'sls_mu' that was not acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_2() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{locking 'sls_mu' that is already acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_3() {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_3'}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_4() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
else
|
|
|
|
sls_mu2.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu2' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_5() {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
if (getBool())
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_6() {
|
|
|
|
if (getBool()) {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
} else {
|
|
|
|
if (getBool()) {
|
|
|
|
getBool(); // EMPTY
|
|
|
|
} else {
|
|
|
|
getBool(); // EMPTY
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sls_mu.Unlock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{unlocking 'sls_mu' that was not acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_7() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
while (getBool()) { // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
|
2011-08-24 02:46:34 +08:00
|
|
|
sls_mu.Unlock();
|
|
|
|
if (getBool()) {
|
|
|
|
if (getBool()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_8() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
do {
|
|
|
|
sls_mu.Unlock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
|
2011-08-24 02:46:34 +08:00
|
|
|
} while (getBool());
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_9() {
|
|
|
|
do {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
} while (getBool());
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_10() {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_10'}}
|
2011-08-24 02:46:34 +08:00
|
|
|
while(getBool()) { // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
|
2011-08-24 02:46:34 +08:00
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sls_fun_bad_11() {
|
|
|
|
while (getBool()) {
|
|
|
|
sls_mu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
sls_mu.Unlock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{unlocking 'sls_mu' that was not acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------//
|
|
|
|
// Handling lock expressions in attribute args
|
|
|
|
// -------------------------------------------//
|
|
|
|
|
|
|
|
Mutex aa_mu;
|
|
|
|
|
|
|
|
class GlobalLocker {
|
|
|
|
public:
|
|
|
|
void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
|
|
|
|
void globalUnlock() __attribute__((unlock_function(aa_mu)));
|
|
|
|
};
|
|
|
|
|
|
|
|
GlobalLocker glock;
|
|
|
|
|
|
|
|
void aa_fun_1() {
|
|
|
|
glock.globalLock();
|
|
|
|
glock.globalUnlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void aa_fun_bad_1() {
|
|
|
|
glock.globalUnlock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{unlocking 'aa_mu' that was not acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void aa_fun_bad_2() {
|
|
|
|
glock.globalLock();
|
|
|
|
glock.globalLock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{locking 'aa_mu' that is already acquired}}
|
2011-08-24 02:46:34 +08:00
|
|
|
glock.globalUnlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void aa_fun_bad_3() {
|
|
|
|
glock.globalLock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{lock 'aa_mu' is not released at the end of function 'aa_fun_bad_3'}}
|
2011-08-24 02:46:34 +08:00
|
|
|
}
|
2011-08-30 01:12:27 +08:00
|
|
|
|
|
|
|
//--------------------------------------------------//
|
|
|
|
// Regression tests for unusual method names
|
|
|
|
//--------------------------------------------------//
|
|
|
|
|
|
|
|
Mutex wmu;
|
|
|
|
|
|
|
|
// Test diagnostics for other method names.
|
|
|
|
class WeirdMethods {
|
|
|
|
WeirdMethods() {
|
|
|
|
wmu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{lock 'wmu' is not released at the end of function 'WeirdMethods'}}
|
2011-08-30 01:12:27 +08:00
|
|
|
}
|
|
|
|
~WeirdMethods() {
|
|
|
|
wmu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{lock 'wmu' is not released at the end of function '~WeirdMethods'}}
|
2011-08-30 01:12:27 +08:00
|
|
|
}
|
|
|
|
void operator++() {
|
|
|
|
wmu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{lock 'wmu' is not released at the end of function 'operator++'}}
|
2011-08-30 01:12:27 +08:00
|
|
|
}
|
|
|
|
operator int*() {
|
|
|
|
wmu.Lock(); // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{lock 'wmu' is not released at the end of function 'operator int *'}}
|
2011-08-30 01:12:27 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-08-30 06:27:51 +08:00
|
|
|
//-----------------------------------------------//
|
|
|
|
// Errors for guarded by or guarded var variables
|
|
|
|
// ----------------------------------------------//
|
|
|
|
|
|
|
|
int *pgb_gvar __attribute__((pt_guarded_var));
|
|
|
|
int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
|
|
|
|
|
|
|
|
class PGBFoo {
|
|
|
|
public:
|
|
|
|
int x;
|
|
|
|
int *pgb_field __attribute__((guarded_by(sls_mu2)))
|
|
|
|
__attribute__((pt_guarded_by(sls_mu)));
|
|
|
|
void testFoo() {
|
|
|
|
pgb_field = &x; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing variable 'pgb_field' requires lock 'sls_mu2' to be held exclusively}}
|
|
|
|
*pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
|
|
|
|
// expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
|
|
|
|
x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
|
|
|
|
// expected-warning {{reading the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held}}
|
|
|
|
(*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
|
|
|
|
// expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class GBFoo {
|
|
|
|
public:
|
|
|
|
int gb_field __attribute__((guarded_by(sls_mu)));
|
|
|
|
|
|
|
|
void testFoo() {
|
|
|
|
gb_field = 0; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing variable 'gb_field' requires lock 'sls_mu' to be held exclusively}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
2011-09-09 02:35:21 +08:00
|
|
|
|
|
|
|
void testNoAnal() __attribute__((no_thread_safety_analysis)) {
|
|
|
|
gb_field = 0;
|
|
|
|
}
|
2011-08-30 06:27:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
|
|
|
|
|
|
|
|
void gb_fun_0() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
int x = *pgb_var;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void gb_fun_1() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
*pgb_var = 2;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void gb_fun_2() {
|
|
|
|
int x;
|
|
|
|
pgb_var = &x;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gb_fun_3() {
|
|
|
|
int *x = pgb_var;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_0() {
|
|
|
|
sls_guard_var = 1; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_1() {
|
|
|
|
int x = sls_guard_var; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_2() {
|
|
|
|
sls_guardby_var = 1; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing variable 'sls_guardby_var' requires lock 'sls_mu' to be held exclusively}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_3() {
|
|
|
|
int x = sls_guardby_var; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{reading variable 'sls_guardby_var' requires lock 'sls_mu' to be held}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_4() {
|
|
|
|
*pgb_gvar = 1; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{accessing the value pointed to by 'pgb_gvar' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_5() {
|
|
|
|
int x = *pgb_gvar; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning {{accessing the value pointed to by 'pgb_gvar' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_6() {
|
|
|
|
*pgb_var = 1; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held exclusively}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_7() {
|
|
|
|
int x = *pgb_var; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{reading the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_8() {
|
|
|
|
GBFoo G;
|
|
|
|
G.gb_field = 0; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing variable 'gb_field' requires lock 'sls_mu'}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void gb_bad_9() {
|
|
|
|
sls_guard_var++; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
sls_guard_var--; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
++sls_guard_var; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
--sls_guard_var; // \
|
2011-09-09 02:07:26 +08:00
|
|
|
// expected-warning{{accessing variable 'sls_guard_var' requires some lock}}
|
2011-08-30 06:27:51 +08:00
|
|
|
}
|
2011-08-30 01:12:27 +08:00
|
|
|
|
2011-09-09 01:42:22 +08:00
|
|
|
//-----------------------------------------------//
|
|
|
|
// Warnings on variables with late parsed attributes
|
|
|
|
// ----------------------------------------------//
|
|
|
|
|
|
|
|
class LateFoo {
|
|
|
|
public:
|
|
|
|
int a __attribute__((guarded_by(mu)));
|
|
|
|
int b;
|
|
|
|
|
|
|
|
void foo() __attribute__((exclusive_locks_required(mu))) { }
|
|
|
|
|
|
|
|
void test() {
|
|
|
|
a = 0; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning{{writing variable 'a' requires lock 'mu' to be held exclusively}}
|
2011-09-09 01:42:22 +08:00
|
|
|
b = a; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{reading variable 'a' requires lock 'mu' to be held}}
|
2011-09-09 01:42:22 +08:00
|
|
|
c = 0; // \
|
2011-09-09 02:19:38 +08:00
|
|
|
// expected-warning {{writing variable 'c' requires lock 'mu' to be held exclusively}}
|
2011-09-09 01:42:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int c __attribute__((guarded_by(mu)));
|
|
|
|
|
|
|
|
Mutex mu;
|
|
|
|
};
|
|
|
|
|
2011-09-09 02:19:38 +08:00
|
|
|
//-----------------------------------------------//
|
|
|
|
// Extra warnings for shared vs. exclusive locks
|
|
|
|
// ----------------------------------------------//
|
|
|
|
|
|
|
|
void shared_fun_0() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
do {
|
|
|
|
sls_mu.Unlock();
|
|
|
|
sls_mu.Lock();
|
|
|
|
} while (getBool());
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_fun_1() {
|
|
|
|
sls_mu.ReaderLock();
|
|
|
|
do {
|
|
|
|
sls_mu.Unlock();
|
|
|
|
sls_mu.Lock(); // \
|
|
|
|
// expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
|
|
|
|
} while (getBool());
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_fun_3() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Lock();
|
|
|
|
else
|
|
|
|
sls_mu.Lock();
|
|
|
|
*pgb_var = 1;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_fun_4() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.ReaderLock();
|
|
|
|
else
|
|
|
|
sls_mu.ReaderLock();
|
|
|
|
int x = sls_guardby_var;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_fun_8() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Lock(); // \
|
|
|
|
// expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
|
|
|
|
else
|
|
|
|
sls_mu.ReaderLock(); // \
|
|
|
|
// expected-note {{the other acquire of lock 'sls_mu' is here}}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_bad_0() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
do {
|
|
|
|
sls_mu.Unlock();
|
|
|
|
sls_mu.ReaderLock(); // \
|
|
|
|
// expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
|
|
|
|
} while (getBool());
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_bad_1() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.Lock(); // \
|
|
|
|
// expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
|
|
|
|
else
|
|
|
|
sls_mu.ReaderLock(); // \
|
|
|
|
// expected-note {{the other acquire of lock 'sls_mu' is here}}
|
|
|
|
*pgb_var = 1;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shared_bad_2() {
|
|
|
|
if (getBool())
|
|
|
|
sls_mu.ReaderLock(); // \
|
|
|
|
// expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
|
|
|
|
else
|
|
|
|
sls_mu.Lock(); // \
|
|
|
|
// expected-note {{the other acquire of lock 'sls_mu' is here}}
|
|
|
|
*pgb_var = 1;
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
2011-09-09 02:27:31 +08:00
|
|
|
|
|
|
|
// 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 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 elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
|
|
|
|
void elr_fun() {}
|
|
|
|
|
|
|
|
LRFoo MyLRFoo;
|
|
|
|
LRBar Bar;
|
|
|
|
|
|
|
|
void es_fun_0() {
|
|
|
|
aa_mu.Lock();
|
|
|
|
Bar.aa_elr_fun();
|
|
|
|
aa_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_1() {
|
|
|
|
aa_mu.Lock();
|
|
|
|
Bar.aa_elr_fun_s();
|
|
|
|
aa_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_2() {
|
|
|
|
aa_mu.ReaderLock();
|
|
|
|
Bar.aa_elr_fun_s();
|
|
|
|
aa_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_3() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
MyLRFoo.test();
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_4() {
|
|
|
|
sls_mu2.Lock();
|
|
|
|
MyLRFoo.testShared();
|
|
|
|
sls_mu2.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_5() {
|
|
|
|
sls_mu2.ReaderLock();
|
|
|
|
MyLRFoo.testShared();
|
|
|
|
sls_mu2.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_6() {
|
|
|
|
Bar.le_fun();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_fun_7() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
elr_fun();
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
2011-09-09 02:35:21 +08:00
|
|
|
void es_fun_8() __attribute__((no_thread_safety_analysis));
|
|
|
|
|
|
|
|
void es_fun_8() {
|
|
|
|
Bar.aa_elr_fun_s();
|
|
|
|
}
|
|
|
|
|
2011-09-09 02:27:31 +08:00
|
|
|
void es_bad_0() {
|
|
|
|
Bar.aa_elr_fun(); // \
|
|
|
|
// expected-warning {{calling function 'aa_elr_fun' requires exclusive lock 'aa_mu'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_1() {
|
|
|
|
aa_mu.ReaderLock();
|
|
|
|
Bar.aa_elr_fun(); // \
|
|
|
|
// expected-warning {{calling function 'aa_elr_fun' requires exclusive lock 'aa_mu'}}
|
|
|
|
aa_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_2() {
|
|
|
|
Bar.aa_elr_fun_s(); // \
|
|
|
|
// expected-warning {{calling function 'aa_elr_fun_s' requires shared lock 'aa_mu'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_3() {
|
|
|
|
MyLRFoo.test(); // \
|
|
|
|
// expected-warning {{calling function 'test' requires exclusive lock 'sls_mu'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_4() {
|
|
|
|
MyLRFoo.testShared(); // \
|
|
|
|
// expected-warning {{calling function 'testShared' requires shared lock 'sls_mu2'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_5() {
|
|
|
|
sls_mu.ReaderLock();
|
|
|
|
MyLRFoo.test(); // \
|
|
|
|
// expected-warning {{calling function 'test' requires exclusive lock 'sls_mu'}}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_6() {
|
|
|
|
sls_mu.Lock();
|
|
|
|
Bar.le_fun(); // \
|
|
|
|
// expected-warning {{cannot call function 'le_fun' while holding lock 'sls_mu'}}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void es_bad_7() {
|
|
|
|
sls_mu.ReaderLock();
|
|
|
|
Bar.le_fun(); // \
|
|
|
|
// expected-warning {{cannot call function 'le_fun' while holding lock 'sls_mu'}}
|
|
|
|
sls_mu.Unlock();
|
|
|
|
}
|