diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -135,6 +135,8 @@ else if (FName == "pthread_mutex_unlock" || FName == "pthread_rwlock_unlock" || FName == "lck_mtx_unlock" || + FName == "lck_rw_unlock_exclusive" || + FName == "lck_rw_unlock_shared" || FName == "lck_rw_done") ReleaseLock(C, CE, C.getSVal(CE->getArg(0))); else if (FName == "pthread_mutex_destroy") diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h b/clang/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h --- a/clang/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h @@ -15,6 +15,10 @@ void *foo; } lck_grp_t; +typedef struct { + void *foo; +} lck_rw_t; + typedef pthread_mutex_t lck_mtx_t; extern int pthread_mutex_lock(pthread_mutex_t *); @@ -28,3 +32,8 @@ extern void lck_mtx_unlock(lck_mtx_t *); extern boolean_t lck_mtx_try_lock(lck_mtx_t *); extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp); + +extern void lck_rw_lock_exclusive(lck_rw_t *lck); +extern void lck_rw_unlock_exclusive(lck_rw_t *lck); +extern void lck_rw_lock_shared(lck_rw_t *lck); +extern void lck_rw_unlock_shared(lck_rw_t *lck); diff --git a/clang/test/Analysis/pthreadlock.c b/clang/test/Analysis/pthreadlock.c --- a/clang/test/Analysis/pthreadlock.c +++ b/clang/test/Analysis/pthreadlock.c @@ -8,6 +8,7 @@ pthread_mutex_t *pmtx; lck_mtx_t lck1, lck2; lck_grp_t grp1; +lck_rw_t rw; #define NULL 0 @@ -213,6 +214,13 @@ } } +void ok29(void) { + lck_rw_lock_shared(&rw); + lck_rw_unlock_shared(&rw); + lck_rw_lock_exclusive(&rw); // no-warning + lck_rw_unlock_exclusive(&rw); // no-warning +} + void bad1(void) { @@ -471,3 +479,10 @@ if (ret != 0) pthread_mutex_lock(&mtx1); } + +void bad32(void) { + lck_rw_lock_shared(&rw); + lck_rw_unlock_exclusive(&rw); // FIXME: warn - should be shared? + lck_rw_lock_exclusive(&rw); + lck_rw_unlock_shared(&rw); // FIXME: warn - should be exclusive? +}