diff options
author | Guillaume Chatelet <gchatelet@google.com> | 2018-11-26 16:25:55 +0000 |
---|---|---|
committer | Guillaume Chatelet <gchatelet@google.com> | 2018-11-26 16:25:55 +0000 |
commit | 8fc7c4411008ea43332b502eb9b622dbad07f6a7 (patch) | |
tree | d58c723842010bd85f862a650d7e385729718acc /clang-tools-extra/test | |
parent | 342b9b2f9f18dd9d3e0af935bc29ff2b68e40777 (diff) |
[clang-tidy] Improving narrowing conversions
Summary:
Newly flagged narrowing conversions:
- integer to narrower signed integer (this is compiler implementation defined),
- integer - floating point narrowing conversions,
- floating point - integer narrowing conversions,
- constants with narrowing conversions (even in ternary operator).
Reviewers: hokein, alexfh, aaron.ballman, JonasToth
Reviewed By: aaron.ballman, JonasToth
Subscribers: lebedev.ri, courbet, nemanjai, xazax.hun, kbarton, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D53488
Diffstat (limited to 'clang-tools-extra/test')
5 files changed, 455 insertions, 26 deletions
diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-long-is-32bits.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-long-is-32bits.cpp new file mode 100644 index 00000000000..dcf1848a30f --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-long-is-32bits.cpp @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \ +// RUN: -- -- -target x86_64-unknown-linux -m32 + +static_assert(sizeof(int) * 8 == 32, "int is 32-bits"); +static_assert(sizeof(long) * 8 == 32, "long is 32-bits"); +static_assert(sizeof(long long) * 8 == 64, "long long is 64-bits"); + +void narrow_integer_to_signed_integer_is_not_ok() { + int i; // i.e. int32_t + long l; // i.e. int32_t + long long ll; // i.e. int64_t + + unsigned int ui; // i.e. uint32_t + unsigned long ul; // i.e. uint32_t + unsigned long long ull; // i.e. uint64_t + + i = l; // int and long are the same type. + i = ll; // int64_t does not fit in an int32_t + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + ll = ul; // uint32_t fits into int64_t + ll = ull; // uint64_t does not fit in an int64_t + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long long' to signed type 'long long' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-narrowingfloatingpoint-option.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-narrowingfloatingpoint-option.cpp new file mode 100644 index 00000000000..14840df18d0 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-narrowingfloatingpoint-option.cpp @@ -0,0 +1,57 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \ +// RUN: -- -- -target x86_64-unknown-linux -fsigned-char + +namespace floats { + +void narrow_constant_floating_point_to_int_not_ok(double d) { + int i = 0; + i += 0.5; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [cppcoreguidelines-narrowing-conversions] + i += 0.5f; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + i *= 0.5f; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + i /= 0.5f; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + i += (double)0.5f; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [cppcoreguidelines-narrowing-conversions] + i += 2.0; + i += 2.0f; +} + +double operator"" _double(unsigned long long); + +float narrow_double_to_float_return() { + return 0.5; +} + +void narrow_double_to_float_not_ok(double d) { + float f; + f = d; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f = 15_double; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f += d; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f = narrow_double_to_float_return(); +} + +void narrow_fp_constants() { + float f; + f = 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + + f = __builtin_huge_valf(); // max float is not narrowing. + f = -__builtin_huge_valf(); // -max float is not narrowing. + f = __builtin_inff(); // float infinity is not narrowing. + f = __builtin_nanf("0"); // float NaN is not narrowing. + + f = __builtin_huge_val(); // max double is not within-range of float. + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from constant 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f = -__builtin_huge_val(); // -max double is not within-range of float. + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from constant 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f = __builtin_inf(); // double infinity is not within-range of float. + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from constant 'double' to 'float' [cppcoreguidelines-narrowing-conversions] + f = __builtin_nan("0"); // double NaN is not narrowing. +} + +} // namespace floats diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-pedanticmode-option.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-pedanticmode-option.cpp new file mode 100644 index 00000000000..f28985d2f31 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-pedanticmode-option.cpp @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \ +// RUN: -config="{CheckOptions: [ \ +// RUN: {key: "cppcoreguidelines-narrowing-conversions.PedanticMode", value: 1} \ +// RUN: ]}" \ +// RUN: -- -target x86_64-unknown-linux -fsigned-char + +namespace floats { + +void triggers_wrong_constant_type_warning(double d) { + int i = 0.0; + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: constant value should be of type of type 'int' instead of 'double' [cppcoreguidelines-narrowing-conversions] + i += 2.0; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constant value should be of type of type 'int' instead of 'double' [cppcoreguidelines-narrowing-conversions] + i += 2.0f; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constant value should be of type of type 'int' instead of 'float' [cppcoreguidelines-narrowing-conversions] +} + +void triggers_narrowing_warning_when_overflowing() { + unsigned short us = 65537.0; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: narrowing conversion from constant 'double' to 'unsigned short' [cppcoreguidelines-narrowing-conversions] +} + +} // namespace floats diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-unsigned-char.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-unsigned-char.cpp new file mode 100644 index 00000000000..6bd437f98d4 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions-unsigned-char.cpp @@ -0,0 +1,83 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \ +// RUN: -- -- -target x86_64-unknown-linux -funsigned-char + +void narrow_integer_to_unsigned_integer_is_ok() { + signed char sc; + short s; + int i; + long l; + long long ll; + + char c; + unsigned short us; + unsigned int ui; + unsigned long ul; + unsigned long long ull; + + ui = sc; + c = s; + c = i; + c = l; + c = ll; + + c = c; + c = us; + c = ui; + c = ul; + c = ull; +} + +void narrow_integer_to_signed_integer_is_not_ok() { + signed char sc; + short s; + int i; + long l; + long long ll; + + char c; + unsigned short us; + unsigned int ui; + unsigned long ul; + unsigned long long ull; + + sc = sc; + sc = s; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'short' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = i; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'int' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = l; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = ll; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + sc = c; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'char' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = us; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned short' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = ui; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned int' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = ul; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + sc = ull; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long long' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + +void narrow_constant_to_unsigned_integer_is_ok() { + char c1 = -128; // unsigned dst type is well defined. + char c2 = 127; // unsigned dst type is well defined. + char c3 = -129; // unsigned dst type is well defined. + char c4 = 128; // unsigned dst type is well defined. + unsigned char uc1 = 0; + unsigned char uc2 = 255; + unsigned char uc3 = -1; // unsigned dst type is well defined. + unsigned char uc4 = 256; // unsigned dst type is well defined. + signed char sc = 128; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: narrowing conversion from constant value 128 (0x00000080) of type 'int' to signed type 'signed char' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + +void narrow_conditional_operator_contant_to_unsigned_is_ok(bool b) { + // conversion to unsigned char type is well defined. + char c1 = b ? 1 : 0; + char c2 = b ? 1 : 256; + char c3 = b ? -1 : 0; +} diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp index ecffba6b844..cc817a021fd 100644 --- a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp @@ -1,4 +1,8 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t +// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \ +// RUN: -config="{CheckOptions: [ \ +// RUN: {key: "cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion", value: 0}, \ +// RUN: ]}" \ +// RUN: -- -target x86_64-unknown-linux -fsigned-char float ceil(float); namespace std { @@ -9,47 +13,282 @@ long double floor(long double); namespace floats { struct ConvertsToFloat { - operator float() const { return 0.5; } + operator float() const { return 0.5f; } }; -float operator "" _Pa(unsigned long long); +float operator"" _float(unsigned long long); -void not_ok(double d) { +void narrow_fp_to_int_not_ok(double d) { int i = 0; i = d; // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] i = 0.5f; - // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] i = static_cast<float>(d); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] i = ConvertsToFloat(); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] - i = 15_Pa; + i = 15_float; // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] -} - -void not_ok_binary_ops(double d) { - int i = 0; + i += d; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] i += 0.5; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [cppcoreguidelines-narrowing-conversions] i += 0.5f; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] - i += d; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] - // We warn on the following even though it's not dangerous because there is no - // reason to use a double literal here. - // TODO(courbet): Provide an automatic fix. - i += 2.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] - i += 2.0f; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] - + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] i *= 0.5f; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] i /= 0.5f; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'float' to 'int' [cppcoreguidelines-narrowing-conversions] i += (double)0.5f; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from constant 'double' to 'int' [cppcoreguidelines-narrowing-conversions] + i += 2.0; + i += 2.0f; +} + +double operator"" _double(unsigned long long); + +float narrow_double_to_float_return() { + return 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. +} + +void narrow_double_to_float_ok(double d) { + float f; + f = d; + f = 15_double; +} + +void narrow_fp_constants() { + float f; + f = 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + + f = __builtin_huge_valf(); // max float is not narrowing. + f = -__builtin_huge_valf(); // -max float is not narrowing. + f = __builtin_inff(); // float infinity is not narrowing. + f = __builtin_nanf("0"); // float NaN is not narrowing. + + f = __builtin_huge_val(); // max double is not within-range of float. + f = -__builtin_huge_val(); // -max double is not within-range of float. + f = __builtin_inf(); // double infinity is not within-range of float. + f = __builtin_nan("0"); // double NaN is not narrowing. +} + +void narrow_double_to_float_not_ok_binary_ops(double d) { + float f; + f += 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + f += 2.0; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + f *= 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + f /= 0.5; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + f += (double)0.5f; // [dcl.init.list] 7.2 : in-range fp constant to narrower float is not a narrowing. + f += d; // We do not warn about floating point narrowing by default. +} + +void narrow_fp_constant_to_bool_not_ok() { + bool b1 = 1.0; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant 'double' to 'bool' [cppcoreguidelines-narrowing-conversions] + bool b2 = 1.0f; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant 'float' to 'bool' [cppcoreguidelines-narrowing-conversions] +} + +void narrow_integer_to_floating() { + { + long long ll; // 64 bits + float f = ll; // doesn't fit in 24 bits + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'long long' to 'float' [cppcoreguidelines-narrowing-conversions] + double d = ll; // doesn't fit in 53 bits. + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: narrowing conversion from 'long long' to 'double' [cppcoreguidelines-narrowing-conversions] + } + { + int i; // 32 bits + float f = i; // doesn't fit in 24 bits + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [cppcoreguidelines-narrowing-conversions] + double d = i; // fits in 53 bits. + } + { + short n1, n2; + float f = n1 + n2; // 'n1 + n2' is of type 'int' because of integer rules + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [cppcoreguidelines-narrowing-conversions] + } + { + short s; // 16 bits + float f = s; // fits in 24 bits + double d = s; // fits in 53 bits. + } +} + +void narrow_integer_to_unsigned_integer_is_ok() { + char c; + short s; + int i; + long l; + long long ll; + + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + unsigned long long ull; + + ui = c; + uc = s; + uc = i; + uc = l; + uc = ll; + + uc = uc; + uc = us; + uc = ui; + uc = ul; + uc = ull; +} + +void narrow_integer_to_signed_integer_is_not_ok() { + char c; + short s; + int i; + long l; + long long ll; + + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + unsigned long long ull; + + c = c; + c = s; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'short' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = i; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = l; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = ll; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + c = uc; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned char' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = us; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned short' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = ui; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = ul; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + c = ull; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long long' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + i = c; + i = s; + i = i; + i = l; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + i = ll; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + i = uc; + i = us; + i = ui; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + i = ul; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + i = ull; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + ll = c; + ll = s; + ll = i; + ll = l; + ll = ll; + + ll = uc; + ll = us; + ll = ui; + ll = ul; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long' to signed type 'long long' is implementation-defined [cppcoreguidelines-narrowing-conversions] + ll = ull; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'unsigned long long' to signed type 'long long' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + +void narrow_constant_to_unsigned_integer_is_ok() { + unsigned char uc1 = 0; + unsigned char uc2 = 255; + unsigned char uc3 = -1; // unsigned dst type is well defined. + unsigned char uc4 = 256; // unsigned dst type is well defined. + unsigned short us1 = 0; + unsigned short us2 = 65535; + unsigned short us3 = -1; // unsigned dst type is well defined. + unsigned short us4 = 65536; // unsigned dst type is well defined. +} + +void narrow_constant_to_signed_integer_is_not_ok() { + char c1 = -128; + char c2 = 127; + char c3 = -129; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant value -129 (0xFFFFFF7F) of type 'int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + char c4 = 128; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from constant value 128 (0x00000080) of type 'int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + + short s1 = -32768; + short s2 = 32767; + short s3 = -32769; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from constant value -32769 (0xFFFF7FFF) of type 'int' to signed type 'short' is implementation-defined [cppcoreguidelines-narrowing-conversions] + short s4 = 32768; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from constant value 32768 (0x00008000) of type 'int' to signed type 'short' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + +void narrow_conditional_operator_contant_to_unsigned_is_ok(bool b) { + // conversion to unsigned dst type is well defined. + unsigned char c1 = b ? 1 : 0; + unsigned char c2 = b ? 1 : 256; + unsigned char c3 = b ? -1 : 0; +} + +void narrow_conditional_operator_contant_to_signed_is_not_ok(bool b) { + char uc1 = b ? 1 : 0; + char uc2 = b ? 1 : 128; + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: narrowing conversion from constant value 128 (0x00000080) of type 'int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + char uc3 = b ? -129 : 0; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: narrowing conversion from constant value -129 (0xFFFFFF7F) of type 'int' to signed type 'char' is implementation-defined [cppcoreguidelines-narrowing-conversions] + unsigned long long ysize; + long long mirror = b ? -1 : ysize - 1; + // 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 [cppcoreguidelines-narrowing-conversions] + // CHECK-MESSAGES: :[[@LINE-2]]:37: warning: narrowing conversion from 'unsigned long long' to signed type 'long long' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + +void narrow_constant_to_floating_point() { + float f_ok = 1ULL << 24; // fits in 24 bits mantissa. + float f_not_ok = (1ULL << 24) + 1ULL; // doesn't fit in 24 bits mantissa. + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: narrowing conversion from constant value 16777217 of type 'unsigned long long' to 'float' [cppcoreguidelines-narrowing-conversions] + double d_ok = 1ULL << 53; // fits in 53 bits mantissa. + double d_not_ok = (1ULL << 53) + 1ULL; // doesn't fit in 53 bits mantissa. + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: narrowing conversion from constant value 9007199254740993 of type 'unsigned long long' to 'double' [cppcoreguidelines-narrowing-conversions] +} + +void casting_integer_to_bool_is_ok() { + int i; + while (i) { + } + for (; i;) { + } + if (i) { + } +} + +void casting_float_to_bool_is_not_ok() { + float f; + while (f) { + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: narrowing conversion from 'float' to 'bool' [cppcoreguidelines-narrowing-conversions] + } + for (; f;) { + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: narrowing conversion from 'float' to 'bool' [cppcoreguidelines-narrowing-conversions] + } + if (f) { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'bool' [cppcoreguidelines-narrowing-conversions] + } +} + +void legitimate_comparison_do_not_warn(unsigned long long size) { + for (int i = 0; i < size; ++i) { + } } void ok(double d) { @@ -89,7 +328,9 @@ void f(T1 one, T2 two) { void template_context() { f(1, 2); + f(1, .5f); f(1, .5); + f(1, .5l); } #define DERP(i, j) (i += j) @@ -97,7 +338,9 @@ void template_context() { void macro_context() { int i = 0; DERP(i, 2); + DERP(i, .5f); DERP(i, .5); + DERP(i, .5l); } -} // namespace floats +} // namespace floats |