1 // RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
2 
3 // CHECK-FIXES: #include <cmath>
4 
5 double acos(double);
6 double acosh(double);
7 double asin(double);
8 double asinh(double);
9 double atan2(double, double);
10 double atan(double);
11 double atanh(double);
12 double cbrt(double);
13 double ceil(double);
14 double copysign(double, double);
15 double cos(double);
16 double cosh(double);
17 double erfc(double);
18 double erf(double);
19 double exp2(double);
20 double exp(double);
21 double expm1(double);
22 double fabs(double);
23 double fdim(double, double);
24 double floor(double);
25 double fma(double, double, double);
26 double fmax(double, double);
27 double fmin(double, double);
28 double fmod(double, double);
29 double frexp(double, int *);
30 double hypot(double, double);
31 double ilogb(double);
32 double ldexp(double, double);
33 double lgamma(double);
34 long long llrint(double);
35 double log10(double);
36 double log1p(double);
37 double log2(double);
38 double logb(double);
39 double log(double);
40 long lrint(double);
41 double modf(double);
42 double nearbyint(double);
43 double nextafter(double, double);
44 double nexttoward(double, long double);
45 double pow(double, double);
46 double remainder(double, double);
47 double remquo(double, double, int *);
48 double rint(double);
49 double round(double);
50 double scalbln(double, long);
51 double scalbn(double, int);
52 double sin(double);
53 double sinh(double);
54 double sqrt(double);
55 double tan(double);
56 double tanh(double);
57 double tgamma(double);
58 double trunc(double);
59 long long llround(double);
60 long lround(double);
61 
check_all_fns()62 void 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.
check_nexttoward()237 void 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.
check_scalbn()259 void 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.
check_scalbln()275 void 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 
288 float cosf(float);
289 double foo(double);         // not a math.h function
290 float cos(float);           // not a math.h function (wrong signature)
291 double cos(double, double); // not a math.h function (wrong signature)
292 
293 namespace std {
294 void cos(float);
295 } // namespace std
296 
check_no_warnings()297 void 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