101 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-inaccurate-erase %t2 3namespace std {4template <typename T> struct vec_iterator {5 T ptr;6 vec_iterator operator++(int);7 8 template <typename X>9 vec_iterator(const vec_iterator<X> &); // Omit enable_if<...>.10};11 12template <typename T> struct vector {13 typedef vec_iterator<T*> iterator;14 15 iterator begin();16 iterator end();17 18 void erase(iterator);19 void erase(iterator, iterator);20};21 22template <typename T> struct vector_with_const_iterator {23 typedef vec_iterator<T*> iterator;24 typedef vec_iterator<const T*> const_iterator;25 26 iterator begin();27 iterator end();28 29 void erase(const_iterator);30 void erase(const_iterator, const_iterator);31};32 33template <typename FwIt, typename T>34FwIt remove(FwIt begin, FwIt end, const T &val);35 36template <typename FwIt, typename Func>37FwIt remove_if(FwIt begin, FwIt end, Func f);38 39template <typename FwIt> FwIt unique(FwIt begin, FwIt end);40 41template <typename T> struct unique_ptr {};42} // namespace std43 44struct custom_iter {};45struct custom_container {46 void erase(...);47 custom_iter begin();48 custom_iter end();49};50 51template <typename T> void g() {52 T t;53 t.erase(std::remove(t.begin(), t.end(), 10));54 // CHECK-FIXES: t.erase(std::remove(t.begin(), t.end(), 10));55 56 std::vector<int> v;57 v.erase(remove(v.begin(), v.end(), 10));58 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one59 // CHECK-FIXES: v.erase(remove(v.begin(), v.end(), 10), v.end());60}61 62#define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))63// CHECK-FIXES: #define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))64 65int main() {66 std::vector<int> v;67 68 v.erase(remove(v.begin(), v.end(), 10));69 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one item even when multiple items should be removed [bugprone-inaccurate-erase]70 // CHECK-FIXES: v.erase(remove(v.begin(), v.end(), 10), v.end());71 v.erase(remove(v.begin(), v.end(), 20), v.end());72 73 auto *p = &v;74 p->erase(remove(p->begin(), p->end(), 11));75 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one76 // CHECK-FIXES: p->erase(remove(p->begin(), p->end(), 11), p->end());77 78 std::vector_with_const_iterator<int> v2;79 v2.erase(remove(v2.begin(), v2.end(), 12));80 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one81 // CHECK-FIXES: v2.erase(remove(v2.begin(), v2.end(), 12), v2.end());82 83 // Fix is not trivial.84 auto it = v.end();85 v.erase(remove(v.begin(), it, 10));86 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one87 // CHECK-FIXES: v.erase(remove(v.begin(), it, 10));88 89 g<std::vector<int>>();90 g<custom_container>();91 92 ERASE(v, 15);93 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: this call will remove at most one94 // CHECK-FIXES: ERASE(v, 15);95 96 std::vector<std::unique_ptr<int>> vupi;97 auto iter = vupi.begin();98 vupi.erase(iter++);99 // CHECK-FIXES: vupi.erase(iter++);100}101