diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -2467,11 +2467,10 @@ PrevBlock, CurrBlock); // Do not update EntrySet. - intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset, - PrevBlockInfo->ExitLoc, - IsLoop ? LEK_LockedSomeLoopIterations - : LEK_LockedSomePredecessors, - false); + intersectAndWarn( + CurrBlockInfo->EntrySet, PrevLockset, PrevBlockInfo->ExitLoc, + IsLoop ? LEK_LockedSomeLoopIterations : LEK_LockedSomePredecessors, + !IsLoop); } } diff --git a/clang/test/PCH/thread-safety-attrs.cpp b/clang/test/PCH/thread-safety-attrs.cpp --- a/clang/test/PCH/thread-safety-attrs.cpp +++ b/clang/test/PCH/thread-safety-attrs.cpp @@ -311,7 +311,8 @@ } sls_mu.Lock(); } - sls_mu.Unlock(); + sls_mu.Unlock(); // \ + // expected-warning{{releasing mutex 'sls_mu' that was not held}} } #endif diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -337,7 +337,8 @@ } sls_mu.Lock(); } - sls_mu.Unlock(); + sls_mu.Unlock(); // \ + // expected-warning{{releasing mutex 'sls_mu' that was not held}} } //-----------------------------------------// @@ -2582,6 +2583,7 @@ void test3(); void test4(); void test5(); + void test6(); }; @@ -2620,6 +2622,18 @@ rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}} } +void Foo::test6() { + ReleasableMutexLock rlock(&mu_); + do { + if (c) { + rlock.Release(); + break; + } + } while (c); + // No warning on join point because the lock will be released by the scope object anyway + a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} +} + } // end namespace ReleasableScopedLock