RE: [PATCH] block: fix Werror=format with GCC 13

From: David Laight
Date: Wed Oct 26 2022 - 04:17:03 EST


From: Jiri Slaby
> Sent: 26 October 2022 08:18
>
> On 24. 10. 22, 21:01, Martin Liška wrote:
> > Starting with GCC 13, since
> > [g3b3083a598ca3f4b] c: C2x enums wider than int [PR36113]
> >
> > GCC promotes enum values with larger than integer types to a wider type.
> > In case of the anonymous enum type in blk-iocost.c it is:
> >
> > enum {
> > MILLION = 1000000,
> > ...
> >
> > WEIGHT_ONE = 1 << 16,
> > ...
> > VTIME_PER_SEC_SHIFT = 37,
> > VTIME_PER_SEC = 1LLU << VTIME_PER_SEC_SHIFT,
> > ...
> >
> > as seen VTIME_PER_SEC cannot fit into 32-bits (int type), thus one needs
> > to use 'long unsigned int' in the format string.
> >
> > It fixes then the following 2 warnings:
> >
> > block/blk-iocost.c: In function ‘ioc_weight_prfill’:
> > block/blk-iocost.c:3035:37: error: format ‘%u’ expects argument of type ‘unsigned int’, but argument
> 4 has type ‘long unsigned int’ [-Werror=format=]
> > 3035 | seq_printf(sf, "%s %u\n", dname, iocg->cfg_weight / WEIGHT_ONE);
> > | ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | | |
> > | unsigned int long unsigned int
> > | %lu
> > block/blk-iocost.c: In function ‘ioc_weight_show’:
> > block/blk-iocost.c:3045:34: error: format ‘%u’ expects argument of type ‘unsigned int’, but argument
> 3 has type ‘long unsigned int’ [-Werror=format=]
> > 3045 | seq_printf(sf, "default %u\n", iocc->dfl_weight / WEIGHT_ONE);
> > | ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | | |
> > | unsigned int long unsigned int
> > | %lu
>
> But introduces two with gcc-12 ;):
> > block/blk-iocost.c: In function ‘ioc_weight_prfill’:
> > block/blk-iocost.c:3037:38: error: format ‘%lu’ expects argument of
> type ‘long unsigned int’, but argument 4 has type ‘u32’ {aka ‘unsigned
> int’} [-Werror=format=]
> > 3037 | seq_printf(sf, "%s %lu\n", dname,
> iocg->cfg_weight / WEIGHT_ONE);
> > | ~~^
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | |
> |
> > | long unsigned int
> u32 {aka unsigned int}
> > | %u
>
>
> Note that:
> 1) the specs says enum behaves as int, or uint in some cases
> 2) iocc->dfl_weight is u32, i.e. uint
> WEIGHT_ONE is 1 << 16, i.e. int
> so the promotion should be to s32/int. Or not?
>
> I think gcc-13 is wrong -- incosistent with gcc-12 at least.

The presence of VTIME_PER_SEC in the enum forces the enum
to 64bits (this must be a gcc extension).

The change in gcc 13 seems to be that the types of all the
enum values are now (probably correctly) that of the enum.

So WEIGHT_ONE changes from 'unsigned int' to 'unsigned long'.

See: https://godbolt.org/z/6K4PoK9sv

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)