[gcc r13-3392] c: C2x %wN, %wfN format checking

Joseph Myers jsm28@gcc.gnu.org
Wed Oct 19 21:56:32 GMT 2022


https://gcc.gnu.org/g:5e1538c5f68abed81204a223db7bdbeef32e0711

commit r13-3392-g5e1538c5f68abed81204a223db7bdbeef32e0711
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Oct 19 21:55:27 2022 +0000

    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.

Diff:
---
 gcc/c-family/c-format.cc                   |  76 +++++++++++-------
 gcc/c-family/c-format.h                    |  44 ++++++++++-
 gcc/testsuite/gcc.dg/format/c11-printf-1.c |  27 ++++++-
 gcc/testsuite/gcc.dg/format/c11-scanf-1.c  |  28 ++++++-
 gcc/testsuite/gcc.dg/format/c2x-printf-1.c | 113 ++++++++++++++++++++++++++-
 gcc/testsuite/gcc.dg/format/c2x-scanf-1.c  | 121 ++++++++++++++++++++++++++++-
 gcc/testsuite/gcc.dg/format/ext-9.c        |  10 ++-
 gcc/testsuite/gcc.dg/format/format.h       |  18 +++++
 8 files changed, 400 insertions(+), 37 deletions(-)

diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index a2026591ed1..01adea4ff41 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -488,6 +488,14 @@ static const format_length_info printf_length_specs[] =
   { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
   { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
   { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
+  { "w8", FMT_LEN_w8, STD_C2X, NO_FMT, 0 },
+  { "w16", FMT_LEN_w16, STD_C2X, NO_FMT, 0 },
+  { "w32", FMT_LEN_w32, STD_C2X, NO_FMT, 0 },
+  { "w64", FMT_LEN_w64, STD_C2X, NO_FMT, 0 },
+  { "wf8", FMT_LEN_wf8, STD_C2X, NO_FMT, 0 },
+  { "wf16", FMT_LEN_wf16, STD_C2X, NO_FMT, 0 },
+  { "wf32", FMT_LEN_wf32, STD_C2X, NO_FMT, 0 },
+  { "wf64", FMT_LEN_wf64, STD_C2X, NO_FMT, 0 },
   { NO_FMT, NO_FMT, 0 }
 };
 
@@ -525,6 +533,14 @@ static const format_length_info scanf_length_specs[] =
   { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
   { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
   { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
+  { "w8", FMT_LEN_w8, STD_C2X, NO_FMT, 0 },
+  { "w16", FMT_LEN_w16, STD_C2X, NO_FMT, 0 },
+  { "w32", FMT_LEN_w32, STD_C2X, NO_FMT, 0 },
+  { "w64", FMT_LEN_w64, STD_C2X, NO_FMT, 0 },
+  { "wf8", FMT_LEN_wf8, STD_C2X, NO_FMT, 0 },
+  { "wf16", FMT_LEN_wf16, STD_C2X, NO_FMT, 0 },
+  { "wf32", FMT_LEN_wf32, STD_C2X, NO_FMT, 0 },
+  { "wf64", FMT_LEN_wf64, STD_C2X, NO_FMT, 0 },
   { NO_FMT, NO_FMT, 0 }
 };
 
@@ -693,26 +709,26 @@ static const format_flag_pair strfmon_flag_pairs[] =
 static const format_char_info print_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +'I",  "i",  NULL },
-  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
-  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0'I",    "i",  NULL },
-  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "",   NULL },
-  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#I",  "",   NULL },
-  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
-  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "cR", NULL },
-  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "c",  NULL },
-  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",          "W",  NULL },
+  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN,   T2X_I8,  T2X_I16, T2X_I32, T2X_I64, T2X_IF8, T2X_IF16, T2X_IF32, T2X_IF64 }, "-wp0 +'I",  "i",  NULL },
+  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "-wp0#",     "i",  NULL },
+  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "-wp0'I",    "i",  NULL },
+  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp0 +#'I", "",   NULL },
+  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp0 +#I",  "",   NULL },
+  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-w",        "",   NULL },
+  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp",       "cR", NULL },
+  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-w",        "c",  NULL },
+  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN,   T2X_I8,  T2X_I16, T2X_I32, T2X_I64, T2X_IF8, T2X_IF16, T2X_IF32, T2X_IF64 }, "",          "W",  NULL },
   /* C99 conversion specifiers.  */
