1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator -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.MismatchedIterator -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 good_insert1(std::vector<int> &v, int n) { 7 v.insert(v.cbegin(), n); // no-warning 8 } 9 10 11 void good_insert2(std::vector<int> &v, int len, int n) { 12 v.insert(v.cbegin(), len, n); // no-warning 13 } 14 15 void good_insert3(std::vector<int> &v1, std::vector<int> &v2) { 16 v1.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // no-warning 17 } 18 19 void good_insert4(std::vector<int> &v, int len, int n) { 20 v.insert(v.cbegin(), {n-1, n, n+1}); // no-warning 21 } 22 23 void good_insert_find(std::vector<int> &v, int n, int m) { 24 auto i = std::find(v.cbegin(), v.cend(), n); 25 v.insert(i, m); // no-warning 26 } 27 28 void good_erase1(std::vector<int> &v) { 29 v.erase(v.cbegin()); // no-warning 30 } 31 32 void good_erase2(std::vector<int> &v) { 33 v.erase(v.cbegin(), v.cend()); // no-warning 34 } 35 36 void good_emplace(std::vector<int> &v, int n) { 37 v.emplace(v.cbegin(), n); // no-warning 38 } 39 40 void good_ctor(std::vector<int> &v) { 41 std::vector<int> new_v(v.cbegin(), v.cend()); // no-warning 42 } 43 44 void good_find(std::vector<int> &v, int n) { 45 std::find(v.cbegin(), v.cend(), n); // no-warning 46 } 47 48 void good_find_first_of(std::vector<int> &v1, std::vector<int> &v2) { 49 std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v2.cend()); // no-warning 50 } 51 52 void good_copy(std::vector<int> &v1, std::vector<int> &v2, int n) { 53 std::copy(v1.cbegin(), v1.cend(), v2.begin()); // no-warning 54 } 55 56 void good_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) { 57 auto i0 = v2.cbegin(); 58 v1 = std::move(v2); 59 std::find(i0, v1.cend(), n); // no-warning 60 } 61 62 void bad_insert1(std::vector<int> &v1, std::vector<int> &v2, int n) { 63 v2.insert(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}} 64 } 65 66 void bad_insert2(std::vector<int> &v1, std::vector<int> &v2, int len, int n) { 67 v2.insert(v1.cbegin(), len, n); // expected-warning{{Container accessed using foreign iterator argument}} 68 } 69 70 void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) { 71 v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}} 72 v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} 73 v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} 74 } 75 76 void bad_insert4(std::vector<int> &v1, std::vector<int> &v2, int len, int n) { 77 v2.insert(v1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}} 78 } 79 80 void bad_erase1(std::vector<int> &v1, std::vector<int> &v2) { 81 v2.erase(v1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}} 82 } 83 84 void bad_erase2(std::vector<int> &v1, std::vector<int> &v2) { 85 v2.erase(v2.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}} 86 v2.erase(v1.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}} 87 v2.erase(v1.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}} 88 } 89 90 void bad_emplace(std::vector<int> &v1, std::vector<int> &v2, int n) { 91 v2.emplace(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}} 92 } 93 94 void good_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) { 95 auto i0 = --v2.cend(); 96 v1 = std::move(v2); 97 std::find(i0, v1.cend(), n); // no-warning 98 } 99 100 void good_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) { 101 auto i0 = v2.cend(); 102 v1 = std::move(v2); 103 v2.push_back(n); 104 std::find(v2.cbegin(), i0, n); // no-warning 105 } 106 107 void good_comparison(std::vector<int> &v) { 108 if (v.cbegin() == v.cend()) {} // no-warning 109 } 110 111 void bad_ctor(std::vector<int> &v1, std::vector<int> &v2) { 112 std::vector<int> new_v(v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} 113 } 114 115 void bad_find(std::vector<int> &v1, std::vector<int> &v2, int n) { 116 std::find(v1.cbegin(), v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} 117 } 118 119 void bad_find_first_of(std::vector<int> &v1, std::vector<int> &v2) { 120 std::find_first_of(v1.cbegin(), v2.cend(), v2.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} 121 std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} 122 } 123 124 void bad_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) { 125 auto i0 = v2.cbegin(); 126 v1 = std::move(v2); 127 std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} 128 } 129 130 void bad_insert_find(std::vector<int> &v1, std::vector<int> &v2, int n, int m) { 131 auto i = std::find(v1.cbegin(), v1.cend(), n); 132 v2.insert(i, m); // expected-warning{{Container accessed using foreign iterator argument}} 133 } 134 135 void good_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) { 136 auto i = v1.cbegin(); 137 i = v2.cbegin(); 138 v2.insert(i, n); // no-warning 139 } 140 141 void bad_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) { 142 auto i = v1.cbegin(); 143 i = v2.cbegin(); 144 v1.insert(i, n); // expected-warning{{Container accessed using foreign iterator argument}} 145 } 146 147 template<typename Container, typename Iterator> 148 bool is_cend(Container cont, Iterator it) { 149 return it == cont.cend(); 150 } 151 152 void good_empty(std::vector<int> &v) { 153 is_cend(v, v.cbegin()); // no-warning 154 } 155 156 void bad_empty(std::vector<int> &v1, std::vector<int> &v2) { 157 is_cend(v1, v2.cbegin()); // expected-warning@-8{{Iterators of different containers used where the same container is expected}} 158 } 159 160 void good_move(std::vector<int> &v1, std::vector<int> &v2) { 161 const auto i0 = ++v2.cbegin(); 162 v1 = std::move(v2); 163 v1.erase(i0); // no-warning 164 } 165 166 void bad_move(std::vector<int> &v1, std::vector<int> &v2) { 167 const auto i0 = ++v2.cbegin(); 168 v1 = std::move(v2); 169 v2.erase(i0); // expected-warning{{Container accessed using foreign iterator argument}} 170 } 171 172 void bad_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) { 173 auto i0 = --v2.cend(); 174 v1 = std::move(v2); 175 std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} 176 } 177 178 void bad_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) { 179 auto i0 = v2.cend(); 180 v1 = std::move(v2); 181 std::find(v1.cbegin(), i0, n); // expected-warning{{Iterators of different containers used where the same container is expected}} 182 } 183 184 void bad_comparison(std::vector<int> &v1, std::vector<int> &v2) { 185 if (v1.cbegin() != v2.cend()) { // expected-warning{{Iterators of different containers used where the same container is expected}} 186 *v1.cbegin(); 187 } 188 } 189