1 | // RUN: %check_clang_tidy %s bugprone-fold-init-type -std=c++17 %t |
---|---|
2 | |
3 | namespace std { |
4 | template <class InputIt, class T> |
5 | T accumulate(InputIt first, InputIt last, T init) { |
6 | // When `InputIt::operator*` returns a deduced `auto` type that refers to a |
7 | // dependent type, the return type is deduced only if `InputIt::operator*` |
8 | // is instantiated. In practice this happens somewhere in the implementation |
9 | // of `accumulate`. For tests, do it here. |
10 | (void)*first; |
11 | return init; |
12 | } |
13 | |
14 | template <class InputIt, class T> |
15 | T reduce(InputIt first, InputIt last, T init) { (void)*first; return init; } |
16 | template <class ExecutionPolicy, class InputIt, class T> |
17 | T reduce(ExecutionPolicy &&policy, |
18 | InputIt first, InputIt last, T init) { (void)*first; return init; } |
19 | |
20 | struct parallel_execution_policy {}; |
21 | constexpr parallel_execution_policy par{}; |
22 | |
23 | template <class InputIt1, class InputIt2, class T> |
24 | T inner_product(InputIt1 first1, InputIt1 last1, |
25 | InputIt2 first2, T value) { (void)*first1; (void)*first2; return value; } |
26 | |
27 | template <class ExecutionPolicy, class InputIt1, class InputIt2, class T> |
28 | T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1, |
29 | InputIt2 first2, T value) { (void)*first1; (void)*first2; return value; } |
30 | |
31 | } // namespace std |
32 | |
33 | struct FloatIterator { |
34 | const float &operator*() const; |
35 | }; |
36 | |
37 | struct DerivedFloatIterator : public FloatIterator { |
38 | }; |
39 | |
40 | template <typename ValueType> struct ByValueTemplateIterator { |
41 | ValueType operator*() const; |
42 | }; |
43 | |
44 | template <typename ValueType> struct ByRefTemplateIterator { |
45 | ValueType &operator*(); |
46 | }; |
47 | |
48 | template <typename ValueType> struct ByRefTemplateIteratorWithAlias { |
49 | using reference = const ValueType&; |
50 | reference operator*(); |
51 | }; |
52 | |
53 | template <typename ValueType> struct AutoByValueTemplateIterator { |
54 | auto operator*() const { return ValueType{}; } |
55 | }; |
56 | |
57 | template <typename ValueType> struct AutoByRefTemplateIterator { |
58 | decltype(auto) operator*() const { return value_; } |
59 | ValueType value_; |
60 | }; |
61 | |
62 | template <typename ValueType> |
63 | struct InheritingByConstRefTemplateIterator |
64 | : public ByRefTemplateIterator<const ValueType> {}; |
65 | |
66 | using TypedeffedIterator = FloatIterator; |
67 | |
68 | // Positives. |
69 | |
70 | int accumulatePositive1() { |
71 | float a[1] = {0.5f}; |
72 | return std::accumulate(first: a, last: a + 1, init: 0); |
73 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
74 | } |
75 | |
76 | int accumulatePositive2() { |
77 | FloatIterator it; |
78 | return std::accumulate(first: it, last: it, init: 0); |
79 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
80 | } |
81 | |
82 | int accumulatePositive3() { |
83 | DerivedFloatIterator it; |
84 | return std::accumulate(first: it, last: it, init: 0); |
85 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
86 | } |
87 | |
88 | int accumulatePositive4() { |
89 | double a[1] = {0.0}; |
90 | return std::accumulate(first: a, last: a + 1, init: 0.0f); |
91 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'double' into type 'float' |
92 | } |
93 | |
94 | int accumulatePositive5() { |
95 | ByValueTemplateIterator<unsigned> it; |
96 | return std::accumulate(first: it, last: it, init: 0); |
97 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
98 | } |
99 | |
100 | int accumulatePositive6() { |
101 | ByRefTemplateIterator<unsigned> it; |
102 | return std::accumulate(first: it, last: it, init: 0); |
103 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
104 | } |
105 | |
106 | int accumulatePositive7() { |
107 | AutoByValueTemplateIterator<unsigned> it; |
108 | return std::accumulate(first: it, last: it, init: 0); |
109 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
110 | } |
111 | |
112 | int accumulatePositive8() { |
113 | TypedeffedIterator it; |
114 | return std::accumulate(first: it, last: it, init: 0); |
115 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
116 | } |
117 | |
118 | int accumulatePositive9() { |
119 | InheritingByConstRefTemplateIterator<unsigned> it; |
120 | return std::accumulate(first: it, last: it, init: 0); |
121 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
122 | } |
123 | |
124 | int accumulatePositive10() { |
125 | AutoByRefTemplateIterator<unsigned> it; |
126 | return std::accumulate(first: it, last: it, init: 0); |
127 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
128 | } |
129 | |
130 | int accumulatePositive11() { |
131 | ByRefTemplateIteratorWithAlias<unsigned> it; |
132 | return std::accumulate(first: it, last: it, init: 0); |
133 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' |
134 | } |
135 | |
136 | int reducePositive1() { |
137 | float a[1] = {0.5f}; |
138 | return std::reduce(first: a, last: a + 1, init: 0); |
139 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
140 | } |
141 | |
142 | int reducePositive2() { |
143 | float a[1] = {0.5f}; |
144 | return std::reduce(policy: std::par, first: a, last: a + 1, init: 0); |
145 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
146 | } |
147 | |
148 | int innerProductPositive1() { |
149 | float a[1] = {0.5f}; |
150 | int b[1] = {1}; |
151 | return std::inner_product(policy: std::par, first1: a, last1: a + 1, first2: b, value: 0); |
152 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
153 | } |
154 | |
155 | int innerProductPositive2() { |
156 | float a[1] = {0.5f}; |
157 | int b[1] = {1}; |
158 | return std::inner_product(policy: std::par, first1: a, last1: a + 1, first2: b, value: 0); |
159 | // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' |
160 | } |
161 | |
162 | // Negatives. |
163 | |
164 | int negative1() { |
165 | float a[1] = {0.5f}; |
166 | // This is OK because types match. |
167 | return std::accumulate(first: a, last: a + 1, init: 0.0); |
168 | } |
169 | |
170 | int negative2() { |
171 | float a[1] = {0.5f}; |
172 | // This is OK because double is bigger than float. |
173 | return std::accumulate(first: a, last: a + 1, init: 0.0); |
174 | } |
175 | |
176 | int negative3() { |
177 | float a[1] = {0.5f}; |
178 | // This is OK because the user explicitly specified T. |
179 | return std::accumulate<float *, float>(first: a, last: a + 1, init: 0); |
180 | } |
181 | |
182 | int negative4() { |
183 | ByValueTemplateIterator<unsigned> it; |
184 | // For now this is OK. |
185 | return std::accumulate(first: it, last: it, init: 0.0); |
186 | } |
187 | |
188 | int negative5() { |
189 | float a[1] = {0.5f}; |
190 | float b[1] = {1.0f}; |
191 | return std::inner_product(policy: std::par, first1: a, last1: a + 1, first2: b, value: 0.0f); |
192 | } |
193 | |
194 | namespace blah { |
195 | namespace std { |
196 | template <class InputIt, class T> |
197 | T accumulate(InputIt, InputIt, T); // We should not care about this one. |
198 | } |
199 | |
200 | int negative5() { |
201 | float a[1] = {0.5f}; |
202 | // Note that this is using blah::std::accumulate. |
203 | return std::accumulate(a, a + 1, 0); |
204 | } |
205 | } |
206 |
Definitions
- accumulate
- reduce
- reduce
- parallel_execution_policy
- par
- inner_product
- inner_product
- FloatIterator
- DerivedFloatIterator
- ByValueTemplateIterator
- ByRefTemplateIterator
- ByRefTemplateIteratorWithAlias
- AutoByValueTemplateIterator
- operator*
- AutoByRefTemplateIterator
- operator*
- InheritingByConstRefTemplateIterator
- accumulatePositive1
- accumulatePositive2
- accumulatePositive3
- accumulatePositive4
- accumulatePositive5
- accumulatePositive6
- accumulatePositive7
- accumulatePositive8
- accumulatePositive9
- accumulatePositive10
- accumulatePositive11
- reducePositive1
- reducePositive2
- innerProductPositive1
- innerProductPositive2
- negative1
- negative2
- negative3
- negative4
- negative5
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more