1 // RUN: %check_clang_tidy %s bugprone-narrowing-conversions %t \ 2 // RUN: -config="{CheckOptions: { \ 3 // RUN: bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: false}}" \ 4 // RUN: -- -target x86_64-unknown-linux -fsigned-char 5 6 float ceil(float); 7 namespace std { 8 double ceil(double); 9 long double floor(long double); 10 } // namespace std 11 12 namespace floats { 13 14 struct ConvertsToFloat { 15 operator float() const { return 0.5f; } 16 }; 17 18 float operator"" _float(unsigned long long); 19 20 void narrow_fp_to_int_not_ok(double d) { 21 int i = 0; 22 i = d; 23 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions] 24 i = 0.5f; 25 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from constant 'float' to 'int' [bugprone-narrowing-conversions] 26 i = static_cast<float>(d); 27 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [bugprone-narrowing-conversions] 28 i = ConvertsToFloat(); 29 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [bugprone-narrowing-conversions] 30 i = 15_float; 31 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [bugprone-narrowing-conversions] 32 i += d; 33 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions] 34 i += 0.5; 35 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [bugprone-narrowing-conversions] 36 i += 0.5f; 37 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [bugprone-narrowing-conversions] 38 i *= 0.5f; 39 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [bugprone-narrowing-conversions] 40 i /= 0.5f; 41 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [bugprone-narrowing-conversions] 42 i += (double)0.5f; 43 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [bugprone-narrowing-conversions] 44 i += 2.0; 45 i += 2.0f; 46 } 47 48 double operator"" _double(unsigned long long); 49 50 float narrow_double_to_float_return() { 51 return 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 52 } 53 54 void narrow_double_to_float_ok(double d) { 55 float f; 56 f = d; 57 f = 15_double; 58 } 59 60 void narrow_fp_constants() { 61 float f; 62 f = 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 63 64 f = __builtin_huge_valf(); // max float is not narrowing. 65 f = -__builtin_huge_valf(); // -max float is not narrowing. 66 f = __builtin_inff(); // float infinity is not narrowing. 67 f = __builtin_nanf("0"); // float NaN is not narrowing. 68 69 f = __builtin_huge_val(); // max double is not within-range of float. 70 f = -__builtin_huge_val(); // -max double is not within-range of float. 71 f = __builtin_inf(); // double infinity is not within-range of float. 72 f = __builtin_nan("0"); // double NaN is not narrowing. 73 } 74 75 void narrow_double_to_float_not_ok_binary_ops(double d) { 76 float f; 77 f += 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 78 f += 2.0; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 79 f *= 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 80 f /= 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 81 f += (double)0.5f; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. 82 f += d; // We do not warn about floating point narrowing by default. 83 } 84 85 void narrow_fp_constant_to_bool_not_ok() { 86 bool b1 = 1.0; 87 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant 'double' to 'bool' [bugprone-narrowing-conversions] 88 bool b2 = 1.0f; 89 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant 'float' to 'bool' [bugprone-narrowing-conversions] 90 } 91 92 void narrow_integer_to_floating() { 93 { 94 long long ll; // 64 bits 95 float f = ll; // doesn't fit in 24 bits 96 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'long long' to 'float' [bugprone-narrowing-conversions] 97 double d = ll; // doesn't fit in 53 bits. 98 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: narrowing conversion from 'long long' to 'double' [bugprone-narrowing-conversions] 99 } 100 { 101 int i; // 32 bits 102 float f = i; // doesn't fit in 24 bits 103 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [bugprone-narrowing-conversions] 104 double d = i; // fits in 53 bits. 105 } 106 { 107 short n1, n2; 108 float f = n1 + n2; // 'n1 + n2' is of type 'int' because of integer rules 109 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [bugprone-narrowing-conversions] 110 } 111 { 112 short s; // 16 bits 113 float f = s; // fits in 24 bits 114 double d = s; // fits in 53 bits. 115 } 116 } 117 118 void narrow_integer_to_unsigned_integer_is_ok() { 119 char c; 120 short s; 121 int i; 122 long l; 123 long long ll; 124 125 unsigned char uc; 126 unsigned short us; 127 unsigned int ui; 128 unsigned long ul; 129 unsigned long long ull; 130 131 ui = c; 132 uc = s; 133 uc = i; 134 uc = l; 135 uc = ll; 136 137 uc = uc; 138 uc = us; 139 uc = ui; 140 uc = ul; 141 uc = ull; 142 } 143 144 void narrow_integer_to_signed_integer_is_not_ok() { 145 char c; 146 short s; 147 int i; 148 long l; 149 long long ll; 150 151 unsigned char uc; 152 unsigned short us; 153 unsigned int ui; 154 unsigned long ul; 155 unsigned long long ull; 156 157 c = c; 158 c = s; 159 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'short' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 160 c = i; 161 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 162 c = l; 163 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 164 c = ll; 165 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 166 167 c = uc; 168 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned char' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 169 c = us; 170 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned short' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 171 c = ui; 172 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 173 c = ul; 174 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 175 c = ull; 176 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long long' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 177 178 i = c; 179 i = s; 180 i = i; 181 i = l; 182 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 183 i = ll; 184 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 185 186 i = uc; 187 i = us; 188 i = ui; 189 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 190 i = ul; 191 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 192 i = ull; 193 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 194 195 ll = c; 196 ll = s; 197 ll = i; 198 ll = l; 199 ll = ll; 200 201 ll = uc; 202 ll = us; 203 ll = ui; 204 ll = ul; 205 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long' to signed type 'long long' is implementation-defined [bugprone-narrowing-conversions] 206 ll = ull; 207 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long long' to signed type 'long long' is implementation-defined [bugprone-narrowing-conversions] 208 } 209 210 void narrow_constant_to_unsigned_integer_is_ok() { 211 unsigned char uc1 = 0; 212 unsigned char uc2 = 255; 213 unsigned char uc3 = -1; // unsigned dst type is well defined. 214 unsigned char uc4 = 256; // unsigned dst type is well defined. 215 unsigned short us1 = 0; 216 unsigned short us2 = 65535; 217 unsigned short us3 = -1; // unsigned dst type is well defined. 218 unsigned short us4 = 65536; // unsigned dst type is well defined. 219 } 220 221 void narrow_constant_to_signed_integer_is_not_ok() { 222 char c1 = -128; 223 char c2 = 127; 224 char c3 = -129; 225 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant value -129 (0xFFFFFF7F) of type 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 226 char c4 = 128; 227 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant value 128 (0x00000080) of type 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 228 229 short s1 = -32768; 230 short s2 = 32767; 231 short s3 = -32769; 232 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from constant value -32769 (0xFFFF7FFF) of type 'int' to signed type 'short' is implementation-defined [bugprone-narrowing-conversions] 233 short s4 = 32768; 234 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from constant value 32768 (0x00008000) of type 'int' to signed type 'short' is implementation-defined [bugprone-narrowing-conversions] 235 } 236 237 void narrow_conditional_operator_contant_to_unsigned_is_ok(bool b) { 238 // conversion to unsigned dst type is well defined. 239 unsigned char c1 = b ? 1 : 0; 240 unsigned char c2 = b ? 1 : 256; 241 unsigned char c3 = b ? -1 : 0; 242 } 243 244 void narrow_conditional_operator_contant_to_signed_is_not_ok(bool b) { 245 char uc1 = b ? 1 : 0; 246 char uc2 = b ? 1 : 128; 247 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: narrowing conversion from constant value 128 (0x00000080) of type 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 248 char uc3 = b ? -129 : 0; 249 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: narrowing conversion from constant value -129 (0xFFFFFF7F) of type 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions] 250 unsigned long long ysize; 251 long long mirror = b ? -1 : ysize - 1; 252 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: narrowing conversion from constant value 18446744073709551615 (0xFFFFFFFFFFFFFFFF) of type 'unsigned long long' to signed type 'long long' is implementation-defined [bugprone-narrowing-conversions] 253 // CHECK-MESSAGES: :[[@LINE-2]]:37: warning: narrowing conversion from 'unsigned long long' to signed type 'long long' is implementation-defined [bugprone-narrowing-conversions] 254 } 255 256 void narrow_constant_to_floating_point() { 257 float f_ok = 1ULL << 24; // fits in 24 bits mantissa. 258 float f_not_ok = (1ULL << 24) + 1ULL; // doesn't fit in 24 bits mantissa. 259 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: narrowing conversion from constant value 16777217 of type 'unsigned long long' to 'float' [bugprone-narrowing-conversions] 260 double d_ok = 1ULL << 53; // fits in 53 bits mantissa. 261 double d_not_ok = (1ULL << 53) + 1ULL; // doesn't fit in 53 bits mantissa. 262 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: narrowing conversion from constant value 9007199254740993 of type 'unsigned long long' to 'double' [bugprone-narrowing-conversions] 263 } 264 265 void casting_integer_to_bool_is_ok() { 266 int i; 267 while (i) { 268 } 269 for (; i;) { 270 } 271 if (i) { 272 } 273 } 274 275 void casting_float_to_bool_is_not_ok() { 276 float f; 277 while (f) { 278 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: narrowing conversion from 'float' to 'bool' [bugprone-narrowing-conversions] 279 } 280 for (; f;) { 281 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: narrowing conversion from 'float' to 'bool' [bugprone-narrowing-conversions] 282 } 283 if (f) { 284 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'bool' [bugprone-narrowing-conversions] 285 } 286 } 287 288 void legitimate_comparison_do_not_warn(unsigned long long size) { 289 for (int i = 0; i < size; ++i) { 290 } 291 } 292 293 void ok(double d) { 294 int i = 0; 295 i = 1; 296 i = static_cast<int>(0.5); 297 i = static_cast<int>(d); 298 i = std::ceil(0.5); 299 i = ::std::floor(0.5); 300 { 301 using std::ceil; 302 i = ceil(0.5f); 303 } 304 i = ceil(0.5f); 305 } 306 307 void ok_binary_ops(double d) { 308 int i = 0; 309 i += 1; 310 i += static_cast<int>(0.5); 311 i += static_cast<int>(d); 312 i += (int)d; 313 i += std::ceil(0.5); 314 i += ::std::floor(0.5); 315 { 316 using std::ceil; 317 i += ceil(0.5f); 318 } 319 i += ceil(0.5f); 320 } 321 322 // We're bailing out in templates and macros. 323 template <typename T1, typename T2> 324 void f(T1 one, T2 two) { 325 one += two; 326 } 327 328 void template_context() { 329 f(1, 2); 330 f(1, .5f); 331 f(1, .5); 332 f(1, .5l); 333 } 334 335 #define DERP(i, j) (i += j) 336 337 void macro_context() { 338 int i = 0; 339 DERP(i, 2); 340 DERP(i, .5f); 341 DERP(i, .5); 342 DERP(i, .5l); 343 } 344 345 // We understand typedefs. 346 void typedef_context() { 347 typedef long long myint64_t; 348 int i; 349 myint64_t i64; 350 351 i64 = i64; // Okay, no conversion. 352 i64 = i; // Okay, no narrowing. 353 354 i = i64; 355 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'myint64_t' (aka 'long long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions] 356 } 357 358 } // namespace floats 359