Baranov Victor a3a60e03e2
[clang-tidy] add new check: modernize-use-scoped-lock (#126434)
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.
2025-06-29 22:34:32 +03:00

55 lines
2.2 KiB
C++

//===--- UseScopedLockCheck.h - clang-tidy ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESCOPEDLOCKCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESCOPEDLOCKCHECK_H
#include "../ClangTidyCheck.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Stmt.h"
#include <optional>
namespace clang::tidy::modernize {
/// Finds uses of ``std::lock_guard`` and suggests replacing them with C++17's
/// alternative ``std::scoped_lock``.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-scoped-lock.html
class UseScopedLockCheck : public ClangTidyCheck {
public:
UseScopedLockCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus17;
}
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}
private:
void diagOnSingleLock(const VarDecl *LockGuard,
const ast_matchers::MatchFinder::MatchResult &Result);
void diagOnMultipleLocks(
const llvm::SmallVector<llvm::SmallVector<const VarDecl *>> &LockGroups,
const ast_matchers::MatchFinder::MatchResult &Result);
void diagOnSourceInfo(const TypeSourceInfo *LockGuardSourceInfo,
const ast_matchers::MatchFinder::MatchResult &Result);
void diagOnUsingDecl(const UsingDecl *UsingDecl,
const ast_matchers::MatchFinder::MatchResult &Result);
const bool WarnOnSingleLocks;
const bool WarnOnUsingAndTypedef;
};
} // namespace clang::tidy::modernize
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESCOPEDLOCKCHECK_H