[clang] Thread safety analysis: Don't warn on acquiring reentrant capability (PR #150857)
Aaron Puchert via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 27 16:24:52 PDT 2025
https://github.com/aaronpuchert created https://github.com/llvm/llvm-project/pull/150857
The point of reentrant capabilities is that they can be acquired multiple times, so they should probably be excluded from requiring a negative capability on acquisition via -Wthread-safety-negative.
However, we still propagate explicit negative requirements.
>From 26716f3b21d39f9cf3eaced3cbc6fff9e8f27be0 Mon Sep 17 00:00:00 2001
From: Aaron Puchert <aaronpuchert at alice-dsl.net>
Date: Sun, 27 Jul 2025 23:24:51 +0200
Subject: [PATCH] Thread safety analysis: Don't warn on acquiring reentrant
capability
The point of reentrant capabilities is that they can be acquired
multiple times, so they should probably be excluded from requiring a
negative capability on acquisition via -Wthread-safety-negative.
However, we still propagate explicit negative requirements.
---
clang/lib/Analysis/ThreadSafety.cpp | 2 +-
.../SemaCXX/warn-thread-safety-negative.cpp | 32 +++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 80e7c8eff671a..dadb0b757a2c8 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1331,7 +1331,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
FSet.removeLock(FactMan, NegC);
}
else {
- if (inCurrentScope(*Entry) && !Entry->asserted())
+ if (inCurrentScope(*Entry) && !Entry->asserted() && !Entry->reentrant())
Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(),
NegC.toString(), Entry->loc());
}
diff --git a/clang/test/SemaCXX/warn-thread-safety-negative.cpp b/clang/test/SemaCXX/warn-thread-safety-negative.cpp
index 9eabd67e4fc76..0caf6d6139e58 100644
--- a/clang/test/SemaCXX/warn-thread-safety-negative.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-negative.cpp
@@ -21,6 +21,15 @@ class LOCKABLE Mutex {
void AssertReaderHeld() ASSERT_SHARED_LOCK();
};
+class LOCKABLE REENTRANT_CAPABILITY ReentrantMutex {
+public:
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+
+ // for negative capabilities
+ const ReentrantMutex& operator!() const { return *this; }
+};
+
class SCOPED_LOCKABLE MutexLock {
public:
MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
@@ -89,6 +98,29 @@ class Foo {
}
};
+class Reentrant {
+ ReentrantMutex mu;
+
+public:
+ void acquire() {
+ mu.Lock(); // no warning -- reentrant mutex
+ mu.Unlock();
+ }
+
+ void requireNegative() EXCLUSIVE_LOCKS_REQUIRED(!mu) { // warning?
+ mu.Lock();
+ mu.Unlock();
+ }
+
+ void callRequireNegative() {
+ requireNegative(); // expected-warning{{calling function 'requireNegative' requires negative capability '!mu'}}
+ }
+
+ void callHaveNegative() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ requireNegative();
+ }
+};
+
} // end namespace SimpleTest
Mutex globalMutex;
More information about the cfe-commits
mailing list