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:

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:

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:

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.

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