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.
This commit is contained in:
Aaron Puchert 2025-08-03 19:50:17 +02:00 committed by GitHub
parent 408fe1d369
commit a048aeb06e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 1 deletions

View File

@ -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());
}

View File

@ -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;