File tree Expand file tree Collapse file tree 2 files changed +26
-1
lines changed
lib/StaticAnalyzer/Checkers Expand file tree Collapse file tree 2 files changed +26
-1
lines changed Original file line number Diff line number Diff 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
121137public:
Original file line number Diff line number Diff 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{};
1921template <typename T>
2022struct 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};
2427template <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+ }
You can’t perform that action at this time.
0 commit comments