.. title:: clang-tidy - bugprone-chained-comparison

bugprone-chained-comparison
===========================

Check detects chained comparison operators that can lead to unintended
behavior or logical errors.

Chained comparisons are expressions that use multiple comparison operators
to compare three or more values. For example, the expression ``a < b < c``
compares the values of ``a``, ``b``, and ``c``. However, this expression does
not evaluate as ``(a < b) && (b < c)``, which is probably what the developer
intended. Instead, it evaluates as ``(a < b) < c``, which may produce
unintended results, especially when the types of ``a``, ``b``, and ``c`` are
different.

To avoid such errors, the check will issue a warning when a chained
comparison operator is detected, suggesting to use parentheses to specify
the order of evaluation or to use a logical operator to separate comparison
expressions.

Consider the following examples:

.. code-block:: c++

    int a = 2, b = 6, c = 4;
    if (a < b < c) {
        // This block will be executed
    }


In this example, the developer intended to check if ``a`` is less than ``b``
and ``b`` is less than ``c``. However, the expression ``a < b < c`` is
equivalent to ``(a < b) < c``. Since ``a < b`` is ``true``, the expression
``(a < b) < c`` is evaluated as ``1 < c``, which is equivalent to ``true < c``
and is invalid in this case as ``b < c`` is ``false``.

Even that above issue could be detected as comparison of ``int`` to ``bool``,
there is more dangerous example:

.. code-block:: c++

    bool a = false, b = false, c = true;
    if (a == b == c) {
        // This block will be executed
    }

In this example, the developer intended to check if ``a``, ``b``, and ``c`` are
all equal. However, the expression ``a == b == c`` is evaluated as
``(a == b) == c``. Since ``a == b`` is true, the expression ``(a == b) == c``
is evaluated as ``true == c``, which is equivalent to ``true == true``.
This comparison yields ``true``, even though ``a`` and ``b`` are ``false``, and
are not equal to ``c``.

To avoid this issue, the developer can use a logical operator to separate the
comparison expressions, like this:

.. code-block:: c++

    if (a == b && b == c) {
        // This block will not be executed
    }


Alternatively, use of parentheses in the comparison expressions can make the
developer's intention more explicit and help avoid misunderstanding.

.. code-block:: c++

    if ((a == b) == c) {
        // This block will be executed
    }

Options
-------

.. option:: IgnoreMacros

    If `true`, the check will not warn on chained comparisons inside macros.
    Default is `false`.

