llvm/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp

//===--- 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/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"

usingnamespaceclang;
usingnamespaceento;

namespace {

struct LockState {};

class PthreadLockChecker : public Checker<check::PostCall, check::DeadSymbols,
                                          check::RegionChanges> {};
} // end anonymous namespace

// A stack of locks for tracking lock-unlock order.
REGISTER_LIST_WITH_PROGRAMSTATE()

// An entry for tracking lock states.
REGISTER_MAP_WITH_PROGRAMSTATE()

// Return values for unresolved calls to pthread_mutex_destroy().
REGISTER_MAP_WITH_PROGRAMSTATE()

void PthreadLockChecker::checkPostCall(const CallEvent &Call,
                                       CheckerContext &C) const {}

// 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 {}

void PthreadLockChecker::printState(raw_ostream &Out, ProgramStateRef State,
                                    const char *NL, const char *Sep) const {}

void PthreadLockChecker::AcquirePthreadLock(const CallEvent &Call,
                                            CheckerContext &C,
                                            CheckerKind CheckKind) const {}

void PthreadLockChecker::AcquireXNULock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::TryPthreadLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::TryXNULock(const CallEvent &Call, CheckerContext &C,
                                    CheckerKind CheckKind) const {}

void PthreadLockChecker::TryFuchsiaLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::TryC11Lock(const CallEvent &Call, CheckerContext &C,
                                    CheckerKind CheckKind) const {}

void PthreadLockChecker::AcquireLockAux(const CallEvent &Call,
                                        CheckerContext &C, const Expr *MtxExpr,
                                        SVal MtxVal, bool IsTryLock,
                                        enum LockingSemantics Semantics,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::ReleaseAnyLock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::ReleaseLockAux(const CallEvent &Call,
                                        CheckerContext &C, const Expr *MtxExpr,
                                        SVal MtxVal,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::DestroyPthreadLock(const CallEvent &Call,
                                            CheckerContext &C,
                                            CheckerKind CheckKind) const {}

void PthreadLockChecker::DestroyXNULock(const CallEvent &Call,
                                        CheckerContext &C,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::DestroyLockAux(const CallEvent &Call,
                                        CheckerContext &C, const Expr *MtxExpr,
                                        SVal MtxVal,
                                        enum LockingSemantics Semantics,
                                        CheckerKind CheckKind) const {}

void PthreadLockChecker::InitAnyLock(const CallEvent &Call, CheckerContext &C,
                                     CheckerKind CheckKind) const {}

void PthreadLockChecker::InitLockAux(const CallEvent &Call, CheckerContext &C,
                                     const Expr *MtxExpr, SVal MtxVal,
                                     CheckerKind CheckKind) const {}

void PthreadLockChecker::reportBug(CheckerContext &C,
                                   std::unique_ptr<BugType> BT[],
                                   const Expr *MtxExpr, CheckerKind CheckKind,
                                   StringRef Desc) const {}

void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper,
                                          CheckerContext &C) const {}

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

void ento::registerPthreadLockBase(CheckerManager &mgr) {}

bool ento::shouldRegisterPthreadLockBase(const CheckerManager &mgr) {}

#define REGISTER_CHECKER(name)

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