//===--- PthreadLockChecker.cpp - Check for locking problems ---*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines:
//  * PthreadLockChecker, a simple lock -> unlock checker.
//    Which also checks for XNU locks, which behave similarly enough to share
//    code.
//  * FuchsiaLocksChecker, which is also rather similar.
//  * C11LockChecker which also closely follows Pthread semantics.
//
//  TODO: Path notes.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"

using namespace clang;
using namespace ento;

namespace {

struct LockState {
  enum Kind {
    Destroyed,
    Locked,
    Unlocked,
    UntouchedAndPossiblyDestroyed,
    UnlockedAndPossiblyDestroyed
  } K;

private:
  LockState(Kind K) : K(K) {}

public:
  static LockState getLocked() { return LockState(Locked); }
  static LockState getUnlocked() { return LockState(Unlocked); }
  static LockState getDestroyed() { return LockState(Destroyed); }
  static LockState getUntouchedAndPossiblyDestroyed() {
    return LockState(UntouchedAndPossiblyDestroyed);
  }
  static LockState getUnlockedAndPossiblyDestroyed() {
    return LockState(UnlockedAndPossiblyDestroyed);
  }

  bool operator==(const LockState &X) const { return K == X.K; }

  bool isLocked() const { return K == Locked; }
  bool isUnlocked() const { return K == Unlocked; }
  bool isDestroyed() const { return K == Destroyed; }
  bool isUntouchedAndPossiblyDestroyed() const {
    return K == UntouchedAndPossiblyDestroyed;
  }
  bool isUnlockedAndPossiblyDestroyed() const {
    return K == UnlockedAndPossiblyDestroyed;
  }

