Browse Source

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
DeLesley Hutchins 13 years ago
parent
commit
879a4334e4

+ 2 - 1
include/clang/Analysis/Analyses/ThreadSafety.h

@@ -60,7 +60,8 @@ enum AccessKind {
 enum LockErrorKind {
 enum LockErrorKind {
   LEK_LockedSomeLoopIterations,
   LEK_LockedSomeLoopIterations,
   LEK_LockedSomePredecessors,
   LEK_LockedSomePredecessors,
-  LEK_LockedAtEndOfFunction
+  LEK_LockedAtEndOfFunction,
+  LEK_NotLockedAtEndOfFunction
 };
 };
 
 
 /// Handler class for thread safety warnings.
 /// Handler class for thread safety warnings.

+ 3 - 0
include/clang/Basic/DiagnosticSemaKinds.td

@@ -1775,6 +1775,9 @@ def warn_double_lock : Warning<
 def warn_no_unlock : Warning<
 def warn_no_unlock : Warning<
   "mutex '%0' is still locked at the end of function">,
   "mutex '%0' is still locked at the end of function">,
   InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
   InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_expecting_locked : Warning<
+  "expecting mutex '%0' to be locked at the end of function">,
+  InGroup<ThreadSafetyAnalysis>, DefaultIgnore;  
 // FIXME: improve the error message about locks not in scope
 // FIXME: improve the error message about locks not in scope
 def warn_lock_some_predecessors : Warning<
 def warn_lock_some_predecessors : Warning<
   "mutex '%0' is not locked on every path through here">,
   "mutex '%0' is not locked on every path through here">,

+ 15 - 6
lib/Analysis/ThreadSafety.cpp

@@ -951,7 +951,13 @@ public:
                          const CFGBlock *CurrBlock);
                          const CFGBlock *CurrBlock);
 
 
   Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2,
   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);
   void runAnalysis(AnalysisDeclContext &AC);
 };
 };
@@ -1541,11 +1547,13 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) {
 /// \param LSet1 The first lockset.
 /// \param LSet1 The first lockset.
 /// \param LSet2 The second lockset.
 /// \param LSet2 The second lockset.
 /// \param JoinLoc The location of the join point for error reporting
 /// \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,
 Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
                                                const Lockset &LSet2,
                                                const Lockset &LSet2,
                                                SourceLocation JoinLoc,
                                                SourceLocation JoinLoc,
-                                               LockErrorKind LEK) {
+                                               LockErrorKind LEK1,
+                                               LockErrorKind LEK2) {
   Lockset Intersection = LSet1;
   Lockset Intersection = LSet1;
 
 
   for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
   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)
       if (!LSet2LockData.Managed)
         Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
         Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
                                           LSet2LockData.AcquireLoc,
                                           LSet2LockData.AcquireLoc,
-                                          JoinLoc, LEK);
+                                          JoinLoc, LEK1);
     }
     }
   }
   }
 
 
@@ -1576,7 +1584,7 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
       if (!MissingLock.Managed)
       if (!MissingLock.Managed)
         Handler.handleMutexHeldEndOfScope(Mutex.getName(),
         Handler.handleMutexHeldEndOfScope(Mutex.getName(),
                                           MissingLock.AcquireLoc,
                                           MissingLock.AcquireLoc,
-                                          JoinLoc, LEK);
+                                          JoinLoc, LEK2);
       Intersection = LocksetFactory.remove(Intersection, Mutex);
       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?
   // FIXME: Should we call this function for all blocks which exit the function?
   intersectAndWarn(Initial->EntrySet, Final->ExitSet,
   intersectAndWarn(Initial->EntrySet, Final->ExitSet,
                    Final->ExitLoc,
                    Final->ExitLoc,
-                   LEK_LockedAtEndOfFunction);
+                   LEK_LockedAtEndOfFunction,
+                   LEK_NotLockedAtEndOfFunction);
 }
 }
 
 
 } // end anonymous namespace
 } // end anonymous namespace

+ 3 - 0
lib/Sema/AnalysisBasedWarnings.cpp

@@ -1061,6 +1061,9 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
       case LEK_LockedAtEndOfFunction:
       case LEK_LockedAtEndOfFunction:
         DiagID = diag::warn_no_unlock;
         DiagID = diag::warn_no_unlock;
         break;
         break;
+      case LEK_NotLockedAtEndOfFunction:
+        DiagID = diag::warn_expecting_locked;
+        break;
     }
     }
     if (LocEndOfScope.isInvalid())
     if (LocEndOfScope.isInvalid())
       LocEndOfScope = FunEndLocation;
       LocEndOfScope = FunEndLocation;

+ 16 - 0
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