2017-08-08 22:53:52 +08:00
// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
2016-01-29 23:21:32 +08:00
// ---------- Classes used in the tests ----------
// Iterator returning by value.
template < typename T >
struct Iterator {
void operator + + ( ) ;
T operator * ( ) ;
bool operator ! = ( const Iterator & other ) ;
} ;
// Iterator returning by reference.
template < typename T >
struct RefIterator {
void operator + + ( ) ;
T & operator * ( ) ;
bool operator ! = ( const RefIterator & other ) ;
} ;
// The template argument is an iterator type, and a view is an object you can
// run a for loop on.
template < typename T >
struct View {
T begin ( ) ;
T end ( ) ;
} ;
2017-08-08 22:53:52 +08:00
// With this class, the implicit conversion is a call to the (implicit)
// constructor of the class.
2016-01-29 23:21:32 +08:00
template < typename T >
class ImplicitWrapper {
public :
// Implicit!
ImplicitWrapper ( const T & t ) ;
} ;
2017-08-08 22:53:52 +08:00
// With this class, the implicit conversion is a call to the conversion
// operators of SimpleClass and ComplexClass.
2016-01-29 23:21:32 +08:00
template < typename T >
class OperatorWrapper {
public :
2018-06-11 20:46:48 +08:00
OperatorWrapper ( ) = delete ;
2016-01-29 23:21:32 +08:00
} ;
struct SimpleClass {
int foo ;
operator OperatorWrapper < SimpleClass > ( ) ;
} ;
// The materialize expression is not the same when the class has a destructor,
// so we make sure we cover that case too.
class ComplexClass {
public :
ComplexClass ( ) ;
~ ComplexClass ( ) ;
operator OperatorWrapper < ComplexClass > ( ) ;
} ;
typedef View < Iterator < SimpleClass > > SimpleView ;
typedef View < RefIterator < SimpleClass > > SimpleRefView ;
typedef View < Iterator < ComplexClass > > ComplexView ;
typedef View < RefIterator < ComplexClass > > ComplexRefView ;
// ---------- The test themselves ----------
// For each test we do, in the same order, const ref, non const ref, const
// value, non const value.
void SimpleClassIterator ( ) {
for ( const SimpleClass & foo : SimpleView ( ) ) { }
// This line does not compile because a temporary cannot be assigned to a non
// const reference.
// for (SimpleClass& foo : SimpleView()) {}
for ( const SimpleClass foo : SimpleView ( ) ) { }
for ( SimpleClass foo : SimpleView ( ) ) { }
}
void SimpleClassRefIterator ( ) {
for ( const SimpleClass & foo : SimpleRefView ( ) ) { }
for ( SimpleClass & foo : SimpleRefView ( ) ) { }
for ( const SimpleClass foo : SimpleRefView ( ) ) { }
for ( SimpleClass foo : SimpleRefView ( ) ) { }
}
void ComplexClassIterator ( ) {
for ( const ComplexClass & foo : ComplexView ( ) ) { }
// for (ComplexClass& foo : ComplexView()) {}
for ( const ComplexClass foo : ComplexView ( ) ) { }
for ( ComplexClass foo : ComplexView ( ) ) { }
}
void ComplexClassRefIterator ( ) {
for ( const ComplexClass & foo : ComplexRefView ( ) ) { }
for ( ComplexClass & foo : ComplexRefView ( ) ) { }
for ( const ComplexClass foo : ComplexRefView ( ) ) { }
for ( ComplexClass foo : ComplexRefView ( ) ) { }
}
void ImplicitSimpleClassIterator ( ) {
for ( const ImplicitWrapper < SimpleClass > & foo : SimpleView ( ) ) { }
2017-08-08 22:53:52 +08:00
// 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]
2016-01-29 23:21:32 +08:00
// for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
for ( const ImplicitWrapper < SimpleClass > foo : SimpleView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( ImplicitWrapper < SimpleClass > foo : SimpleView ( ) ) { }
2016-01-29 23:21:32 +08:00
}
void ImplicitSimpleClassRefIterator ( ) {
for ( const ImplicitWrapper < SimpleClass > & foo : SimpleRefView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
for ( const ImplicitWrapper < SimpleClass > foo : SimpleRefView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( ImplicitWrapper < SimpleClass > foo : SimpleRefView ( ) ) { }
}
void ImplicitSimpleClassArray ( ) {
SimpleClass array [ 5 ] ;
for ( const ImplicitWrapper < SimpleClass > & foo : array ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (ImplicitWrapper<SimpleClass>& foo : array) {}
for ( const ImplicitWrapper < SimpleClass > foo : array ) { }
for ( ImplicitWrapper < SimpleClass > foo : array ) { }
2016-01-29 23:21:32 +08:00
}
void ImplicitComplexClassIterator ( ) {
for ( const ImplicitWrapper < ComplexClass > & foo : ComplexView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
for ( const ImplicitWrapper < ComplexClass > foo : ComplexView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( ImplicitWrapper < ComplexClass > foo : ComplexView ( ) ) { }
2016-01-29 23:21:32 +08:00
}
void ImplicitComplexClassRefIterator ( ) {
2018-06-11 20:46:48 +08:00
ComplexClass array [ 5 ] ;
for ( const ImplicitWrapper < ComplexClass > & foo : array ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (ImplicitWrapper<ComplexClass>& foo : array) {}
for ( const ImplicitWrapper < ComplexClass > foo : array ) { }
for ( ImplicitWrapper < ComplexClass > foo : array ) { }
}
void ImplicitComplexClassArray ( ) {
2016-01-29 23:21:32 +08:00
for ( const ImplicitWrapper < ComplexClass > & foo : ComplexRefView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
for ( const ImplicitWrapper < ComplexClass > foo : ComplexRefView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( ImplicitWrapper < ComplexClass > foo : ComplexRefView ( ) ) { }
2016-01-29 23:21:32 +08:00
}
void OperatorSimpleClassIterator ( ) {
for ( const OperatorWrapper < SimpleClass > & foo : SimpleView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
for ( const OperatorWrapper < SimpleClass > foo : SimpleView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( OperatorWrapper < SimpleClass > foo : SimpleView ( ) ) { }
2016-01-29 23:21:32 +08:00
}
void OperatorSimpleClassRefIterator ( ) {
for ( const OperatorWrapper < SimpleClass > & foo : SimpleRefView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
for ( const OperatorWrapper < SimpleClass > foo : SimpleRefView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( OperatorWrapper < SimpleClass > foo : SimpleRefView ( ) ) { }
}
void OperatorSimpleClassArray ( ) {
SimpleClass array [ 5 ] ;
for ( const OperatorWrapper < SimpleClass > & foo : array ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (OperatorWrapper<SimpleClass>& foo : array) {}
for ( const OperatorWrapper < SimpleClass > foo : array ) { }
for ( OperatorWrapper < SimpleClass > foo : array ) { }
2016-01-29 23:21:32 +08:00
}
void OperatorComplexClassIterator ( ) {
for ( const OperatorWrapper < ComplexClass > & foo : ComplexView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
for ( const OperatorWrapper < ComplexClass > foo : ComplexView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( OperatorWrapper < ComplexClass > foo : ComplexView ( ) ) { }
2016-01-29 23:21:32 +08:00
}
void OperatorComplexClassRefIterator ( ) {
for ( const OperatorWrapper < ComplexClass > & foo : ComplexRefView ( ) ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
for ( const OperatorWrapper < ComplexClass > foo : ComplexRefView ( ) ) { }
2018-06-11 20:46:48 +08:00
for ( OperatorWrapper < ComplexClass > foo : ComplexRefView ( ) ) { }
}
void OperatorComplexClassArray ( ) {
ComplexClass array [ 5 ] ;
for ( const OperatorWrapper < ComplexClass > & foo : array ) { }
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (OperatorWrapper<ComplexClass>& foo : array) {}
for ( const OperatorWrapper < ComplexClass > foo : array ) { }
for ( OperatorWrapper < ComplexClass > foo : array ) { }
2016-01-29 23:21:32 +08:00
}