From: DeLesley Hutchins Date: Mon, 2 Jul 2012 22:16:54 +0000 (+0000) Subject: Thread safety analysis: fixed incorrect error message at the end of a locks_required... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=879a4334e4c4cab0c22ba91492ffc2838bbc21fc;p=clang Thread safety analysis: fixed incorrect error message at the end of a locks_required function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159607 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index beb1938f85..742cc04344 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -60,7 +60,8 @@ enum AccessKind { enum LockErrorKind { LEK_LockedSomeLoopIterations, LEK_LockedSomePredecessors, - LEK_LockedAtEndOfFunction + LEK_LockedAtEndOfFunction, + LEK_NotLockedAtEndOfFunction }; /// Handler class for thread safety warnings. diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 18b36e512f..66ae44fb28 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1775,6 +1775,9 @@ def warn_double_lock : Warning< def warn_no_unlock : Warning< "mutex '%0' is still locked at the end of function">, InGroup, DefaultIgnore; +def warn_expecting_locked : Warning< + "expecting mutex '%0' to be locked at the end of function">, + InGroup, DefaultIgnore; // FIXME: improve the error message about locks not in scope def warn_lock_some_predecessors : Warning< "mutex '%0' is not locked on every path through here">, diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index e29b2a9d06..b82bc55dff 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -951,7 +951,13 @@ public: const CFGBlock *CurrBlock); Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2, - SourceLocation JoinLoc, LockErrorKind LEK); + SourceLocation JoinLoc, + LockErrorKind LEK1, LockErrorKind LEK2); + + Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2, + SourceLocation JoinLoc, LockErrorKind LEK1) { + return intersectAndWarn(LSet1, LSet2, JoinLoc, LEK1, LEK1); + } void runAnalysis(AnalysisDeclContext &AC); }; @@ -1541,11 +1547,13 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) { /// \param LSet1 The first lockset. /// \param LSet2 The second lockset. /// \param JoinLoc The location of the join point for error reporting -/// \param LEK The error message to report. +/// \param LEK1 The error message to report if a mutex is missing from LSet1 +/// \param LEK2 The error message to report if a mutex is missing from Lset2 Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2, SourceLocation JoinLoc, - LockErrorKind LEK) { + LockErrorKind LEK1, + LockErrorKind LEK2) { Lockset Intersection = LSet1; for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) { @@ -1564,7 +1572,7 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1, if (!LSet2LockData.Managed) Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(), LSet2LockData.AcquireLoc, - JoinLoc, LEK); + JoinLoc, LEK1); } } @@ -1576,7 +1584,7 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1, if (!MissingLock.Managed) Handler.handleMutexHeldEndOfScope(Mutex.getName(), MissingLock.AcquireLoc, - JoinLoc, LEK); + JoinLoc, LEK2); Intersection = LocksetFactory.remove(Intersection, Mutex); } } @@ -1818,7 +1826,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { // FIXME: Should we call this function for all blocks which exit the function? intersectAndWarn(Initial->EntrySet, Final->ExitSet, Final->ExitLoc, - LEK_LockedAtEndOfFunction); + LEK_LockedAtEndOfFunction, + LEK_NotLockedAtEndOfFunction); } } // end anonymous namespace diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 1d74d7f765..d696283f7f 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -1061,6 +1061,9 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { case LEK_LockedAtEndOfFunction: DiagID = diag::warn_no_unlock; break; + case LEK_NotLockedAtEndOfFunction: + DiagID = diag::warn_expecting_locked; + break; } if (LocEndOfScope.isInvalid()) LocEndOfScope = FunEndLocation; diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 53f3bee2ac..35a2dd0121 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -2451,6 +2451,22 @@ void Foo::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }; +namespace UnlockBug { +class Foo { +public: + Mutex mutex_; + + void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}} + mutex_.Unlock(); + } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}} + + + void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}} + mutex_.Unlock(); + } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}} +}; + +} // end namespace UnlockBug