.. title:: clang-tidy - cppcoreguidelines-narrowing-conversions

cppcoreguidelines-narrowing-conversions
=======================================

Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While
the issue is obvious in this former example, it might not be so in the
following: ``void MyClass::f(double d) { int_member_ += d; }``.

This rule is part of the "Expressions and statements" profile of the C++ Core
Guidelines, corresponding to rule ES.46. See

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es46-avoid-lossy-narrowing-truncating-arithmetic-conversions.

We enforce only part of the guideline, more specifically, we flag narrowing conversions from:
 - an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)
   if WarnOnIntegerNarrowingConversion Option is set,
 - an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``),
 - a floating-point to an integer (e.g. ``double`` to ``int``),
 - a floating-point to a narrower floating-point (e.g. ``double`` to ``float``)
   if WarnOnFloatingPointNarrowingConversion Option is set.

This check will flag:
 - All narrowing conversions that are not marked by an explicit cast (c-style or
   ``static_cast``). For example: ``int i = 0; i += 0.1;``,
   ``void f(int); f(0.1);``,
 - All applications of binary operators with a narrowing conversions.
   For example: ``int i; i+= 0.1;``.


Options
-------

.. option:: WarnOnIntegerNarrowingConversion

    When `true`, the check will warn on narrowing integer conversion
    (e.g. ``int`` to ``size_t``). `true` by default.

.. option:: WarnOnFloatingPointNarrowingConversion

    When `true`, the check will warn on narrowing floating point conversion
    (e.g. ``double`` to ``float``). `true` by default.

.. option:: WarnWithinTemplateInstantiation

    When `true`, the check will warn on narrowing conversions within template
    instantiations. `false` by default.

.. option:: WarnOnEquivalentBitWidth

    When `true`, the check will warn on narrowing conversions that arise from
    casting between types of equivalent bit width. (e.g.
    `int n = uint(0);` or `long long n = double(0);`) `true` by default.

.. option:: IgnoreConversionFromTypes

   Narrowing conversions from any type in this semicolon-separated list will be
   ignored. This may be useful to weed out commonly occurring, but less commonly
   problematic assignments such as `int n = std::vector<char>().size();` or
   `int n = std::difference(it1, it2);`. The default list is empty, but one
   suggested list for a legacy codebase would be
   `size_t;ptrdiff_t;size_type;difference_type`.

.. option:: PedanticMode

    When `true`, the check will warn on assigning a floating point constant
    to an integer value even if the floating point value is exactly
    representable in the destination type (e.g. ``int i = 1.0;``).
    `false` by default.

FAQ
---

 - What does "narrowing conversion from 'int' to 'float'" mean?

An IEEE754 Floating Point number can represent all integer values in the range
[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits in
the mantissa.

For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values in
the range [-2^31, 2^31-1].

 - What does "implementation-defined" mean?

You may have encountered messages like "narrowing conversion from 'unsigned int'
to signed type 'int' is implementation-defined".
The C/C++ standard does not mandate two's complement for signed integers, and so
the compiler is free to define what the semantics are for converting an unsigned
integer to signed integer. Clang's implementation uses the two's complement
format.
