diff options
author | Aaron Puchert <aaronpuchert@alice-dsl.net> | 2025-08-03 19:50:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-03 19:50:17 +0200 |
commit | a048aeb06e5de571eadd646860c320b9a67d1efc (patch) | |
tree | 954d6e6bb271409180d58df2538c09244f94ba65 | |
parent | 408fe1d369df926eecd6c15ce939d38652b4b58d (diff) | |
download | llvm-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.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-thread-safety-negative.cpp | 32 |
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; |