]> granicus.if.org Git - clang/commitdiff
Thread safety analysis: fixed incorrect error message at the end of a locks_required...
authorDeLesley Hutchins <delesley@google.com>
Mon, 2 Jul 2012 22:16:54 +0000 (22:16 +0000)
committerDeLesley Hutchins <delesley@google.com>
Mon, 2 Jul 2012 22:16:54 +0000 (22:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159607 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/Analyses/ThreadSafety.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Analysis/ThreadSafety.cpp
lib/Sema/AnalysisBasedWarnings.cpp
test/SemaCXX/warn-thread-safety-analysis.cpp

index beb1938f859303839381eeb8adfdd6c46863e6b1..742cc04344568478ac31cd45166e26ec33b114f1 100644 (file)
@@ -60,7 +60,8 @@ enum AccessKind {
 enum LockErrorKind {
   LEK_LockedSomeLoopIterations,
   LEK_LockedSomePredecessors,
-  LEK_LockedAtEndOfFunction
+  LEK_LockedAtEndOfFunction,
+  LEK_NotLockedAtEndOfFunction
 };
 
 /// Handler class for thread safety warnings.
index 18b36e512f35565c45d0c6a84809b3367f535ea6..66ae44fb28194568e72f3c8d365281a8d6dcfb7c 100644 (file)
@@ -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<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
 def warn_lock_some_predecessors : Warning<
   "mutex '%0' is not locked on every path through here">,
index e29b2a9d0694d09976683eef65de590fbf1ff164..b82bc55dffdcb5cda0ff3996c44d2633809ac445 100644 (file)
@@ -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
index 1d74d7f765b283a55b3317b6cad5bdd4fb43feab..d696283f7f510924dd6f6137111269fbf3238cdb 100644 (file)
@@ -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;
index 53f3bee2ac74c34149a573a8b4dea637a3de6854..35a2dd012146cb1e2bb01ad20ea02af1e66ca1ab 100644 (file)
@@ -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