  void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
};

class PthreadLockChecker : public Checker<check::PostCall, check::DeadSymbols,
                                          check::RegionChanges> {
public:
  enum LockingSemantics { NotApplicable = 0, PthreadSemantics, XNUSemantics };
  enum CheckerKind {
    CK_PthreadLockChecker,
    CK_FuchsiaLockChecker,
    CK_C11LockChecker,
    CK_NumCheckKinds
  };
  DefaultBool ChecksEnabled[CK_NumCheckKinds];
  CheckerNameRef CheckNames[CK_NumCheckKinds];

private:
  typedef void (PthreadLockChecker::*FnCheck)(const CallEvent &Call,
                                              CheckerContext &C,
                                              CheckerKind checkkind) const;
  CallDescriptionMap<FnCheck> PThreadCallbacks = {
      // Init.
      {{"pthread_mutex_init", 2}, &PthreadLockChecker::InitAnyLock},
      // TODO: pthread_rwlock_init(2 arguments).
      // TODO: lck_mtx_init(3 arguments).
      // TODO: lck_mtx_alloc_init(2 arguments) => returns the mutex.
      // TODO: lck_rw_init(3 arguments).
      // TODO: lck_rw_alloc_init(2 arguments) => returns the mutex.

      // Acquire.
      {{"pthread_mutex_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
      {{"pthread_rwlock_rdlock", 1}, &PthreadLockChecker::AcquirePthreadLock},
      {{"pthread_rwlock_wrlock", 1}, &PthreadLockChecker::AcquirePthreadLock},
      {{"lck_mtx_lock", 1}, &PthreadLockChecker::AcquireXNULock},
      {{"lck_rw_lock_exclusive", 1}, &PthreadLockChecker::AcquireXNULock},
      {{"lck_rw_lock_shared", 1}, &PthreadLockChecker::AcquireXNULock},

      // Try.
      {{"pthread_mutex_trylock", 1}, &PthreadLockChecker::TryPthreadLock},
      {{"pthread_rwlock_tryrdlock", 1}, &PthreadLockChecker::TryPthreadLock},
      {{"pthread_rwlock_trywrlock", 1}, &PthreadLockChecker::TryPthreadLock},
      {{"lck_mtx_try_lock", 1}, &PthreadLockChecker::TryXNULock},
      {{"lck_rw_try_lock_exclusive", 1}, &PthreadLockChecker::TryXNULock},
      {{"lck_rw_try_lock_shared", 1}, &PthreadLockChecker::TryXNULock},

      // Release.
      {{"pthread_mutex_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"pthread_rwlock_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"lck_mtx_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"lck_rw_unlock_exclusive", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"lck_rw_unlock_shared", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"lck_rw_done", 1}, &PthreadLockChecker::ReleaseAnyLock},

      // Destroy.
      {{"pthread_mutex_destroy", 1}, &PthreadLockChecker::DestroyPthreadLock},
      {{"lck_mtx_destroy", 2}, &PthreadLockChecker::DestroyXNULock},
      // TODO: pthread_rwlock_destroy(1 argument).
      // TODO: lck_rw_destroy(2 arguments).
  };

  CallDescriptionMap<FnCheck> FuchsiaCallbacks = {
      // Init.
      {{"spin_lock_init", 1}, &PthreadLockChecker::InitAnyLock},

      // Acquire.
      {{"spin_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
      {{"spin_lock_save", 3}, &PthreadLockChecker::AcquirePthreadLock},
      {{"sync_mutex_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
      {{"sync_mutex_lock_with_waiter", 1},
       &PthreadLockChecker::AcquirePthreadLock},

      // Try.
      {{"spin_trylock", 1}, &PthreadLockChecker::TryFuchsiaLock},
      {{"sync_mutex_trylock", 1}, &PthreadLockChecker::TryFuchsiaLock},
      {{"sync_mutex_timedlock", 2}, &PthreadLockChecker::TryFuchsiaLock},

      // Release.
      {{"spin_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
      {{"spin_unlock_restore", 3}, &PthreadLockChecker::ReleaseAnyLock},
      {{"sync_mutex_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
  };

  CallDescriptionMap<FnCheck> C11Callbacks = {
      // Init.
      {{"mtx_init", 2}, &PthreadLockChecker::InitAnyLock},

      // Acquire.
      {{"mtx_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},

      // Try.
      {{"mtx_trylock", 1}, &PthreadLockChecker::TryC11Lock},
      {{"mtx_timedlock", 2}, &PthreadLockChecker::TryC11Lock},

      // Release.
      {{"mtx_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},

      // Destroy
      {{"mtx_destroy", 1}, &PthreadLockChecker::DestroyPthreadLock},
  };

  ProgramStateRef resolvePossiblyDestroyedMutex(ProgramStateRef state,
                                                const MemRegion *lockR,
                                                const SymbolRef *sym) const;
  void reportUseDestroyedBug(const CallEvent &Call, CheckerContext &C,
                             unsigned ArgNo, CheckerKind checkKind) const;

  // Init.
  void InitAnyLock(const CallEvent &Call, CheckerContext &C,
                   CheckerKind checkkind) const;
  void InitLockAux(const CallEvent &Call, CheckerContext &C, unsigned ArgNo,
                   SVal Lock, CheckerKind checkkind) const;

  // Lock, Try-lock.
  void AcquirePthreadLock(const CallEvent &Call, CheckerContext &C,
                          CheckerKind checkkind) const;
  void AcquireXNULock(const CallEvent &Call, CheckerContext &C,
                      CheckerKind checkkind) const;
  void TryPthreadLock(const CallEvent &Call, CheckerContext &C,
                      CheckerKind checkkind) const;
  void TryXNULock(const CallEvent &Call, CheckerContext &C,
                  CheckerKind checkkind) const;
  void TryFuchsiaLock(const CallEvent &Call, CheckerContext &C,
                      CheckerKind checkkind) const;
  void TryC11Lock(const CallEvent &Call, CheckerContext &C,
                  CheckerKind checkkind) const;
  void AcquireLockAux(const CallEvent &Call, CheckerContext &C, unsigned ArgNo,
                      SVal lock, bool isTryLock, LockingSemantics semantics,
                      CheckerKind checkkind) const;

  // Release.
  void ReleaseAnyLock(const CallEvent &Call, CheckerContext &C,
                      CheckerKind checkkind) const;
  void ReleaseLockAux(const CallEvent &Call, CheckerContext &C, unsigned ArgNo,
                      SVal lock, CheckerKind checkkind) const;

  // Destroy.
  void DestroyPthreadLock(const CallEvent &Call, CheckerContext &C,
                          CheckerKind checkkind) const;
  void DestroyXNULock(const CallEvent &Call, CheckerContext &C,
                      CheckerKind checkkind) const;
  void DestroyLockAux(const CallEvent &Call, CheckerContext &C, unsigned ArgNo,
                      SVal Lock, LockingSemantics semantics,
                      CheckerKind checkkind) const;

public:
  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
  ProgramStateRef
  checkRegionChanges(ProgramStateRef State, const InvalidatedSymbols *Symbols,
                     ArrayRef<const MemRegion *> ExplicitRegions,
                     ArrayRef<const MemRegion *> Regions,
                     const LocationContext *LCtx, const CallEvent *Call) const;
  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
                  const char *Sep) const override;

private:
  mutable std::unique_ptr<BugType> BT_doublelock[CK_NumCheckKinds];
  mutable std::unique_ptr<BugType> BT_doubleunlock[CK_NumCheckKinds];
  mutable std::unique_ptr<BugType> BT_destroylock[CK_NumCheckKinds];
  mutable std::unique_ptr<BugType> BT_initlock[CK_NumCheckKinds];
  mutable std::unique_ptr<BugType> BT_lor[CK_NumCheckKinds];

  void initBugType(CheckerKind checkKind) const {
    if (BT_doublelock[checkKind])
      return;
    BT_doublelock[checkKind].reset(
        new BugType{CheckNames[checkKind], "Double locking", "Lock checker"});
    BT_doubleunlock[checkKind].reset(
        new BugType{CheckNames[checkKind], "Double unlocking", "Lock checker"});
    BT_destroylock[checkKind].reset(new BugType{
        CheckNames[checkKind], "Use destroyed lock", "Lock checker"});
    BT_initlock[checkKind].reset(new BugType{
        CheckNames[checkKind], "Init invalid lock", "Lock checker"});
    BT_lor[checkKind].reset(new BugType{CheckNames[checkKind],
                                        "Lock order reversal", "Lock checker"});
  }
};
} // end anonymous namespace

// A stack of locks for tracking lock-unlock order.
REGISTER_LIST_WITH_PROGRAMSTATE(LockSet, const MemRegion *)

// An entry for tracking lock states.
REGISTER_MAP_WITH_PROGRAMSTATE(LockMap, const MemRegion *, LockState)

// Return values for unresolved calls to pthread_mutex_destroy().
REGISTER_MAP_WITH_PROGRAMSTATE(DestroyRetVal, const MemRegion *, SymbolRef)

void PthreadLockChecker::checkPostCall(const CallEvent &Call,
                                       CheckerContext &C) const {
  // An additional umbrella check that all functions modeled by this checker
  // are global C functions.
  // TODO: Maybe make this the default behavior of CallDescription
  // with exactly one identifier?
  // FIXME: Try to handle cases when the implementation was inlined rather
  // than just giving up.
  if (!Call.isGlobalCFunction() || C.wasInlined)
    return;

  if (const FnCheck *Callback = PThreadCallbacks.lookup(Call))
    (this->**Callback)(Call, C, CK_PthreadLockChecker);
  else if (const FnCheck *Callback = FuchsiaCallbacks.lookup(Call))
    (this->**Callback)(Call, C, CK_FuchsiaLockChecker);
  else if (const FnCheck *Callback = C11Callbacks.lookup(Call))
    (this->**Callback)(Call, C, CK_C11LockChecker);
}

// When a lock is destroyed, in some semantics(like PthreadSemantics) we are not
// sure if the destroy call has succeeded or failed, and the lock enters one of
// the 'possibly destroyed' state. There is a short time frame for the
// programmer to check the return value to see if the lock was successfully
// destroyed. Before we model the next operation over that lock, we call this
// function to see if the return value was checked by now and set the lock state
// - either to destroyed state or back to its previous state.

// In PthreadSemantics, pthread_mutex_destroy() returns zero if the lock is
// successfully destroyed and it returns a non-zero value otherwise.
ProgramStateRef PthreadLockChecker::resolvePossiblyDestroyedMutex(
    ProgramStateRef state, const MemRegion *lockR, const SymbolRef *sym) const {
  const LockState *lstate = state->get<LockMap>(lockR);
  // Existence in DestroyRetVal ensures existence in LockMap.
  // Existence in Destroyed also ensures that the lock state for lockR is either
  // UntouchedAndPossiblyDestroyed or UnlockedAndPossiblyDestroyed.
  assert(lstate->isUntouchedAndPossiblyDestroyed() ||
         lstate->isUnlockedAndPossiblyDestroyed());

  ConstraintManager &CMgr = state->getConstraintManager();
  ConditionTruthVal retZero = CMgr.isNull(state, *sym);
  if (retZero.isConstrainedFalse()) {
    if (lstate->isUntouchedAndPossiblyDestroyed())
      state = state->remove<LockMap>(lockR);
    else if (lstate->isUnlockedAndPossiblyDestroyed())
      state = state->set<LockMap>(lockR, LockState::getUnlocked());
  } else
    state = state->set<LockMap>(lockR, LockState::getDestroyed());

  // Removing the map entry (lockR, sym) from DestroyRetVal as the lock state is
  // now resolved.
  state = state->remove<DestroyRetVal>(lockR);
  return state;
}

void PthreadLockChecker::printState(raw_ostream &Out, ProgramStateRef State,
                                    const char *NL, const char *Sep) const {
  LockMapTy LM = State->get<LockMap>();
  if (!LM.isEmpty()) {
    Out << Sep << "Mutex states:" << NL;
    for (auto I : LM) {
      I.first->dumpToStream(Out);
      if (I.second.isLocked())
        Out << ": locked";
      else if (I.second.isUnlocked())
        Out << ": unlocked";
      else if (I.second.isDestroyed())
        Out << ": destroyed";
      else if (I.second.isUntouchedAndPossiblyDestroyed())
        Out << ": not tracked, possibly destroyed";
      else if (I.second.isUnlockedAndPossiblyDestroyed())
        Out << ": unlocked, possibly destroyed";
      Out << NL;
    }
  }

  LockSetTy LS = State->get<LockSet>();
  if (!LS.isEmpty()) {
    Out << Sep << "Mutex lock order:" << NL;
    for (auto I : LS) {
      I->dumpToStream(Out);
      Out << NL;
    }
  }

  // TODO: Dump destroyed mutex symbols?
}

void PthreadLockChecker::AcquirePthreadLock(const CallEvent &Call,
                                            CheckerContext &C,
                                            CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), false, PthreadSemantics,
                 checkKind);
}

void PthreadLockChecker::AcquireXNULock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), false, XNUSemantics,
                 checkKind);
}

void PthreadLockChecker::TryPthreadLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), true, PthreadSemantics,
                 checkKind);
}

void PthreadLockChecker::TryXNULock(const CallEvent &Call, CheckerContext &C,
                                    CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), true, PthreadSemantics,
                 checkKind);
}

void PthreadLockChecker::TryFuchsiaLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), true, PthreadSemantics,
                 checkKind);
}

void PthreadLockChecker::TryC11Lock(const CallEvent &Call, CheckerContext &C,
                                    CheckerKind checkKind) const {
  AcquireLockAux(Call, C, 0, Call.getArgSVal(0), true, PthreadSemantics,
                 checkKind);
}

void PthreadLockChecker::AcquireLockAux(const CallEvent &Call,
                                        CheckerContext &C, unsigned ArgNo,
                                        SVal lock, bool isTryLock,
                                        enum LockingSemantics semantics,
                                        CheckerKind checkKind) const {
  if (!ChecksEnabled[checkKind])
    return;

  const MemRegion *lockR = lock.getAsRegion();
  if (!lockR)
    return;

  ProgramStateRef state = C.getState();
  const SymbolRef *sym = state->get<DestroyRetVal>(lockR);
  if (sym)
    state = resolvePossiblyDestroyedMutex(state, lockR, sym);

  if (const LockState *LState = state->get<LockMap>(lockR)) {
    if (LState->isLocked()) {
      ExplodedNode *N = C.generateErrorNode();
      if (!N)
        return;
      initBugType(checkKind);
      auto report = std::make_unique<PathSensitiveBugReport>(
          *BT_doublelock[checkKind], "This lock has already been acquired", N);
      report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
      C.emitReport(std::move(report));
      return;
    } else if (LState->isDestroyed()) {
      reportUseDestroyedBug(Call, C, ArgNo, checkKind);
      return;
    }
  }

  ProgramStateRef lockSucc = state;
  if (isTryLock) {
    // Bifurcate the state, and allow a mode where the lock acquisition fails.
    SVal RetVal = Call.getReturnValue();
    if (auto DefinedRetVal = RetVal.getAs<DefinedSVal>()) {
      ProgramStateRef lockFail;
      switch (semantics) {
      case PthreadSemantics:
        std::tie(lockFail, lockSucc) = state->assume(*DefinedRetVal);
        break;
      case XNUSemantics:
        std::tie(lockSucc, lockFail) = state->assume(*DefinedRetVal);
        break;
      default:
        llvm_unreachable("Unknown tryLock locking semantics");
      }
      assert(lockFail && lockSucc);
      C.addTransition(lockFail);
    }
    // We might want to handle the case when the mutex lock function was inlined
    // and returned an Unknown or Undefined value.
  } else if (semantics == PthreadSemantics) {
    // Assume that the return value was 0.
    SVal RetVal = Call.getReturnValue();
    if (auto DefinedRetVal = RetVal.getAs<DefinedSVal>()) {
      // FIXME: If the lock function was inlined and returned true,
      // we need to behave sanely - at least generate sink.
      lockSucc = state->assume(*DefinedRetVal, false);
      assert(lockSucc);
    }
    // We might want to handle the case when the mutex lock function was inlined
    // and returned an Unknown or Undefined value.
  } else {
    // XNU locking semantics return void on non-try locks
    assert((semantics == XNUSemantics) && "Unknown locking semantics");
    lockSucc = state;
  }

  // Record that the lock was acquired.
  lockSucc = lockSucc->add<LockSet>(lockR);
  lockSucc = lockSucc->set<LockMap>(lockR, LockState::getLocked());
  C.addTransition(lockSucc);
}

void PthreadLockChecker::ReleaseAnyLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind checkKind) const {
  ReleaseLockAux(Call, C, 0, Call.getArgSVal(0), checkKind);
}

void PthreadLockChecker::ReleaseLockAux(const CallEvent &Call,
                                        CheckerContext &C, unsigned ArgNo,
                                        SVal lock,
                                        CheckerKind checkKind) const {
  if (!ChecksEnabled[checkKind])
    return;

  const MemRegion *lockR = lock.getAsRegion();
  if (!lockR)
    return;

  ProgramStateRef state = C.getState();
  const SymbolRef *sym = state->get<DestroyRetVal>(lockR);
  if (sym)
    state = resolvePossiblyDestroyedMutex(state, lockR, sym);

  if (const LockState *LState = state->get<LockMap>(lockR)) {
    if (LState->isUnlocked()) {
      ExplodedNode *N = C.generateErrorNode();
      if (!N)
        return;
      initBugType(checkKind);
      auto Report = std::make_unique<PathSensitiveBugReport>(
          *BT_doubleunlock[checkKind], "This lock has already been unlocked",
          N);
      Report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
      C.emitReport(std::move(Report));
      return;
    } else if (LState->isDestroyed()) {
      reportUseDestroyedBug(Call, C, ArgNo, checkKind);
      return;
    }
  }

  LockSetTy LS = state->get<LockSet>();

  if (!LS.isEmpty()) {
    const MemRegion *firstLockR = LS.getHead();
    if (firstLockR != lockR) {
      ExplodedNode *N = C.generateErrorNode();
      if (!N)
        return;
      initBugType(checkKind);
      auto report = std::make_unique<PathSensitiveBugReport>(
          *BT_lor[checkKind],
          "This was not the most recently acquired lock. Possible "
          "lock order reversal",
          N);
      report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
      C.emitReport(std::move(report));
      return;
    }
    // Record that the lock was released.
    state = state->set<LockSet>(LS.getTail());
  }

  state = state->set<LockMap>(lockR, LockState::getUnlocked());
  C.addTransition(state);
}

void PthreadLockChecker::DestroyPthreadLock(const CallEvent &Call,
                                            CheckerContext &C,
                                            CheckerKind checkKind) const {
  DestroyLockAux(Call, C, 0, Call.getArgSVal(0), PthreadSemantics, checkKind);
}

void PthreadLockChecker::DestroyXNULock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind checkKind) const {
  DestroyLockAux(Call, C, 0, Call.getArgSVal(0), XNUSemantics, checkKind);
}

