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{{Iterator accessed outside of its range}} 27 } 28 29 void simple_good_begin(const std::vector<int> &v) { 30 auto i = v.begin(); 31 if (i != v.begin()) { 32 clang_analyzer_warnIfReached(); 33 *--i; // no-warning 34 } 35 } 36 37 void simple_good_begin_negated(const std::vector<int> &v) { 38 auto i = v.begin(); 39 if (!(i == v.begin())) { 40 clang_analyzer_warnIfReached(); 41 *--i; // no-warning 42 } 43 } 44 45 void simple_bad_begin(const std::vector<int> &v) { 46 auto i = v.begin(); 47 *--i; // expected-warning{{Iterator accessed outside of its range}} 48 } 49 50 void copy(const std::vector<int> &v) { 51 auto i1 = v.end(); 52 auto i2 = i1; 53 *i2; // expected-warning{{Iterator accessed outside of its range}} 54 } 55 56 void decrease(const std::vector<int> &v) { 57 auto i = v.end(); 58 --i; 59 *i; // no-warning 60 } 61 62 void copy_and_decrease1(const std::vector<int> &v) { 63 auto i1 = v.end(); 64 auto i2 = i1; 65 --i1; 66 *i1; // no-warning 67 } 68 69 void copy_and_decrease2(const std::vector<int> &v) { 70 auto i1 = v.end(); 71 auto i2 = i1; 72 --i1; 73 *i2; // expected-warning{{Iterator accessed outside of its range}} 74 } 75 76 void copy_and_increase1(const std::vector<int> &v) { 77 auto i1 = v.begin(); 78 auto i2 = i1; 79 ++i1; 80 if (i1 == v.end()) 81 *i2; // no-warning 82 } 83 84 void copy_and_increase2(const std::vector<int> &v) { 85 auto i1 = v.begin(); 86 auto i2 = i1; 87 ++i1; 88 if (i2 == v.end()) 89 *i2; // expected-warning{{Iterator accessed outside of its range}} 90 } 91 92 void copy_and_increase3(const std::vector<int> &v) { 93 auto i1 = v.begin(); 94 auto i2 = i1; 95 ++i1; 96 if (v.end() == i2) 97 *i2; // expected-warning{{Iterator accessed outside of its range}} 98 } 99 100 template <class InputIterator, class T> 101 InputIterator nonStdFind(InputIterator first, InputIterator last, 102 const T &val) { 103 for (auto i = first; i != last; ++i) { 104 if (*i == val) { 105 return i; 106 } 107 } 108 return last; 109 } 110 111 void good_non_std_find(std::vector<int> &V, int e) { 112 auto first = nonStdFind(V.begin(), V.end(), e); 113 if (V.end() != first) 114 *first; // no-warning 115 } 116 117 void bad_non_std_find(std::vector<int> &V, int e) { 118 auto first = nonStdFind(V.begin(), V.end(), e); 119 *first; // expected-warning{{Iterator accessed outside of its range}} 120 } 121 122 void tricky(std::vector<int> &V, int e) { 123 const auto first = V.begin(); 124 const auto comp1 = (first != V.end()), comp2 = (first == V.end()); 125 if (comp1) 126 *first; 127 } 128 129 void loop(std::vector<int> &V, int e) { 130 auto start = V.begin(); 131 while (true) { 132 auto item = std::find(start, V.end(), e); 133 if (item == V.end()) 134 break; 135 *item; // no-warning 136 start = ++item; // no-warning 137 } 138 } 139 140 void good_push_back(std::list<int> &L, int n) { 141 auto i0 = --L.cend(); 142 L.push_back(n); 143 *++i0; // no-warning 144 } 145 146 void bad_push_back(std::list<int> &L, int n) { 147 auto i0 = --L.cend(); 148 L.push_back(n); 149 ++i0; 150 *++i0; // expected-warning{{Iterator accessed outside of its range}} 151 } 152 153 void good_pop_back(std::list<int> &L, int n) { 154 auto i0 = --L.cend(); --i0; 155 L.pop_back(); 156 *i0; // no-warning 157 } 158 159 void bad_pop_back(std::list<int> &L, int n) { 160 auto i0 = --L.cend(); --i0; 161 L.pop_back(); 162 *++i0; // expected-warning{{Iterator accessed outside of its range}} 163 } 164 165 void good_push_front(std::list<int> &L, int n) { 166 auto i0 = L.cbegin(); 167 L.push_front(n); 168 *--i0; // no-warning 169 } 170 171 void bad_push_front(std::list<int> &L, int n) { 172 auto i0 = L.cbegin(); 173 L.push_front(n); 174 --i0; 175 *--i0; // expected-warning{{Iterator accessed outside of its range}} 176 } 177 178 void good_pop_front(std::list<int> &L, int n) { 179 auto i0 = ++L.cbegin(); 180 L.pop_front(); 181 *i0; // no-warning 182 } 183 184 void bad_pop_front(std::list<int> &L, int n) { 185 auto i0 = ++L.cbegin(); 186 L.pop_front(); 187 *--i0; // expected-warning{{Iterator accessed outside of its range}} 188 } 189 190 void bad_move(std::list<int> &L1, std::list<int> &L2) { 191 auto i0 = --L2.cend(); 192 L1 = std::move(L2); 193 *++i0; // expected-warning{{Iterator accessed outside of its range}} 194 } 195 196 void bad_move_push_back(std::list<int> &L1, std::list<int> &L2, int n) { 197 auto i0 = --L2.cend(); 198 L2.push_back(n); 199 L1 = std::move(L2); 200 ++i0; 201 *++i0; // expected-warning{{Iterator accessed outside of its range}} 202 } 203