1480093f4SDimitry Andric //=== Iterator.h - Common functions for iterator checkers. ---------*- C++ -*-// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // Defines common functions to be used by the itertor checkers . 10480093f4SDimitry Andric // 11480093f4SDimitry Andric //===----------------------------------------------------------------------===// 12480093f4SDimitry Andric 13480093f4SDimitry Andric #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H 14480093f4SDimitry Andric #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H 15480093f4SDimitry Andric 16480093f4SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h" 17480093f4SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 18480093f4SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" 19480093f4SDimitry Andric 20480093f4SDimitry Andric namespace clang { 21480093f4SDimitry Andric namespace ento { 22480093f4SDimitry Andric namespace iterator { 23480093f4SDimitry Andric 24480093f4SDimitry Andric // Abstract position of an iterator. This helps to handle all three kinds 25480093f4SDimitry Andric // of operators in a common way by using a symbolic position. 26480093f4SDimitry Andric struct IteratorPosition { 27480093f4SDimitry Andric private: 28480093f4SDimitry Andric 29480093f4SDimitry Andric // Container the iterator belongs to 30480093f4SDimitry Andric const MemRegion *Cont; 31480093f4SDimitry Andric 32480093f4SDimitry Andric // Whether iterator is valid 33480093f4SDimitry Andric const bool Valid; 34480093f4SDimitry Andric 35480093f4SDimitry Andric // Abstract offset 36480093f4SDimitry Andric const SymbolRef Offset; 37480093f4SDimitry Andric 38480093f4SDimitry Andric IteratorPosition(const MemRegion *C, bool V, SymbolRef Of) 39480093f4SDimitry Andric : Cont(C), Valid(V), Offset(Of) {} 40480093f4SDimitry Andric 41480093f4SDimitry Andric public: 42480093f4SDimitry Andric const MemRegion *getContainer() const { return Cont; } 43480093f4SDimitry Andric bool isValid() const { return Valid; } 44480093f4SDimitry Andric SymbolRef getOffset() const { return Offset; } 45480093f4SDimitry Andric 46480093f4SDimitry Andric IteratorPosition invalidate() const { 47480093f4SDimitry Andric return IteratorPosition(Cont, false, Offset); 48480093f4SDimitry Andric } 49480093f4SDimitry Andric 50480093f4SDimitry Andric static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) { 51480093f4SDimitry Andric return IteratorPosition(C, true, Of); 52480093f4SDimitry Andric } 53480093f4SDimitry Andric 54480093f4SDimitry Andric IteratorPosition setTo(SymbolRef NewOf) const { 55480093f4SDimitry Andric return IteratorPosition(Cont, Valid, NewOf); 56480093f4SDimitry Andric } 57480093f4SDimitry Andric 58480093f4SDimitry Andric IteratorPosition reAssign(const MemRegion *NewCont) const { 59480093f4SDimitry Andric return IteratorPosition(NewCont, Valid, Offset); 60480093f4SDimitry Andric } 61480093f4SDimitry Andric 62480093f4SDimitry Andric bool operator==(const IteratorPosition &X) const { 63480093f4SDimitry Andric return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset; 64480093f4SDimitry Andric } 65480093f4SDimitry Andric 66480093f4SDimitry Andric bool operator!=(const IteratorPosition &X) const { 67480093f4SDimitry Andric return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset; 68480093f4SDimitry Andric } 69480093f4SDimitry Andric 70480093f4SDimitry Andric void Profile(llvm::FoldingSetNodeID &ID) const { 71480093f4SDimitry Andric ID.AddPointer(Cont); 72480093f4SDimitry Andric ID.AddInteger(Valid); 73480093f4SDimitry Andric ID.Add(Offset); 74480093f4SDimitry Andric } 75480093f4SDimitry Andric }; 76480093f4SDimitry Andric 77480093f4SDimitry Andric // Structure to record the symbolic begin and end position of a container 78480093f4SDimitry Andric struct ContainerData { 79480093f4SDimitry Andric private: 80480093f4SDimitry Andric const SymbolRef Begin, End; 81480093f4SDimitry Andric 82480093f4SDimitry Andric ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {} 83480093f4SDimitry Andric 84480093f4SDimitry Andric public: 85480093f4SDimitry Andric static ContainerData fromBegin(SymbolRef B) { 86480093f4SDimitry Andric return ContainerData(B, nullptr); 87480093f4SDimitry Andric } 88480093f4SDimitry Andric 89480093f4SDimitry Andric static ContainerData fromEnd(SymbolRef E) { 90480093f4SDimitry Andric return ContainerData(nullptr, E); 91480093f4SDimitry Andric } 92480093f4SDimitry Andric 93480093f4SDimitry Andric SymbolRef getBegin() const { return Begin; } 94480093f4SDimitry Andric SymbolRef getEnd() const { return End; } 95480093f4SDimitry Andric 96480093f4SDimitry Andric ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); } 97480093f4SDimitry Andric 98480093f4SDimitry Andric ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); } 99480093f4SDimitry Andric 100480093f4SDimitry Andric bool operator==(const ContainerData &X) const { 101480093f4SDimitry Andric return Begin == X.Begin && End == X.End; 102480093f4SDimitry Andric } 103480093f4SDimitry Andric 104480093f4SDimitry Andric bool operator!=(const ContainerData &X) const { 105480093f4SDimitry Andric return Begin != X.Begin || End != X.End; 106480093f4SDimitry Andric } 107480093f4SDimitry Andric 108480093f4SDimitry Andric void Profile(llvm::FoldingSetNodeID &ID) const { 109480093f4SDimitry Andric ID.Add(Begin); 110480093f4SDimitry Andric ID.Add(End); 111480093f4SDimitry Andric } 112480093f4SDimitry Andric }; 113480093f4SDimitry Andric 114480093f4SDimitry Andric class IteratorSymbolMap {}; 115480093f4SDimitry Andric class IteratorRegionMap {}; 116480093f4SDimitry Andric class ContainerMap {}; 117480093f4SDimitry Andric 118*5ffd83dbSDimitry Andric using IteratorSymbolMapTy = 119*5ffd83dbSDimitry Andric CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, IteratorPosition); 120*5ffd83dbSDimitry Andric using IteratorRegionMapTy = 121*5ffd83dbSDimitry Andric CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, IteratorPosition); 122*5ffd83dbSDimitry Andric using ContainerMapTy = 123*5ffd83dbSDimitry Andric CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, ContainerData); 124480093f4SDimitry Andric 125480093f4SDimitry Andric } // namespace iterator 126480093f4SDimitry Andric 127480093f4SDimitry Andric template<> 128480093f4SDimitry Andric struct ProgramStateTrait<iterator::IteratorSymbolMap> 129480093f4SDimitry Andric : public ProgramStatePartialTrait<iterator::IteratorSymbolMapTy> { 130480093f4SDimitry Andric static void *GDMIndex() { static int Index; return &Index; } 131480093f4SDimitry Andric }; 132480093f4SDimitry Andric 133480093f4SDimitry Andric template<> 134480093f4SDimitry Andric struct ProgramStateTrait<iterator::IteratorRegionMap> 135480093f4SDimitry Andric : public ProgramStatePartialTrait<iterator::IteratorRegionMapTy> { 136480093f4SDimitry Andric static void *GDMIndex() { static int Index; return &Index; } 137480093f4SDimitry Andric }; 138480093f4SDimitry Andric 139480093f4SDimitry Andric template<> 140480093f4SDimitry Andric struct ProgramStateTrait<iterator::ContainerMap> 141480093f4SDimitry Andric : public ProgramStatePartialTrait<iterator::ContainerMapTy> { 142480093f4SDimitry Andric static void *GDMIndex() { static int Index; return &Index; } 143480093f4SDimitry Andric }; 144480093f4SDimitry Andric 145480093f4SDimitry Andric namespace iterator { 146480093f4SDimitry Andric 147480093f4SDimitry Andric bool isIteratorType(const QualType &Type); 148480093f4SDimitry Andric bool isIterator(const CXXRecordDecl *CRD); 149480093f4SDimitry Andric bool isComparisonOperator(OverloadedOperatorKind OK); 150480093f4SDimitry Andric bool isInsertCall(const FunctionDecl *Func); 151480093f4SDimitry Andric bool isEraseCall(const FunctionDecl *Func); 152480093f4SDimitry Andric bool isEraseAfterCall(const FunctionDecl *Func); 153480093f4SDimitry Andric bool isEmplaceCall(const FunctionDecl *Func); 154480093f4SDimitry Andric bool isAccessOperator(OverloadedOperatorKind OK); 155*5ffd83dbSDimitry Andric bool isAccessOperator(UnaryOperatorKind OK); 156*5ffd83dbSDimitry Andric bool isAccessOperator(BinaryOperatorKind OK); 157480093f4SDimitry Andric bool isDereferenceOperator(OverloadedOperatorKind OK); 158*5ffd83dbSDimitry Andric bool isDereferenceOperator(UnaryOperatorKind OK); 159*5ffd83dbSDimitry Andric bool isDereferenceOperator(BinaryOperatorKind OK); 160480093f4SDimitry Andric bool isIncrementOperator(OverloadedOperatorKind OK); 161*5ffd83dbSDimitry Andric bool isIncrementOperator(UnaryOperatorKind OK); 162480093f4SDimitry Andric bool isDecrementOperator(OverloadedOperatorKind OK); 163*5ffd83dbSDimitry Andric bool isDecrementOperator(UnaryOperatorKind OK); 164480093f4SDimitry Andric bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK); 165*5ffd83dbSDimitry Andric bool isRandomIncrOrDecrOperator(BinaryOperatorKind OK); 166480093f4SDimitry Andric const ContainerData *getContainerData(ProgramStateRef State, 167480093f4SDimitry Andric const MemRegion *Cont); 168480093f4SDimitry Andric const IteratorPosition *getIteratorPosition(ProgramStateRef State, 169480093f4SDimitry Andric const SVal &Val); 170480093f4SDimitry Andric ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, 171480093f4SDimitry Andric const IteratorPosition &Pos); 172*5ffd83dbSDimitry Andric ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val, 173*5ffd83dbSDimitry Andric const MemRegion *Cont, const Stmt* S, 174*5ffd83dbSDimitry Andric const LocationContext *LCtx, 175*5ffd83dbSDimitry Andric unsigned blockCount); 176480093f4SDimitry Andric ProgramStateRef advancePosition(ProgramStateRef State, 177480093f4SDimitry Andric const SVal &Iter, 178480093f4SDimitry Andric OverloadedOperatorKind Op, 179480093f4SDimitry Andric const SVal &Distance); 180*5ffd83dbSDimitry Andric ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, 181*5ffd83dbSDimitry Andric long Scale); 182480093f4SDimitry Andric bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, 183480093f4SDimitry Andric BinaryOperator::Opcode Opc); 184480093f4SDimitry Andric bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2, 185480093f4SDimitry Andric BinaryOperator::Opcode Opc); 186480093f4SDimitry Andric 187480093f4SDimitry Andric } // namespace iterator 188480093f4SDimitry Andric } // namespace ento 189480093f4SDimitry Andric } // namespace clang 190480093f4SDimitry Andric 191480093f4SDimitry Andric #endif 192