This is an archive of the discontinued LLVM Phabricator instance.

New warning for mismatch between not and and/or operators.
Needs ReviewPublic

Authored by rtrieu on Oct 13 2014, 6:27 PM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

Emit a warning when a bitwise not operator is used with a logical and/or operator or a logical not with bitwise and/or is detected. Also emit fix-it hints to change the not operator and to change the and/or operator.

Examples:
int x = ~y || ~z;
Fixed with || => |

bool a = ~b && !c
Fixed with ~b => !b

No false positives found, although the impact of using a bitwise operator in place of a logical operator is lower than the other way round.

Diff Detail

Event Timeline

rtrieu updated this revision to Diff 14839.Oct 13 2014, 6:27 PM
rtrieu retitled this revision from to New warning for mismatch between not and and/or operators..
rtrieu updated this object.
rtrieu edited the test plan for this revision. (Show Details)
rtrieu added a subscriber: Unknown Object (MLST).

Test cases?

Examples:
int x = ~y | ~z;
Fixed with | => ||

The code ~y | ~z looks reasonable to me. It's equivalent to ~(y & z), a.k.a. "all the flags that aren't part of either y or z".
Did you mean to denigrate !y | !z instead? In that case, the fixit | => || would definitely be appropriate IMHO.

bool a = ~b && !c
Fixed with ~b => !b

I wouldn't expect the compiler to suggest a fixit in this case, but if it did, this code is sufficiently confusing that I personally would rather see the compiler suggest ~b => (b != -1), rather than suggesting a fixit that quietly changes the meaning of the code.

rtrieu updated this object.Oct 13 2014, 7:33 PM
rtrieu updated this revision to Diff 14848.Oct 13 2014, 7:36 PM

Test cases?

Forgot to add the test case so the diff didn't pick it up. Test is included now.

Examples:
int x = ~y | ~z;
Fixed with | => ||

The code ~y | ~z looks reasonable to me. It's equivalent to ~(y & z), a.k.a. "all the flags that aren't part of either y or z".
Did you mean to denigrate !y | !z instead? In that case, the fixit | => || would definitely be appropriate IMHO.

Fixed the test case. I intended to go || to | in the example.

bool a = ~b && !c
Fixed with ~b => !b

I wouldn't expect the compiler to suggest a fixit in this case, but if it did, this code is sufficiently confusing that I personally would rather see the compiler suggest ~b => (b != -1), rather than suggesting a fixit that quietly changes the meaning of the code.

Both operator~ and operator! are called the not operator and the keys are right next to each other on US keyboards, so it would be easy to confuse the two. From my testing, this was a common mistake of using ! when ~ was intended in bitwise contexts.

rtrieu updated this revision to Diff 21158.Mar 3 2015, 4:49 PM

Update to newer base revision.

I am personally a bit skeptic about this.

what does it solve to use:

a = !b || !c;

instead of:

a = !b | !c;

If it's only stylistic .. then why not let the programmer decide which way is better.

I am not saying that I am against this.. just that I am a bit skeptic.

rtrieu added a comment.Apr 2 2015, 6:08 PM

I am personally a bit skeptic about this.

what does it solve to use:

a = !b || !c;

instead of:

a = !b | !c;

If it's only stylistic .. then why not let the programmer decide which way is better.

The same reason Clang suggests parentheses for possible order of operations bugs. It is easy to make such bugs and the correction helps make the code more readable. Perhaps the opposite suggestion should also be made?

a = ~b | ~c;

which does change how the code works.

I am not saying that I am against this.. just that I am a bit skeptic.

Switching from bitwise to logical operator also produced different code when compiled in at least one case. See https://llvm.org/bugs/show_bug.cgi?id=22723