Skip to content

Commit b11b7b3

Browse files
gamesh411NagyDonatlialan
authored
[clang][analyzer] Add defer_lock_t modelling to BlockInCriticalSectionChecker (#168338)
Fixes #166573 --------- Co-authored-by: Donát Nagy <[email protected]> Co-authored-by: Alan Li <[email protected]>
1 parent 71e3de8 commit b11b7b3

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,23 @@ class RAIIMutexDescriptor {
115115
return false;
116116
const IdentifierInfo *II =
117117
cast<CXXRecordDecl>(C->getDecl()->getParent())->getIdentifier();
118-
return II == Guard;
118+
if (II != Guard)
119+
return false;
120+
121+
// For unique_lock, check if it's constructed with a ctor that takes the tag
122+
// type defer_lock_t. In this case, the lock is not acquired.
123+
if constexpr (std::is_same_v<T, CXXConstructorCall>) {
124+
if (GuardName == "unique_lock" && C->getNumArgs() >= 2) {
125+
const Expr *SecondArg = C->getArgExpr(1);
126+
QualType ArgType = SecondArg->getType().getNonReferenceType();
127+
if (const auto *RD = ArgType->getAsRecordDecl();
128+
RD && RD->getName() == "defer_lock_t" && RD->isInStdNamespace()) {
129+
return false;
130+
}
131+
}
132+
}
133+
134+
return true;
119135
}
120136

121137
public:

clang/test/Analysis/block-in-critical-section.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ struct lock_guard {
1616
lock_guard<T>(std::mutex) {}
1717
~lock_guard<T>() {}
1818
};
19+
struct defer_lock_t {};
20+
constexpr defer_lock_t defer_lock{};
1921
template<typename T>
2022
struct unique_lock {
2123
unique_lock<T>(std::mutex) {}
24+
unique_lock<T>(std::mutex, defer_lock_t) {} // defer_lock parameter
2225
~unique_lock<T>() {}
2326
};
2427
template<typename T>
@@ -309,3 +312,9 @@ void testTrylockCurrentlyFalsePositive(pthread_mutex_t *m) {
309312
// FIXME: this is a false positive, the lock was not acquired
310313
}
311314
}
315+
316+
void testBlockInCriticalSectionUniqueLockWithDeferLock() {
317+
std::mutex g_mutex;
318+
std::unique_lock<std::mutex> lock(g_mutex, std::defer_lock);
319+
sleep(1); // no-warning
320+
}

0 commit comments

Comments
 (0)