Index: lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -49,7 +49,8 @@ } }; -class PthreadLockChecker : public Checker< check::PostStmt > { +class PthreadLockChecker : public Checker< eval::Call, + check::PostStmt > { mutable std::unique_ptr BT_doublelock; mutable std::unique_ptr BT_doubleunlock; mutable std::unique_ptr BT_destroylock; @@ -62,7 +63,8 @@ }; public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; - + bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock, bool isTryLock, enum LockingSemantics semantics) const; @@ -78,44 +80,64 @@ REGISTER_MAP_WITH_PROGRAMSTATE(LockMap, const MemRegion *, LockState) -void PthreadLockChecker::checkPostStmt(const CallExpr *CE, - CheckerContext &C) const { +bool PthreadLockChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); const LocationContext *LCtx = C.getLocationContext(); StringRef FName = C.getCalleeName(CE); if (FName.empty()) - return; + return false; if (CE->getNumArgs() != 1 && CE->getNumArgs() != 2) - return; + return false; if (FName == "pthread_mutex_lock" || FName == "pthread_rwlock_rdlock" || - FName == "pthread_rwlock_wrlock") + FName == "pthread_rwlock_wrlock") { AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), false, PthreadSemantics); - else if (FName == "lck_mtx_lock" || + return true; + } else if (FName == "lck_mtx_lock" || FName == "lck_rw_lock_exclusive" || - FName == "lck_rw_lock_shared") + FName == "lck_rw_lock_shared") { AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), false, XNUSemantics); - else if (FName == "pthread_mutex_trylock" || + return true; + } else if (FName == "pthread_mutex_trylock" || FName == "pthread_rwlock_tryrdlock" || - FName == "pthread_rwlock_trywrlock") + FName == "pthread_rwlock_trywrlock") { AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), true, PthreadSemantics); - else if (FName == "lck_mtx_try_lock" || + return true; + } else if (FName == "lck_mtx_try_lock" || FName == "lck_rw_try_lock_exclusive" || - FName == "lck_rw_try_lock_shared") + FName == "lck_rw_try_lock_shared") { AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), true, XNUSemantics); - else if (FName == "pthread_mutex_unlock" || + return true; + } else if (FName == "pthread_mutex_unlock" || FName == "pthread_rwlock_unlock" || FName == "lck_mtx_unlock" || - FName == "lck_rw_done") + FName == "lck_rw_done") { ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); - else if (FName == "pthread_mutex_destroy" || - FName == "lck_mtx_destroy") + return true; + } + return false; +} + + +void PthreadLockChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { + ProgramStateRef state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); + StringRef FName = C.getCalleeName(CE); + if (FName.empty()) + return; + + if (CE->getNumArgs() != 1 && CE->getNumArgs() != 2) + return; + + if (FName == "pthread_mutex_destroy" || + FName == "lck_mtx_destroy") DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); else if (FName == "pthread_mutex_init") InitLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); @@ -130,12 +152,11 @@ return; ProgramStateRef state = C.getState(); - - SVal X = state->getSVal(CE, C.getLocationContext()); - if (X.isUnknownOrUndef()) - return; - - DefinedSVal retVal = X.castAs(); + const LocationContext *LCtx = C.getLocationContext(); + DefinedSVal retVal = C.getSValBuilder() .conjureSymbolVal(nullptr, CE, LCtx, + C.blockCount()) + .castAs(); + state = state->BindExpr(CE, LCtx, retVal); if (const LockState *LState = state->get(lockR)) { if (LState->isLocked()) { @@ -246,6 +267,11 @@ } state = state->set(lockR, LockState::getUnlocked()); + const LocationContext *LCtx = C.getLocationContext(); + DefinedSVal retVal = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, + C.blockCount()) + .castAs(); + state = state->BindExpr(CE, LCtx, retVal); C.addTransition(state); } Index: test/Analysis/pthreadlock.c =================================================================== --- test/Analysis/pthreadlock.c +++ test/Analysis/pthreadlock.c @@ -30,6 +30,8 @@ lck_mtx_t lck1, lck2; lck_grp_t grp1; +pthread_mutex_t *pmtx; + #define NULL 0 void @@ -184,6 +186,21 @@ } void +ok21(void) { + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning +} + +void +ok22(void) { + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning +} + + +void bad1(void) { pthread_mutex_lock(&mtx1); // no-warning