void PthreadLockChecker::DestroyLockAux(const CallEvent &Call,
                                        CheckerContext &C, unsigned ArgNo,
                                        SVal Lock,
                                        enum LockingSemantics semantics,
                                        CheckerKind checkKind) const {
  if (!ChecksEnabled[checkKind])
    return;

  const MemRegion *LockR = Lock.getAsRegion();
  if (!LockR)
    return;

  ProgramStateRef State = C.getState();

  const SymbolRef *sym = State->get<DestroyRetVal>(LockR);
  if (sym)
    State = resolvePossiblyDestroyedMutex(State, LockR, sym);

  const LockState *LState = State->get<LockMap>(LockR);
  // Checking the return value of the destroy method only in the case of
  // PthreadSemantics
  if (semantics == PthreadSemantics) {
    if (!LState || LState->isUnlocked()) {
      SymbolRef sym = Call.getReturnValue().getAsSymbol();
      if (!sym) {
        State = State->remove<LockMap>(LockR);
        C.addTransition(State);
        return;
      }
      State = State->set<DestroyRetVal>(LockR, sym);
      if (LState && LState->isUnlocked())
        State = State->set<LockMap>(
            LockR, LockState::getUnlockedAndPossiblyDestroyed());
      else
        State = State->set<LockMap>(
            LockR, LockState::getUntouchedAndPossiblyDestroyed());
      C.addTransition(State);
      return;
    }
  } else {
    if (!LState || LState->isUnlocked()) {
      State = State->set<LockMap>(LockR, LockState::getDestroyed());
      C.addTransition(State);
      return;
    }
  }
  StringRef Message;

  if (LState->isLocked()) {
    Message = "This lock is still locked";
  } else {
    Message = "This lock has already been destroyed";
  }

  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return;
  initBugType(checkKind);
  auto Report = std::make_unique<PathSensitiveBugReport>(
      *BT_destroylock[checkKind], Message, N);
  Report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
  C.emitReport(std::move(Report));
}

