#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);
}
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) { … }
ProgramStateRef rebaseSymbolInIteratorPositionsIf(
ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc) { … }
SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB,
SymbolRef OrigExpr, SymbolRef OldExpr,
SymbolRef NewSym) { … }
bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) { … }
}
void ento::registerContainerModeling(CheckerManager &mgr) { … }
bool ento::shouldRegisterContainerModeling(const CheckerManager &mgr) { … }