llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: JasonHonKL

<details>
<summary>Changes</summary>

Add explicit cast&lt;CXXMethodDecl&gt;() when obtaining the method declaration 
from CXXMemberCall in RAIIMemberMutexDescriptor::matches().

This change:

- Improves type safety by making pointer conversions explicit
- Provides debug build validation through LLVM's cast&lt;T&gt;() assertion
- Has zero runtime overhead (optimized away in release builds)
- Aligns with LLVM coding style for known-valid type conversions


The RAIIMemberMutexDescriptor class handles explicit lock()/unlock() member 
calls on RAII mutex wrappers like std::unique_lock, complementing the 
constructor/destructor handling in RAIIMutexDescriptor. This ensures the 
BlockInCriticalSection checker correctly tracks lock state when manual 
lock/unlock methods are used.

Fixes #<!-- -->204304

---
Full diff: https://github.com/llvm/llvm-project/pull/204338.diff


1 Files Affected:

- (modified) 
clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp (+51-3) 


``````````diff
diff --git 
a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 03c576270797b..3d0b27af79763 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -157,9 +157,55 @@ class RAIIMutexDescriptor {
   }
 };
 
+class RAIIMemberMutexDescriptor {
+  mutable const IdentifierInfo *WrapperType{};
+  mutable bool IdentifierInitialized{};
+  mutable llvm::SmallString<32> WrapperTypeName{};
+
+  void initIdentifierInfo(const CallEvent &Call) const {
+    if (!IdentifierInitialized) {
+      const auto &ASTCtx = Call.getASTContext();
+      WrapperType = &ASTCtx.Idents.get(WrapperTypeName);
+      IdentifierInitialized = true;
+    }
+  }
+
+public:
+  RAIIMemberMutexDescriptor(StringRef WrapperTypeName)
+      : WrapperTypeName(WrapperTypeName) {}
+
+  [[nodiscard]] bool matches(const CallEvent &Call, bool IsLock) const {
+    initIdentifierInfo(Call);
+
+    const auto *MemCall = dyn_cast<CXXMemberCall>(&Call);
+    if (!MemCall)
+      return false;
+
+    const CXXMethodDecl *Method = cast<CXXMethodDecl>(MemCall->getDecl());
+    const CXXRecordDecl *ClassDecl = Method->getParent();
+    const IdentifierInfo *ClassName = ClassDecl->getIdentifier();
+
+    if (ClassName != WrapperType)
+      return false;
+
+    const IdentifierInfo *MethodName = Method->getIdentifier();
+    if (!MethodName)
+      return false;
+
+    if (IsLock)
+      return MethodName->isStr("lock");
+    else
+      return MethodName->isStr("unlock");
+  }
+
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent &Call, bool) const {
+    return cast<CXXMemberCall>(Call).getCXXThisVal().getAsRegion();
+  }
+};
+
 using MutexDescriptor =
     std::variant<FirstArgMutexDescriptor, MemberMutexDescriptor,
-                 RAIIMutexDescriptor>;
+                 RAIIMutexDescriptor, RAIIMemberMutexDescriptor>;
 
 class SuppressNonBlockingStreams : public BugReporterVisitor {
 private:
@@ -214,7 +260,7 @@ class SuppressNonBlockingStreams : public 
BugReporterVisitor {
 
 class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
 private:
-  const std::array<MutexDescriptor, 9> MutexDescriptors{
+  const std::array<MutexDescriptor, 11> MutexDescriptors{
       // NOTE: There are standard library implementations where some methods
       // of `std::mutex` are inherited from an implementation detail base
       // class, and those aren't matched by the name specification {"std",
@@ -239,7 +285,9 @@ class BlockInCriticalSectionChecker : public 
Checker<check::PostCall> {
                               {CDM::CLibrary, {"mtx_unlock"}, 1}),
       RAIIMutexDescriptor("lock_guard"),
       RAIIMutexDescriptor("unique_lock"),
-      RAIIMutexDescriptor("scoped_lock")};
+      RAIIMemberMutexDescriptor("unique_lock"),
+      RAIIMutexDescriptor("scoped_lock"),
+      RAIIMemberMutexDescriptor("scoped_lock")};
 
   const CallDescriptionSet BlockingFunctions{{CDM::CLibrary, {"sleep"}},
                                              {CDM::CLibrary, {"getc"}},

``````````

</details>


https://github.com/llvm/llvm-project/pull/204338
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to