void PthreadLockChecker::InitAnyLock(const CallEvent &Call, CheckerContext &C,
                                     CheckerKind checkKind) const {
  InitLockAux(Call, C, 0, Call.getArgSVal(0), checkKind);
}

void PthreadLockChecker::InitLockAux(const CallEvent &Call, CheckerContext &C,
                                     unsigned ArgNo, SVal Lock,
                                     CheckerKind checkKind) const {
  if (!ChecksEnabled[checkKind])
    return;

  const MemRegion *LockR = Lock.getAsRegion();
  if (!LockR)
    return;

  ProgramStateRef State = C.getState();

  const SymbolRef *sym = State->get<DestroyRetVal>(LockR);
  if (sym)
    State = resolvePossiblyDestroyedMutex(State, LockR, sym);

  const struct LockState *LState = State->get<LockMap>(LockR);
  if (!LState || LState->isDestroyed()) {
    State = State->set<LockMap>(LockR, LockState::getUnlocked());
    C.addTransition(State);
    return;
  }

  StringRef Message;

  if (LState->isLocked()) {
    Message = "This lock is still being held";
  } else {
    Message = "This lock has already been initialized";
  }

  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return;
  initBugType(checkKind);
  auto Report = std::make_unique<PathSensitiveBugReport>(
      *BT_initlock[checkKind], Message, N);
  Report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
  C.emitReport(std::move(Report));
}

