brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · e1e25d7 Raw
427 lines · cpp
1// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- \2// RUN: -format-style=llvm \3// RUN: -config='{CheckOptions: \4// RUN:  {performance-inefficient-vector-operation.EnableProto: true}}'5 6namespace std {7 8typedef decltype(sizeof 0) size_t;9 10template<class E> class initializer_list {11public:12  using value_type = E;13  using reference = E&;14  using const_reference = const E&;15  using size_type = size_t;16  using iterator = const E*;17  using const_iterator = const E*;18  iterator p;19  size_t sz;20  initializer_list();21  size_t size() const; // number of elements22  const E* begin() const; // first element23  const E* end() const; // one past the last element24};25 26// initializer list range access27template<class E> const E* begin(initializer_list<E> il);28template<class E> const E* end(initializer_list<E> il);29 30template <class T>31class vector {32 public:33  typedef T* iterator;34  typedef const T* const_iterator;35  typedef T& reference;36  typedef const T& const_reference;37  typedef size_t size_type;38 39  explicit vector();40  explicit vector(size_type n);41 42  void push_back(const T& val);43 44  template <class... Args> void emplace_back(Args &&... args);45 46  void reserve(size_t n);47  void resize(size_t n);48 49  size_t size() const;50  const_reference operator[] (size_type) const;51  reference operator[] (size_type);52 53  const_iterator begin() const;54  const_iterator end() const;55};56} // namespace std57 58class Foo {59 public:60  explicit Foo(int);61};62 63class Bar {64 public:65  Bar(int);66};67 68int Op(int);69 70namespace proto2 {71class MessageLite {};72class Message : public MessageLite {};73} // namespace proto274 75class FooProto : public proto2::Message {76 public:77  int *add_x();  // repeated int x;78  void add_x(int x);79  void mutable_x();80  void mutable_y();81  int add_z() const; // optional int add_z;82};83 84class BarProto : public proto2::Message {85 public:86  int *add_x();87  void add_x(int x);88  void mutable_x();89  void mutable_y();90};91 92void f(std::vector<int>& t) {93  {94    std::vector<int> v0;95    // CHECK-FIXES: v0.reserve(10);96    for (int i = 0; i < 10; ++i)97      v0.push_back(i);98      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the container capacity before the loop99  }100  {101    std::vector<int> v1;102    // CHECK-FIXES: v1.reserve(10);103    for (int i = 0; i < 10; i++)104      v1.push_back(i);105      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called106  }107  {108    std::vector<int> v2;109    // CHECK-FIXES: v2.reserve(10);110    for (int i = 0; i < 10; ++i)111      v2.push_back(0);112      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called113  }114  {115    std::vector<int> v3;116    // CHECK-FIXES: v3.reserve(5);117    for (int i = 0; i < 5; ++i) {118      v3.push_back(i);119      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called120    }121    // CHECK-FIXES-NOT: v3.reserve(10);122    for (int i = 0; i < 10; ++i) {123      // No fix for this loop as we encounter the prior loops.124      v3.push_back(i);125    }126  }127  {128    std::vector<int> v4;129    std::vector<int> v5;130    v5.reserve(3);131    // CHECK-FIXES: v4.reserve(10);132    for (int i = 0; i < 10; ++i)133      v4.push_back(i);134      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called135  }136  {137    std::vector<int> v6;138    // CHECK-FIXES: v6.reserve(t.size());139    for (std::size_t i = 0; i < t.size(); ++i) {140      v6.push_back(t[i]);141      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called142    }143  }144  {145    std::vector<int> v7;146    // CHECK-FIXES: v7.reserve(t.size() - 1);147    for (std::size_t i = 0; i < t.size() - 1; ++i) {148      v7.push_back(t[i]);149    } // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called150  }151  {152    std::vector<int> v8;153    // CHECK-FIXES: v8.reserve(t.size());154    for (const auto &e : t) {155      v8.push_back(e);156      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called157    }158  }159  {160    std::vector<int> v9;161    // CHECK-FIXES: v9.reserve(t.size());162    for (const auto &e : t) {163      v9.push_back(Op(e));164      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called165    }166  }167  {168    std::vector<Foo> v10;169    // CHECK-FIXES: v10.reserve(t.size());170    for (const auto &e : t) {171      v10.push_back(Foo(e));172      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called173    }174  }175  {176    std::vector<Bar> v11;177    // CHECK-FIXES: v11.reserve(t.size());178    for (const auto &e : t) {179      v11.push_back(e);180      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called181    }182  }183  {184    std::vector<Foo> v12;185    // CHECK-FIXES: v12.reserve(t.size());186    for (const auto &e : t) {187      v12.emplace_back(e);188      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'emplace_back' is called189    }190  }191 192  {193    FooProto foo;194    // CHECK-FIXES: foo.mutable_x()->Reserve(5);195    for (int i = 0; i < 5; i++) {196      foo.add_x(i);197      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'add_x' is called inside a loop; consider pre-allocating the container capacity before the loop198    }199  }200 201  // ---- Non-fixed Cases ----202  {203    std::vector<int> z0;204    z0.reserve(20);205    // CHECK-FIXES-NOT: z0.reserve(10);206    // There is a "reserve" call already.207    for (int i = 0; i < 10; ++i) {208      z0.push_back(i);209    }210  }211  {212    std::vector<int> z1;213    z1.reserve(5);214    // CHECK-FIXES-NOT: z1.reserve(10);215    // There is a "reserve" call already.216    for (int i = 0; i < 10; ++i) {217      z1.push_back(i);218    }219  }220  {221    std::vector<int> z2;222    z2.resize(5);223    // CHECK-FIXES-NOT: z2.reserve(10);224    // There is a ref usage of v before the loop.225    for (int i = 0; i < 10; ++i) {226      z2.push_back(i);227    }228  }229  {230    std::vector<int> z3;231    z3.push_back(0);232    // CHECK-FIXES-NOT: z3.reserve(10);233    // There is a ref usage of v before the loop.234    for (int i = 0; i < 10; ++i) {235      z3.push_back(i);236    }237  }238  {239    std::vector<int> z4;240    f(z4);241    // CHECK-FIXES-NOT: z4.reserve(10);242    // There is a ref usage of z4 before the loop.243    for (int i = 0; i < 10; ++i) {244      z4.push_back(i);245    }246  }247  {248    std::vector<int> z5(20);249    // CHECK-FIXES-NOT: z5.reserve(10);250    // z5 is not constructed with default constructor.251    for (int i = 0; i < 10; ++i) {252      z5.push_back(i);253    }254  }255  {256    std::vector<int> z6;257    // CHECK-FIXES-NOT: z6.reserve(10);258    // For-loop is not started with 0.259    for (int i = 1; i < 10; ++i) {260      z6.push_back(i);261    }262  }263  {264    std::vector<int> z7;265    // CHECK-FIXES-NOT: z7.reserve(t.size());266    // z7 isn't referenced in for-loop body.267    for (std::size_t i = 0; i < t.size(); ++i) {268      t.push_back(i);269    }270  }271  {272    std::vector<int> z8;273    int k;274    // CHECK-FIXES-NOT: z8.reserve(10);275    // For-loop isn't a fixable loop.276    for (std::size_t i = 0; k < 10; ++i) {277      z8.push_back(t[i]);278    }279  }280  {281    std::vector<int> z9;282    // CHECK-FIXES-NOT: z9.reserve(i + 1);283    // The loop end expression refers to the loop variable i.284    for (int i = 0; i < i + 1; i++)285      z9.push_back(i);286  }287  {288    std::vector<int> z10;289    int k;290    // CHECK-FIXES-NOT: z10.reserve(10);291    // For-loop isn't a fixable loop.292    for (std::size_t i = 0; i < 10; ++k) {293      z10.push_back(t[i]);294    }295  }296  {297    std::vector<int> z11;298    // initializer_list should not trigger the check.299    for (int e : {1, 2, 3, 4, 5}) {300      z11.push_back(e);301    }302  }303  {304    std::vector<int> z12;305    std::vector<int>* z13 = &t;306    // We only support detecting the range init expression which references307    // container directly.308    // Complex range init expressions like `*z13` is not supported.309    for (const auto &e : *z13) {310      z12.push_back(e);311    }312  }313 314  {315    FooProto foo;316    foo.mutable_x();317    // CHECK-FIXES-NOT: foo.mutable_x()->Reserve(5);318    for (int i = 0; i < 5; i++) {319      foo.add_x(i);320    }321  }322  {323    FooProto foo;324    // CHECK-FIXES-NOT: foo.mutable_x()->Reserve(5);325    for (int i = 0; i < 5; i++) {326      foo.add_x(i);327      foo.add_x(i);328    }329  }330  {331    FooProto foo;332    // CHECK-FIXES-NOT: foo.mutable_x()->Reserve(5);333    foo.add_x(-1);334    for (int i = 0; i < 5; i++) {335      foo.add_x(i);336    }337  }338  {339    FooProto foo;340    BarProto bar;341    bar.mutable_x();342    // CHECK-FIXES-NOT: foo.mutable_x()->Reserve(5);343    for (int i = 0; i < 5; i++) {344      foo.add_x();345      bar.add_x();346    }347  }348  {349    FooProto foo;350    foo.mutable_y();351    // CHECK-FIXES-NOT: foo.mutable_x()->Reserve(5);352    for (int i = 0; i < 5; i++) {353      foo.add_x(i);354    }355  }356  {357    FooProto foo;358    // CHECK-FIXES-NOT: foo.mutable_z()->Reserve(5);359    for (int i = 0; i < 5; i++) {360      foo.add_z();361    }362  }363}364 365struct StructWithFieldContainer {366  std::vector<int> Numbers;367  std::vector<int> getNumbers() const {368    std::vector<int> Result;369    // CHECK-FIXES: Result.reserve(Numbers.size());370    for (auto Number : Numbers) {371      Result.push_back(Number);372      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called373    }374    return Result;375  }376};377 378StructWithFieldContainer getStructWithField();379 380void foo(const StructWithFieldContainer &Src) {381  std::vector<int> A;382  // CHECK-FIXES: A.reserve(Src.Numbers.size());383  for (auto Number : Src.Numbers) {384    A.push_back(Number);385    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'push_back' is called386  }387  std::vector<int> B;388  for (auto Number : getStructWithField().Numbers) {389    B.push_back(Number);390  }391}392 393namespace gh95596 {394 395void f(std::vector<int>& t) {396  {397    std::vector<int> gh95596_0;398    // CHECK-FIXES: gh95596_0.reserve(10);399    for (unsigned i = 0; i < 10; ++i)400      gh95596_0.push_back(i);401      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the container capacity before the loop402  }403  {404    std::vector<int> gh95596_1;405    // CHECK-FIXES: gh95596_1.reserve(10);406    for (int i = 0U; i < 10; ++i)407      gh95596_1.push_back(i);408      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the container capacity before the loop409  }410  {411    std::vector<int> gh95596_2;412    // CHECK-FIXES: gh95596_2.reserve(10);413    for (unsigned i = 0U; i < 10; ++i)414      gh95596_2.push_back(i);415      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the container capacity before the loop416  }417  {418    std::vector<int> gh95596_3;419    // CHECK-FIXES: gh95596_3.reserve(10U);420    for (int i = 0; i < 10U; ++i)421      gh95596_3.push_back(i);422      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the container capacity before the loop423  }424}425 426} // namespace gh95596427