aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Puchert <aaronpuchert@alice-dsl.net>2025-08-03 19:50:17 +0200
committerGitHub <noreply@github.com>2025-08-03 19:50:17 +0200
commita048aeb06e5de571eadd646860c320b9a67d1efc (patch)
tree954d6e6bb271409180d58df2538c09244f94ba65
parent408fe1d369df926eecd6c15ce939d38652b4b58d (diff)
downloadllvm-a048aeb06e5de571eadd646860c320b9a67d1efc.zip
llvm-a048aeb06e5de571eadd646860c320b9a67d1efc.tar.gz
llvm-a048aeb06e5de571eadd646860c320b9a67d1efc.tar.bz2
Thread safety analysis: Don't warn on acquiring reentrant capability (#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.
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp2
-rw-r--r--clang/test/SemaCXX/warn-thread-safety-negative.cpp32
2 files changed, 33 insertions, 1 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 80e7c8e..dadb0b7 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 9eabd67..0caf6d6 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 @@ public:
}
};
+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;