void PthreadLockChecker::reportUseDestroyedBug(const CallEvent &Call,
                                               CheckerContext &C,
                                               unsigned ArgNo,
                                               CheckerKind checkKind) const {
  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return;
  initBugType(checkKind);
  auto Report = std::make_unique<PathSensitiveBugReport>(
      *BT_destroylock[checkKind], "This lock has already been destroyed", N);
  Report->addRange(Call.getArgExpr(ArgNo)->getSourceRange());
  C.emitReport(std::move(Report));
}

void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper,
                                          CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  for (auto I : State->get<DestroyRetVal>()) {
    // Once the return value symbol dies, no more checks can be performed
    // against it. See if the return value was checked before this point.
    // This would remove the symbol from the map as well.
    if (SymReaper.isDead(I.second))
      State = resolvePossiblyDestroyedMutex(State, I.first, &I.second);
  }

  for (auto I : State->get<LockMap>()) {
    // Stop tracking dead mutex regions as well.
    if (!SymReaper.isLiveRegion(I.first))
      State = State->remove<LockMap>(I.first);
  }

  // TODO: We probably need to clean up the lock stack as well.
  // It is tricky though: even if the mutex cannot be unlocked anymore,
  // it can still participate in lock order reversal resolution.

  C.addTransition(State);
}

