Summary:
We unwrap conditional expressions containing try-lock functions.
Additionally we don't acquire on conditional expression branches, since
that is usually not helpful. When joining the branches we would almost
certainly get a warning then.
Hopefully fixes an issue that was raised in D52398.
Reviewers: aaron.ballman, delesley, hokein
Reviewed By: aaron.ballman
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D52888
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@343902
91177308-0d34-0410-b5e6-
96231b3b80d8
if (BOP->getOpcode() == BO_LOr)
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
return nullptr;
+ } else if (const auto *COP = dyn_cast<ConditionalOperator>(Cond)) {
+ bool TCond, FCond;
+ if (getStaticBooleanValue(COP->getTrueExpr(), TCond) &&
+ getStaticBooleanValue(COP->getFalseExpr(), FCond)) {
+ if (TCond && !FCond)
+ return getTrylockCallExpr(COP->getCond(), C, Negate);
+ if (!TCond && FCond) {
+ Negate = !Negate;
+ return getTrylockCallExpr(COP->getCond(), C, Negate);
+ }
+ }
}
return nullptr;
}
Result = ExitSet;
const Stmt *Cond = PredBlock->getTerminatorCondition();
- if (!Cond)
+ // We don't acquire try-locks on ?: branches, only when its result is used.
+ if (!Cond || isa<ConditionalOperator>(PredBlock->getTerminator()))
return;
bool Negate = false;
int i = a;
mu.Unlock();
}
+
+ // Test with conditional operator
+ void foo13() {
+ if (mu.TryLock() ? 1 : 0)
+ mu.Unlock();
+ }
+
+ void foo14() {
+ if (mu.TryLock() ? 0 : 1)
+ return;
+ mu.Unlock();
+ }
+
+ void foo15() {
+ if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
+ mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}
+ } // expected-warning{{mutex 'mu' is not held on every path through here}}
}; // end TestTrylock
} // end namespace TrylockTest