359 lines · cpp
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-char5 6float ceil(float);7namespace std {8double ceil(double);9long double floor(long double);10} // namespace std11 12namespace floats {13 14struct ConvertsToFloat {15 operator float() const { return 0.5f; }16};17 18float operator"" _float(unsigned long long);19 20void 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 48double operator"" _double(unsigned long long);49 50float 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 54void narrow_double_to_float_ok(double d) {55 float f;56 f = d;57 f = 15_double;58}59 60void 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 75void 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 85void 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 92void narrow_integer_to_floating() {93 {94 long long ll; // 64 bits95 float f = ll; // doesn't fit in 24 bits96 // 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 bits102 float f = i; // doesn't fit in 24 bits103 // 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 rules109 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [bugprone-narrowing-conversions]110 }111 {112 short s; // 16 bits113 float f = s; // fits in 24 bits114 double d = s; // fits in 53 bits.115 }116}117 118void 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 144void 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 210void 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 221void 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 237void 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 244void 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 256void 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 265void casting_integer_to_bool_is_ok() {266 int i;267 while (i) {268 }269 for (; i;) {270 }271 if (i) {272 }273}274 275void 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 288void legitimate_comparison_do_not_warn(unsigned long long size) {289 for (int i = 0; i < size; ++i) {290 }291}292 293void 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 307void 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.323template <typename T1, typename T2>324void f(T1 one, T2 two) {325 one += two;326}327 328void 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 337void 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.346void 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 floats359