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