Add new clang-tidy check that finds uses of `std::lock_guard` and suggests
replacing them with C++17's more flexible and safer alternative
`std::scoped_lock`.
Here is a small description of how it works for better understanding of
the code:
Two separate AST matchers are registered:
- The first one matches declarations of `std::lock_guard` that are
single in their scope (only one `std::lock_guard` in `CompoundStmt`).
It's an easy case, we can emit warning right away.
- The second one matches `CompoundStmt`'s that have multiple
`std::lock_guard` declarations, which means that we may have consecutive
declarations of `std::lock_guard` that can be replaced by a single
`std::scoped_lock`. In order to ensure that declarations are
consecutive, we need to loop over `Stmt`'s in `CompoundStmt`. Here is a
small example:
```cpp
{
std::mutex m1, m2;
std::lock(m1, m2);
std::lock_guard<std::mutex> l1(m, std::adopt_lock); // first declaration of 'std::lock_guard'
std::lock_guard<std::mutex> l2(m, std::adopt_lock); // second declaration of 'std::lock_guard' that can be merged with first using 'scoped_lock'
}
```
This PR closes https://github.com/llvm/llvm-project/issues/107839.
34 lines
696 B
Plaintext
34 lines
696 B
Plaintext
#ifndef _MUTEX_
|
|
#define _MUTEX_
|
|
|
|
namespace std {
|
|
|
|
struct mutex {
|
|
void lock() {}
|
|
void unlock() {}
|
|
};
|
|
|
|
template<class Lockable1, class Lockable2, class... LockableN >
|
|
void lock(Lockable1& lock1, Lockable2& lock2, LockableN&... lockn );
|
|
|
|
struct adopt_lock_t { };
|
|
std::adopt_lock_t adopt_lock {};
|
|
|
|
template <typename Mutex>
|
|
struct lock_guard {
|
|
lock_guard(Mutex &m) { }
|
|
lock_guard(Mutex &m, std::adopt_lock_t t) {}
|
|
lock_guard(const lock_guard&) = delete;
|
|
};
|
|
|
|
template <typename... MutexTypes>
|
|
struct scoped_lock {
|
|
scoped_lock(MutexTypes&... m) {}
|
|
scoped_lock(std::adopt_lock_t t, MutexTypes&... m) {}
|
|
scoped_lock(const scoped_lock&) = delete;
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
#endif // _MUTEX_
|