1 // RUN: %check_clang_tidy %s bugprone-fold-init-type %t
2
3 namespace std {
4 template <class InputIt, class T>
5 T accumulate(InputIt first, InputIt last, T init);
6
7 template <class InputIt, class T>
8 T reduce(InputIt first, InputIt last, T init);
9 template <class ExecutionPolicy, class InputIt, class T>
10 T reduce(ExecutionPolicy &&policy,
11 InputIt first, InputIt last, T init);
12
13 struct parallel_execution_policy {};
14 constexpr parallel_execution_policy par{};
15
16 template <class InputIt1, class InputIt2, class T>
17 T inner_product(InputIt1 first1, InputIt1 last1,
18 InputIt2 first2, T value);
19
20 template <class ExecutionPolicy, class InputIt1, class InputIt2, class T>
21 T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1,
22 InputIt2 first2, T value);
23
24 } // namespace std
25
26 struct FloatIterator {
27 typedef float value_type;
28 };
29 template <typename ValueType>
30 struct TypedefTemplateIterator { typedef ValueType value_type; };
31 template <typename ValueType>
32 struct UsingTemplateIterator { using value_type = ValueType; };
33 template <typename ValueType>
34 struct DependentTypedefTemplateIterator { typedef typename ValueType::value_type value_type; };
35 template <typename ValueType>
36 struct DependentUsingTemplateIterator : public TypedefTemplateIterator<ValueType> { using typename TypedefTemplateIterator<ValueType>::value_type; };
37 using TypedeffedIterator = FloatIterator;
38
39 // Positives.
40
accumulatePositive1()41 int accumulatePositive1() {
42 float a[1] = {0.5f};
43 return std::accumulate(a, a + 1, 0);
44 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
45 }
46
accumulatePositive2()47 int accumulatePositive2() {
48 FloatIterator it;
49 return std::accumulate(it, it, 0);
50 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
51 }
52
accumulatePositive3()53 int accumulatePositive3() {
54 double a[1] = {0.0};
55 return std::accumulate(a, a + 1, 0.0f);
56 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'double' into type 'float'
57 }
58
accumulatePositive4()59 int accumulatePositive4() {
60 TypedefTemplateIterator<unsigned> it;
61 return std::accumulate(it, it, 0);
62 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
63 }
64
accumulatePositive5()65 int accumulatePositive5() {
66 UsingTemplateIterator<unsigned> it;
67 return std::accumulate(it, it, 0);
68 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
69 }
70
accumulatePositive6()71 int accumulatePositive6() {
72 DependentTypedefTemplateIterator<UsingTemplateIterator<unsigned>> it;
73 return std::accumulate(it, it, 0);
74 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
75 }
76
accumulatePositive7()77 int accumulatePositive7() {
78 TypedeffedIterator it;
79 return std::accumulate(it, it, 0);
80 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
81 }
82
accumulatePositive8()83 int accumulatePositive8() {
84 DependentUsingTemplateIterator<unsigned> it;
85 return std::accumulate(it, it, 0);
86 // FIXME: this one should trigger too.
87 }
88
reducePositive1()89 int reducePositive1() {
90 float a[1] = {0.5f};
91 return std::reduce(a, a + 1, 0);
92 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
93 }
94
reducePositive2()95 int reducePositive2() {
96 float a[1] = {0.5f};
97 return std::reduce(std::par, a, a + 1, 0);
98 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
99 }
100
innerProductPositive1()101 int innerProductPositive1() {
102 float a[1] = {0.5f};
103 int b[1] = {1};
104 return std::inner_product(std::par, a, a + 1, b, 0);
105 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
106 }
107
innerProductPositive2()108 int innerProductPositive2() {
109 float a[1] = {0.5f};
110 int b[1] = {1};
111 return std::inner_product(std::par, a, a + 1, b, 0);
112 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
113 }
114
115 // Negatives.
116
negative1()117 int negative1() {
118 float a[1] = {0.5f};
119 // This is OK because types match.
120 return std::accumulate(a, a + 1, 0.0);
121 }
122
negative2()123 int negative2() {
124 float a[1] = {0.5f};
125 // This is OK because double is bigger than float.
126 return std::accumulate(a, a + 1, 0.0);
127 }
128
negative3()129 int negative3() {
130 float a[1] = {0.5f};
131 // This is OK because the user explicitly specified T.
132 return std::accumulate<float *, float>(a, a + 1, 0);
133 }
134
negative4()135 int negative4() {
136 TypedefTemplateIterator<unsigned> it;
137 // For now this is OK.
138 return std::accumulate(it, it, 0.0);
139 }
140
negative5()141 int negative5() {
142 float a[1] = {0.5f};
143 float b[1] = {1.0f};
144 return std::inner_product(std::par, a, a + 1, b, 0.0f);
145 }
146
147 namespace blah {
148 namespace std {
149 template <class InputIt, class T>
150 T accumulate(InputIt, InputIt, T); // We should not care about this one.
151 }
152
negative5()153 int negative5() {
154 float a[1] = {0.5f};
155 // Note that this is using blah::std::accumulate.
156 return std::accumulate(a, a + 1, 0);
157 }
158 }
159