| 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 | |
| 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. |
| 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. |
| 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. |
| 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 | |
| 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 | |