Re: [PATCH v2 4/4] minmax: remove useless cast in __is_nonneg()
David Laight <[email protected]> Sat, 20 Dec 2025 10:02:01 +0000
| Newsgroups | org.kernel.vger.linux-sparse,dev.linux.lists.llvm,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-hardening,org.kernel.vger.linux-kbuild,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20251220100201.26d9b0db@pumpkin> |
On Fri, 19 Dec 2025 23:39:48 +0100 Vincent Mailhol <[email protected]> wrote: > The function like macro __is_nonneg() casts its argument to (long long) > in an attempt to silence -Wtype-limits warnings on unsigned values. nak. The cast is needed for pointer types, not for -Wtype-limits. which is why the '#if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__' test is there. David > > But this workaround is incomplete as proven here: > > $ cat foo.c > #include <linux/minmax.h> > > int foo(unsigned int a) > { > return __is_nonneg(a); > } > $ make CFLAGS_KERNEL="-Wtype-limits" foo.o > CALL scripts/checksyscalls.sh > DESCEND objtool > INSTALL libsubcmd_headers > CC foo.o > foo.c: In function 'foo': > ./include/linux/minmax.h:68:57: warning: comparison is always true due to limited range of data type [-Wtype-limits] > 68 | #define __is_nonneg(ux) statically_true((long long)(ux) >= 0) > | ^~ > ./include/linux/compiler.h:350:50: note: in definition of macro 'statically_true' > 350 | #define statically_true(x) (__builtin_constant_p(x) && (x)) > | ^ > foo.c:5:16: note: in expansion of macro '__is_nonneg' > 5 | return __is_nonneg(a); > | ^~~~~~~~~~~ > ./include/linux/minmax.h:68:57: warning: comparison is always true due to limited range of data type [-Wtype-limits] > 68 | #define __is_nonneg(ux) statically_true((long long)(ux) >= 0) > | ^~ > ./include/linux/compiler.h:350:57: note: in definition of macro 'statically_true' > 350 | #define statically_true(x) (__builtin_constant_p(x) && (x)) > | ^ > foo.c:5:16: note: in expansion of macro '__is_nonneg' > 5 | return __is_nonneg(a); > | ^~~~~~~~~~~ > > And because -Wtype-limits is now globally disabled, such a workaround > now becomes useless. Remove the __is_nonneg()'s cast and its related > comment. > > Signed-off-by: Vincent Mailhol <[email protected]> > --- > Changelog: > > v1 -> v2: new patch > --- > include/linux/minmax.h | 5 +---- > 1 file changed, 1 insertion(+), 4 deletions(-) > > diff --git a/include/linux/minmax.h b/include/linux/minmax.h > index a0158db54a04..3e2e3e539ba1 100644 > --- a/include/linux/minmax.h > +++ b/include/linux/minmax.h > @@ -52,9 +52,6 @@ > /* > * Check whether a signed value is always non-negative. > * > - * A cast is needed to avoid any warnings from values that aren't signed > - * integer types (in which case the result doesn't matter). > - * > * On 64-bit any integer or pointer type can safely be cast to 'long long'. > * But on 32-bit we need to avoid warnings about casting pointers to integers > * of different sizes without truncating 64-bit values so 'long' or 'long long' > @@ -65,7 +62,7 @@ > * but they are handled by the !is_signed_type() case). > */ > #if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__ > -#define __is_nonneg(ux) statically_true((long long)(ux) >= 0) > +#define __is_nonneg(ux) statically_true((ux) >= 0) > #else > #define __is_nonneg(ux) statically_true( \ > (typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)))(ux) >= 0) >