Index: lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp	(revision 130989)
+++ lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp	(working copy)
@@ -18,14 +18,15 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "llvm/ADT/ImmutableSet.h"
 
 using namespace clang;
 using namespace ento;
 
 namespace {
-class PthreadLockChecker
-  : public Checker< check::PostStmt<CallExpr> > {
+class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > {
+  mutable llvm::OwningPtr<BugType> BT;
 public:
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
     
@@ -65,17 +66,30 @@
     return;
   llvm::StringRef FName = II->getName();
   
-  if (FName == "pthread_mutex_lock") {
+  if (FName == "pthread_mutex_lock" ||
+      FName == "pthread_rwlock_rdlock" ||
+      FName == "pthread_rwlock_wrlock" ||
+      FName == "lck_mtx_lock" ||
+      FName == "lck_rw_lock_exclusive" ||
+      FName == "lck_rw_lock_shared") {
     if (CE->getNumArgs() != 1)
       return;
     AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false);
   }
-  else if (FName == "pthread_mutex_trylock") {
+  else if (FName == "pthread_mutex_trylock" ||
+           FName == "pthread_rwlock_tryrdlock" ||
+           FName == "pthread_rwlock_tryrwlock" ||
+           FName == "lck_mtx_try_lock" ||
+           FName == "lck_rw_try_lock_exclusive" ||
+           FName == "lck_rw_try_lock_shared") {
     if (CE->getNumArgs() != 1)
       return;
     AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true);
   }  
-  else if (FName == "pthread_mutex_unlock") {
+  else if (FName == "pthread_mutex_unlock" ||
+           FName == "pthread_rwlock_unlock" ||
+           FName == "lck_mtx_unlock" ||
+           FName == "lck_rw_done") {
     if (CE->getNumArgs() != 1)
       return;
     ReleaseLock(C, CE, state->getSVal(CE->getArg(0)));
@@ -97,6 +111,19 @@
   
   DefinedSVal retVal = cast<DefinedSVal>(X);
   const GRState *lockSucc = state;
+
+  if (state->contains<LockSet>(lockR)) {
+    ExplodedNode *N = C.generateSink();
+    if (!N)
+      return;
+
+    BT.reset(new BuiltinBug("Locking an already locked lock"));
+
+    EnhancedBugReport *report =
+      new EnhancedBugReport(*BT, BT->getName(), N);
+    C.EmitReport(report);
+    return;
+  }
   
   if (isTryLock) {
       // Bifurcate the state, and allow a mode where the lock acquisition fails.
@@ -113,7 +140,7 @@
   
     // Record that the lock was acquired.  
   lockSucc = lockSucc->add<LockSet>(lockR);
-  
+
   C.addTransition(lockSucc != state ? C.generateNode(CE, lockSucc) :
                   C.getPredecessor());
 }
@@ -132,9 +159,19 @@
   // require IPA for wrappers.
   const GRState *unlockState = state->remove<LockSet>(lockR);
   
-  if (state == unlockState)
+  if (state == unlockState) {
+    ExplodedNode *N = C.generateSink();
+    if (!N)
+      return;
+
+    BT.reset(new BuiltinBug("Unlocked an unlocked lock"));
+
+    EnhancedBugReport *report =
+      new EnhancedBugReport(*BT, BT->getName(), N);
+    C.EmitReport(report);
     return;
-  
+  }
+
   C.addTransition(C.generateNode(CE, unlockState));  
 }
 
