c: C2x %wN, %wfN format checking
authorJoseph Myers <joseph@codesourcery.com>
Wed, 19 Oct 2022 21:55:27 +0000 (21:55 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Wed, 19 Oct 2022 21:55:27 +0000 (21:55 +0000)
commit5e1538c5f68abed81204a223db7bdbeef32e0711
tree36e729f78b3571499120ea4169c3f12178d19ee2
parentf0068278f7e75507c1f40e7c829d7a9d6ade269c
c: C2x %wN, %wfN format checking

C2x adds printf and scanf wN and wfN length modifiers (wN for
int_leastN_t / uint_leastN_t, also usable for intN_t and uintN_t which
are now required to be the same type as the "least" versions when both
are supported; wfN for int_fastN_t / uint_fastN_t).  Add corresponding
format checking support for those length modifiers, for all the
standard integer conversion speciciers plus the recommended integer
specifier %B.

Note that, as with the %b support, this only deals with format
checking, not other format handling elsewhere in the compiler (in
particular, it doesn't add any -Wformat-overflow support; cf. Frolov
Daniil's patch
<https://gcc.gnu.org/pipermail/gcc-patches/2022-September/600790.html>
adding such support for %b and %B, which I think is still pending
review).  And of course library support is a separate matter for each
library implementation (I hope to add corresponding glibc support in
due course).

None of the tables of format conversions for kinds of formats not
supporting the new length modifiers are updated; they don't need
updating because the entries not matching some length modifier listed
for that kind of format can never be accessed, and the tables
generally thus already only explicitly covered a sufficient initial
subsequence of the length modifiers, rather than listing a full 13
possibilities before this patch or 21 after it.  %w (as used for
HOST_WIDE_INT in GCC-internal formats) comes after the new modifiers
in the FMT_LEN_* enumeration, but that's not a problem because the
tables don't actually use FMT_LEN_w entries; rather, such entries get
rewritten at runtime once GCC knows the value of HOST_WIDE_INT in the
GCC it's compiling.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

gcc/c-family/
* c-format.h (enum format_lengths): Add FMT_LEN_w8, FMT_LEN_w16,
FMT_LEN_w32, FMT_LEN_w64, FMT_LEN_wf8, FMT_LEN_wf16, FMT_LEN_wf32
and FMT_LEN_wf64.
(NOARGUMENTS, NOLENGTHS): Update definitions.
(T_I8, T2X_I8, T_I16, T2X_I16, T_I32, T2X_I32, T_I64, T2X_I64)
(T_U8, T2X_U8, T_U16, T2X_U16, T_U32, T2X_U32, T_U64, T2X_U64)
(T_IF8, T2X_IF8, T_IF16, T2X_IF16, T_IF32, T2X_IF32, T_IF64)
(T2X_IF64, T_UF8, T2X_UF8, T_UF16, T2X_UF16, T_UF32, T2X_UF32)
(T_UF64, T2X_UF64): New macros.
* c-format.cc (printf_length_specs, scanf_length_specs): Add wN
and wfN length modifiers.
(print_char_table, scan_char_table): Add entries using wN and wfN
length modifiers.

gcc/testsuite/
* gcc.dg/format/format.h (int_least8_t, int_least16_t)
(int_least32_t, int_least64_t, uint_least8_t, uint_least16_t)
(uint_least32_t, uint_least64_t, int_fast8_t, int_fast16_t)
(int_fast32_t, int_fast64_t, uint_fast8_t, uint_fast16_t)
(uint_fast32_t, uint_fast64_t): New typedefs.
* gcc.dg/format/c11-printf-1.c, gcc.dg/format/c11-scanf-1.c,
gcc.dg/format/c2x-printf-1.c, gcc.dg/format/c2x-scanf-1.c,
gcc.dg/format/ext-9.c: Add tests using wN and wfN length
modifiers.
gcc/c-family/c-format.cc
gcc/c-family/c-format.h
gcc/testsuite/gcc.dg/format/c11-printf-1.c
gcc/testsuite/gcc.dg/format/c11-scanf-1.c
gcc/testsuite/gcc.dg/format/c2x-printf-1.c
gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
gcc/testsuite/gcc.dg/format/ext-9.c
gcc/testsuite/gcc.dg/format/format.h