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