// RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
// CHECK-FIXES: #include <cmath>
double acos(double);
double acosh(double);
double asin(double);
double asinh(double);
double atan2(double, double);
double atan(double);
double atanh(double);
double cbrt(double);
double ceil(double);
double copysign(double, double);
double cos(double);
double cosh(double);
double erfc(double);
double erf(double);
double exp2(double);
double exp(double);
double expm1(double);
double fabs(double);
double fdim(double, double);
double floor(double);
double fma(double, double, double);
double fmax(double, double);
double fmin(double, double);
double fmod(double, double);
double frexp(double, int *);
double hypot(double, double);
double ilogb(double);
double ldexp(double, double);
double lgamma(double);
long long llrint(double);
double log10(double);
double log1p(double);
double log2(double);
double logb(double);
double log(double);
long lrint(double);
double modf(double);
double nearbyint(double);
double nextafter(double, double);
double nexttoward(double, long double);
double pow(double, double);
double remainder(double, double);
double remquo(double, double, int *);
double rint(double);
double round(double);
double scalbln(double, long);
double scalbn(double, int);
double sin(double);
double sinh(double);
double sqrt(double);
double tan(double);
double tanh(double);
double tgamma(double);
double trunc(double);
long long llround(double);
long lround(double);
void check_all_fns() {
float a, b, c;
int i;
long l;
int *int_ptr;
acos(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acos' promotes float to double [performance-type-promotion-in-math-fn]
// CHECK-FIXES: {{^}} std::acos(a);{{$}}
acosh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acosh'
// CHECK-FIXES: {{^}} std::acosh(a);{{$}}
asin(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asin'
// CHECK-FIXES: {{^}} std::asin(a);{{$}}
asinh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asinh'
// CHECK-FIXES: {{^}} std::asinh(a);{{$}}
atan2(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan2'
// CHECK-FIXES: {{^}} std::atan2(a, b);{{$}}
atan(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan'
// CHECK-FIXES: {{^}} std::atan(a);{{$}}
atanh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atanh'
// CHECK-FIXES: {{^}} std::atanh(a);{{$}}
cbrt(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cbrt'
// CHECK-FIXES: {{^}} std::cbrt(a);{{$}}
ceil(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ceil'
// CHECK-FIXES: {{^}} std::ceil(a);{{$}}
copysign(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'copysign'
// CHECK-FIXES: {{^}} std::copysign(a, b);{{$}}
cos(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cos'
// CHECK-FIXES: {{^}} std::cos(a);{{$}}
cosh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cosh'
// CHECK-FIXES: {{^}} std::cosh(a);{{$}}
erf(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erf'
// CHECK-FIXES: {{^}} std::erf(a);{{$}}
erfc(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erfc'
// CHECK-FIXES: {{^}} std::erfc(a);{{$}}
exp2(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp2'
// CHECK-FIXES: {{^}} std::exp2(a);{{$}}
exp(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp'
// CHECK-FIXES: {{^}} std::exp(a);{{$}}
expm1(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'expm1'
// CHECK-FIXES: {{^}} std::expm1(a);{{$}}
fabs(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fabs'
// CHECK-FIXES: {{^}} std::fabs(a);{{$}}
fdim(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fdim'
// CHECK-FIXES: {{^}} std::fdim(a, b);{{$}}
floor(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'floor'
// CHECK-FIXES: {{^}} std::floor(a);{{$}}
fma(a, b, c);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fma'
// CHECK-FIXES: {{^}} std::fma(a, b, c);{{$}}
fmax(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmax'
// CHECK-FIXES: {{^}} std::fmax(a, b);{{$}}
fmin(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmin'
// CHECK-FIXES: {{^}} std::fmin(a, b);{{$}}
fmod(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmod'
// CHECK-FIXES: {{^}} std::fmod(a, b);{{$}}
frexp(a, int_ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'frexp'
// CHECK-FIXES: {{^}} std::frexp(a, int_ptr);{{$}}
hypot(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'hypot'
// CHECK-FIXES: {{^}} std::hypot(a, b);{{$}}
ilogb(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ilogb'
// CHECK-FIXES: {{^}} std::ilogb(a);{{$}}
ldexp(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ldexp'
// CHECK-FIXES: {{^}} std::ldexp(a, b);{{$}}
lgamma(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lgamma'
// CHECK-FIXES: {{^}} std::lgamma(a);{{$}}
llrint(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llrint'
// CHECK-FIXES: {{^}} std::llrint(a);{{$}}
llround(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llround'
// CHECK-FIXES: {{^}} std::llround(a);{{$}}
log10(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log10'
// CHECK-FIXES: {{^}} std::log10(a);{{$}}
log1p(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log1p'
// CHECK-FIXES: {{^}} std::log1p(a);{{$}}
log2(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log2'
// CHECK-FIXES: {{^}} std::log2(a);{{$}}
log(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log'
// CHECK-FIXES: {{^}} std::log(a);{{$}}
logb(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'logb'
// CHECK-FIXES: {{^}} std::logb(a);{{$}}
lrint(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lrint'
// CHECK-FIXES: {{^}} std::lrint(a);{{$}}
lround(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lround'
// CHECK-FIXES: {{^}} std::lround(a);{{$}}
nearbyint(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nearbyint'
// CHECK-FIXES: {{^}} std::nearbyint(a);{{$}}
nextafter(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nextafter'
// CHECK-FIXES: {{^}} std::nextafter(a, b);{{$}}
nexttoward(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
// CHECK-FIXES: {{^}} std::nexttoward(a, b);{{$}}
pow(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'pow'
// CHECK-FIXES: {{^}} std::pow(a, b);{{$}}
remainder(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remainder'
// CHECK-FIXES: {{^}} std::remainder(a, b);{{$}}
remquo(a, b, int_ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remquo'
// CHECK-FIXES: {{^}} std::remquo(a, b, int_ptr);{{$}}
rint(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'rint'
// CHECK-FIXES: {{^}} std::rint(a);{{$}}
round(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'round'
// CHECK-FIXES: {{^}} std::round(a);{{$}}
scalbln(a, l);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
// CHECK-FIXES: {{^}} std::scalbln(a, l);{{$}}
scalbn(a, i);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
// CHECK-FIXES: {{^}} std::scalbn(a, i);{{$}}
sin(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sin'
// CHECK-FIXES: {{^}} std::sin(a);{{$}}
sinh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sinh'
// CHECK-FIXES: {{^}} std::sinh(a);{{$}}
sqrt(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sqrt'
// CHECK-FIXES: {{^}} std::sqrt(a);{{$}}
tan(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tan'
// CHECK-FIXES: {{^}} std::tan(a);{{$}}
tanh(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tanh'
// CHECK-FIXES: {{^}} std::tanh(a);{{$}}
tgamma(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tgamma'
// CHECK-FIXES: {{^}} std::tgamma(a);{{$}}
trunc(a);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'trunc'
// CHECK-FIXES: {{^}} std::trunc(a);{{$}}
}
// nexttoward/nexttowardf are weird -- the second param is always long double.
// So we warn if the first arg is a float, regardless of what the second arg is.
void check_nexttoward() {
nexttoward(0.f, 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
// CHECK-FIXES: {{^}} std::nexttoward(0.f, 0);{{$}}
nexttoward(0.f, 0l);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
// CHECK-FIXES: {{^}} std::nexttoward(0.f, 0l);{{$}}
nexttoward(0.f, 0.f);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
// CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.f);{{$}}
nexttoward(0.f, 0.);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
// CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.);{{$}}
// No warnings for these.
nexttoward(0., 0);
nexttoward(0., 0.f);
nexttoward(0., 0.);
}
// The second parameter to scalbn and scalbnf is an int, so we don't care what
// type you pass as that argument; we warn iff the first argument is a float.
void check_scalbn() {
scalbn(0.f, 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
// CHECK-FIXES: {{^}} std::scalbn(0.f, 0);{{$}}
scalbn(0.f, static_cast<char>(0));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
// CHECK-FIXES: {{^}} std::scalbn(0.f, static_cast<char>(0));{{$}}
// No warnings for these.
scalbn(0., 0);
scalbn(0., static_cast<char>(0));
}
// scalbln/scalblnf are like scalbn/scalbnf except their second arg is a long.
// Again, doesn't matter what we pass for the second arg; we warn iff the first
// arg is a float.
void check_scalbln() {
scalbln(0.f, 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
// CHECK-FIXES: {{^}} std::scalbln(0.f, 0);{{$}}
scalbln(0.f, 0l);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
// CHECK-FIXES: {{^}} std::scalbln(0.f, 0l);{{$}}
// No warnings for these.
scalbln(0., 0);
scalbln(0., 0l);
}
float cosf(float);
double foo(double); // not a math.h function
float cos(float); // not a math.h function (wrong signature)
double cos(double, double); // not a math.h function (wrong signature)
namespace std {
void cos(float);
} // namespace std
void check_no_warnings() {
foo(0.); // no warning because not a math.h function.
sin(0); // no warning because arg is an int
cos(0.); // no warning because arg is a double
std::cos(0.f); // no warning because not ::cos.
cosf(0.f); // no warning; we expect this to take a float
cos(0.f); // does not match the expected signature of ::cos
cos(0.f, 0.f); // does not match the expected signature of ::cos
// No warnings because all args are not floats.
remainder(0., 0.f);
remainder(0.f, 0.);
remainder(0, 0.f);
remainder(0.f, 0);
fma(0.f, 0.f, 0);
fma(0.f, 0.f, 0.);
fma(0.f, 0., 0.f);
fma(0., 0.f, 0.f);
}