198 lines · cpp
1// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t2 3// ---------- Classes used in the tests ----------4 5// Iterator returning by value.6template <typename T>7struct Iterator {8 void operator++();9 T operator*();10 bool operator!=(const Iterator& other);11};12 13// Iterator returning by reference.14template <typename T>15struct RefIterator {16 void operator++();17 T& operator*();18 bool operator!=(const RefIterator& other);19};20 21// The template argument is an iterator type, and a view is an object you can22// run a for loop on.23template <typename T>24struct View {25 T begin();26 T end();27};28 29// With this class, the implicit conversion is a call to the (implicit)30// constructor of the class.31template <typename T>32class ImplicitWrapper {33 public:34 // Implicit!35 ImplicitWrapper(const T& t);36};37 38// With this class, the implicit conversion is a call to the conversion39// operators of SimpleClass and ComplexClass.40template <typename T>41class OperatorWrapper {42 public:43 OperatorWrapper() = delete;44};45 46struct SimpleClass {47 int foo;48 operator OperatorWrapper<SimpleClass>();49};50 51// The materialize expression is not the same when the class has a destructor,52// so we make sure we cover that case too.53class ComplexClass {54 public:55 ComplexClass();56 ~ComplexClass();57 operator OperatorWrapper<ComplexClass>();58};59 60typedef View<Iterator<SimpleClass>> SimpleView;61typedef View<RefIterator<SimpleClass>> SimpleRefView;62typedef View<Iterator<ComplexClass>> ComplexView;63typedef View<RefIterator<ComplexClass>> ComplexRefView;64 65// ---------- The test themselves ----------66// For each test we do, in the same order, const ref, non const ref, const67// value, non const value.68 69void SimpleClassIterator() {70 for (const SimpleClass& foo : SimpleView()) {}71 // This line does not compile because a temporary cannot be assigned to a non72 // const reference.73 // for (SimpleClass& foo : SimpleView()) {}74 for (const SimpleClass foo : SimpleView()) {}75 for (SimpleClass foo : SimpleView()) {}76}77 78void SimpleClassRefIterator() {79 for (const SimpleClass& foo : SimpleRefView()) {}80 for (SimpleClass& foo : SimpleRefView()) {}81 for (const SimpleClass foo : SimpleRefView()) {}82 for (SimpleClass foo : SimpleRefView()) {}83}84 85void ComplexClassIterator() {86 for (const ComplexClass& foo : ComplexView()) {}87 // for (ComplexClass& foo : ComplexView()) {}88 for (const ComplexClass foo : ComplexView()) {}89 for (ComplexClass foo : ComplexView()) {}90}91 92void ComplexClassRefIterator() {93 for (const ComplexClass& foo : ComplexRefView()) {}94 for (ComplexClass& foo : ComplexRefView()) {}95 for (const ComplexClass foo : ComplexRefView()) {}96 for (ComplexClass foo : ComplexRefView()) {}97}98 99void ImplicitSimpleClassIterator() {100 for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}101 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]102 // for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}103 for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}104 for (ImplicitWrapper<SimpleClass> foo : SimpleView()) {}105}106 107void ImplicitSimpleClassRefIterator() {108 for (const ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}109 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}110 // for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}111 for (const ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}112 for (ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}113}114 115void ImplicitSimpleClassArray() {116 SimpleClass array[5];117 for (const ImplicitWrapper<SimpleClass>& foo : array) {}118 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}119 // for (ImplicitWrapper<SimpleClass>& foo : array) {}120 for (const ImplicitWrapper<SimpleClass> foo : array) {}121 for (ImplicitWrapper<SimpleClass> foo : array) {}122}123 124void ImplicitComplexClassIterator() {125 for (const ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}126 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}127 // for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}128 for (const ImplicitWrapper<ComplexClass> foo : ComplexView()) {}129 for (ImplicitWrapper<ComplexClass> foo : ComplexView()) {}130}131 132void ImplicitComplexClassRefIterator() {133 ComplexClass array[5];134 for (const ImplicitWrapper<ComplexClass>& foo : array) {}135 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}136 // for (ImplicitWrapper<ComplexClass>& foo : array) {}137 for (const ImplicitWrapper<ComplexClass> foo : array) {}138 for (ImplicitWrapper<ComplexClass> foo : array) {}139}140 141void ImplicitComplexClassArray() {142 for (const ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}143 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}144 // for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}145 for (const ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}146 for (ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}147}148 149void OperatorSimpleClassIterator() {150 for (const OperatorWrapper<SimpleClass>& foo : SimpleView()) {}151 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}152 // for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}153 for (const OperatorWrapper<SimpleClass> foo : SimpleView()) {}154 for (OperatorWrapper<SimpleClass> foo : SimpleView()) {}155}156 157void OperatorSimpleClassRefIterator() {158 for (const OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}159 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}160 // for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}161 for (const OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}162 for (OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}163}164 165void OperatorSimpleClassArray() {166 SimpleClass array[5];167 for (const OperatorWrapper<SimpleClass>& foo : array) {}168 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}169 // for (OperatorWrapper<SimpleClass>& foo : array) {}170 for (const OperatorWrapper<SimpleClass> foo : array) {}171 for (OperatorWrapper<SimpleClass> foo : array) {}172}173 174void OperatorComplexClassIterator() {175 for (const OperatorWrapper<ComplexClass>& foo : ComplexView()) {}176 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}177 // for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}178 for (const OperatorWrapper<ComplexClass> foo : ComplexView()) {}179 for (OperatorWrapper<ComplexClass> foo : ComplexView()) {}180}181 182void OperatorComplexClassRefIterator() {183 for (const OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}184 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}185 // for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}186 for (const OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}187 for (OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}188}189 190void OperatorComplexClassArray() {191 ComplexClass array[5];192 for (const OperatorWrapper<ComplexClass>& foo : array) {}193 // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}194 // for (OperatorWrapper<ComplexClass>& foo : array) {}195 for (const OperatorWrapper<ComplexClass> foo : array) {}196 for (OperatorWrapper<ComplexClass> foo : array) {}197}198