[clang-tidy] Flag consecutive scoped_locks in use-scoped-lock (#209272)

Fixes https://github.com/llvm/llvm-project/issues/209112.
This commit is contained in:
Baranov Victor 2026-07-14 10:39:24 +03:00 committed by GitHub
parent 9a342c137d
commit 5514c1eff5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 185 additions and 53 deletions

View file

@ -27,19 +27,39 @@ static bool isLockGuardDecl(const NamedDecl *Decl) {
Decl->getName() == "lock_guard" && Decl->isInStdNamespace();
}
static bool isLockGuard(const QualType &Type) {
static bool isScopedLockDecl(const NamedDecl *Decl) {
return Decl->getDeclName().isIdentifier() &&
Decl->getName() == "scoped_lock" && Decl->isInStdNamespace();
}
static const NamedDecl *getLockClassDecl(const QualType &Type) {
if (const auto *Record = Type->getAsCanonical<RecordType>())
if (const RecordDecl *Decl = Record->getDecl())
return isLockGuardDecl(Decl);
return Record->getDecl();
if (const auto *TemplateSpecType = Type->getAs<TemplateSpecializationType>())
if (const TemplateDecl *Decl =
TemplateSpecType->getTemplateName().getAsTemplateDecl())
return isLockGuardDecl(Decl);
return TemplateSpecType->getTemplateName().getAsTemplateDecl();
return nullptr;
}
static bool isLockGuard(const QualType &Type) {
if (const NamedDecl *LockDecl = getLockClassDecl(Type))
return isLockGuardDecl(LockDecl);
return false;
}
static bool isScopedLock(const QualType &Type) {
if (const NamedDecl *LockDecl = getLockClassDecl(Type))
return isScopedLockDecl(LockDecl);
return false;
}
static StringRef getLockClassName(const QualType &Type) {
const NamedDecl *LockDecl = getLockClassDecl(Type);
assert(LockDecl);
return LockDecl->getName();
}
static SmallVector<const VarDecl *> getLockGuardsFromDecl(const DeclStmt *DS) {
SmallVector<const VarDecl *> LockGuards;
@ -47,7 +67,7 @@ static SmallVector<const VarDecl *> getLockGuardsFromDecl(const DeclStmt *DS) {
if (const auto *VD = dyn_cast<VarDecl>(Decl)) {
const QualType Type =
VD->getType().getCanonicalType().getUnqualifiedType();
if (isLockGuard(Type))
if (isLockGuard(Type) || isScopedLock(Type))
LockGuards.push_back(VD);
}
}
@ -123,19 +143,25 @@ void UseScopedLockCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) {
const auto LockGuardClassDecl =
namedDecl(hasName("lock_guard"), isInStdNamespace());
const auto ScopedLockClassDecl =
namedDecl(hasName("scoped_lock"), isInStdNamespace());
const auto LockClassDecl = anyOf(LockGuardClassDecl, ScopedLockClassDecl);
const auto LockGuardType =
qualType(anyOf(hasUnqualifiedDesugaredType(
recordType(hasDeclaration(LockGuardClassDecl))),
hasUnqualifiedDesugaredType(templateSpecializationType(
hasDeclaration(LockGuardClassDecl)))));
const auto LockGuardType = qualType(hasUnqualifiedDesugaredType(
mapAnyOf(recordType, templateSpecializationType)
.with(hasDeclaration(LockGuardClassDecl))));
const auto LockVarDecl = varDecl(hasType(LockGuardType));
const auto LockType = qualType(hasUnqualifiedDesugaredType(
mapAnyOf(recordType, templateSpecializationType)
.with(hasDeclaration(LockClassDecl))));
const auto LockGuardVarDecl = varDecl(hasType(LockGuardType));
const auto LockVarDecl = varDecl(hasType(LockType));
if (WarnOnSingleLocks) {
Finder->addMatcher(
compoundStmt(
has(declStmt(has(LockVarDecl)).bind("lock-decl-single")),
has(declStmt(has(LockGuardVarDecl)).bind("lock-decl-single")),
unless(has(declStmt(unless(equalsBoundNode("lock-decl-single")),
has(LockVarDecl))))),
this);
@ -251,16 +277,24 @@ void UseScopedLockCheck::diagOnMultipleLocks(
const ast_matchers::MatchFinder::MatchResult &Result) {
for (const SmallVector<const VarDecl *> &Group : LockGroups) {
if (Group.size() == 1) {
if (WarnOnSingleLocks)
if (WarnOnSingleLocks &&
isLockGuard(
Group[0]->getType().getCanonicalType().getUnqualifiedType()))
diagOnSingleLock(Group[0], Result);
} else {
diag(Group[0]->getBeginLoc(),
"use single 'std::scoped_lock' instead of multiple "
"'std::lock_guard'");
continue;
}
for (const VarDecl *Lock : llvm::drop_begin(Group))
diag(Lock->getLocation(), "additional 'std::lock_guard' declared here",
DiagnosticIDs::Note);
diag(Group[0]->getBeginLoc(),
"use single 'std::scoped_lock' instead of multiple locks");
for (const VarDecl *Lock : llvm::drop_begin(Group)) {
const QualType Type =
Lock->getType().getCanonicalType().getUnqualifiedType();
diag(Lock->getLocation(),
(llvm::Twine("additional 'std::") + getLockClassName(Type) +
"' declared here")
.str(),
DiagnosticIDs::Note);
}
}
}

View file

@ -702,6 +702,12 @@ Changes in existing checks
``std::remove_if``, ``std::partition``, ``std::stable_partition``, and
``std::rotate`` calls with their ``std::ranges`` counterparts.
- Improved :doc:`modernize-use-scoped-lock
<clang-tidy/checks/modernize/use-scoped-lock>` check by fixing a false
negative where multiple ``std::scoped_lock`` declarations, or a mix of
``std::scoped_lock`` and ``std::lock_guard`` declarations, in the same scope
were not flagged.
- Improved :doc:`modernize-use-std-format
<clang-tidy/checks/modernize/use-std-format>` check:

View file

@ -7,8 +7,8 @@ Finds uses of ``std::lock_guard`` and suggests replacing them with C++17's
alternative ``std::scoped_lock``.
Fix-its are provided for single declarations of ``std::lock_guard`` and warning
is emitted for multiple declarations of ``std::lock_guard`` that can be
replaced with a single declaration of ``std::scoped_lock``.
is emitted for multiple declarations of ``std::lock_guard`` or ``std::scoped_lock``
that can be replaced with a single declaration of ``std::scoped_lock``.
Examples
--------
@ -45,14 +45,14 @@ Transforms to:
std::lock(M);
std::scoped_lock L(std::adopt_lock, M);
Multiple ``std::lock_guard`` declarations only emit warnings:
Multiple consecutive lock declarations only emit warnings:
.. code-block:: c++
std::mutex M1, M2;
std::lock(M1, M2);
std::lock_guard Lock1(M1, std::adopt_lock); // warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
std::lock_guard Lock2(M2, std::adopt_lock); // note: additional 'std::lock_guard' declared here
std::lock_guard Lock1(M1, std::adopt_lock); // warning: use single 'std::scoped_lock' instead of multiple locks
std::scoped_lock<std::mutex> Lock2(M2, std::adopt_lock); // note: additional 'std::scoped_lock' declared here
Limitations

View file

@ -10,14 +10,14 @@ void Positive() {
{
std::lock_guard<std::mutex> l1(m);
std::lock_guard<std::mutex> l2(m);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
}
{
std::lock_guard<std::mutex> l1(m), l2(m), l3(m);
std::lock_guard<std::mutex> l4(m);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:40: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:47: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:33: note: additional 'std::lock_guard' declared here
@ -27,7 +27,7 @@ void Positive() {
std::lock(m, m);
std::lock_guard<std::mutex> l1(m, std::adopt_lock);
std::lock_guard<std::mutex> l2(m, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
}
}
@ -42,17 +42,28 @@ void Negative() {
std::lock_guard<std::mutex> l(m, std::adopt_lock);
}
{
{
std::lock_guard<std::mutex> l3(m);
int a = 0;
std::lock_guard<std::mutex> l4(m, std::adopt_lock);
}
}
void NegativeSingleScopedLock() {
std::mutex m1, m2;
{
std::scoped_lock<std::mutex> l(m1);
}
{
std::scoped_lock<std::mutex, std::mutex> l(m1, m2);
}
}
void PositiveInsideArg(std::mutex &m1, std::mutex &m2, std::mutex &m3) {
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:31: note: additional 'std::lock_guard' declared here
}
@ -67,7 +78,7 @@ void PositiveTemplated() {
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:31: note: additional 'std::lock_guard' declared here
}
@ -83,7 +94,7 @@ void PositiveTemplatedMutex() {
std::lock_guard<Mutex> l1(m1);
std::lock_guard<Mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:26: note: additional 'std::lock_guard' declared here
}

View file

@ -19,20 +19,20 @@ void Positive() {
{
std::lock_guard<std::mutex> l1(m);
std::lock_guard<std::mutex> l2(m);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
}
{
std::lock_guard<std::mutex> l1(m), l2(m);
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:40: note: additional 'std::lock_guard' declared here
}
{
std::lock_guard<std::mutex> l1(m), l2(m), l3(m);
std::lock_guard<std::mutex> l4(m);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:40: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:47: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:33: note: additional 'std::lock_guard' declared here
@ -42,7 +42,7 @@ void Positive() {
std::lock(m, m);
std::lock_guard<std::mutex> l1(m, std::adopt_lock);
std::lock_guard<std::mutex> l2(m, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m);
@ -77,7 +77,7 @@ void PositiveNested() {
{
std::lock_guard<std::mutex> l3(m1);
std::lock_guard<std::mutex> l4(m1);
// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:37: note: additional 'std::lock_guard' declared here
}
{
@ -96,7 +96,7 @@ void PositiveNested() {
void PositiveInsideArg(std::mutex &m1, std::mutex &m2, std::mutex &m3) {
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:31: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m3);
@ -143,12 +143,12 @@ void PositiveLambda() {
std::lock_guard<std::mutex> l3(m);
std::lock_guard<std::mutex> l4(m);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:31: note: additional 'std::lock_guard' declared here
auto lamda2 = [&]() {
std::lock_guard<std::mutex> l3(m);
std::lock_guard<std::mutex> l4(m);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
};
@ -156,7 +156,7 @@ void PositiveLambda() {
std::lock(m, m);
std::lock_guard<std::mutex> l1(m, std::adopt_lock);
std::lock_guard<std::mutex> l2(m, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m);
@ -191,7 +191,7 @@ void PositiveTemplated() {
{
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
}
@ -199,7 +199,7 @@ void PositiveTemplated() {
std::lock(m1, m2);
std::lock_guard<std::mutex> l1(m1, std::adopt_lock);
std::lock_guard<std::mutex> l2(m2, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m3);
@ -220,7 +220,7 @@ void PositiveTemplatedMutex() {
{
std::lock_guard<Mutex> l1(m1);
std::lock_guard<Mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:28: note: additional 'std::lock_guard' declared here
}
@ -228,7 +228,7 @@ void PositiveTemplatedMutex() {
std::lock(m1, m2);
std::lock_guard<Mutex> l1(m1, std::adopt_lock);
std::lock_guard<Mutex> l2(m2, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:28: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<Mutex> l3(m3);
@ -266,7 +266,7 @@ struct PositiveClass {
{
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:35: note: additional 'std::lock_guard' declared here
}
@ -274,7 +274,7 @@ struct PositiveClass {
std::lock(m1, m2);
std::lock_guard<std::mutex> l1(m1, std::adopt_lock);
std::lock_guard<std::mutex> l2(m2, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:35: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m3);
@ -302,7 +302,7 @@ struct PositiveTemplatedClass {
std::lock(m1, m2);
std::lock_guard<std::mutex> l1(m1, std::adopt_lock);
std::lock_guard<std::mutex> l2(m2, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:35: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m3);
@ -323,7 +323,7 @@ struct PositiveTemplatedClass {
std::lock(m1, m2);
std::lock_guard<std::mutex> l1(m1, std::adopt_lock);
std::lock_guard<std::mutex> l2(m2, std::adopt_lock);
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:35: note: additional 'std::lock_guard' declared here
int a = 0;
std::lock_guard<std::mutex> l3(m3);
@ -416,7 +416,7 @@ void PositiveInUsingTypedefs() {
Lock<std::mutex> l1(m, std::adopt_lock);
LockM l2(m, std::adopt_lock);
LockDef l3(m), l4(m);
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:11: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-3]]:13: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:20: note: additional 'std::lock_guard' declared here
@ -441,7 +441,7 @@ void PositiveInUsingTypedefsTemplated() {
Lock<Mutex> l1(m, std::adopt_lock);
LockM l2(m, std::adopt_lock);
LockDef l3(m), l4(m);
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard'
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:11: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-3]]:13: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-4]]:20: note: additional 'std::lock_guard' declared here
@ -469,3 +469,84 @@ void NegativeNonStdLockGuard() {
lock_guard<std::mutex> l2(m);
}
}
void PositiveMultipleScopedLocks() {
std::mutex m1, m2;
{
std::scoped_lock<std::mutex> l1(m1);
std::scoped_lock<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:34: note: additional 'std::scoped_lock' declared here
}
{
std::scoped_lock<std::mutex> l1(m1), l2(m2);
std::scoped_lock<std::mutex> l3(m1);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:42: note: additional 'std::scoped_lock' declared here
// CHECK-MESSAGES: :[[@LINE-3]]:34: note: additional 'std::scoped_lock' declared here
}
}
void PositiveMixedLockGuardAndScopedLock() {
std::mutex m1, m2;
{
std::lock_guard<std::mutex> l1(m1);
std::scoped_lock<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:34: note: additional 'std::scoped_lock' declared here
}
{
std::scoped_lock<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:33: note: additional 'std::lock_guard' declared here
}
}
void NegativeMultiMutexScopedLock() {
std::mutex m1, m2;
std::scoped_lock<std::mutex, std::mutex> l(m1, m2);
}
void PositiveMultipleMultiMutexLocks() {
std::mutex m1, m2, m3, m4;
std::scoped_lock<std::mutex, std::mutex> l1(m1, m2);
std::scoped_lock<std::mutex, std::mutex> l2(m3, m4);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-2]]:44: note: additional 'std::scoped_lock' declared here
}
void PositiveOneTwoOneLocks() {
std::mutex m1, m2, m3, m4;
std::scoped_lock<std::mutex> l1(m1);
std::scoped_lock<std::mutex, std::mutex> l2(m2, m3);
std::lock_guard<std::mutex> l3(m4);
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:44: note: additional 'std::scoped_lock' declared here
// CHECK-MESSAGES: :[[@LINE-3]]:31: note: additional 'std::lock_guard' declared here
}
void PositiveOneOneTwoLocks() {
std::mutex m1, m2, m3, m4;
std::scoped_lock<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
std::scoped_lock<std::mutex, std::mutex> l3(m3, m4);
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use single 'std::scoped_lock' instead of multiple locks
// CHECK-MESSAGES: :[[@LINE-3]]:31: note: additional 'std::lock_guard' declared here
// CHECK-MESSAGES: :[[@LINE-3]]:44: note: additional 'std::scoped_lock' declared here
}
void NegativeSingleScopedLock() {
std::mutex m1, m2;
{
std::scoped_lock<std::mutex> l(m1);
}
{
std::scoped_lock<std::mutex> l1(m1);
int a = 0;
std::scoped_lock<std::mutex> l2(m2);
}
}