summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAaron Puchert <aaronpuchert@alice-dsl.net>2018-10-06 01:09:28 +0000
committerAaron Puchert <aaronpuchert@alice-dsl.net>2018-10-06 01:09:28 +0000
commitb0a2a0cf7dddcb79074767f59401859c6ff30fab (patch)
tree7b3f5eda870185c7a4b9756c8d11440926a8033b /clang
parent34c0e470ae30d7205ad257a56db7e8c588edd3d5 (diff)
downloadbcm5719-llvm-b0a2a0cf7dddcb79074767f59401859c6ff30fab.tar.gz
bcm5719-llvm-b0a2a0cf7dddcb79074767f59401859c6ff30fab.zip
Thread safety analysis: Handle conditional expression in getTrylockCallExpr
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 llvm-svn: 343902
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp14
-rw-r--r--clang/test/SemaCXX/warn-thread-safety-analysis.cpp17
2 files changed, 30 insertions, 1 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 846dc80a4d0..dad2417d8e6 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1435,6 +1435,17 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
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;
}
@@ -1449,7 +1460,8 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
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;
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
index 9df0e2a3b4d..54e3369f4d3 100644
--- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1873,6 +1873,23 @@ struct TestTryLock {
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
OpenPOWER on IntegriCloud