[clang-tools-extra] [clang-tidy] add new check: modernize-use-scoped-lock (PR #126434)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 12 14:38:36 PST 2025
================
@@ -0,0 +1,333 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s modernize-use-scoped-lock %t -- -- -fno-delayed-template-parsing
+
+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) {}
+};
+
+} // namespace std
+
+
+void Positive() {
+ std::mutex m;
+ {
+ std::lock_guard<std::mutex> l(m);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m);
+ }
+
+ {
+ std::lock_guard<std::mutex> l(m, std::adopt_lock);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(std::adopt_lock, m);
+ }
+
+ {
+ 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]]: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-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
+ }
+
+ {
+ 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]]:33: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m);
+ int b = 0;
+ std::lock_guard<std::mutex> l4(m, std::adopt_lock);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l4(std::adopt_lock, m);
+ }
+}
+
+
+std::mutex p_m1;
+void PositiveShortFunction() {
+ std::lock_guard<std::mutex> l(p_m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(p_m1);
+}
+
+
+void PositiveNested() {
+ std::mutex m1;
+ if (true) {
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+ {
+ std::lock_guard<std::mutex> l2(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l2(m1);
+ {
+ 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]]:37: note: additional 'std::lock_guard' declared here
+ }
+ {
+ std::lock_guard<std::mutex> l2(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l2(m1);
+ }
+ }
+ }
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+}
+
+
+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]]:31: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m3);
+}
+
+
+void PositiveInsideConditional() {
+ std::mutex m1;
+ if (true) {
+ std::lock_guard<std::mutex> l1(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l1(m1);
+ } else {
+ std::lock_guard<std::mutex> l1(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l1(m1);
+ }
+
+ while (true) {
+ std::lock_guard<std::mutex> l1(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l1(m1);
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ std::lock_guard<std::mutex> l1(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l1(m1);
+ }
+}
+
+
+template <typename T>
+void PositiveTemplated() {
+ std::mutex m1, m2, m3;
+ {
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+ }
+
+ {
+ 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]]:33: note: additional 'std::lock_guard' declared here
+ }
+
+ {
+ 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]]:33: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m3);
+ }
+}
+
+
+template <typename Mutex>
+void PositiveTemplatedMutex() {
+ Mutex m1, m2, m3;
+ {
+ std::lock_guard<Mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ }
+
+ {
+ 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]]:28: note: additional 'std::lock_guard' declared here
+ }
+
+ {
+ 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]]:28: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<Mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ }
+}
+
+
+template <template <typename> typename Lock>
+void NegativeTemplate() {
+ std::mutex m1, m2;
+ {
+ Lock<std::mutex> l(m1);
+ }
+
+ {
+ Lock<std::mutex> l1(m1);
+ Lock<std::mutex> l2(m2);
+ }
+}
+
+void instantiate() {
+ NegativeTemplate<std::lock_guard>();
+}
+
+
+struct PositiveClass {
+ void Positive() {
+ {
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+ }
+
+ {
+ 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]]:35: note: additional 'std::lock_guard' declared here
+ }
+
+ {
+ 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]]:35: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m3);
+ }
+ }
+
+ std::mutex m1;
+ std::mutex m2;
+ std::mutex m3;
+};
+
+
+template <typename T>
+struct PositiveTemplatedClass {
+ void Positive() {
+ {
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+ }
+
+ {
+ 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]]:35: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m3);
+ }
+ }
+
+ template <typename... Ts>
+ void TemplatedPositive() {
+ {
+ std::lock_guard<std::mutex> l(m1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l(m1);
+ }
+
+ {
+ 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]]:35: note: additional 'std::lock_guard' declared here
+ int a = 0;
+ std::lock_guard<std::mutex> l3(m3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'std::scoped_lock' instead of 'std::lock_guard'
+ // CHECK-FIXES: std::scoped_lock l3(m3);
+ }
+ }
+
+ std::mutex m1;
+ std::mutex m2;
+ std::mutex m3;
+};
+
+
+template <typename T>
+using Lock = std::lock_guard<T>;
+using LockM = std::lock_guard<std::mutex>;
+typedef std::lock_guard<std::mutex> LockDef;
+
+void NegativeUsingTypedefs() {
----------------
vbvictor wrote:
Added new flag `WarnOnUsingAndTypedef` that warns about usage of `std:lock_guard` in `using`, `typedef`
https://github.com/llvm/llvm-project/pull/126434
More information about the cfe-commits
mailing list