2017-03-04 02:02:02 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
|
2016-09-21 04:28:50 +08:00
|
|
|
|
|
|
|
void sleep(int x) {}
|
|
|
|
|
|
|
|
namespace std {
|
|
|
|
struct mutex {
|
|
|
|
void lock() {}
|
|
|
|
void unlock() {}
|
|
|
|
};
|
2017-10-30 18:09:55 +08:00
|
|
|
template<typename T>
|
|
|
|
struct lock_guard {
|
|
|
|
lock_guard<T>(std::mutex) {}
|
|
|
|
~lock_guard<T>() {}
|
|
|
|
};
|
|
|
|
template<typename T>
|
|
|
|
struct unique_lock {
|
|
|
|
unique_lock<T>(std::mutex) {}
|
|
|
|
~unique_lock<T>() {}
|
|
|
|
};
|
|
|
|
template<typename T>
|
|
|
|
struct not_real_lock {
|
|
|
|
not_real_lock<T>(std::mutex) {}
|
|
|
|
};
|
2016-09-21 04:28:50 +08:00
|
|
|
}
|
|
|
|
|
2017-03-10 22:50:12 +08:00
|
|
|
void getc() {}
|
|
|
|
void fgets() {}
|
|
|
|
void read() {}
|
|
|
|
void recv() {}
|
|
|
|
|
|
|
|
void pthread_mutex_lock() {}
|
|
|
|
void pthread_mutex_trylock() {}
|
|
|
|
void pthread_mutex_unlock() {}
|
|
|
|
|
|
|
|
void mtx_lock() {}
|
|
|
|
void mtx_timedlock() {}
|
|
|
|
void mtx_trylock() {}
|
|
|
|
void mtx_unlock() {}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionWithStdMutex() {
|
2016-09-21 04:28:50 +08:00
|
|
|
std::mutex m;
|
|
|
|
m.lock();
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
m.unlock();
|
|
|
|
}
|
|
|
|
|
2017-03-10 22:50:12 +08:00
|
|
|
void testBlockInCriticalSectionWithPthreadMutex() {
|
|
|
|
pthread_mutex_lock();
|
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
|
|
|
pthread_mutex_unlock();
|
|
|
|
|
|
|
|
pthread_mutex_trylock();
|
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
|
|
|
pthread_mutex_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionC11Locks() {
|
|
|
|
mtx_lock();
|
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
|
|
|
mtx_unlock();
|
|
|
|
|
|
|
|
mtx_timedlock();
|
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
|
|
|
mtx_unlock();
|
|
|
|
|
|
|
|
mtx_trylock();
|
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
|
|
|
|
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
|
|
|
|
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
|
|
|
|
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
|
|
|
|
mtx_unlock();
|
|
|
|
}
|
|
|
|
|
2016-09-21 04:28:50 +08:00
|
|
|
void testBlockInCriticalSectionWithNestedMutexes() {
|
|
|
|
std::mutex m, n, k;
|
|
|
|
m.lock();
|
|
|
|
n.lock();
|
|
|
|
k.lock();
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
k.unlock();
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
n.unlock();
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
m.unlock();
|
|
|
|
sleep(3); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void f() {
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionInterProcedural() {
|
|
|
|
std::mutex m;
|
|
|
|
m.lock();
|
|
|
|
f();
|
|
|
|
m.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionUnexpectedUnlock() {
|
|
|
|
std::mutex m;
|
|
|
|
m.unlock();
|
|
|
|
sleep(1); // no-warning
|
|
|
|
m.lock();
|
2017-03-10 22:50:12 +08:00
|
|
|
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
2016-09-21 04:28:50 +08:00
|
|
|
}
|
2017-10-30 18:09:55 +08:00
|
|
|
|
|
|
|
void testBlockInCriticalSectionLockGuard() {
|
|
|
|
std::mutex g_mutex;
|
|
|
|
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
|
|
|
|
sleep(1); // no-warning
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_mutex);
|
|
|
|
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionLockGuardNested() {
|
|
|
|
testBlockInCriticalSectionLockGuard();
|
|
|
|
sleep(1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionUniqueLock() {
|
|
|
|
std::mutex g_mutex;
|
|
|
|
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
|
|
|
|
sleep(1); // no-warning
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(g_mutex);
|
|
|
|
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void testBlockInCriticalSectionUniqueLockNested() {
|
|
|
|
testBlockInCriticalSectionUniqueLock();
|
|
|
|
sleep(1); // no-warning
|
|
|
|
}
|