platform/x86: thinkpad_acpi: Fix bitwise vs. logical warning
PATCH 1/1 platform/x86: thinkpad_acpi: Fix bitwise vs. logical warning
A new warning in clang points out a use of bitwise OR with boolean expressions in this driver:
drivers/platform/x86/thinkpad_acpi.c:9061:11: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]
else if ((strlencmp(cmd, "level disengaged") == 0) |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
||drivers/platform/x86/thinkpad_acpi.c:9061:11: note: cast one or both operands to int to silence this warning 1 error generated.
This should clearly be a logical OR so change it to fix the warning.
--- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/thinkpad_acpi.c +1 -1
@@ -9058,7 +9058,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc)if (strlencmp (cmd,"level auto" ) ==0 ) level =TP_EC_FAN_AUTO ; -else if ((strlencmp (cmd,"level disengaged" ) ==0 ) | +else if ((strlencmp (cmd,"level disengaged" ) ==0 ) || (strlencmp (cmd,"level full-speed" ) ==0 )) level =TP_EC_FAN_FULLSPEED ;else if (sscanf (cmd,"level %d" , &level) !=1 )
base-commit: 85303db36b6e170917a7bc6aae4898c31a5272a0
Signature · 1 line
2.33.1.637.gf443b226ca
Quoted 11 lines · Nathan Chancellor
A new warning in clang points out a use of bitwise OR with boolean expressions in this driver:
drivers/platform/x86/thinkpad_acpi.c:9061:11: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]else if ((strlencmp(cmd, "level disengaged") == 0) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
drivers/platform/x86/thinkpad_acpi.c:9061:11: note: cast one or both operands to int to silence this warning 1 error generated.
Quoted 6 lines
This should clearly be a logical OR so change it to fix the warning.
Fixes fe98a52ce754 ("ACPI: thinkpad-acpi: add sysfs support to fan subdriver")Reported-by Tor Vic <[email protected]>Signed-off-by Nathan Chancellor <[email protected]>
LGTM, thanks for the patch! I guess this would be the first "interesting" case this warning has found in kernel sources?
Quoted 22 lines
--- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/platform/x86/thinkpad_acpi.c +1
-1@@ -9058,7 +9058,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc)if (strlencmp (cmd,"level auto" ) ==0 ) level =TP_EC_FAN_AUTO ; -else if ((strlencmp (cmd,"level disengaged" ) ==0 ) | +else if ((strlencmp (cmd,"level disengaged" ) ==0 ) || (strlencmp (cmd,"level full-speed" ) ==0 )) level =TP_EC_FAN_FULLSPEED ;else if (sscanf (cmd,"level %d" , &level) !=1 )base-commit:
85303db36b6e170917a7bc6aae4898c31a5272a0--
2.33.1.637.gf443b226ca
Signature · 2 lines
Thanks, ~Nick Desaulniers
Quoted 3 lines · Nick Desaulniers
LGTM, thanks for the patch! I guess this would be the first "interesting" case this warning has found in kernel sources?
The patch looks obviously correct (tm), but I'm not convinced that the warning is actually all that interesting.
The thing is, using bitwise operators for booleans is _exactly_ the same as using logical ones as long as there are no side effects. In fact, any compiler worth its salt will already convert some cases between the two as an optimization just as part of code generation.
Of course, that "as long as there are no side effects" is the big thing - then the short-circuiting of the actual logical operations clearly matters. But that wasn't actually the case in this situation (or in the kvm situation elsewhere).
So in both of these cases, the difference between "|" and "||" ends up purely being a hint to the compiler.
In this case, even if there are no side effects, it's clearly pointless to do the second strlencmp() if the first one already matched, and the "||" is unquestionably the right hint (and honestly, most compilers probably wouldn't even be able to tell "no side effects" because it's a fairly complex expression - but since it's inlined and uses compiler intrinsics, the compiler _might_ actually be able to see that the two are equivalent).
But no, I don't think that warning is very interesting. In fact, the warning might be overall detrimental, in case the hints were intentional (like the kvm case - although I'm not convinced the kvm hinting was actually meaningful).
Linus
Quoted 4 lines · Linus Torvalds
Quoted 1 line · Nick Desaulniers
Quoted 8 lines
Quoted 2 lines
LGTM, thanks for the patch! I guess this would be the first "interesting" case this warning has found in kernel sources?
The patch looks obviously correct (tm), but I'm not convinced that the warning is actually all that interesting.
The thing is, using bitwise operators for booleans is _exactly_ the same as using logical ones as long as there are no side effects.
Right, the patch that added the warning explicitly checks for side effects.
https://reviews.llvm.org/D108003
https://lore.kernel.org/lkml/[email protected]/
is another example that I would point to in favor of the error.
Signature · 2 lines
Thanks, ~Nick Desaulniers
Quoted 2 lines · Nick Desaulniers
Right, the patch that added the warning explicitly checks for side effects.
Well, it's a bit questionable. The "side effects" are things like any pointer dereference, because it could fault, but if you know that isn't an issue, then clang basically ends up complaining about code that is perfectly fine. Maybe it was written that way on purpose, like the kvm code.
Now, it's probably not worth keeping that "bitops of booleans" logic - if it is a noticeable optimization, it's generally something that the compiler should do for us, but basically clang is warning about perfectly valid code.
And what I find absolutely disgusting is the suggested "fix" that clang gives you.
If the warning said "maybe you meant to use a logical or (||)", then that would be one thing. But what clang suggests as the "fix" for the warning is just bad coding practice.
If a warning fix involves making the code uglier, then the warning fix is wrong.
This is not the first time we've had compilers suggesting garbage. Gcc used to suggest (perhaps still does) the "extra parenthesis" for "assignment used as a truth value" situation. Which is - once again - disgusting garbage.
Writing code like
if (a = b) ..
is bad and error prone. But the suggestion to "fix" the warning with
if ((a = b)) ..
is just completely unacceptably stupid, and is just BAD CODE.
The proper fix might be to write it like
if ((a = b) != 0) ...
which at least makes the truth value part explicit - in ways that a silly double parenthesis does not. Or, better yet, write it as
a = b;
if (a) ..instead, which is legible and fine.
The clang suggestion to add a cast to 'int' to avoid the warning is the same kind of "write bad code" suggestion. Just don't do it.
Linus
Quoted 16 lines · Linus Torvalds
Quoted 2 lines · Nick Desaulniers
Right, the patch that added the warning explicitly checks for side effects.
Well, it's a bit questionable. The "side effects" are things like any pointer dereference, because it could fault, but if you know that isn't an issue, then clang basically ends up complaining about code that is perfectly fine. Maybe it was written that way on purpose, like the kvm code.
Now, it's probably not worth keeping that "bitops of booleans" logic - if it is a noticeable optimization, it's generally something that the compiler should do for us, but basically clang is warning about perfectly valid code.
Quoted 6 lines
And what I find absolutely disgusting is the suggested "fix" that clang gives you.
If the warning said "maybe you meant to use a logical or (||)", then that would be one thing. But what clang suggests as the "fix" for the warning is just bad coding practice.
For what it's worth, the suggested fix is the '||' underneath the warning text:
In file included from arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]
return __is_bad_mt_xwr(rsvd_check, spte) |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
||arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning 1 error generated.
Perhaps that hint should also be added to the warning text, like:
In file included from arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands; did you mean logical '||'? [-Werror,-Wbitwise-instead-of-logical]
return __is_bad_mt_xwr(rsvd_check, spte) |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
||arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning 1 error generated.
It is late for me but I can push that change to the clang developers and see what they think tomorrow if that would help?
Cheers,
Nathan
Quoted 11 lines · Nathan Chancellor
For what it's worth, the suggested fix is the '||' underneath the warning text:
In file included from
arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]return __is_bad_mt_xwr(rsvd_check, spte) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning 1 error generated.
Hmm. That's not at all obvious.
The *much* bigger part is that
note: cast one or both operands to int to silence this warning
which is what I'm complaining about. That note should die. It should say "maybe you meant to use a logical or" or something like that.
Quoted 8 lines
Perhaps that hint should also be added to the warning text, like:
In file included from
arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands; did you mean logical '||'? [-Werror,-Wbitwise-instead-of-logical]return __is_bad_mt_xwr(rsvd_check, spte) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning
I don't understand why you seem to continue to ignore the "note" message, which makes a completely crazy suggestion.
Linus
Trimming up the replies as we are not really talking about the x86 platform drivers warning anymore.
Quoted 13 lines · Linus Torvalds
Quoted 11 lines · Nathan Chancellor
For what it's worth, the suggested fix is the '||' underneath the warning text:
In file included from
arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]return __is_bad_mt_xwr(rsvd_check, spte) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning 1 error generated.
Quoted 1 line
Hmm. That's not at all obvious.
I agree, hence the question added to the warning.
Quoted 16 lines
The *much* bigger part is that
note: cast one or both operands to int to silence this warning
which is what I'm complaining about. That note should die. It should say "maybe you meant to use a logical or" or something like that.
Quoted 8 lines
Perhaps that hint should also be added to the warning text, like:
In file included from
arch/x86/kvm/mmu/tdp_iter.c:5:arch/x86/kvm/mmu/spte.h:318:9: error: use of bitwise '|' with boolean operands; did you mean logical '||'? [-Werror,-Wbitwise-instead-of-logical]return __is_bad_mt_xwr(rsvd_check, spte) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
arch/x86/kvm/mmu/spte.h:318:9: note: cast one or both operands to int to silence this warning
Quoted 2 lines
I don't understand why you seem to continue to ignore the "note" message, which makes a completely crazy suggestion.
Sorry, I was not intentionally ignoring the note. As far as I understand it, it is fairly common for clang to offer a fix up in case the answer to the question of "did you mean to do this?" is "no" but also offer a way to shut the warning up in case the answer is "yes, I know what I am doing", hence the note about casting.
Changing to logical OR is not always the answer, as something like
int a, b, c;
changed = foo(&a) | foo(&b) | foo(&c);
if (changed)
bar(a, b, c);no longer works. It could be changed to
int a, b, c;
changed = foo(&a);
changed |= foo(&b);
changed |= foo(&c);
if (changed)
baz(a, b, c);to make it clearer to both humans and the compiler that every call to foo() needs to happen and the results are being aggregated. With that, perhaps the note could be changed to something like:
note: separate expressions with '|=' to silence this warning
Although, that would require that the expression was being assigned to a variable, rather than being returned or used in a loop like the KVM one or this other one that is seen in fs/namei.c on big endian ARM configurations with CONFIG_DCACHE_WORD_ACCESS because has_zero() returns bool instead of unsigned long on little endian architectures:
fs/namei.c:2149:13: warning: use of bitwise '|' with boolean operands [-Wbitwise-instead-of-logical]
} while (!(has_zero(a, &adata, &constants) | has_zero(b, &bdata, &constants)));
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
||fs/namei.c:2149:13: note: cast one or both operands to int to silence this warning 1 warning generated.
Perhaps the note should just be eliminated entirely so that developers can be left to try and figure out a way to silence it on their own or just rework the code to use logical OR or not use boolean types, I do not know.
There was some discussion upstream around how the warning should be silenced during the warning's creation. I have added the author of the warning, David, to this thread to see if he has any insights.
David, you can see the start of this thread here and follow along with the threading at the bottom:
https://lore.kernel.org/r/CAHk-=wi7hUsTTcmPfZCkUEw51Y3ayq3JJxzFsNgodsxxDyk9Ww@mail.gmail.com/
Cheers,
Nathan
Hi,
Quoted 10 lines · Nathan Chancellor
A new warning in clang points out a use of bitwise OR with boolean expressions in this driver:
drivers/platform/x86/thinkpad_acpi.c:9061:11: error: use of bitwise '|' with boolean operands [-Werror,-Wbitwise-instead-of-logical]else if ((strlencmp(cmd, "level disengaged") == 0) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ||
drivers/platform/x86/thinkpad_acpi.c:9061:11: note: cast one or both operands to int to silence this warning 1 error generated.
Quoted 6 lines
This should clearly be a logical OR so change it to fix the warning.
Fixes fe98a52ce754 ("ACPI: thinkpad-acpi: add sysfs support to fan subdriver")Reported-by Tor Vic <[email protected]>Signed-off-by Nathan Chancellor <[email protected]>
Thank you for your patch, I've applied this patch to my review-hans branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while.
Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window.
Regards,
Hans
Quoted 20 lines
--- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/platform/x86/thinkpad_acpi.c +1
-1@@ -9058,7 +9058,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc)if (strlencmp (cmd,"level auto" ) ==0 ) level =TP_EC_FAN_AUTO ; -else if ((strlencmp (cmd,"level disengaged" ) ==0 ) | +else if ((strlencmp (cmd,"level disengaged" ) ==0 ) || (strlencmp (cmd,"level full-speed" ) ==0 )) level =TP_EC_FAN_FULLSPEED ;else if (sscanf (cmd,"level %d" , &level) !=1 )base-commit:
85303db36b6e170917a7bc6aae4898c31a5272a0