128 lines · plain
1.. title:: clang-tidy - bugprone-narrowing-conversions2 3bugprone-narrowing-conversions4==============================5 6`cppcoreguidelines-narrowing-conversions` redirects here as an alias for7this check.8 9Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While10the issue is obvious in this former example, it might not be so in the11following: ``void MyClass::f(double d) { int_member_ += d; }``.12 13We flag narrowing conversions from:14 - an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)15 if WarnOnIntegerNarrowingConversion Option is set,16 - an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``)17 if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,18 - a floating-point to an integer (e.g. ``double`` to ``int``),19 - a floating-point to a narrower floating-point (e.g. ``double`` to ``float``)20 if WarnOnFloatingPointNarrowingConversion Option is set.21 22This check will flag:23 - All narrowing conversions that are not marked by an explicit cast (c-style24 or ``static_cast``). For example: ``int i = 0; i += 0.1;``,25 ``void f(int); f(0.1);``,26 - All applications of binary operators with a narrowing conversions.27 For example: ``int i; i+= 0.1;``.28 29Arithmetic with smaller integer types than ``int`` trigger implicit conversions,30as explained under `"Integral Promotion" on cppreference.com31<https://en.cppreference.com/w/cpp/language/implicit_conversion>`_.32This check diagnoses more instances of narrowing than the compiler warning33`-Wconversion` does. The example below demonstrates this behavior.34 35.. code-block:: c++36 37 // The following function definition demonstrates usage of arithmetic with38 // integer types smaller than `int` and how the narrowing conversion happens39 // implicitly.40 void computation(short argument1, short argument2) {41 // Arithmetic written by humans:42 short result = argument1 + argument2;43 // Arithmetic actually performed by C++:44 short result = static_cast<short>(static_cast<int>(argument1) + static_cast<int>(argument2));45 }46 47 void recommended_resolution(short argument1, short argument2) {48 short result = argument1 + argument2;49 // ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined50 51 // The cppcoreguidelines recommend to resolve this issue by using the GSL52 // in one of two ways. Either by a cast that throws if a loss of precision53 // would occur.54 short result = gsl::narrow<short>(argument1 + argument2);55 // Or it can be resolved without checking the result risking invalid results.56 short result = gsl::narrow_cast<short>(argument1 + argument2);57 58 // A classical `static_cast` will silence the warning as well if the GSL59 // is not available.60 short result = static_cast<short>(argument1 + argument2);61 }62 63Options64-------65 66.. option:: WarnOnIntegerNarrowingConversion67 68 When `true`, the check will warn on narrowing integer conversion69 (e.g. ``int`` to ``size_t``). `true` by default.70 71.. option:: WarnOnIntegerToFloatingPointNarrowingConversion72 73 When `true`, the check will warn on narrowing integer to floating-point74 conversion (e.g. ``size_t`` to ``double``). `true` by default.75 76.. option:: WarnOnFloatingPointNarrowingConversion77 78 When `true`, the check will warn on narrowing floating point conversion79 (e.g. ``double`` to ``float``). `true` by default.80 81.. option:: WarnWithinTemplateInstantiation82 83 When `true`, the check will warn on narrowing conversions within template84 instantiations. `false` by default.85 86.. option:: WarnOnEquivalentBitWidth87 88 When `true`, the check will warn on narrowing conversions that arise from89 casting between types of equivalent bit width. (e.g.90 `int n = uint(0);` or `long long n = double(0);`) `true` by default.91 92.. option:: IgnoreConversionFromTypes93 94 Narrowing conversions from any type in this semicolon-separated list will be95 ignored. This may be useful to weed out commonly occurring, but less commonly96 problematic assignments such as `int n = std::vector<char>().size();` or97 `int n = std::difference(it1, it2);`. The default list is empty, but one98 suggested list for a legacy codebase would be99 `size_t;ptrdiff_t;size_type;difference_type`.100 101.. option:: PedanticMode102 103 When `true`, the check will warn on assigning a floating point constant104 to an integer value even if the floating point value is exactly105 representable in the destination type (e.g. ``int i = 1.0;``).106 `false` by default.107 108FAQ109---110 111 - What does "narrowing conversion from 'int' to 'float'" mean?112 113An IEEE754 Floating Point number can represent all integer values in the range114[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits115in the mantissa.116 117For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values118in the range [-2^31, 2^31-1].119 120 - What does "implementation-defined" mean?121 122You may have encountered messages like "narrowing conversion from 'unsigned123int' to signed type 'int' is implementation-defined".124The C/C++ standard does not mandate two's complement for signed integers, and125so the compiler is free to define what the semantics are for converting an126unsigned integer to signed integer. Clang's implementation uses the two's127complement format.128