performance-implicit-conversion-in-loop.cpp
7.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
// ---------- 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();
};
// With this class, the implicit conversion is a call to the (implicit)
// constructor of the class.
template <typename T>
class ImplicitWrapper {
public:
// Implicit!
ImplicitWrapper(const T& t);
};
// With this class, the implicit conversion is a call to the conversion
// operators of SimpleClass and ComplexClass.
template <typename T>
class OperatorWrapper {
public:
OperatorWrapper() = delete;
};
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()) {}
// 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]
// for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
for (ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
}
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()) {}
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) {}
}
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()) {}
for (ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
}
void ImplicitComplexClassRefIterator() {
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() {
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()) {}
for (ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
}
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()) {}
for (OperatorWrapper<SimpleClass> foo : SimpleView()) {}
}
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()) {}
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) {}
}
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()) {}
for (OperatorWrapper<ComplexClass> foo : ComplexView()) {}
}
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()) {}
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) {}
}