ProgramStateRef PthreadLockChecker::checkRegionChanges(
    ProgramStateRef State, const InvalidatedSymbols *Symbols,
    ArrayRef<const MemRegion *> ExplicitRegions,
    ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
    const CallEvent *Call) const {

  bool IsLibraryFunction = false;
  if (Call && Call->isGlobalCFunction()) {
    // Avoid invalidating mutex state when a known supported function is called.
    if (PThreadCallbacks.lookup(*Call) || FuchsiaCallbacks.lookup(*Call) ||
        C11Callbacks.lookup(*Call))
      return State;

    if (Call->isInSystemHeader())
      IsLibraryFunction = true;
  }

  for (auto R : Regions) {
    // We assume that system library function wouldn't touch the mutex unless
    // it takes the mutex explicitly as an argument.
    // FIXME: This is a bit quadratic.
    if (IsLibraryFunction &&
        std::find(ExplicitRegions.begin(), ExplicitRegions.end(), R) ==
            ExplicitRegions.end())
      continue;

    State = State->remove<LockMap>(R);
    State = State->remove<DestroyRetVal>(R);

    // TODO: We need to invalidate the lock stack as well. This is tricky
    // to implement correctly and efficiently though, because the effects
    // of mutex escapes on lock order may be fairly varied.
  }

  return State;
}

void ento::registerPthreadLockBase(CheckerManager &mgr) {
  mgr.registerChecker<PthreadLockChecker>();
}

bool ento::shouldRegisterPthreadLockBase(const LangOptions &LO) { return true; }

#define REGISTER_CHECKER(name)                                                 \
  void ento::register##name(CheckerManager &mgr) {                             \
    PthreadLockChecker *checker = mgr.getChecker<PthreadLockChecker>();        \
    checker->ChecksEnabled[PthreadLockChecker::CK_##name] = true;              \
    checker->CheckNames[PthreadLockChecker::CK_##name] =                       \
        mgr.getCurrentCheckerName();                                           \
  }                                                                            \
                                                                               \
  bool ento::shouldRegister##name(const LangOptions &LO) { return true; }

REGISTER_CHECKER(PthreadLockChecker)
REGISTER_CHECKER(FuchsiaLockChecker)
REGISTER_CHECKER(C11LockChecker)
