xref: /llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst (revision 06c3c3b67cb0287856145806cfb0179def3214bd)
1.. title:: clang-tidy - bugprone-chained-comparison
2
3bugprone-chained-comparison
4===========================
5
6Check detects chained comparison operators that can lead to unintended
7behavior or logical errors.
8
9Chained comparisons are expressions that use multiple comparison operators
10to compare three or more values. For example, the expression ``a < b < c``
11compares the values of ``a``, ``b``, and ``c``. However, this expression does
12not evaluate as ``(a < b) && (b < c)``, which is probably what the developer
13intended. Instead, it evaluates as ``(a < b) < c``, which may produce
14unintended results, especially when the types of ``a``, ``b``, and ``c`` are
15different.
16
17To avoid such errors, the check will issue a warning when a chained
18comparison operator is detected, suggesting to use parentheses to specify
19the order of evaluation or to use a logical operator to separate comparison
20expressions.
21
22Consider the following examples:
23
24.. code-block:: c++
25
26    int a = 2, b = 6, c = 4;
27    if (a < b < c) {
28        // This block will be executed
29    }
30
31
32In this example, the developer intended to check if ``a`` is less than ``b``
33and ``b`` is less than ``c``. However, the expression ``a < b < c`` is
34equivalent to ``(a < b) < c``. Since ``a < b`` is ``true``, the expression
35``(a < b) < c`` is evaluated as ``1 < c``, which is equivalent to ``true < c``
36and is invalid in this case as ``b < c`` is ``false``.
37
38Even that above issue could be detected as comparison of ``int`` to ``bool``,
39there is more dangerous example:
40
41.. code-block:: c++
42
43    bool a = false, b = false, c = true;
44    if (a == b == c) {
45        // This block will be executed
46    }
47
48In this example, the developer intended to check if ``a``, ``b``, and ``c`` are
49all equal. However, the expression ``a == b == c`` is evaluated as
50``(a == b) == c``. Since ``a == b`` is true, the expression ``(a == b) == c``
51is evaluated as ``true == c``, which is equivalent to ``true == true``.
52This comparison yields ``true``, even though ``a`` and ``b`` are ``false``, and
53are not equal to ``c``.
54
55To avoid this issue, the developer can use a logical operator to separate the
56comparison expressions, like this:
57
58.. code-block:: c++
59
60    if (a == b && b == c) {
61        // This block will not be executed
62    }
63
64
65Alternatively, use of parentheses in the comparison expressions can make the
66developer's intention more explicit and help avoid misunderstanding.
67
68.. code-block:: c++
69
70    if ((a == b) == c) {
71        // This block will be executed
72    }
73
74