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

//===-- ContainerModeling.cpp -------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Defines a modeling-checker for modeling STL container-like containers.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclTemplate.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"

#include "Iterator.h"

#include <utility>

usingnamespaceclang;
usingnamespaceento;
usingnamespaceiterator;

namespace {

class ContainerModeling
  : public Checker<check::PostCall, check::LiveSymbols, check::DeadSymbols> {};

bool isBeginCall(const FunctionDecl *Func);
bool isEndCall(const FunctionDecl *Func);
bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg);
bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
ProgramStateRef createContainerBegin(ProgramStateRef State,
                                     const MemRegion *Cont, const Expr *E,
                                     QualType T, const LocationContext *LCtx,
                                     unsigned BlockCount);
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
                                   const Expr *E, QualType T,
                                   const LocationContext *LCtx,
                                   unsigned BlockCount);
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
                                 const ContainerData &CData);
ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
                                               const MemRegion *Cont);
ProgramStateRef
invalidateAllIteratorPositionsExcept(ProgramStateRef State,
                                     const MemRegion *Cont, SymbolRef Offset,
                                     BinaryOperator::Opcode Opc);
ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
                                            SymbolRef Offset,
                                            BinaryOperator::Opcode Opc);
ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
                                            SymbolRef Offset1,
                                            BinaryOperator::Opcode Opc1,
                                            SymbolRef Offset2,
                                            BinaryOperator::Opcode Opc2);
ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
                                             const MemRegion *Cont,
                                             const MemRegion *NewCont);
ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
                                                   const MemRegion *Cont,
                                                   const MemRegion *NewCont,
                                                   SymbolRef Offset,
                                                   BinaryOperator::Opcode Opc);
ProgramStateRef rebaseSymbolInIteratorPositionsIf(
    ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
    SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc);
SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB, SymbolRef Expr,
                        SymbolRef OldSym, SymbolRef NewSym);
bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);

} // namespace

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

void ContainerModeling::checkLiveSymbols(ProgramStateRef State,
                                         SymbolReaper &SR) const {}

void ContainerModeling::checkDeadSymbols(SymbolReaper &SR,
                                         CheckerContext &C) const {}

void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
                                   SVal RetVal, SVal Cont) const {}

void ContainerModeling::handleEnd(CheckerContext &C, const Expr *CE,
                                 SVal RetVal, SVal Cont) const {}

void ContainerModeling::handleAssignment(CheckerContext &C, SVal Cont,
                                         const Expr *CE, SVal OldCont) const {}

void ContainerModeling::handleAssign(CheckerContext &C, SVal Cont,
                                     const Expr *ContE) const {}

void ContainerModeling::handleClear(CheckerContext &C, SVal Cont,
                                    const Expr *ContE) const {}

void ContainerModeling::handlePushBack(CheckerContext &C, SVal Cont,
                                       const Expr *ContE) const {}

void ContainerModeling::handlePopBack(CheckerContext &C, SVal Cont,
                                      const Expr *ContE) const {}

void ContainerModeling::handlePushFront(CheckerContext &C, SVal Cont,
                                        const Expr *ContE) const {}

void ContainerModeling::handlePopFront(CheckerContext &C, SVal Cont,
                                       const Expr *ContE) const {}

void ContainerModeling::handleInsert(CheckerContext &C, SVal Cont,
                                     SVal Iter) const {}

void ContainerModeling::handleErase(CheckerContext &C, SVal Cont,
                                    SVal Iter) const {}

void ContainerModeling::handleErase(CheckerContext &C, SVal Cont, SVal Iter1,
                                    SVal Iter2) const {}

void ContainerModeling::handleEraseAfter(CheckerContext &C, SVal Cont,
                                        SVal Iter) const {}

void ContainerModeling::handleEraseAfter(CheckerContext &C, SVal Cont,
                                         SVal Iter1, SVal Iter2) const {}

const NoteTag *ContainerModeling::getChangeTag(CheckerContext &C,
                                               StringRef Text,
                                               const MemRegion *ContReg,
                                               const Expr *ContE) const {}

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

namespace {

bool isBeginCall(const FunctionDecl *Func) {}

bool isEndCall(const FunctionDecl *Func) {}

const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
                                      const MemRegion *Reg) {}

bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg) {}

bool frontModifiable(ProgramStateRef State, const MemRegion *Reg) {}

bool backModifiable(ProgramStateRef State, const MemRegion *Reg) {}

SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont) {}

SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {}

ProgramStateRef createContainerBegin(ProgramStateRef State,
                                     const MemRegion *Cont, const Expr *E,
                                     QualType T, const LocationContext *LCtx,
                                     unsigned BlockCount) {}

ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
                                   const Expr *E, QualType T,
                                   const LocationContext *LCtx,
                                   unsigned BlockCount) {}

ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
                                 const ContainerData &CData) {}

template <typename Condition, typename Process>
ProgramStateRef processIteratorPositions(ProgramStateRef State, Condition Cond,
                                         Process Proc) {}

ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
                                               const MemRegion *Cont) {}

ProgramStateRef
invalidateAllIteratorPositionsExcept(ProgramStateRef State,
                                     const MemRegion *Cont, SymbolRef Offset,
                                     BinaryOperator::Opcode Opc) {}

ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
                                            SymbolRef Offset,
                                            BinaryOperator::Opcode Opc) {}

ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
                                            SymbolRef Offset1,
                                            BinaryOperator::Opcode Opc1,
                                            SymbolRef Offset2,
                                            BinaryOperator::Opcode Opc2) {}

ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
                                             const MemRegion *Cont,
                                             const MemRegion *NewCont) {}

ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
                                                   const MemRegion *Cont,
                                                   const MemRegion *NewCont,
                                                   SymbolRef Offset,
                                                   BinaryOperator::Opcode Opc) {}

// This function rebases symbolic expression `OldSym + Int` to `NewSym + Int`,
// `OldSym - Int` to `NewSym - Int` and  `OldSym` to `NewSym` in any iterator
// position offsets where `CondSym` is true.
ProgramStateRef rebaseSymbolInIteratorPositionsIf(
    ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
    SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc) {}

// This function rebases symbolic expression `OldExpr + Int` to `NewExpr + Int`,
// `OldExpr - Int` to `NewExpr - Int` and  `OldExpr` to `NewExpr` in expression
// `OrigExpr`.
SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB,
                       SymbolRef OrigExpr, SymbolRef OldExpr,
                       SymbolRef NewSym) {}

bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {}

} // namespace

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

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