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 <aaronpuch...@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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits