diff options
Diffstat (limited to 'clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp')
-rw-r--r-- | clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp b/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp index fcd5a96eb66..f76d84bb97a 100644 --- a/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp +++ b/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp @@ -1,9 +1,27 @@ -// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm -- +// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm -- --std=c++11 namespace std { typedef int size_t; +template<class E> class initializer_list { +public: + using value_type = E; + using reference = E&; + using const_reference = const E&; + using size_type = size_t; + using iterator = const E*; + using const_iterator = const E*; + initializer_list(); + size_t size() const; // number of elements + const E* begin() const; // first element + const E* end() const; // one past the last element +}; + +// initializer list range access +template<class E> const E* begin(initializer_list<E> il); +template<class E> const E* end(initializer_list<E> il); + template <class T> class vector { public: @@ -23,9 +41,24 @@ class vector { size_t size(); const_reference operator[] (size_type) const; reference operator[] (size_type); + + const_iterator begin() const; + const_iterator end() const; }; } // namespace std +class Foo { + public: + explicit Foo(int); +}; + +class Bar { + public: + Bar(int); +}; + +int Op(int); + void f(std::vector<int>& t) { { std::vector<int> v; @@ -85,7 +118,38 @@ void f(std::vector<int>& t) { v.push_back(t[i]); } // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called } - + { + std::vector<int> v; + // CHECK-FIXES: v.reserve(t.size()); + for (const auto &e : t) { + v.push_back(e); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called + } + } + { + std::vector<int> v; + // CHECK-FIXES: v.reserve(t.size()); + for (const auto &e : t) { + v.push_back(Op(e)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called + } + } + { + std::vector<Foo> v; + // CHECK-FIXES: v.reserve(t.size()); + for (const auto &e : t) { + v.push_back(Foo(e)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called + } + } + { + std::vector<Bar> v; + // CHECK-FIXES: v.reserve(t.size()); + for (const auto &e : t) { + v.push_back(e); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called + } + } // ---- Non-fixed Cases ---- { std::vector<int> v; @@ -181,4 +245,21 @@ void f(std::vector<int>& t) { v.push_back(t[i]); } } + { + std::vector<int> v; + // initializer_list should not trigger the check. + for (int e : {1, 2, 3, 4, 5}) { + v.push_back(e); + } + } + { + std::vector<int> v; + std::vector<int>* v2 = &t; + // We only support detecting the range init expression which references + // container directly. + // Complex range init expressions like `*v2` is not supported. + for (const auto &e : *v2) { + v.push_back(e); + } + } } |