Hi,

I've contributed a check to clang-tidy that simplifies

statements involving boolean literals. The name of the check is

simplify-boolean-expr. It is not enabled by default, so you must request

this check to get fixes applied to your code by clang-tidy.

I believe this check is sufficiently robust that it should make no changes

to your code that change the semantics of the code. I've run this on

the clang and LLVM code bases and addressed issues and made improvements

to correct and such problems encountered there. However, I would love

for this check to be run on more code bases to check for any additional

problems I might have missed. You can provide feedback directly to me

by email or via the clang bug tracker. <https://llvm.org/bugs/>

This check looks for boolean expressions involving boolean constants and

simplifies them to use the appropriate boolean expression directly.

Examples:

`if (b == true)` becomes `if (b)`

`if (b == false)` becomes `if (!b)`

`if (b && true)` becomes `if (b)`

`if (b && false)` becomes `if (false)`

`if (b || true)` becomes `if (true)`

`if (b || false)` becomes `if (b)`

`e ? true : false` becomes `e`

`e ? false : true` becomes `!e`

`if (true) t(); else f();` becomes `t();`

`if (false) t(); else f();` becomes `f();`

`if (e) return true; else return false;` becomes `return e;`

`if (e) return false; else return true;` becomes `return !e;`

`if (e) b = true; else b = false;` becomes `b = e;`

`if (e) b = false; else b = true;` becomes `b = !e;`

`if (e) return true; return false;` becomes `return e;`

`if (e) return false; return true;` becomes `return !e;`

The resulting expression `e` is modified as follows:

1. Unnecessary parentheses around the expression are removed.

2. Negated applications of `!` are eliminated.

3. Negated applications of comparison operators are changed to use the

opposite condition.

4. Implicit conversions of pointer to `bool` are replaced with explicit

comparisons to `nullptr`.

5. Implicit casts to `bool` are replaced with explicit casts to `bool`.

6. Object expressions with `explicit operator bool` conversion operators

are replaced with explicit casts to `bool`.

Examples:

1. The ternary assignment `bool b = (i < 0) ? true : false;` has redundant

parentheses and becomes `bool b = i < 0;`.

2. The conditional return `if (!b) return false; return true;` has an

implied double negation and becomes `return b;`.

3. The conditional return `if (i < 0) return false; return true;` becomes

`return i >= 0;`.

The conditional return `if (i != 0) return false; return true;` becomes

`return i == 0;`.

4. The conditional return `if (p) return true; return false;` has an

implicit conversion of a pointer to `bool` and becomes

`return p != nullptr;`.

The ternary assignment `bool b = (i & 1) ? true : false;` has an implicit

conversion of `i & 1` to `bool` and becomes

`bool b = static_cast<bool>(i & 1);`.

5. The conditional return `if (i & 1) return true; else return false;` has

an implicit conversion of an integer quantity `i & 1` to `bool` and becomes

`return static_cast<bool>(i & 1);`

6. Given `struct X { explicit operator bool(); };`, and an instance `x` of

`struct X`, the conditional return `if (x) return true; return false;`

becomes `return static_cast<bool>(x);`

When a conditional boolean return or assignment appears at the end of a

chain of `if`, `else if` statements, the conditional statement is left

unchanged unless the option `ChainedConditionalReturn` or

`ChainedConditionalAssignment`, respectively, is specified as non-zero.

The default value for both options is zero.