diff options
| -rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 16 | ||||
| -rw-r--r-- | clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 123 |
2 files changed, 94 insertions, 45 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 0c90751155d..d0655878c7c 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1660,15 +1660,22 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond, if (!TCond) Negate = !Negate; return getTrylockCallExpr(BOP->getLHS(), C, Negate); } - else if (getStaticBooleanValue(BOP->getLHS(), TCond)) { + TCond = false; + if (getStaticBooleanValue(BOP->getLHS(), TCond)) { if (!TCond) Negate = !Negate; return getTrylockCallExpr(BOP->getRHS(), C, Negate); } return 0; } + if (BOP->getOpcode() == BO_LAnd) { + // LHS must have been evaluated in a different block. + return getTrylockCallExpr(BOP->getRHS(), C, Negate); + } + if (BOP->getOpcode() == BO_LOr) { + return getTrylockCallExpr(BOP->getRHS(), C, Negate); + } return 0; } - // FIXME -- handle && and || as well. return 0; } @@ -1682,11 +1689,11 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result, const CFGBlock *CurrBlock) { Result = ExitSet; - if (!PredBlock->getTerminatorCondition()) + const Stmt *Cond = PredBlock->getTerminatorCondition(); + if (!Cond) return; bool Negate = false; - const Stmt *Cond = PredBlock->getTerminatorCondition(); const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()]; const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext; @@ -1699,7 +1706,6 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result, if(!FunDecl || !FunDecl->hasAttrs()) return; - MutexIDList ExclusiveLocksToAdd; MutexIDList SharedLocksToAdd; diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 20b1a563541..6c5fd854acd 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -107,14 +107,14 @@ class MutexWrapper { public: Mutex mu; int x __attribute__((guarded_by(mu))); - void MyLock() __attribute__((exclusive_lock_function(mu))); + void MyLock() __attribute__((exclusive_lock_function(mu))); }; MutexWrapper sls_mw; void sls_fun_0() { sls_mw.mu.Lock(); - sls_mw.x = 5; + sls_mw.x = 5; sls_mw.mu.Unlock(); } @@ -3074,44 +3074,6 @@ void Foo::test1() { #endif } - -void Foo::test2() { -/* FIXME: these tests depend on changes to the CFG. - * - if (mu_.TryLock() && c) { - a = 0; - unlock(); - } - else return; - - if (c && mu_.TryLock()) { - a = 0; - unlock(); - } - else return; - - if (!(mu_.TryLock() && c)) - return; - a = 0; - unlock(); - - if (!(c && mu_.TryLock())) - return; - a = 0; - unlock(); - - if (!(mu_.TryLock() == 0) && c) { - a = 0; - unlock(); - } - - if (!mu_.TryLock() || c) - return; - a = 0; - unlock(); -*/ -} - } // end namespace TryLockEqTest @@ -4092,3 +4054,84 @@ public: } // end namespace AssertHeldTest +namespace LogicalConditionalTryLock { + +class Foo { +public: + Mutex mu; + int a GUARDED_BY(mu); + bool c; + + bool newc(); + + void test1() { + if (c && mu.TryLock()) { + a = 0; + mu.Unlock(); + } + } + + void test2() { + bool b = mu.TryLock(); + if (c && b) { + a = 0; + mu.Unlock(); + } + } + + void test3() { + if (c || !mu.TryLock()) + return; + a = 0; + mu.Unlock(); + } + + void test4() { + while (c && mu.TryLock()) { + a = 0; + c = newc(); + mu.Unlock(); + } + } + + void test5() { + while (c) { + if (newc() || !mu.TryLock()) + break; + a = 0; + mu.Unlock(); + } + } + + void test6() { + mu.Lock(); + do { + a = 0; + mu.Unlock(); + } while (newc() && mu.TryLock()); + } + + void test7() { + for (bool b = mu.TryLock(); c && b;) { + a = 0; + mu.Unlock(); + } + } + + void test8() { + if (c && newc() && mu.TryLock()) { + a = 0; + mu.Unlock(); + } + } + + void test9() { + if (!(c && newc() && mu.TryLock())) + return; + a = 0; + mu.Unlock(); + } +}; + +} // end namespace LogicalConditionalTryLock + |

