[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHk-=wg+_6eQnLWm-kihFxJo1_EmyLSGruKVGzuRUwACE=osrA@mail.gmail.com>
Date: Sun, 8 Dec 2024 11:05:34 -0800
From: Linus Torvalds <torvalds@...ux-foundation.org>
To: Martin Uecker <muecker@...g.de>
Cc: David Laight <David.Laight@...lab.com>, Vincent Mailhol <mailhol.vincent@...adoo.fr>,
Luc Van Oostenryck <luc.vanoostenryck@...il.com>, Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <ndesaulniers@...gle.com>, Bill Wendling <morbo@...gle.com>,
Justin Stitt <justinstitt@...gle.com>, Yury Norov <yury.norov@...il.com>,
Rasmus Villemoes <linux@...musvillemoes.dk>, Kees Cook <kees@...nel.org>,
"Gustavo A. R. Silva" <gustavoars@...nel.org>, Jani Nikula <jani.nikula@...ux.intel.com>,
Joonas Lahtinen <joonas.lahtinen@...ux.intel.com>, Rodrigo Vivi <rodrigo.vivi@...el.com>,
Tvrtko Ursulin <tursulin@...ulin.net>, David Airlie <airlied@...il.com>,
Simona Vetter <simona@...ll.ch>, Suzuki K Poulose <suzuki.poulose@....com>,
Mike Leach <mike.leach@...aro.org>, James Clark <james.clark@...aro.org>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
Rikard Falkeborn <rikard.falkeborn@...il.com>,
"linux-sparse@...r.kernel.org" <linux-sparse@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"llvm@...ts.linux.dev" <llvm@...ts.linux.dev>,
"linux-hardening@...r.kernel.org" <linux-hardening@...r.kernel.org>,
"intel-gfx@...ts.freedesktop.org" <intel-gfx@...ts.freedesktop.org>,
"dri-devel@...ts.freedesktop.org" <dri-devel@...ts.freedesktop.org>,
"coresight@...ts.linaro.org" <coresight@...ts.linaro.org>,
"linux-arm-kernel@...ts.infradead.org" <linux-arm-kernel@...ts.infradead.org>
Subject: Re: [PATCH 02/10] compiler.h: add is_const() as a replacement of __is_constexpr()
On Sun, 8 Dec 2024 at 10:11, Martin Uecker <muecker@...g.de> wrote:
> >
> > A lot of the 'macro business' for min/max is avoiding unexpected
> > conversion of negative values to very large unsigned ones.
> > And no, -Wsign-compare is spectacularly useless.
>
> This is a different topic, but what would be needed here?
Dan Carpenter actually wrote up some of the issues in:
https://staticthinking.wordpress.com/2023/07/25/wsign-compare-is-garbage/
but the basic issue is that -Wsign-compare has over the years been
truly spectacularly bad.
It has literally started out from the completely nonsensical and
incorrect assumption that the types of a comparison have to match in
signedness, and it shows in the name itself, but it also showed in
early implementations.
The very first versions of gcc that did -Wsign-compare literally
complained about code like
sizeof(x) < 5
because obviously one side is an unsigned 'size_t', and the other side
is a signed 'int'. So comparing the two is clearly invalid, right?
No.
It's obviously *not* invalid, and any compiler that complains about
different signedness of that compare is just complete useless garbage.
It's literally checking two constants against each other, and the
result doesn't depend on the signedness or the silent C implicit type
conversion.
And no, gcc doesn't complain about that particular code any more.
*That* particular problem was I think only visible in a gcc
pre-release that sadly did actually ship as part of a SUSE release, so
we saw it in the wild even if it was never in an official gcc release.
I'm pointing out the history because it's relevant due to explaining
*why* the whole concept of looking at just the type is so broken, and
how the whole background to the warning was broken from the very
beginning. The very name of the warning is a sign of the problem.
Because gcc still *does* complain about entirely valid code, where
"fixing" the warning just means you have to write worse code.
I think Dan's example from the link above is a good one: if
for (int i = 0; i < sizeof(x); i++)
causes a warning, the compiler got things entirely wrong.
And yes, modern gcc very much warns about that:
t.c:4:27: warning: comparison of integer expressions of different
signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
4 | for (int i = 0; i < sizeof(b); i++)
| ^
So if you want a general-purpose "Warn about dangerous comparisons",
you need to get away from the mindset that it's about different signs.
A compiler needs to do proper value range analysis before warning
about comparing said values. Not just mindlessly say "different types
bad" like some marsupial that has been dropped on its head a few too
many times.
End result: calling it "Warn about sign compare" is a disease. It
shows a lack of understanding of how complex the warning logic needs
to be.
Now, I'm not claiming that our min/max type warnings are great either:
they *do* end up basically being the same silly "just check signs, but
at least don't complain about signed positive constants being used for
unsigned comparisons".
So our min/max macros most definitely are *not* doing that "value
range analysis" that I claim is required for a *general* comparison
thing.
But our min//max macros aren't some general thing. They are very
specific, and so it's a lot easier to accept the not-great-analysis
for those specific cases where we then may have to change types
explicitly or do some other massaging to avoid the warning.
Put another way: a warning that triggers on really basic C absolutely
*must*not* have silly easily triggerable false positives for good and
idiomatic source code.
Such a warning is worse than useless, and gets disabled.
But a warning that is overly restrictive and gives silly false
positives can still be entirely acceptable when the context of that
warning is very limited.
So this is why in the kernel we disable '-Wsign-compare' in the
general case, but *do* basically manually then implement that very
same logic in the very _specific_ case of the min/max() macros.
What is unacceptable nonsense in one case may be acceptable "good
enough" in another. Life is not fair, I'm afraid.
Linus
Powered by blists - more mailing lists