123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- //=== Iterator.h - Common functions for iterator checkers. ---------*- 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 common functions to be used by the itertor checkers .
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
- #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
- #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
- namespace clang {
- namespace ento {
- namespace iterator {
- // Abstract position of an iterator. This helps to handle all three kinds
- // of operators in a common way by using a symbolic position.
- struct IteratorPosition {
- private:
- // Container the iterator belongs to
- const MemRegion *Cont;
- // Whether iterator is valid
- const bool Valid;
- // Abstract offset
- const SymbolRef Offset;
- IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
- : Cont(C), Valid(V), Offset(Of) {}
- public:
- const MemRegion *getContainer() const { return Cont; }
- bool isValid() const { return Valid; }
- SymbolRef getOffset() const { return Offset; }
- IteratorPosition invalidate() const {
- return IteratorPosition(Cont, false, Offset);
- }
- static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
- return IteratorPosition(C, true, Of);
- }
- IteratorPosition setTo(SymbolRef NewOf) const {
- return IteratorPosition(Cont, Valid, NewOf);
- }
- IteratorPosition reAssign(const MemRegion *NewCont) const {
- return IteratorPosition(NewCont, Valid, Offset);
- }
- bool operator==(const IteratorPosition &X) const {
- return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
- }
- bool operator!=(const IteratorPosition &X) const {
- return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(Cont);
- ID.AddInteger(Valid);
- ID.Add(Offset);
- }
- };
- // Structure to record the symbolic begin and end position of a container
- struct ContainerData {
- private:
- const SymbolRef Begin, End;
- ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
- public:
- static ContainerData fromBegin(SymbolRef B) {
- return ContainerData(B, nullptr);
- }
- static ContainerData fromEnd(SymbolRef E) {
- return ContainerData(nullptr, E);
- }
- SymbolRef getBegin() const { return Begin; }
- SymbolRef getEnd() const { return End; }
- ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
- ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
- bool operator==(const ContainerData &X) const {
- return Begin == X.Begin && End == X.End;
- }
- bool operator!=(const ContainerData &X) const {
- return Begin != X.Begin || End != X.End;
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.Add(Begin);
- ID.Add(End);
- }
- };
- class IteratorSymbolMap {};
- class IteratorRegionMap {};
- class ContainerMap {};
- using IteratorSymbolMapTy =
- CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, IteratorPosition);
- using IteratorRegionMapTy =
- CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, IteratorPosition);
- using ContainerMapTy =
- CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, ContainerData);
- } // namespace iterator
- template<>
- struct ProgramStateTrait<iterator::IteratorSymbolMap>
- : public ProgramStatePartialTrait<iterator::IteratorSymbolMapTy> {
- static void *GDMIndex() { static int Index; return &Index; }
- };
- template<>
- struct ProgramStateTrait<iterator::IteratorRegionMap>
- : public ProgramStatePartialTrait<iterator::IteratorRegionMapTy> {
- static void *GDMIndex() { static int Index; return &Index; }
- };
- template<>
- struct ProgramStateTrait<iterator::ContainerMap>
- : public ProgramStatePartialTrait<iterator::ContainerMapTy> {
- static void *GDMIndex() { static int Index; return &Index; }
- };
- namespace iterator {
- bool isIteratorType(const QualType &Type);
- bool isIterator(const CXXRecordDecl *CRD);
- bool isComparisonOperator(OverloadedOperatorKind OK);
- bool isInsertCall(const FunctionDecl *Func);
- bool isEraseCall(const FunctionDecl *Func);
- bool isEraseAfterCall(const FunctionDecl *Func);
- bool isEmplaceCall(const FunctionDecl *Func);
- bool isAccessOperator(OverloadedOperatorKind OK);
- bool isAccessOperator(UnaryOperatorKind OK);
- bool isAccessOperator(BinaryOperatorKind OK);
- bool isDereferenceOperator(OverloadedOperatorKind OK);
- bool isDereferenceOperator(UnaryOperatorKind OK);
- bool isDereferenceOperator(BinaryOperatorKind OK);
- bool isIncrementOperator(OverloadedOperatorKind OK);
- bool isIncrementOperator(UnaryOperatorKind OK);
- bool isDecrementOperator(OverloadedOperatorKind OK);
- bool isDecrementOperator(UnaryOperatorKind OK);
- bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
- bool isRandomIncrOrDecrOperator(BinaryOperatorKind OK);
- const ContainerData *getContainerData(ProgramStateRef State,
- const MemRegion *Cont);
- const IteratorPosition *getIteratorPosition(ProgramStateRef State,
- const SVal &Val);
- ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
- const IteratorPosition &Pos);
- ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
- const MemRegion *Cont, const Stmt* S,
- const LocationContext *LCtx,
- unsigned blockCount);
- ProgramStateRef advancePosition(ProgramStateRef State,
- const SVal &Iter,
- OverloadedOperatorKind Op,
- const SVal &Distance);
- ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
- long Scale);
- bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
- BinaryOperator::Opcode Opc);
- bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
- BinaryOperator::Opcode Opc);
- } // namespace iterator
- } // namespace ento
- } // namespace clang
- #endif
|