https://github.com/vbvictor updated https://github.com/llvm/llvm-project/pull/209272
>From adba5005e2e45e4daf70a3dcc788db8bc002b6f9 Mon Sep 17 00:00:00 2001 From: Victor Baranov <[email protected]> Date: Mon, 13 Jul 2026 22:07:01 +0300 Subject: [PATCH 1/2] [clang-tidy] Flag consecutive scoped_locks in use-scoped-lock --- .../modernize/UseScopedLockCheck.cpp | 73 ++++++++--- clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../checks/modernize/use-scoped-lock.rst | 10 +- ...scoped-lock-warn-on-single-locks-false.cpp | 25 ++-- .../checkers/modernize/use-scoped-lock.cpp | 119 +++++++++++++++--- 5 files changed, 184 insertions(+), 49 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp index 74f15a68d6326..a63113f362d2f 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp @@ -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) { + if (const NamedDecl *LockDecl = getLockClassDecl(Type)) + return LockDecl->getName(); + return ""; +} + 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,6 +143,9 @@ 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( @@ -130,12 +153,18 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) { hasUnqualifiedDesugaredType(templateSpecializationType( hasDeclaration(LockGuardClassDecl))))); - const auto LockVarDecl = varDecl(hasType(LockGuardType)); + const auto LockType = qualType(anyOf( + hasUnqualifiedDesugaredType(recordType(hasDeclaration(LockClassDecl))), + hasUnqualifiedDesugaredType( + templateSpecializationType(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 +280,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'"); - - for (const VarDecl *Lock : llvm::drop_begin(Group)) - diag(Lock->getLocation(), "additional 'std::lock_guard' declared here", - DiagnosticIDs::Note); + continue; + } + + 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); } } } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2581a9d3c5657..92445ee26bf51 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -690,6 +690,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: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-scoped-lock.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-scoped-lock.rst index 9235d4246782e..03da2da0d4d3c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-scoped-lock.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-scoped-lock.rst @@ -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 diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock-warn-on-single-locks-false.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock-warn-on-single-locks-false.cpp index 503ebe1ebc7b2..2dc0f6d9a8c53 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock-warn-on-single-locks-false.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock-warn-on-single-locks-false.cpp @@ -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 } diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock.cpp index e09c28f73a5df..4ef8298536054 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-scoped-lock.cpp @@ -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); + } +} >From 1f742de4a652f1b28c5ed9276ce58d70cf43237a Mon Sep 17 00:00:00 2001 From: Victor Baranov <[email protected]> Date: Tue, 14 Jul 2026 08:26:01 +0300 Subject: [PATCH 2/2] fix --- .../modernize/UseScopedLockCheck.cpp | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp index a63113f362d2f..dabb3ffeb7c2b 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp @@ -55,9 +55,9 @@ static bool isScopedLock(const QualType &Type) { } static StringRef getLockClassName(const QualType &Type) { - if (const NamedDecl *LockDecl = getLockClassDecl(Type)) - return LockDecl->getName(); - return ""; + const NamedDecl *LockDecl = getLockClassDecl(Type); + assert(LockDecl); + return LockDecl->getName(); } static SmallVector<const VarDecl *> getLockGuardsFromDecl(const DeclStmt *DS) { @@ -147,16 +147,13 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) { 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 LockType = qualType(anyOf( - hasUnqualifiedDesugaredType(recordType(hasDeclaration(LockClassDecl))), - hasUnqualifiedDesugaredType( - templateSpecializationType(hasDeclaration(LockClassDecl))))); + const auto LockType = qualType(hasUnqualifiedDesugaredType( + mapAnyOf(recordType, templateSpecializationType) + .with(hasDeclaration(LockClassDecl)))); const auto LockGuardVarDecl = varDecl(hasType(LockGuardType)); const auto LockVarDecl = varDecl(hasType(LockType)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
