[clang] [clang][analyzer] Add defer_lock_t modelling to BlockInCriticalSectionChecker (PR #168338)
Endre Fülöp via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 17 02:19:08 PST 2025
https://github.com/gamesh411 created https://github.com/llvm/llvm-project/pull/168338
None
>From b5a831cca3113e3dfeead21438bdfa1803094d7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Fri, 14 Nov 2025 11:46:38 +0100
Subject: [PATCH] [clang][analyzer] Add defer_lock_t modelling to
BlockInCriticalSectionChecker
---
.../BlockInCriticalSectionChecker.cpp | 20 ++++++++++++++++++-
.../Analysis/block-in-critical-section.cpp | 9 +++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 68bee710e5ce5..99137e038811d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -115,7 +115,25 @@ class RAIIMutexDescriptor {
return false;
const IdentifierInfo *II =
cast<CXXRecordDecl>(C->getDecl()->getParent())->getIdentifier();
- return II == Guard;
+ if (II != Guard)
+ return false;
+
+ // For unique_lock, check if it's constructed with a ctor that takes the tag
+ // type defer_lock_t. In this case, the lock is not acquired.
+ if constexpr (std::is_same_v<T, CXXConstructorCall>) {
+ if (GuardName == "unique_lock" && C->getNumArgs() >= 2) {
+ const Expr *SecondArg = C->getArgExpr(1);
+ QualType ArgType = SecondArg->getType().getNonReferenceType();
+ QualType UnqualifiedType = ArgType.getUnqualifiedType();
+ if (const auto *RD = UnqualifiedType->getAsRecordDecl();
+ RD && RD->getName() == "defer_lock_t" &&
+ RD->getDeclContext()->isStdNamespace()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
public:
diff --git a/clang/test/Analysis/block-in-critical-section.cpp b/clang/test/Analysis/block-in-critical-section.cpp
index ee9a708f231a8..674a09265faa5 100644
--- a/clang/test/Analysis/block-in-critical-section.cpp
+++ b/clang/test/Analysis/block-in-critical-section.cpp
@@ -16,9 +16,12 @@ struct lock_guard {
lock_guard<T>(std::mutex) {}
~lock_guard<T>() {}
};
+struct defer_lock_t {};
+constexpr defer_lock_t defer_lock{};
template<typename T>
struct unique_lock {
unique_lock<T>(std::mutex) {}
+ unique_lock<T>(std::mutex, defer_lock_t) {} // defer_lock parameter
~unique_lock<T>() {}
};
template<typename T>
@@ -309,3 +312,9 @@ void testTrylockCurrentlyFalsePositive(pthread_mutex_t *m) {
// FIXME: this is a false positive, the lock was not acquired
}
}
+
+void testBlockInCriticalSectionUniqueLockWithDeferLock() {
+ std::mutex g_mutex;
+ std::unique_lock<std::mutex> lock(g_mutex, std::defer_lock);
+ sleep(1); // no-warning
+}
More information about the cfe-commits
mailing list