handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
- if (!managed() && !asserted() && !negative() && !isUniversal()) {
+ if (!asserted() && !negative() && !isUniversal()) {
Handler.handleMutexHeldEndOfScope("mutex", toString(), loc(), JoinLoc,
LEK);
}
if (Iter1 != FSet1.end()) {
if (join(FactMan[*Iter1], LDat2) && LEK1 == LEK_LockedSomePredecessors)
*Iter1 = Fact;
- } else {
+ } else if (!LDat2.managed()) {
LDat2.handleRemovalFromIntersection(FSet2, FactMan, JoinLoc, LEK1,
Handler);
}
const FactEntry *LDat2 = FSet2.findLock(FactMan, *LDat1);
if (!LDat2) {
- LDat1->handleRemovalFromIntersection(FSet1Orig, FactMan, JoinLoc, LEK2,
- Handler);
+ if (!LDat1->managed() || LEK2 == LEK_LockedSomeLoopIterations)
+ LDat1->handleRemovalFromIntersection(FSet1Orig, FactMan, JoinLoc, LEK2,
+ Handler);
if (LEK2 == LEK_LockedSomePredecessors)
FSet1.removeLock(FactMan, *LDat1);
}
CFGBlock *FirstLoopBlock = *SI;
CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()];
CFGBlockInfo *LoopEnd = &BlockInfo[CurrBlockID];
- intersectAndWarn(LoopEnd->ExitSet, PreLoop->EntrySet, PreLoop->EntryLoc,
+ intersectAndWarn(PreLoop->EntrySet, LoopEnd->ExitSet, PreLoop->EntryLoc,
LEK_LockedSomeLoopIterations);
}
}
void shared_fun_1() {
sls_mu.ReaderLock(); // \
- // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
+ // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
do {
sls_mu.Unlock();
sls_mu.Lock(); // \
- // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
+ // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
} while (getBool());
sls_mu.Unlock();
}
void shared_bad_0() {
sls_mu.Lock(); // \
- // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
+ // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
do {
sls_mu.Unlock();
sls_mu.ReaderLock(); // \
- // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
+ // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
} while (getBool());
sls_mu.Unlock();
}
x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
}
+void loopAcquire() {
+ RelockableMutexLock scope(&mu, DeferTraits{});
+ for (unsigned i = 1; i < 10; ++i)
+ scope.Lock(); // We could catch this double lock with negative capabilities.
+}
+
+void loopRelease() {
+ RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
+ // We have to warn on this join point despite the lock being managed ...
+ for (unsigned i = 1; i < 10; ++i) { // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
+ x = 1; // ... because we might miss that this doesn't always happen under lock.
+ if (i == 5)
+ scope.Unlock();
+ }
+}
+
+void loopAcquireContinue() {
+ RelockableMutexLock scope(&mu, DeferTraits{});
+ for (unsigned i = 1; i < 10; ++i) {
+ x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+ if (i == 5) {
+ scope.Lock();
+ continue;
+ }
+ }
+}
+
+void loopReleaseContinue() {
+ RelockableMutexLock scope(&mu, ExclusiveTraits{}); // expected-note {{mutex acquired here}}
+ // We have to warn on this join point despite the lock being managed ...
+ for (unsigned i = 1; i < 10; ++i) {
+ x = 1; // ... because we might miss that this doesn't always happen under lock.
+ if (i == 5) {
+ scope.Unlock();
+ continue; // expected-warning {{expecting mutex 'mu' to be held at start of each loop}}
+ }
+ }
+}
+
void exclusiveSharedJoin() {
RelockableMutexLock scope(&mu, DeferTraits{});
if (b)