iterator-range.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
  2. // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
  3. #include "Inputs/system-header-simulator-cxx.h"
  4. void clang_analyzer_warnIfReached();
  5. void simple_good_end(const std::vector<int> &v) {
  6. auto i = v.end();
  7. if (i != v.end()) {
  8. clang_analyzer_warnIfReached();
  9. *i; // no-warning
  10. }
  11. }
  12. void simple_good_end_negated(const std::vector<int> &v) {
  13. auto i = v.end();
  14. if (!(i == v.end())) {
  15. clang_analyzer_warnIfReached();
  16. *i; // no-warning
  17. }
  18. }
  19. void simple_bad_end(const std::vector<int> &v) {
  20. auto i = v.end();
  21. *i; // expected-warning{{Past-the-end iterator dereferenced}}
  22. clang_analyzer_warnIfReached();
  23. }
  24. void copy(const std::vector<int> &v) {
  25. auto i1 = v.end();
  26. auto i2 = i1;
  27. *i2; // expected-warning{{Past-the-end iterator dereferenced}}
  28. }
  29. void decrease(const std::vector<int> &v) {
  30. auto i = v.end();
  31. --i;
  32. *i; // no-warning
  33. }
  34. void copy_and_decrease1(const std::vector<int> &v) {
  35. auto i1 = v.end();
  36. auto i2 = i1;
  37. --i1;
  38. *i1; // no-warning
  39. }
  40. void copy_and_decrease2(const std::vector<int> &v) {
  41. auto i1 = v.end();
  42. auto i2 = i1;
  43. --i1;
  44. *i2; // expected-warning{{Past-the-end iterator dereferenced}}
  45. }
  46. void copy_and_increase1(const std::vector<int> &v) {
  47. auto i1 = v.begin();
  48. auto i2 = i1;
  49. ++i1;
  50. if (i1 == v.end())
  51. *i2; // no-warning
  52. }
  53. void copy_and_increase2(const std::vector<int> &v) {
  54. auto i1 = v.begin();
  55. auto i2 = i1;
  56. ++i1;
  57. if (i2 == v.end())
  58. *i2; // expected-warning{{Past-the-end iterator dereferenced}}
  59. }
  60. void copy_and_increase3(const std::vector<int> &v) {
  61. auto i1 = v.begin();
  62. auto i2 = i1;
  63. ++i1;
  64. if (v.end() == i2)
  65. *i2; // expected-warning{{Past-the-end iterator dereferenced}}
  66. }
  67. template <class InputIterator, class T>
  68. InputIterator nonStdFind(InputIterator first, InputIterator last,
  69. const T &val) {
  70. for (auto i = first; i != last; ++i) {
  71. if (*i == val) {
  72. return i;
  73. }
  74. }
  75. return last;
  76. }
  77. void good_non_std_find(std::vector<int> &V, int e) {
  78. auto first = nonStdFind(V.begin(), V.end(), e);
  79. if (V.end() != first)
  80. *first; // no-warning
  81. }
  82. void bad_non_std_find(std::vector<int> &V, int e) {
  83. auto first = nonStdFind(V.begin(), V.end(), e);
  84. *first; // expected-warning{{Past-the-end iterator dereferenced}}
  85. }
  86. void tricky(std::vector<int> &V, int e) {
  87. const auto first = V.begin();
  88. const auto comp1 = (first != V.end()), comp2 = (first == V.end());
  89. if (comp1)
  90. *first; // no-warning
  91. }
  92. void loop(std::vector<int> &V, int e) {
  93. auto start = V.begin();
  94. while (true) {
  95. auto item = std::find(start, V.end(), e);
  96. if (item == V.end())
  97. break;
  98. *item; // no-warning
  99. start = ++item; // no-warning
  100. }
  101. }
  102. void good_push_back(std::list<int> &L, int n) {
  103. auto i0 = --L.cend();
  104. L.push_back(n);
  105. *++i0; // no-warning
  106. }
  107. void bad_push_back(std::list<int> &L, int n) {
  108. auto i0 = --L.cend();
  109. L.push_back(n);
  110. ++i0;
  111. *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
  112. }
  113. void good_pop_back(std::list<int> &L, int n) {
  114. auto i0 = --L.cend(); --i0;
  115. L.pop_back();
  116. *i0; // no-warning
  117. }
  118. void bad_pop_back(std::list<int> &L, int n) {
  119. auto i0 = --L.cend(); --i0;
  120. L.pop_back();
  121. *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
  122. }
  123. void good_push_front(std::list<int> &L, int n) {
  124. auto i0 = L.cbegin();
  125. L.push_front(n);
  126. *--i0; // no-warning
  127. }
  128. void bad_push_front(std::list<int> &L, int n) {
  129. auto i0 = L.cbegin();
  130. L.push_front(n);
  131. --i0;
  132. --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
  133. }
  134. void good_pop_front(std::list<int> &L, int n) {
  135. auto i0 = ++L.cbegin();
  136. L.pop_front();
  137. *i0; // no-warning
  138. }
  139. void bad_pop_front(std::list<int> &L, int n) {
  140. auto i0 = ++L.cbegin();
  141. L.pop_front();
  142. --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
  143. }
  144. void bad_move(std::list<int> &L1, std::list<int> &L2) {
  145. auto i0 = --L2.cend();
  146. L1 = std::move(L2);
  147. *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
  148. }
  149. void bad_move_push_back(std::list<int> &L1, std::list<int> &L2, int n) {
  150. auto i0 = --L2.cend();
  151. L2.push_back(n);
  152. L1 = std::move(L2);
  153. ++i0;
  154. *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
  155. }
  156. void good_incr_begin(const std::list<int> &L) {
  157. auto i0 = L.begin();
  158. ++i0; // no-warning
  159. }
  160. void bad_decr_begin(const std::list<int> &L) {
  161. auto i0 = L.begin();
  162. --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
  163. }
  164. void good_decr_end(const std::list<int> &L) {
  165. auto i0 = L.end();
  166. --i0; // no-warning
  167. }
  168. void bad_incr_end(const std::list<int> &L) {
  169. auto i0 = L.end();
  170. ++i0; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
  171. }
  172. struct simple_iterator_base {
  173. simple_iterator_base();
  174. simple_iterator_base(const simple_iterator_base& rhs);
  175. simple_iterator_base &operator=(const simple_iterator_base& rhs);
  176. virtual ~simple_iterator_base();
  177. bool friend operator==(const simple_iterator_base &lhs,
  178. const simple_iterator_base &rhs);
  179. bool friend operator!=(const simple_iterator_base &lhs,
  180. const simple_iterator_base &rhs);
  181. private:
  182. int *ptr;
  183. };
  184. struct simple_derived_iterator: public simple_iterator_base {
  185. int& operator*();
  186. int* operator->();
  187. simple_iterator_base &operator++();
  188. simple_iterator_base operator++(int);
  189. simple_iterator_base &operator--();
  190. simple_iterator_base operator--(int);
  191. };
  192. struct simple_container {
  193. typedef simple_derived_iterator iterator;
  194. iterator begin();
  195. iterator end();
  196. };
  197. void good_derived(simple_container c) {
  198. auto i0 = c.end();
  199. if (i0 != c.end()) {
  200. clang_analyzer_warnIfReached();
  201. *i0; // no-warning
  202. }
  203. }
  204. void iter_diff(std::vector<int> &V) {
  205. auto i0 = V.begin(), i1 = V.end();
  206. ptrdiff_t len = i1 - i0; // no-crash
  207. }