Skip to content

Commit e64ef63

Browse files
authored
Thread Safety Analysis: Differentiate between lock sets at real join points and expected/actual sets at function end (#105526)
This fixes false positives related to returning a scoped lockable object. At the end of a function, we check managed locks instead of scoped locks. At real join points, we skip checking managed locks because we assume that the scope keeps track of its underlying mutexes and will release them at its destruction. So, checking for the scopes is sufficient. However, at the end of a function, we aim at comparing the expected and the actual lock sets. There, we skip checking scoped locks to prevent to get duplicate warnings for the same lock.
1 parent 30f1cfb commit e64ef63

File tree

2 files changed

+14
-14
lines changed

2 files changed

+14
-14
lines changed

clang/lib/Analysis/ThreadSafety.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,9 @@ class ScopedLockableFactEntry : public FactEntry {
922922
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
923923
SourceLocation JoinLoc, LockErrorKind LEK,
924924
ThreadSafetyHandler &Handler) const override {
925+
if (LEK == LEK_LockedAtEndOfFunction || LEK == LEK_NotLockedAtEndOfFunction)
926+
return;
927+
925928
for (const auto &UnderlyingMutex : UnderlyingMutexes) {
926929
const auto *Entry = FSet.findLock(FactMan, UnderlyingMutex.Cap);
927930
if ((UnderlyingMutex.Kind == UCK_Acquired && Entry) ||
@@ -2224,7 +2227,7 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &EntrySet,
22242227
if (join(FactMan[*EntryIt], ExitFact,
22252228
EntryLEK != LEK_LockedSomeLoopIterations))
22262229
*EntryIt = Fact;
2227-
} else if (!ExitFact.managed()) {
2230+
} else if (!ExitFact.managed() || EntryLEK == LEK_LockedAtEndOfFunction) {
22282231
ExitFact.handleRemovalFromIntersection(ExitSet, FactMan, JoinLoc,
22292232
EntryLEK, Handler);
22302233
}
@@ -2236,7 +2239,8 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &EntrySet,
22362239
const FactEntry *ExitFact = ExitSet.findLock(FactMan, *EntryFact);
22372240

22382241
if (!ExitFact) {
2239-
if (!EntryFact->managed() || ExitLEK == LEK_LockedSomeLoopIterations)
2242+
if (!EntryFact->managed() || ExitLEK == LEK_LockedSomeLoopIterations ||
2243+
ExitLEK == LEK_NotLockedAtEndOfFunction)
22402244
EntryFact->handleRemovalFromIntersection(EntrySetOrig, FactMan, JoinLoc,
22412245
ExitLEK, Handler);
22422246
if (ExitLEK == LEK_LockedSomePredecessors)

clang/test/SemaCXX/warn-thread-safety-analysis.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6077,24 +6077,20 @@ namespace ReturnScopedLockable {
60776077
class Object {
60786078
public:
60796079
MutexLock lock() EXCLUSIVE_LOCK_FUNCTION(mutex) {
6080-
// TODO: False positive because scoped lock isn't destructed.
6081-
return MutexLock(&mutex); // expected-note {{mutex acquired here}}
6082-
} // expected-warning {{mutex 'mutex' is still held at the end of function}}
6080+
return MutexLock(&mutex);
6081+
}
60836082

60846083
ReaderMutexLock lockShared() SHARED_LOCK_FUNCTION(mutex) {
6085-
// TODO: False positive because scoped lock isn't destructed.
6086-
return ReaderMutexLock(&mutex); // expected-note {{mutex acquired here}}
6087-
} // expected-warning {{mutex 'mutex' is still held at the end of function}}
6084+
return ReaderMutexLock(&mutex);
6085+
}
60886086

60896087
MutexLock adopt() EXCLUSIVE_LOCKS_REQUIRED(mutex) {
6090-
// TODO: False positive because scoped lock isn't destructed.
6091-
return MutexLock(&mutex, true); // expected-note {{mutex acquired here}}
6092-
} // expected-warning {{mutex 'mutex' is still held at the end of function}}
6088+
return MutexLock(&mutex, true);
6089+
}
60936090

60946091
ReaderMutexLock adoptShared() SHARED_LOCKS_REQUIRED(mutex) {
6095-
// TODO: False positive because scoped lock isn't destructed.
6096-
return ReaderMutexLock(&mutex, true); // expected-note {{mutex acquired here}}
6097-
} // expected-warning {{mutex 'mutex' is still held at the end of function}}
6092+
return ReaderMutexLock(&mutex, true);
6093+
}
60986094

60996095
int x GUARDED_BY(mutex);
61006096
void needsLock() EXCLUSIVE_LOCKS_REQUIRED(mutex);

0 commit comments

Comments
 (0)