Author: Endre Fülöp Date: 2025-11-19T15:55:44+01:00 New Revision: b11b7b333ddb90db42dfd2d5003e3a51c3a7c38a
URL: https://github.com/llvm/llvm-project/commit/b11b7b333ddb90db42dfd2d5003e3a51c3a7c38a DIFF: https://github.com/llvm/llvm-project/commit/b11b7b333ddb90db42dfd2d5003e3a51c3a7c38a.diff LOG: [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]> Added: Modified: clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp clang/test/Analysis/block-in-critical-section.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index 68bee710e5ce5..2db5310271e1d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -115,7 +115,23 @@ 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(); + if (const auto *RD = ArgType->getAsRecordDecl(); + RD && RD->getName() == "defer_lock_t" && RD->isInStdNamespace()) { + 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 +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