-  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "",   NULL },
-  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64,  T2X_D128 }, "-wp0 +#",   "",   NULL },
+  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp0 +#'I", "",   NULL },
+  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp0 +#",   "",   NULL },
   /* C2X conversion specifiers.  */
-  { "b",   0, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
+  { "b",   0, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "-wp0#",     "i",  NULL },
   /* X/Open conversion specifiers.  */
-  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
-  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "R",  NULL },
+  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-w",        "",   NULL },
+  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp",       "R",  NULL },
   /* GNU conversion specifiers.  */
-  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "",   NULL },
-  { "B",   0, STD_EXT, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
+  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "-wp",       "",   NULL },
+  { "B",   0, STD_EXT, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "-wp0#",     "i",  NULL },
   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
 };
 
@@ -860,23 +876,23 @@ static const format_char_info gcc_dump_printf_char_table[] =
 static const format_char_info scan_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "*w'I", "W",   NULL },
-  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "*w'I", "W",   NULL },
-  { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
-  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "*w'",  "W",   NULL },
-  { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*mw",   "cW",  NULL },
-  { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "cW",  NULL },
-  { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "cW[", NULL },
-  { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
-  { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",     "W",   NULL },
+  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN,   T2X_I8,  T2X_I16, T2X_I32, T2X_I64, T2X_IF8, T2X_IF16, T2X_IF32, T2X_IF64 }, "*w'I", "W",   NULL },
+  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "*w'I", "W",   NULL },
+  { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "*w",   "W",   NULL },
+  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*w'",  "W",   NULL },
+  { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*mw",   "cW",  NULL },
+  { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*amw",  "cW",  NULL },
+  { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*amw",  "cW[", NULL },
+  { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*w",   "W",   NULL },
+  { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN,   T2X_I8,  T2X_I16, T2X_I32, T2X_I64, T2X_IF8, T2X_IF16, T2X_IF32, T2X_IF64 }, "",     "W",   NULL },
   /* C99 conversion specifiers.  */
-  { "F",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "*w'",  "W",   NULL },
-  { "aA",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32,  T2X_D64,  T2X_D128 }, "*w'",  "W",   NULL },
+  { "F",   1, STD_C99,   { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*w'",  "W",   NULL },
+  { "aA",   1, STD_C99,  { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*w'",  "W",   NULL },
   /* C2X conversion specifiers.  */
-  { "b",     1, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
+  { "b",     1, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN,   T2X_U8,  T2X_U16, T2X_U32, T2X_U64, T2X_UF8, T2X_UF16, T2X_UF32, T2X_UF64 }, "*w",   "W",   NULL },
   /* X/Open conversion specifiers.  */
-  { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*mw",   "W",   NULL },
-  { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "W",   NULL },
+  { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*mw",   "W",   NULL },
+  { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,   BADLEN,   BADLEN }, "*amw",  "W",   NULL },
   { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
 };
 
diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
index 7f32f8d64ca..173d3cd82d3 100644
--- a/gcc/c-family/c-format.h
+++ b/gcc/c-family/c-format.h
@@ -36,6 +36,14 @@ enum format_lengths
   FMT_LEN_H,
   FMT_LEN_D,
   FMT_LEN_DD,
+  FMT_LEN_w8,
+  FMT_LEN_w16,
+  FMT_LEN_w32,
+  FMT_LEN_w64,
+  FMT_LEN_wf8,
+  FMT_LEN_wf16,
+  FMT_LEN_wf32,
+  FMT_LEN_wf64,
   FMT_LEN_w,   /* GCC's HOST_WIDE_INT.  */
   FMT_LEN_MAX
 };
@@ -124,9 +132,9 @@ struct format_type_detail
 
 
 /* Macros to fill out tables of these.  */
-#define NOARGUMENTS	{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
+#define NOARGUMENTS	{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
 #define BADLEN	{ STD_C89, NULL, NULL }
-#define NOLENGTHS	{ BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
+#define NOLENGTHS	{ BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
 
 
 /* Structure describing a format conversion specifier (or a set of specifiers
@@ -338,6 +346,38 @@ struct format_kind_info
 #define T2X_D64 { STD_C2X, "_Decimal64", T_D64 }
 #define T_D128  &dfloat128_type_node
 #define T2X_D128 { STD_C2X, "_Decimal128", T_D128 }
+#define T_I8	&int_least8_type_node
+#define T2X_I8	{ STD_C2X, "int_least8_t", T_I8 }
+#define T_I16	&int_least16_type_node
+#define T2X_I16	{ STD_C2X, "int_least16_t", T_I16 }
+#define T_I32	&int_least32_type_node
+#define T2X_I32	{ STD_C2X, "int_least32_t", T_I32 }
+#define T_I64	&int_least64_type_node
+#define T2X_I64	{ STD_C2X, "int_least64_t", T_I64 }
+#define T_U8	&uint_least8_type_node
+#define T2X_U8	{ STD_C2X, "uint_least8_t", T_U8 }
+#define T_U16	&uint_least16_type_node
+#define T2X_U16	{ STD_C2X, "uint_least16_t", T_U16 }
+#define T_U32	&uint_least32_type_node
+#define T2X_U32	{ STD_C2X, "uint_least32_t", T_U32 }
+#define T_U64	&uint_least64_type_node
+#define T2X_U64	{ STD_C2X, "uint_least64_t", T_U64 }
+#define T_IF8	&int_fast8_type_node
+#define T2X_IF8	{ STD_C2X, "int_fast8_t", T_IF8 }
+#define T_IF16	&int_fast16_type_node
+#define T2X_IF16 { STD_C2X, "int_fast16_t", T_IF16 }
+#define T_IF32	&int_fast32_type_node
+#define T2X_IF32 { STD_C2X, "int_fast32_t", T_IF32 }
+#define T_IF64	&int_fast64_type_node
+#define T2X_IF64 { STD_C2X, "int_fast64_t", T_IF64 }
+#define T_UF8	&uint_fast8_type_node
+#define T2X_UF8	{ STD_C2X, "uint_fast8_t", T_UF8 }
+#define T_UF16	&uint_fast16_type_node
+#define T2X_UF16 { STD_C2X, "uint_fast16_t", T_UF16 }
+#define T_UF32	&uint_fast32_type_node
+#define T2X_UF32 { STD_C2X, "uint_fast32_t", T_UF32 }
+#define T_UF64	&uint_fast64_type_node
+#define T2X_UF64 { STD_C2X, "uint_fast64_t", T_UF64 }
 
 /* Structure describing how format attributes such as "printf" are
    interpreted as "gnu_printf" or "ms_printf" on a particular system.
diff --git a/gcc/testsuite/gcc.dg/format/c11-printf-1.c b/gcc/testsuite/gcc.dg/format/c11-printf-1.c
index 7b8a9928098..05d242ecf28 100644
--- a/gcc/testsuite/gcc.dg/format/c11-printf-1.c
+++ b/gcc/testsuite/gcc.dg/format/c11-printf-1.c
@@ -6,8 +6,33 @@
 #include "format.h"
 
 void
-foo (int i)
+foo (int i, int_least8_t i8, int_least16_t i16, int_least32_t i32,
+     int_least64_t i64, uint_least8_t u8, uint_least16_t u16,
+     uint_least32_t u32, uint_least64_t u64, int_fast8_t if8,
+     int_fast16_t if16, int_fast32_t if32, int_fast64_t if64, uint_fast8_t uf8,
+     uint_fast16_t uf16, uint_fast32_t uf32, uint_fast64_t uf64)
 {
   printf ("%b", i); /* { dg-warning "C" } */
   printf ("%B", i); /* { dg-warning "C" } */
+  printf ("%w8d", i8); /* { dg-warning "C" } */
+  printf ("%w16d", i16); /* { dg-warning "C" } */
+  printf ("%w32d", i32); /* { dg-warning "C" } */
+  printf ("%w64d", i64); /* { dg-warning "C" } */
+  printf ("%wf8d", if8); /* { dg-warning "C" } */
+  printf ("%wf16d", if16); /* { dg-warning "C" } */
+  printf ("%wf32d", if32); /* { dg-warning "C" } */
+  printf ("%wf64d", if64); /* { dg-warning "C" } */
+  printf ("%w8u", u8); /* { dg-warning "C" } */
+  printf ("%w16u", u16); /* { dg-warning "C" } */
+  printf ("%w32u", u32); /* { dg-warning "C" } */
+  printf ("%w64u", u64); /* { dg-warning "C" } */
+  printf ("%wf8u", uf8); /* { dg-warning "C" } */
+  printf ("%wf16u", uf16); /* { dg-warning "C" } */
+  printf ("%wf32u", uf32); /* { dg-warning "C" } */
+  printf ("%wf64u", uf64); /* { dg-warning "C" } */
+  printf ("%w8i", i8); /* { dg-warning "C" } */
+  printf ("%w8o", u8); /* { dg-warning "C" } */
+  printf ("%w8x", u8); /* { dg-warning "C" } */
+  printf ("%w8X", u8); /* { dg-warning "C" } */
+  printf ("%w8n", &i8); /* { dg-warning "C" } */
 }
diff --git a/gcc/testsuite/gcc.dg/format/c11-scanf-1.c b/gcc/testsuite/gcc.dg/format/c11-scanf-1.c
index d2b9bfb23b5..4edd2a3183f 100644
--- a/gcc/testsuite/gcc.dg/format/c11-scanf-1.c
+++ b/gcc/testsuite/gcc.dg/format/c11-scanf-1.c
@@ -5,7 +5,33 @@
 #include "format.h"
 
 void
-foo (unsigned int *uip)
+foo (unsigned int *uip, int_least8_t *i8, int_least16_t *i16,
+     int_least32_t *i32, int_least64_t *i64, uint_least8_t *u8,
+     uint_least16_t *u16, uint_least32_t *u32, uint_least64_t *u64,
+     int_fast8_t *if8, int_fast16_t *if16, int_fast32_t *if32,
+     int_fast64_t *if64, uint_fast8_t *uf8, uint_fast16_t *uf16,
+     uint_fast32_t *uf32, uint_fast64_t *uf64)
 {
   scanf ("%b", uip); /* { dg-warning "C" } */
+  scanf ("%w8d", i8); /* { dg-warning "C" } */
+  scanf ("%w16d", i16); /* { dg-warning "C" } */
+  scanf ("%w32d", i32); /* { dg-warning "C" } */
+  scanf ("%w64d", i64); /* { dg-warning "C" } */
+  scanf ("%wf8d", if8); /* { dg-warning "C" } */
+  scanf ("%wf16d", if16); /* { dg-warning "C" } */
+  scanf ("%wf32d", if32); /* { dg-warning "C" } */
+  scanf ("%wf64d", if64); /* { dg-warning "C" } */
+  scanf ("%w8u", u8); /* { dg-warning "C" } */
+  scanf ("%w16u", u16); /* { dg-warning "C" } */
+  scanf ("%w32u", u32); /* { dg-warning "C" } */
+  scanf ("%w64u", u64); /* { dg-warning "C" } */
+  scanf ("%wf8u", uf8); /* { dg-warning "C" } */
+  scanf ("%wf16u", uf16); /* { dg-warning "C" } */
+  scanf ("%wf32u", uf32); /* { dg-warning "C" } */
+  scanf ("%wf64u", uf64); /* { dg-warning "C" } */
+  scanf ("%w8i", i8); /* { dg-warning "C" } */
+  scanf ("%w8o", u8); /* { dg-warning "C" } */
+  scanf ("%w8x", u8); /* { dg-warning "C" } */
+  scanf ("%w8X", u8); /* { dg-warning "C" } */
+  scanf ("%w8n", i8); /* { dg-warning "C" } */
 }
diff --git a/gcc/testsuite/gcc.dg/format/c2x-printf-1.c b/gcc/testsuite/gcc.dg/format/c2x-printf-1.c
index 3ae7713ff05..ca43d7997e5 100644
--- a/gcc/testsuite/gcc.dg/format/c2x-printf-1.c
+++ b/gcc/testsuite/gcc.dg/format/c2x-printf-1.c
@@ -6,7 +6,12 @@
 
 void
 foo (unsigned int u, unsigned short us, unsigned char uc, unsigned long ul,
-     unsigned long long ull, uintmax_t uj, size_t z, unsigned_ptrdiff_t ut)
+     unsigned long long ull, uintmax_t uj, size_t z, unsigned_ptrdiff_t ut,
+     int_least8_t i8, int_least16_t i16, int_least32_t i32, int_least64_t i64,
+     uint_least8_t u8, uint_least16_t u16, uint_least32_t u32,
+     uint_least64_t u64, int_fast8_t if8, int_fast16_t if16, int_fast32_t if32,
+     int_fast64_t if64, uint_fast8_t uf8, uint_fast16_t uf16,
+     uint_fast32_t uf32, uint_fast64_t uf64)
 {
   /* Use of %b with each length modifier and other valid features.  */
   printf ("%b %hb %hhb %lb %llb %jb %zb %tb\n", u, us, uc, ul, ull, uj, z, ut);
@@ -23,4 +28,110 @@ foo (unsigned int u, unsigned short us, unsigned char uc, unsigned long ul,
   /* Use of 'L' and 'q' for long long is an extension.  */
   printf ("%Lb", ull); /* { dg-warning "does not support" } */
   printf ("%qb", ull); /* { dg-warning "does not support" } */
+  /* Use of %wN and %wfN with each valid conversion specifier.  */
+  printf ("%w8d %w16d %w32d %w64d %wf8d %wf16d %wf32d %wf64d",
+	  i8, i16, i32, i64, if8, if16, if32, if64);
+  printf ("%w8i %w16i %w32i %w64i %wf8i %wf16i %wf32i %wf64i",
+	  i8, i16, i32, i64, if8, if16, if32, if64);
+  printf ("%w8b %w16b %w32b %w64b %wf8b %wf16b %wf32b %wf64b",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  printf ("%w8o %w16o %w32o %w64o %wf8o %wf16o %wf32o %wf64o",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  printf ("%w8u %w16u %w32u %w64u %wf8u %wf16u %wf32u %wf64u",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  printf ("%w8x %w16x %w32x %w64x %wf8x %wf16x %wf32x %wf64x",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  printf ("%w8X %w16X %w32X %w64X %wf8X %wf16X %wf32X %wf64X",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  printf ("%w8n %w16n %w32n %w64n %wf8n %wf16n %wf32n %wf64n",
+	  &i8, &i16, &i32, &i64, &if8, &if16, &if32, &if64);
+  /* Use of %wN and %wfN with bad conversion specifiers.  */
+  printf ("%w8a", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16a", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32a", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64a", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8a", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16a", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32a", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64a", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8A", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16A", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32A", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64A", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8A", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16A", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32A", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64A", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8c", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16c", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32c", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64c", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8c", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16c", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32c", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64c", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8e", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16e", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32e", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64e", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8e", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16e", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32e", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64e", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8E", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16E", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32E", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64E", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8E", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16E", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32E", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64E", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8f", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16f", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32f", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64f", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8f", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16f", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32f", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64f", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8F", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16F", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32F", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64F", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8F", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16F", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32F", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64F", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8g", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16g", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32g", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64g", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8g", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16g", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32g", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64g", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8G", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16G", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32G", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64G", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8G", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16G", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32G", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64G", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8p", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16p", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32p", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64p", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8p", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16p", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32p", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64p", if64); /* { dg-warning "length modifier" } */
+  printf ("%w8s", i8); /* { dg-warning "length modifier" } */
+  printf ("%w16s", i16); /* { dg-warning "length modifier" } */
+  printf ("%w32s", i32); /* { dg-warning "length modifier" } */
+  printf ("%w64s", i64); /* { dg-warning "length modifier" } */
+  printf ("%wf8s", if8); /* { dg-warning "length modifier" } */
+  printf ("%wf16s", if16); /* { dg-warning "length modifier" } */
+  printf ("%wf32s", if32); /* { dg-warning "length modifier" } */
+  printf ("%wf64s", if64); /* { dg-warning "length modifier" } */
 }
diff --git a/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c b/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
index f46a7152769..88fab12fbbb 100644
--- a/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
+++ b/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
@@ -7,11 +7,130 @@
 void
 foo (unsigned int *uip, unsigned short int *uhp, unsigned char *uhhp,
      unsigned long int *ulp, unsigned long long *ullp, uintmax_t *ujp,
-     size_t *zp, unsigned_ptrdiff_t *utp)
+     size_t *zp, unsigned_ptrdiff_t *utp, int_least8_t *i8, int_least16_t *i16,
+     int_least32_t *i32, int_least64_t *i64, uint_least8_t *u8,
+     uint_least16_t *u16, uint_least32_t *u32, uint_least64_t *u64,
+     int_fast8_t *if8, int_fast16_t *if16, int_fast32_t *if32,
+     int_fast64_t *if64, uint_fast8_t *uf8, uint_fast16_t *uf16,
+     uint_fast32_t *uf32, uint_fast64_t *uf64)
 {
   scanf ("%*b");
   scanf ("%2b", uip);
   scanf ("%hb%hhb%lb%llb%jb%zb%tb", uhp, uhhp, ulp, ullp, ujp, zp, utp);
   scanf ("%Lb", ullp); /* { dg-warning "does not support" } */
   scanf ("%qb", ullp); /* { dg-warning "does not support" } */
+  /* Use of %wN and %wfN with each valid conversion specifier.  */
+  scanf ("%w8d %w16d %w32d %w64d %wf8d %wf16d %wf32d %wf64d",
+	 i8, i16, i32, i64, if8, if16, if32, if64);
+  scanf ("%w8i %w16i %w32i %w64i %wf8i %wf16i %wf32i %wf64i",
+	 i8, i16, i32, i64, if8, if16, if32, if64);
+  scanf ("%w8b %w16b %w32b %w64b %wf8b %wf16b %wf32b %wf64b",
+	 u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  scanf ("%w8o %w16o %w32o %w64o %wf8o %wf16o %wf32o %wf64o",
+	 u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  scanf ("%w8u %w16u %w32u %w64u %wf8u %wf16u %wf32u %wf64u",
+	 u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  scanf ("%w8x %w16x %w32x %w64x %wf8x %wf16x %wf32x %wf64x",
+	 u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  scanf ("%w8X %w16X %w32X %w64X %wf8X %wf16X %wf32X %wf64X",
+	 u8, u16, u32, u64, uf8, uf16, uf32, uf64);
+  scanf ("%w8n %w16n %w32n %w64n %wf8n %wf16n %wf32n %wf64n",
+	 i8, i16, i32, i64, if8, if16, if32, if64);
+  /* Use of %wN and %wfN with bad conversion specifiers.  */
+  scanf ("%w8a", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16a", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32a", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64a", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8a", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16a", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32a", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64a", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8A", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16A", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32A", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64A", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8A", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16A", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32A", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64A", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8c", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16c", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32c", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64c", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8c", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16c", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32c", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64c", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8e", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16e", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32e", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64e", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8e", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16e", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32e", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64e", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8E", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16E", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32E", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64E", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8E", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16E", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32E", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64E", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8f", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16f", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32f", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64f", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8f", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16f", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32f", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64f", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8F", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16F", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32F", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64F", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8F", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16F", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32F", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64F", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8g", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16g", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32g", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64g", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8g", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16g", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32g", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64g", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8G", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16G", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32G", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64G", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8G", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16G", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32G", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64G", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8p", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16p", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32p", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64p", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8p", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16p", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32p", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64p", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8s", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16s", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32s", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64s", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8s", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16s", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32s", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64s", if64); /* { dg-warning "length modifier" } */
+  scanf ("%w8[abc]", i8); /* { dg-warning "length modifier" } */
+  scanf ("%w16[abc]", i16); /* { dg-warning "length modifier" } */
+  scanf ("%w32[abc]", i32); /* { dg-warning "length modifier" } */
+  scanf ("%w64[abc]", i64); /* { dg-warning "length modifier" } */
+  scanf ("%wf8[abc]", if8); /* { dg-warning "length modifier" } */
+  scanf ("%wf16[abc]", if16); /* { dg-warning "length modifier" } */
+  scanf ("%wf32[abc]", if32); /* { dg-warning "length modifier" } */
+  scanf ("%wf64[abc]", if64); /* { dg-warning "length modifier" } */
 }
diff --git a/gcc/testsuite/gcc.dg/format/ext-9.c b/gcc/testsuite/gcc.dg/format/ext-9.c
index 15f59e21dbe..0aeb365e767 100644
--- a/gcc/testsuite/gcc.dg/format/ext-9.c
+++ b/gcc/testsuite/gcc.dg/format/ext-9.c
@@ -8,7 +8,12 @@
 void
 foo (u_quad_t uq, unsigned int u, unsigned short us, unsigned char uc,
      unsigned long ul, unsigned long long ull, uintmax_t uj, size_t z,
-     unsigned_ptrdiff_t ut)
+     unsigned_ptrdiff_t ut, int_least8_t i8, int_least16_t i16,
+     int_least32_t i32, int_least64_t i64, uint_least8_t u8,
+     uint_least16_t u16, uint_least32_t u32, uint_least64_t u64,
+     int_fast8_t if8, int_fast16_t if16, int_fast32_t if32, int_fast64_t if64,
+     uint_fast8_t uf8, uint_fast16_t uf16, uint_fast32_t uf32,
+     uint_fast64_t uf64)
 {
   /* Deprecated length modifiers with %b and %B.  */
   printf ("%qb%qB", uq, uq);
@@ -26,4 +31,7 @@ foo (u_quad_t uq, unsigned int u, unsigned short us, unsigned char uc,
   /* Flags ignored in certain combinations.  */
   printf ("%-08B\n", u); /* { dg-warning "ignored" } */
   printf ("%08.5B\n", u); /* { dg-warning "ignored" } */
+  /* Use of %wN and %wfN with %B.  */
+  printf ("%w8B %w16B %w32B %w64B %wf8B %wf16B %wf32B %wf64B",
+	  u8, u16, u32, u64, uf8, uf16, uf32, uf64);
 }
diff --git a/gcc/testsuite/gcc.dg/format/format.h b/gcc/testsuite/gcc.dg/format/format.h
index a99927e3c64..2863e7e9827 100644
--- a/gcc/testsuite/gcc.dg/format/format.h
+++ b/gcc/testsuite/gcc.dg/format/format.h
@@ -77,6 +77,24 @@ typedef ullong u_quad_t;
 __extension__ typedef __INTMAX_TYPE__ intmax_t;
 __extension__ typedef __UINTMAX_TYPE__ uintmax_t;
 
+__extension__ typedef __INT_LEAST8_TYPE__ int_least8_t;
+__extension__ typedef __INT_LEAST16_TYPE__ int_least16_t;
+__extension__ typedef __INT_LEAST32_TYPE__ int_least32_t;
+__extension__ typedef __INT_LEAST64_TYPE__ int_least64_t;
+__extension__ typedef __UINT_LEAST8_TYPE__ uint_least8_t;
+__extension__ typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+__extension__ typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+__extension__ typedef __UINT_LEAST64_TYPE__ uint_least64_t;
+
+__extension__ typedef __INT_FAST8_TYPE__ int_fast8_t;
+__extension__ typedef __INT_FAST16_TYPE__ int_fast16_t;
+__extension__ typedef __INT_FAST32_TYPE__ int_fast32_t;
+__extension__ typedef __INT_FAST64_TYPE__ int_fast64_t;
+__extension__ typedef __UINT_FAST8_TYPE__ uint_fast8_t;
+__extension__ typedef __UINT_FAST16_TYPE__ uint_fast16_t;
+__extension__ typedef __UINT_FAST32_TYPE__ uint_fast32_t;
+__extension__ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
+
 #if __STDC_VERSION__ < 199901L && !defined(restrict)
 #define restrict /* "restrict" not in old C standard.  */
 #endif


More information about the Gcc-cvs mailing list