Iterator.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //=== Iterator.h - Common functions for iterator checkers. ---------*- C++ -*-//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Defines common functions to be used by the itertor checkers .
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
  13. #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  17. namespace clang {
  18. namespace ento {
  19. namespace iterator {
  20. // Abstract position of an iterator. This helps to handle all three kinds
  21. // of operators in a common way by using a symbolic position.
  22. struct IteratorPosition {
  23. private:
  24. // Container the iterator belongs to
  25. const MemRegion *Cont;
  26. // Whether iterator is valid
  27. const bool Valid;
  28. // Abstract offset
  29. const SymbolRef Offset;
  30. IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
  31. : Cont(C), Valid(V), Offset(Of) {}
  32. public:
  33. const MemRegion *getContainer() const { return Cont; }
  34. bool isValid() const { return Valid; }
  35. SymbolRef getOffset() const { return Offset; }
  36. IteratorPosition invalidate() const {
  37. return IteratorPosition(Cont, false, Offset);
  38. }
  39. static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
  40. return IteratorPosition(C, true, Of);
  41. }
  42. IteratorPosition setTo(SymbolRef NewOf) const {
  43. return IteratorPosition(Cont, Valid, NewOf);
  44. }
  45. IteratorPosition reAssign(const MemRegion *NewCont) const {
  46. return IteratorPosition(NewCont, Valid, Offset);
  47. }
  48. bool operator==(const IteratorPosition &X) const {
  49. return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
  50. }
  51. bool operator!=(const IteratorPosition &X) const {
  52. return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
  53. }
  54. void Profile(llvm::FoldingSetNodeID &ID) const {
  55. ID.AddPointer(Cont);
  56. ID.AddInteger(Valid);
  57. ID.Add(Offset);
  58. }
  59. };
  60. // Structure to record the symbolic begin and end position of a container
  61. struct ContainerData {
  62. private:
  63. const SymbolRef Begin, End;
  64. ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
  65. public:
  66. static ContainerData fromBegin(SymbolRef B) {
  67. return ContainerData(B, nullptr);
  68. }
  69. static ContainerData fromEnd(SymbolRef E) {
  70. return ContainerData(nullptr, E);
  71. }
  72. SymbolRef getBegin() const { return Begin; }
  73. SymbolRef getEnd() const { return End; }
  74. ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
  75. ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
  76. bool operator==(const ContainerData &X) const {
  77. return Begin == X.Begin && End == X.End;
  78. }
  79. bool operator!=(const ContainerData &X) const {
  80. return Begin != X.Begin || End != X.End;
  81. }
  82. void Profile(llvm::FoldingSetNodeID &ID) const {
  83. ID.Add(Begin);
  84. ID.Add(End);
  85. }
  86. };
  87. class IteratorSymbolMap {};
  88. class IteratorRegionMap {};
  89. class ContainerMap {};
  90. using IteratorSymbolMapTy =
  91. CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, IteratorPosition);
  92. using IteratorRegionMapTy =
  93. CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, IteratorPosition);
  94. using ContainerMapTy =
  95. CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, ContainerData);
  96. } // namespace iterator
  97. template<>
  98. struct ProgramStateTrait<iterator::IteratorSymbolMap>
  99. : public ProgramStatePartialTrait<iterator::IteratorSymbolMapTy> {
  100. static void *GDMIndex() { static int Index; return &Index; }
  101. };
  102. template<>
  103. struct ProgramStateTrait<iterator::IteratorRegionMap>
  104. : public ProgramStatePartialTrait<iterator::IteratorRegionMapTy> {
  105. static void *GDMIndex() { static int Index; return &Index; }
  106. };
  107. template<>
  108. struct ProgramStateTrait<iterator::ContainerMap>
  109. : public ProgramStatePartialTrait<iterator::ContainerMapTy> {
  110. static void *GDMIndex() { static int Index; return &Index; }
  111. };
  112. namespace iterator {
  113. bool isIteratorType(const QualType &Type);
  114. bool isIterator(const CXXRecordDecl *CRD);
  115. bool isComparisonOperator(OverloadedOperatorKind OK);
  116. bool isInsertCall(const FunctionDecl *Func);
  117. bool isEraseCall(const FunctionDecl *Func);
  118. bool isEraseAfterCall(const FunctionDecl *Func);
  119. bool isEmplaceCall(const FunctionDecl *Func);
  120. bool isAccessOperator(OverloadedOperatorKind OK);
  121. bool isAccessOperator(UnaryOperatorKind OK);
  122. bool isAccessOperator(BinaryOperatorKind OK);
  123. bool isDereferenceOperator(OverloadedOperatorKind OK);
  124. bool isDereferenceOperator(UnaryOperatorKind OK);
  125. bool isDereferenceOperator(BinaryOperatorKind OK);
  126. bool isIncrementOperator(OverloadedOperatorKind OK);
  127. bool isIncrementOperator(UnaryOperatorKind OK);
  128. bool isDecrementOperator(OverloadedOperatorKind OK);
  129. bool isDecrementOperator(UnaryOperatorKind OK);
  130. bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
  131. bool isRandomIncrOrDecrOperator(BinaryOperatorKind OK);
  132. const ContainerData *getContainerData(ProgramStateRef State,
  133. const MemRegion *Cont);
  134. const IteratorPosition *getIteratorPosition(ProgramStateRef State,
  135. const SVal &Val);
  136. ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
  137. const IteratorPosition &Pos);
  138. ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
  139. const MemRegion *Cont, const Stmt* S,
  140. const LocationContext *LCtx,
  141. unsigned blockCount);
  142. ProgramStateRef advancePosition(ProgramStateRef State,
  143. const SVal &Iter,
  144. OverloadedOperatorKind Op,
  145. const SVal &Distance);
  146. ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
  147. long Scale);
  148. bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
  149. BinaryOperator::Opcode Opc);
  150. bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
  151. BinaryOperator::Opcode Opc);
  152. } // namespace iterator
  153. } // namespace ento
  154. } // namespace clang
  155. #endif