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

Reply via email to