llvm-project/clang/test/Analysis/block-in-critical-section-nested-namespace.cpp
Arseniy Zaostrovnykh 82e314e366
[analyzer] Fix false positive for mutexes inheriting mutex_base (#106240)
If a mutex interface is split in inheritance chain, e.g. struct mutex
has `unlock` and inherits `lock` from __mutex_base then calls m.lock()
and m.unlock() have different "this" targets: m and the __mutex_base of
m, which used to confuse the `ActiveCritSections` list.

Taking base region canonicalizes the region used to identify a critical
section and enables search in ActiveCritSections list regardless of
which class the callee is the member of.

This likely fixes #104241

CPP-5541
2024-08-28 11:30:18 +02:00

43 lines
1.0 KiB
C++

// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=unix.BlockInCriticalSection \
// RUN: -std=c++11 \
// RUN: -analyzer-output text \
// RUN: -verify %s
unsigned int sleep(unsigned int seconds) {return 0;}
namespace std {
namespace __detail {
class __mutex_base {
public:
void lock();
};
} // namespace __detail
class mutex : public __detail::__mutex_base{
public:
void unlock();
bool try_lock();
};
} // namespace std
void gh_99628() {
std::mutex m;
m.lock();
// expected-note@-1 {{Entering critical section here}}
sleep(10);
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
m.unlock();
}
void no_false_positive_gh_104241() {
std::mutex m;
m.lock();
// If inheritance not handled properly, this unlock might not match the lock
// above because technically they act on different memory regions:
// __mutex_base and mutex.
m.unlock();
sleep(10); // no-warning
}