1// RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
2
3// CHECK-FIXES: #include <cmath>
4
5double acos(double);
6double acosh(double);
7double asin(double);
8double asinh(double);
9double atan2(double, double);
10double atan(double);
11double atanh(double);
12double cbrt(double);
13double ceil(double);
14double copysign(double, double);
15double cos(double);
16double cosh(double);
17double erfc(double);
18double erf(double);
19double exp2(double);
20double exp(double);
21double expm1(double);
22double fabs(double);
23double fdim(double, double);
24double floor(double);
25double fma(double, double, double);
26double fmax(double, double);
27double fmin(double, double);
28double fmod(double, double);
29double frexp(double, int *);
30double hypot(double, double);
31double ilogb(double);
32double ldexp(double, double);
33double lgamma(double);
34long long llrint(double);
35double log10(double);
36double log1p(double);
37double log2(double);
38double logb(double);
39double log(double);
40long lrint(double);
41double modf(double);
42double nearbyint(double);
43double nextafter(double, double);
44double nexttoward(double, long double);
45double pow(double, double);
46double remainder(double, double);
47double remquo(double, double, int *);
48double rint(double);
49double round(double);
50double scalbln(double, long);
51double scalbn(double, int);
52double sin(double);
53double sinh(double);
54double sqrt(double);
55double tan(double);
56double tanh(double);
57double tgamma(double);
58double trunc(double);
59long long llround(double);
60long lround(double);
61
62void check_all_fns() {
63 float a, b, c;
64 int i;
65 long l;
66 int *int_ptr;
67
68 acos(a);
69 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acos' promotes float to double [performance-type-promotion-in-math-fn]
70 // CHECK-FIXES: {{^}} std::acos(a);{{$}}
71 acosh(a);
72 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acosh'
73 // CHECK-FIXES: {{^}} std::acosh(a);{{$}}
74 asin(a);
75 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asin'
76 // CHECK-FIXES: {{^}} std::asin(a);{{$}}
77 asinh(a);
78 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asinh'
79 // CHECK-FIXES: {{^}} std::asinh(a);{{$}}
80 atan2(a, b);
81 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan2'
82 // CHECK-FIXES: {{^}} std::atan2(a, b);{{$}}
83 atan(a);
84 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan'
85 // CHECK-FIXES: {{^}} std::atan(a);{{$}}
86 atanh(a);
87 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atanh'
88 // CHECK-FIXES: {{^}} std::atanh(a);{{$}}
89 cbrt(a);
90 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cbrt'
91 // CHECK-FIXES: {{^}} std::cbrt(a);{{$}}
92 ceil(a);
93 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ceil'
94 // CHECK-FIXES: {{^}} std::ceil(a);{{$}}
95 copysign(a, b);
96 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'copysign'
97 // CHECK-FIXES: {{^}} std::copysign(a, b);{{$}}
98 cos(a);
99 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cos'
100 // CHECK-FIXES: {{^}} std::cos(a);{{$}}
101 cosh(a);
102 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cosh'
103 // CHECK-FIXES: {{^}} std::cosh(a);{{$}}
104 erf(a);
105 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erf'
106 // CHECK-FIXES: {{^}} std::erf(a);{{$}}
107 erfc(a);
108 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erfc'
109 // CHECK-FIXES: {{^}} std::erfc(a);{{$}}
110 exp2(a);
111 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp2'
112 // CHECK-FIXES: {{^}} std::exp2(a);{{$}}
113 exp(a);
114 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp'
115 // CHECK-FIXES: {{^}} std::exp(a);{{$}}
116 expm1(a);
117 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'expm1'
118 // CHECK-FIXES: {{^}} std::expm1(a);{{$}}
119 fabs(a);
120 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fabs'
121 // CHECK-FIXES: {{^}} std::fabs(a);{{$}}
122 fdim(a, b);
123 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fdim'
124 // CHECK-FIXES: {{^}} std::fdim(a, b);{{$}}
125 floor(a);
126 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'floor'
127 // CHECK-FIXES: {{^}} std::floor(a);{{$}}
128 fma(a, b, c);
129 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fma'
130 // CHECK-FIXES: {{^}} std::fma(a, b, c);{{$}}
131 fmax(a, b);
132 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmax'
133 // CHECK-FIXES: {{^}} std::fmax(a, b);{{$}}
134 fmin(a, b);
135 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmin'
136 // CHECK-FIXES: {{^}} std::fmin(a, b);{{$}}
137 fmod(a, b);
138 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmod'
139 // CHECK-FIXES: {{^}} std::fmod(a, b);{{$}}
140 frexp(a, int_ptr);
141 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'frexp'
142 // CHECK-FIXES: {{^}} std::frexp(a, int_ptr);{{$}}
143 hypot(a, b);
144 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'hypot'
145 // CHECK-FIXES: {{^}} std::hypot(a, b);{{$}}
146 ilogb(a);
147 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ilogb'
148 // CHECK-FIXES: {{^}} std::ilogb(a);{{$}}
149 ldexp(a, b);
150 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ldexp'
151 // CHECK-FIXES: {{^}} std::ldexp(a, b);{{$}}
152 lgamma(a);
153 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lgamma'
154 // CHECK-FIXES: {{^}} std::lgamma(a);{{$}}
155 llrint(a);
156 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llrint'
157 // CHECK-FIXES: {{^}} std::llrint(a);{{$}}
158 llround(a);
159 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llround'
160 // CHECK-FIXES: {{^}} std::llround(a);{{$}}
161 log10(a);
162 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log10'
163 // CHECK-FIXES: {{^}} std::log10(a);{{$}}
164 log1p(a);
165 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log1p'
166 // CHECK-FIXES: {{^}} std::log1p(a);{{$}}
167 log2(a);
168 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log2'
169 // CHECK-FIXES: {{^}} std::log2(a);{{$}}
170 log(a);
171 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log'
172 // CHECK-FIXES: {{^}} std::log(a);{{$}}
173 logb(a);
174 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'logb'
175 // CHECK-FIXES: {{^}} std::logb(a);{{$}}
176 lrint(a);
177 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lrint'
178 // CHECK-FIXES: {{^}} std::lrint(a);{{$}}
179 lround(a);
180 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lround'
181 // CHECK-FIXES: {{^}} std::lround(a);{{$}}
182 nearbyint(a);
183 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nearbyint'
184 // CHECK-FIXES: {{^}} std::nearbyint(a);{{$}}
185 nextafter(a, b);
186 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nextafter'
187 // CHECK-FIXES: {{^}} std::nextafter(a, b);{{$}}
188 nexttoward(a, b);
189 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
190 // CHECK-FIXES: {{^}} std::nexttoward(a, b);{{$}}
191 pow(a, b);
192 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'pow'
193 // CHECK-FIXES: {{^}} std::pow(a, b);{{$}}
194 remainder(a, b);
195 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remainder'
196 // CHECK-FIXES: {{^}} std::remainder(a, b);{{$}}
197 remquo(a, b, int_ptr);
198 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remquo'
199 // CHECK-FIXES: {{^}} std::remquo(a, b, int_ptr);{{$}}
200 rint(a);
201 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'rint'
202 // CHECK-FIXES: {{^}} std::rint(a);{{$}}
203 round(a);
204 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'round'
205 // CHECK-FIXES: {{^}} std::round(a);{{$}}
206 scalbln(a, l);
207 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
208 // CHECK-FIXES: {{^}} std::scalbln(a, l);{{$}}
209 scalbn(a, i);
210 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
211 // CHECK-FIXES: {{^}} std::scalbn(a, i);{{$}}
212 sin(a);
213 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sin'
214 // CHECK-FIXES: {{^}} std::sin(a);{{$}}
215 sinh(a);
216 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sinh'
217 // CHECK-FIXES: {{^}} std::sinh(a);{{$}}
218 sqrt(a);
219 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sqrt'
220 // CHECK-FIXES: {{^}} std::sqrt(a);{{$}}
221 tan(a);
222 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tan'
223 // CHECK-FIXES: {{^}} std::tan(a);{{$}}
224 tanh(a);
225 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tanh'
226 // CHECK-FIXES: {{^}} std::tanh(a);{{$}}
227 tgamma(a);
228 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tgamma'
229 // CHECK-FIXES: {{^}} std::tgamma(a);{{$}}
230 trunc(a);
231 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'trunc'
232 // CHECK-FIXES: {{^}} std::trunc(a);{{$}}
233}
234
235// nexttoward/nexttowardf are weird -- the second param is always long double.
236// So we warn if the first arg is a float, regardless of what the second arg is.
237void check_nexttoward() {
238 nexttoward(0.f, 0);
239 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
240 // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0);{{$}}
241 nexttoward(0.f, 0l);
242 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
243 // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0l);{{$}}
244 nexttoward(0.f, 0.f);
245 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
246 // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.f);{{$}}
247 nexttoward(0.f, 0.);
248 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
249 // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.);{{$}}
250
251 // No warnings for these.
252 nexttoward(0., 0);
253 nexttoward(0., 0.f);
254 nexttoward(0., 0.);
255}
256
257// The second parameter to scalbn and scalbnf is an int, so we don't care what
258// type you pass as that argument; we warn iff the first argument is a float.
259void check_scalbn() {
260 scalbn(0.f, 0);
261 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
262 // CHECK-FIXES: {{^}} std::scalbn(0.f, 0);{{$}}
263 scalbn(0.f, static_cast<char>(0));
264 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
265 // CHECK-FIXES: {{^}} std::scalbn(0.f, static_cast<char>(0));{{$}}
266
267 // No warnings for these.
268 scalbn(0., 0);
269 scalbn(0., static_cast<char>(0));
270}
271
272// scalbln/scalblnf are like scalbn/scalbnf except their second arg is a long.
273// Again, doesn't matter what we pass for the second arg; we warn iff the first
274// arg is a float.
275void check_scalbln() {
276 scalbln(0.f, 0);
277 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
278 // CHECK-FIXES: {{^}} std::scalbln(0.f, 0);{{$}}
279 scalbln(0.f, 0l);
280 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
281 // CHECK-FIXES: {{^}} std::scalbln(0.f, 0l);{{$}}
282
283 // No warnings for these.
284 scalbln(0., 0);
285 scalbln(0., 0l);
286}
287
288float cosf(float);
289double foo(double); // not a math.h function
290float cos(float); // not a math.h function (wrong signature)
291double cos(double, double); // not a math.h function (wrong signature)
292
293namespace std {
294void cos(float);
295} // namespace std
296
297void check_no_warnings() {
298 foo(0.); // no warning because not a math.h function.
299
300 sin(0); // no warning because arg is an int
301 cos(0.); // no warning because arg is a double
302 std::cos(0.f); // no warning because not ::cos.
303 cosf(0.f); // no warning; we expect this to take a float
304 cos(0.f); // does not match the expected signature of ::cos
305 cos(0.f, 0.f); // does not match the expected signature of ::cos
306
307 // No warnings because all args are not floats.
308 remainder(0., 0.f);
309 remainder(0.f, 0.);
310 remainder(0, 0.f);
311 remainder(0.f, 0);
312 fma(0.f, 0.f, 0);
313 fma(0.f, 0.f, 0.);
314 fma(0.f, 0., 0.f);
315 fma(0., 0.f, 0.f);
316}
317

source code of clang-tools-extra/test/clang-tidy/checkers/performance/type-promotion-in-math-fn.cpp