diff mbox series

Add %[zt][diox] support to pretty-print

Message ID ZcdEsvSrRD7YGymU@tucnak
State New
Headers show
Series Add %[zt][diox] support to pretty-print | expand

Commit Message

Jakub Jelinek Feb. 10, 2024, 9:41 a.m. UTC
Hi!

In the previous patch I haven't touched the gcc diagnostic routines,
using HOST_SIZE_T_PRINT* for those is obviously undesirable because we
want the strings to be translatable.  We already have %w[diox] for
HOST_WIDE_INT arguments, this patch adds t and z modifiers for those.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-02-10  Jakub Jelinek  <jakub@redhat.com>

gcc/
	* pretty-print.cc (pp_integer_with_precision): Handle precision 3 for
	size_t and precision 4 for ptrdiff_t.  Formatting fix.
	(pp_format): Document %{t,z}{d,i,u,o,x}.  Implement t and z modifiers.
	Formatting fixes.
	(test_pp_format): Test t and z modifiers.
	* gcc.cc (read_specs): Use %td instead of %ld and casts to long.
gcc/c-family/
	* c-format.cc (gcc_diag_length_specs): Add t and z modifiers.
	(PP_FORMAT_CHAR_TABLE, gcc_gfc_char_table): Add entries for t and
	z modifiers.
gcc/fortran/
	* error.cc (error_print): Handle z and t modifiers on d, i and u.
	* check.cc (gfc_check_transfer): Use %zd instead of %ld and casts to
	long.
	* primary.cc (gfc_convert_to_structure_constructor): Use %td instead
	of %ld and casts to long.


	Jakub

Comments

Richard Biener Feb. 10, 2024, 9:49 a.m. UTC | #1
> Am 10.02.2024 um 10:41 schrieb Jakub Jelinek <jakub@redhat.com>:
> 
> Hi!
> 
> In the previous patch I haven't touched the gcc diagnostic routines,
> using HOST_SIZE_T_PRINT* for those is obviously undesirable because we
> want the strings to be translatable.  We already have %w[diox] for
> HOST_WIDE_INT arguments, this patch adds t and z modifiers for those.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Thanks,
Richard 


> 2024-02-10  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/
>    * pretty-print.cc (pp_integer_with_precision): Handle precision 3 for
>    size_t and precision 4 for ptrdiff_t.  Formatting fix.
>    (pp_format): Document %{t,z}{d,i,u,o,x}.  Implement t and z modifiers.
>    Formatting fixes.
>    (test_pp_format): Test t and z modifiers.
>    * gcc.cc (read_specs): Use %td instead of %ld and casts to long.
> gcc/c-family/
>    * c-format.cc (gcc_diag_length_specs): Add t and z modifiers.
>    (PP_FORMAT_CHAR_TABLE, gcc_gfc_char_table): Add entries for t and
>    z modifiers.
> gcc/fortran/
>    * error.cc (error_print): Handle z and t modifiers on d, i and u.
>    * check.cc (gfc_check_transfer): Use %zd instead of %ld and casts to
>    long.
>    * primary.cc (gfc_convert_to_structure_constructor): Use %td instead
>    of %ld and casts to long.
> 
> --- gcc/gcc.cc.jj    2024-02-09 14:54:09.141489744 +0100
> +++ gcc/gcc.cc    2024-02-09 22:04:37.655678742 +0100
> @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
>          if (*p1++ != '<' || p[-2] != '>')
>        fatal_error (input_location,
>                 "specs %%include syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p1 - buffer + 1));
> +                 "%td characters", p1 - buffer + 1);
> 
>          p[-2] = '\0';
>          new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
> @@ -2431,8 +2430,7 @@ read_specs (const char *filename, bool m
>          if (*p1++ != '<' || p[-2] != '>')
>        fatal_error (input_location,
>                 "specs %%include syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p1 - buffer + 1));
> +                 "%td characters", p1 - buffer + 1);
> 
>          p[-2] = '\0';
>          new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
> @@ -2458,8 +2456,7 @@ read_specs (const char *filename, bool m
>          if (! ISALPHA ((unsigned char) *p1))
>        fatal_error (input_location,
>                 "specs %%rename syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p1 - buffer));
> +                 "%td characters", p1 - buffer);
> 
>          p2 = p1;
>          while (*p2 && !ISSPACE ((unsigned char) *p2))
> @@ -2468,8 +2465,7 @@ read_specs (const char *filename, bool m
>          if (*p2 != ' ' && *p2 != '\t')
>        fatal_error (input_location,
>                 "specs %%rename syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p2 - buffer));
> +                 "%td characters", p2 - buffer);
> 
>          name_len = p2 - p1;
>          *p2++ = '\0';
> @@ -2479,8 +2475,7 @@ read_specs (const char *filename, bool m
>          if (! ISALPHA ((unsigned char) *p2))
>        fatal_error (input_location,
>                 "specs %%rename syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p2 - buffer));
> +                 "%td characters", p2 - buffer);
> 
>          /* Get new spec name.  */
>          p3 = p2;
> @@ -2490,8 +2485,7 @@ read_specs (const char *filename, bool m
>          if (p3 != p - 1)
>        fatal_error (input_location,
>                 "specs %%rename syntax malformed after "
> -                 "%ld characters",
> -                 (long) (p3 - buffer));
> +                 "%td characters", p3 - buffer);
>          *p3 = '\0';
> 
>          for (sl = specs; sl; sl = sl->next)
> @@ -2530,8 +2524,8 @@ read_specs (const char *filename, bool m
>        }
>      else
>        fatal_error (input_location,
> -             "specs unknown %% command after %ld characters",
> -             (long) (p1 - buffer));
> +             "specs unknown %% command after %td characters",
> +             p1 - buffer);
>    }
> 
>       /* Find the colon that should end the suffix.  */
> @@ -2542,8 +2536,8 @@ read_specs (const char *filename, bool m
>       /* The colon shouldn't be missing.  */
>       if (*p1 != ':')
>    fatal_error (input_location,
> -             "specs file malformed after %ld characters",
> -             (long) (p1 - buffer));
> +             "specs file malformed after %td characters",
> +             p1 - buffer);
> 
>       /* Skip back over trailing whitespace.  */
>       p2 = p1;
> @@ -2556,8 +2550,8 @@ read_specs (const char *filename, bool m
>       p = skip_whitespace (p1 + 1);
>       if (p[1] == 0)
>    fatal_error (input_location,
> -             "specs file malformed after %ld characters",
> -             (long) (p - buffer));
> +             "specs file malformed after %td characters",
> +             p - buffer);
> 
>       p1 = p;
>       /* Find next blank line or end of string.  */
> --- gcc/c-family/c-format.cc.jj    2024-02-09 14:54:08.958492278 +0100
> +++ gcc/c-family/c-format.cc    2024-02-09 22:27:20.021113168 +0100
> @@ -512,6 +512,8 @@ static const format_length_info gcc_diag
> {
>   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
>   { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
> +  { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
> +  { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
>   { NO_FMT, NO_FMT, 0 }
> };
> 
> @@ -758,9 +760,9 @@ static const format_char_info asm_fprint
>    by all pretty_printer instances within GCC.  */
> 
> #define PP_FORMAT_CHAR_TABLE \
> -  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> -  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> -  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
>   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
>   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL }, \
>   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL }, \
> @@ -833,8 +835,8 @@ static const format_char_info gcc_cxxdia
> static const format_char_info gcc_gfc_char_table[] =
> {
>   /* C89 conversion specifiers.  */
> -  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
> -  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
> +  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
> +  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
>   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
>   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
> 
> --- gcc/fortran/error.cc.jj    2024-01-03 12:07:06.006680415 +0100
> +++ gcc/fortran/error.cc    2024-02-09 22:40:33.054339955 +0100
> @@ -536,7 +536,8 @@ error_print (const char *type, const cha
> {
>   enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_UINTEGER,
>     TYPE_LONGINT, TYPE_ULONGINT, TYPE_LLONGINT, TYPE_ULLONGINT,
> -     TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, NOTYPE };
> +     TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, TYPE_SIZE,
> +     TYPE_SSIZE, TYPE_PTRDIFF, NOTYPE };
>   struct
>   {
>     int type;
> @@ -553,6 +554,9 @@ error_print (const char *type, const cha
>       unsigned HOST_WIDE_INT hwuintval;
>       char charval;
>       const char * stringval;
> +      size_t sizeval;
> +      ssize_t ssizeval;
> +      ptrdiff_t ptrdiffval;
>     } u;
>   } arg[MAX_ARGS], spec[MAX_ARGS];
>   /* spec is the array of specifiers, in the same order as they
> @@ -662,6 +666,24 @@ error_print (const char *type, const cha
>          gcc_unreachable ();
>        break;
> 
> +      case 'z':
> +        c = *format++;
> +        if (c == 'u')
> +          arg[pos].type = TYPE_SIZE;
> +        else if (c == 'i' || c == 'd')
> +          arg[pos].type = TYPE_SSIZE;
> +        else
> +          gcc_unreachable ();
> +        break;
> +
> +      case 't':
> +        c = *format++;
> +        if (c == 'u' || c == 'i' || c == 'd')
> +          arg[pos].type = TYPE_PTRDIFF;
> +        else
> +          gcc_unreachable ();
> +        break;
> +
>      case 'c':
>        arg[pos].type = TYPE_CHAR;
>        break;
> @@ -742,6 +764,18 @@ error_print (const char *type, const cha
>        arg[pos].u.hwuintval = va_arg (argp, unsigned HOST_WIDE_INT);
>        break;
> 
> +      case TYPE_SSIZE:
> +        arg[pos].u.ssizeval = va_arg (argp, ssize_t);
> +        break;
> +
> +      case TYPE_SIZE:
> +        arg[pos].u.sizeval = va_arg (argp, size_t);
> +        break;
> +
> +      case TYPE_PTRDIFF:
> +        arg[pos].u.ptrdiffval = va_arg (argp, ptrdiff_t);
> +        break;
> +
>      case TYPE_CHAR:
>        arg[pos].u.charval = (char) va_arg (argp, int);
>        break;
> @@ -839,6 +873,30 @@ error_print (const char *type, const cha
>      else
>        error_hwint (spec[n++].u.hwuintval);
>      break;
> +
> +    case 'z':
> +      format++;
> +      if (*format == 'u')
> +        error_uinteger (spec[n++].u.sizeval);
> +      else
> +        error_integer (spec[n++].u.ssizeval);
> +      break;
> +
> +    case 't':
> +      format++;
> +      if (*format == 'u')
> +        {
> +          ptrdiff_t ptrdiffval = spec[n++].u.ptrdiffval;
> +          if (sizeof (ptrdiff_t) == sizeof (int))
> +        error_uinteger ((unsigned) ptrdiffval);
> +          else if (sizeof (ptrdiff_t) == sizeof (long))
> +        error_uinteger ((unsigned long) ptrdiffval);
> +          else
> +        error_uinteger (ptrdiffval);
> +        }
> +      else
> +        error_integer (spec[n++].u.ptrdiffval);
> +      break;
>    }
>     }
> 
> --- gcc/fortran/primary.cc.jj    2024-02-09 14:54:09.102490284 +0100
> +++ gcc/fortran/primary.cc    2024-02-09 22:04:37.654678756 +0100
> @@ -1190,14 +1190,14 @@ got_delim:
>    {
>      if (istart < 1)
>        {
> -          gfc_error ("Substring start index (%ld) at %L below 1",
> -             (long) istart, &e->ref->u.ss.start->where);
> +          gfc_error ("Substring start index (%td) at %L below 1",
> +             istart, &e->ref->u.ss.start->where);
>          return MATCH_ERROR;
>        }
>      if (iend > (ssize_t) length)
>        {
> -          gfc_error ("Substring end index (%ld) at %L exceeds string "
> -             "length", (long) iend, &e->ref->u.ss.end->where);
> +          gfc_error ("Substring end index (%td) at %L exceeds string "
> +             "length", iend, &e->ref->u.ss.end->where);
>          return MATCH_ERROR;
>        }
>      length = iend - istart + 1;
> @@ -3240,8 +3240,8 @@ gfc_convert_to_structure_constructor (gf
>          if (warn_line_truncation && c < e1)
>        gfc_warning_now (OPT_Wcharacter_truncation,
>                 "CHARACTER expression will be truncated "
> -                 "in constructor (%ld/%ld) at %L", (long int) c,
> -                 (long int) e1, &actual->expr->where);
> +                 "in constructor (%td/%td) at %L", c,
> +                 e1, &actual->expr->where);
>        }
>    }
> 
> --- gcc/fortran/check.cc.jj    2024-02-09 14:54:09.086490505 +0100
> +++ gcc/fortran/check.cc    2024-02-09 22:04:37.653678770 +0100
> @@ -6298,8 +6298,8 @@ gfc_check_transfer (gfc_expr *source, gf
>   if (source_size < result_size)
>     gfc_warning (OPT_Wsurprising,
>         "Intrinsic TRANSFER at %L has partly undefined result: "
> -         "source size %ld < result size %ld", &source->where,
> -         (long) source_size, (long) result_size);
> +         "source size %zd < result size %zd", &source->where,
> +         source_size, result_size);
> 
>   return true;
> }
> --- gcc/pretty-print.cc.jj    2024-02-09 14:54:09.225488581 +0100
> +++ gcc/pretty-print.cc    2024-02-09 22:04:37.652678783 +0100
> @@ -769,7 +769,30 @@ output_buffer::~output_buffer ()
>         break;                                               \
>                                                              \
>       case 2:                                                \
> -        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T));  \
> +        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,          \
> +                   va_arg (ARG, long long T));               \
> +        break;                                               \
> +                                                             \
> +      case 3:                                                \
> +        if (T (-1) < T (0))                                  \
> +          pp_scalar (PP, "%" GCC_PRISZ F,                    \
> +                     (fmt_size_t) va_arg (ARG, ssize_t));    \
> +        else                                                 \
> +          pp_scalar (PP, "%" GCC_PRISZ F,                    \
> +                     (fmt_size_t) va_arg (ARG, size_t));     \
> +        break;                                               \
> +                                                             \
> +      case 4:                                                \
> +        if (sizeof (ptrdiff_t) <= sizeof (int))              \
> +          pp_scalar (PP, "%" F,                              \
> +                     (int) va_arg (ARG, ptrdiff_t));         \
> +        else if (sizeof (ptrdiff_t) <= sizeof (long))        \
> +          pp_scalar (PP, "%l" F,                             \
> +                     (long int) va_arg (ARG, ptrdiff_t));    \
> +        else                                                 \
> +          pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,        \
> +                     (long long int)                         \
> +                     va_arg (ARG, ptrdiff_t));               \
>         break;                                               \
>                                                              \
>       default:                                               \
> @@ -1237,6 +1260,8 @@ on_end_quote (pretty_printer *pp,
>    %ld, %li, %lo, %lu, %lx: long versions of the above.
>    %lld, %lli, %llo, %llu, %llx: long long versions.
>    %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
> +   %zd, %zi, %zo, %zu, %zx: size_t versions.
> +   %td, %ti, %to, %tu, %tx: ptrdiff_t versions.
>    %f: double
>    %c: character.
>    %s: string.
> @@ -1422,7 +1447,7 @@ pp_format (pretty_printer *pp,
>      obstack_1grow (&buffer->chunk_obstack, *p);
>      p++;
>    }
> -      while (strchr ("qwl+#", p[-1]));
> +      while (strchr ("qwlzt+#", p[-1]));
> 
>       if (p[-1] == '.')
>    {
> @@ -1524,6 +1549,16 @@ pp_format (pretty_printer *pp,
>          wide = true;
>          continue;
> 
> +        case 'z':
> +          gcc_assert (!precision);
> +          precision = 3;
> +          continue;
> +
> +        case 't':
> +          gcc_assert (!precision);
> +          precision = 4;
> +          continue;
> +
>        case 'l':
>          /* We don't support precision beyond that of "long long".  */
>          gcc_assert (precision < 2);
> @@ -1570,8 +1605,8 @@ pp_format (pretty_printer *pp,
>      if (wide)
>        pp_wide_integer (pp, va_arg (*text->m_args_ptr, HOST_WIDE_INT));
>      else
> -        pp_integer_with_precision
> -          (pp, *text->m_args_ptr, precision, int, "d");
> +        pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                       int, "d");
>      break;
> 
>    case 'o':
> @@ -1579,8 +1614,8 @@ pp_format (pretty_printer *pp,
>        pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
>               va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>      else
> -        pp_integer_with_precision
> -          (pp, *text->m_args_ptr, precision, unsigned, "o");
> +        pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                       unsigned, "o");
>      break;
> 
>    case 's':
> @@ -1599,8 +1634,8 @@ pp_format (pretty_printer *pp,
>        pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
>               va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>      else
> -        pp_integer_with_precision
> -          (pp, *text->m_args_ptr, precision, unsigned, "u");
> +        pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                       unsigned, "u");
>      break;
> 
>    case 'f':
> @@ -1629,8 +1664,8 @@ pp_format (pretty_printer *pp,
>        pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
>               va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>      else
> -        pp_integer_with_precision
> -          (pp, *text->m_args_ptr, precision, unsigned, "x");
> +        pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                       unsigned, "x");
>      break;
> 
>    case '.':
> @@ -2774,6 +2809,18 @@ test_pp_format ()
>   ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
>   ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
>              0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-27 12345678", "%zd %x", (ssize_t)-27, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-5 12345678", "%zi %x", (ssize_t)-5, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("10 12345678", "%zu %x", (size_t)10, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("17 12345678", "%zo %x", (size_t)15, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%zx %x", (size_t)0xcafebabe,
> +              0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-27 12345678", "%td %x", (ptrdiff_t)-27, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-5 12345678", "%ti %x", (ptrdiff_t)-5, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("10 12345678", "%tu %x", (ptrdiff_t)10, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("17 12345678", "%to %x", (ptrdiff_t)15, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("1afebabe 12345678", "%tx %x", (ptrdiff_t)0x1afebabe,
> +              0x12345678);
>   ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
>   ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
>   ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
> 
>    Jakub
>
Joseph Myers Feb. 12, 2024, 4:10 p.m. UTC | #2
On Sat, 10 Feb 2024, Jakub Jelinek wrote:

> 	* c-format.cc (gcc_diag_length_specs): Add t and z modifiers.
> 	(PP_FORMAT_CHAR_TABLE, gcc_gfc_char_table): Add entries for t and
> 	z modifiers.

Please also add some tests of format checking for these modifiers in 
gcc.dg/format/gcc_*.c.
YunQiang Su May 22, 2024, 9:05 a.m. UTC | #3
Jakub Jelinek <jakub@redhat.com> 于2024年2月10日周六 17:41写道:
>
> Hi!
>
> In the previous patch I haven't touched the gcc diagnostic routines,
> using HOST_SIZE_T_PRINT* for those is obviously undesirable because we
> want the strings to be translatable.  We already have %w[diox] for
> HOST_WIDE_INT arguments, this patch adds t and z modifiers for those.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2024-02-10  Jakub Jelinek  <jakub@redhat.com>
>
> gcc/
>         * pretty-print.cc (pp_integer_with_precision): Handle precision 3 for
>         size_t and precision 4 for ptrdiff_t.  Formatting fix.
>         (pp_format): Document %{t,z}{d,i,u,o,x}.  Implement t and z modifiers.
>         Formatting fixes.
>         (test_pp_format): Test t and z modifiers.
>         * gcc.cc (read_specs): Use %td instead of %ld and casts to long.
> gcc/c-family/
>         * c-format.cc (gcc_diag_length_specs): Add t and z modifiers.
>         (PP_FORMAT_CHAR_TABLE, gcc_gfc_char_table): Add entries for t and
>         z modifiers.
> gcc/fortran/
>         * error.cc (error_print): Handle z and t modifiers on d, i and u.
>         * check.cc (gfc_check_transfer): Use %zd instead of %ld and casts to
>         long.
>         * primary.cc (gfc_convert_to_structure_constructor): Use %td instead
>         of %ld and casts to long.
>
> --- gcc/gcc.cc.jj       2024-02-09 14:54:09.141489744 +0100
> +++ gcc/gcc.cc  2024-02-09 22:04:37.655678742 +0100
> @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
>               if (*p1++ != '<' || p[-2] != '>')
>                 fatal_error (input_location,
>                              "specs %%include syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p1 - buffer + 1));
> +                            "%td characters", p1 - buffer + 1);
>

Should we use %td later for gcc itself? Since we may use older
compiler to build gcc.
My major workstation is Debian Bookworm, which has GCC 12, and then I
get some warnings:

../../gcc/gcc.cc: In function ‘void read_specs(const char*, bool,
bool)’:
../../gcc/gcc.cc:2417:32: warning: unknown conversion type character
‘t’ in format [-Wformat=]
 2417 |                              "%td characters", p1 - buffer +
1);
      |                                ^
../../gcc/gcc.cc:2416:30: warning: too many arguments for format
[-Wformat-extra-args]
 2416 |                              "specs %%include syntax malformed
after "
      |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2417 |                              "%td characters", p1 - buffer + 1);

>               p[-2] = '\0';
>               new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
> @@ -2431,8 +2430,7 @@ read_specs (const char *filename, bool m
>               if (*p1++ != '<' || p[-2] != '>')
>                 fatal_error (input_location,
>                              "specs %%include syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p1 - buffer + 1));
> +                            "%td characters", p1 - buffer + 1);
>
>               p[-2] = '\0';
>               new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
> @@ -2458,8 +2456,7 @@ read_specs (const char *filename, bool m
>               if (! ISALPHA ((unsigned char) *p1))
>                 fatal_error (input_location,
>                              "specs %%rename syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p1 - buffer));
> +                            "%td characters", p1 - buffer);
>
>               p2 = p1;
>               while (*p2 && !ISSPACE ((unsigned char) *p2))
> @@ -2468,8 +2465,7 @@ read_specs (const char *filename, bool m
>               if (*p2 != ' ' && *p2 != '\t')
>                 fatal_error (input_location,
>                              "specs %%rename syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p2 - buffer));
> +                            "%td characters", p2 - buffer);
>
>               name_len = p2 - p1;
>               *p2++ = '\0';
> @@ -2479,8 +2475,7 @@ read_specs (const char *filename, bool m
>               if (! ISALPHA ((unsigned char) *p2))
>                 fatal_error (input_location,
>                              "specs %%rename syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p2 - buffer));
> +                            "%td characters", p2 - buffer);
>
>               /* Get new spec name.  */
>               p3 = p2;
> @@ -2490,8 +2485,7 @@ read_specs (const char *filename, bool m
>               if (p3 != p - 1)
>                 fatal_error (input_location,
>                              "specs %%rename syntax malformed after "
> -                            "%ld characters",
> -                            (long) (p3 - buffer));
> +                            "%td characters", p3 - buffer);
>               *p3 = '\0';
>
>               for (sl = specs; sl; sl = sl->next)
> @@ -2530,8 +2524,8 @@ read_specs (const char *filename, bool m
>             }
>           else
>             fatal_error (input_location,
> -                        "specs unknown %% command after %ld characters",
> -                        (long) (p1 - buffer));
> +                        "specs unknown %% command after %td characters",
> +                        p1 - buffer);
>         }
>
>        /* Find the colon that should end the suffix.  */
> @@ -2542,8 +2536,8 @@ read_specs (const char *filename, bool m
>        /* The colon shouldn't be missing.  */
>        if (*p1 != ':')
>         fatal_error (input_location,
> -                    "specs file malformed after %ld characters",
> -                    (long) (p1 - buffer));
> +                    "specs file malformed after %td characters",
> +                    p1 - buffer);
>
>        /* Skip back over trailing whitespace.  */
>        p2 = p1;
> @@ -2556,8 +2550,8 @@ read_specs (const char *filename, bool m
>        p = skip_whitespace (p1 + 1);
>        if (p[1] == 0)
>         fatal_error (input_location,
> -                    "specs file malformed after %ld characters",
> -                    (long) (p - buffer));
> +                    "specs file malformed after %td characters",
> +                    p - buffer);
>
>        p1 = p;
>        /* Find next blank line or end of string.  */
> --- gcc/c-family/c-format.cc.jj 2024-02-09 14:54:08.958492278 +0100
> +++ gcc/c-family/c-format.cc    2024-02-09 22:27:20.021113168 +0100
> @@ -512,6 +512,8 @@ static const format_length_info gcc_diag
>  {
>    { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
>    { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
> +  { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
> +  { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
>    { NO_FMT, NO_FMT, 0 }
>  };
>
> @@ -758,9 +760,9 @@ static const format_char_info asm_fprint
>     by all pretty_printer instances within GCC.  */
>
>  #define PP_FORMAT_CHAR_TABLE \
> -  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> -  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> -  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
> +  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
>    { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
>    { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL }, \
>    { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL }, \
> @@ -833,8 +835,8 @@ static const format_char_info gcc_cxxdia
>  static const format_char_info gcc_gfc_char_table[] =
>  {
>    /* C89 conversion specifiers.  */
> -  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
> -  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
> +  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
> +  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
>    { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
>    { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
>
> --- gcc/fortran/error.cc.jj     2024-01-03 12:07:06.006680415 +0100
> +++ gcc/fortran/error.cc        2024-02-09 22:40:33.054339955 +0100
> @@ -536,7 +536,8 @@ error_print (const char *type, const cha
>  {
>    enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_UINTEGER,
>          TYPE_LONGINT, TYPE_ULONGINT, TYPE_LLONGINT, TYPE_ULLONGINT,
> -        TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, NOTYPE };
> +        TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, TYPE_SIZE,
> +        TYPE_SSIZE, TYPE_PTRDIFF, NOTYPE };
>    struct
>    {
>      int type;
> @@ -553,6 +554,9 @@ error_print (const char *type, const cha
>        unsigned HOST_WIDE_INT hwuintval;
>        char charval;
>        const char * stringval;
> +      size_t sizeval;
> +      ssize_t ssizeval;
> +      ptrdiff_t ptrdiffval;
>      } u;
>    } arg[MAX_ARGS], spec[MAX_ARGS];
>    /* spec is the array of specifiers, in the same order as they
> @@ -662,6 +666,24 @@ error_print (const char *type, const cha
>               gcc_unreachable ();
>             break;
>
> +         case 'z':
> +           c = *format++;
> +           if (c == 'u')
> +             arg[pos].type = TYPE_SIZE;
> +           else if (c == 'i' || c == 'd')
> +             arg[pos].type = TYPE_SSIZE;
> +           else
> +             gcc_unreachable ();
> +           break;
> +
> +         case 't':
> +           c = *format++;
> +           if (c == 'u' || c == 'i' || c == 'd')
> +             arg[pos].type = TYPE_PTRDIFF;
> +           else
> +             gcc_unreachable ();
> +           break;
> +
>           case 'c':
>             arg[pos].type = TYPE_CHAR;
>             break;
> @@ -742,6 +764,18 @@ error_print (const char *type, const cha
>             arg[pos].u.hwuintval = va_arg (argp, unsigned HOST_WIDE_INT);
>             break;
>
> +         case TYPE_SSIZE:
> +           arg[pos].u.ssizeval = va_arg (argp, ssize_t);
> +           break;
> +
> +         case TYPE_SIZE:
> +           arg[pos].u.sizeval = va_arg (argp, size_t);
> +           break;
> +
> +         case TYPE_PTRDIFF:
> +           arg[pos].u.ptrdiffval = va_arg (argp, ptrdiff_t);
> +           break;
> +
>           case TYPE_CHAR:
>             arg[pos].u.charval = (char) va_arg (argp, int);
>             break;
> @@ -839,6 +873,30 @@ error_print (const char *type, const cha
>           else
>             error_hwint (spec[n++].u.hwuintval);
>           break;
> +
> +       case 'z':
> +         format++;
> +         if (*format == 'u')
> +           error_uinteger (spec[n++].u.sizeval);
> +         else
> +           error_integer (spec[n++].u.ssizeval);
> +         break;
> +
> +       case 't':
> +         format++;
> +         if (*format == 'u')
> +           {
> +             ptrdiff_t ptrdiffval = spec[n++].u.ptrdiffval;
> +             if (sizeof (ptrdiff_t) == sizeof (int))
> +               error_uinteger ((unsigned) ptrdiffval);
> +             else if (sizeof (ptrdiff_t) == sizeof (long))
> +               error_uinteger ((unsigned long) ptrdiffval);
> +             else
> +               error_uinteger (ptrdiffval);
> +           }
> +         else
> +           error_integer (spec[n++].u.ptrdiffval);
> +         break;
>         }
>      }
>
> --- gcc/fortran/primary.cc.jj   2024-02-09 14:54:09.102490284 +0100
> +++ gcc/fortran/primary.cc      2024-02-09 22:04:37.654678756 +0100
> @@ -1190,14 +1190,14 @@ got_delim:
>         {
>           if (istart < 1)
>             {
> -             gfc_error ("Substring start index (%ld) at %L below 1",
> -                        (long) istart, &e->ref->u.ss.start->where);
> +             gfc_error ("Substring start index (%td) at %L below 1",
> +                        istart, &e->ref->u.ss.start->where);
>               return MATCH_ERROR;
>             }
>           if (iend > (ssize_t) length)
>             {
> -             gfc_error ("Substring end index (%ld) at %L exceeds string "
> -                        "length", (long) iend, &e->ref->u.ss.end->where);
> +             gfc_error ("Substring end index (%td) at %L exceeds string "
> +                        "length", iend, &e->ref->u.ss.end->where);
>               return MATCH_ERROR;
>             }
>           length = iend - istart + 1;
> @@ -3240,8 +3240,8 @@ gfc_convert_to_structure_constructor (gf
>               if (warn_line_truncation && c < e1)
>                 gfc_warning_now (OPT_Wcharacter_truncation,
>                                  "CHARACTER expression will be truncated "
> -                                "in constructor (%ld/%ld) at %L", (long int) c,
> -                                (long int) e1, &actual->expr->where);
> +                                "in constructor (%td/%td) at %L", c,
> +                                e1, &actual->expr->where);
>             }
>         }
>
> --- gcc/fortran/check.cc.jj     2024-02-09 14:54:09.086490505 +0100
> +++ gcc/fortran/check.cc        2024-02-09 22:04:37.653678770 +0100
> @@ -6298,8 +6298,8 @@ gfc_check_transfer (gfc_expr *source, gf
>    if (source_size < result_size)
>      gfc_warning (OPT_Wsurprising,
>                  "Intrinsic TRANSFER at %L has partly undefined result: "
> -                "source size %ld < result size %ld", &source->where,
> -                (long) source_size, (long) result_size);
> +                "source size %zd < result size %zd", &source->where,
> +                source_size, result_size);
>
>    return true;
>  }
> --- gcc/pretty-print.cc.jj      2024-02-09 14:54:09.225488581 +0100
> +++ gcc/pretty-print.cc 2024-02-09 22:04:37.652678783 +0100
> @@ -769,7 +769,30 @@ output_buffer::~output_buffer ()
>          break;                                               \
>                                                               \
>        case 2:                                                \
> -        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T));  \
> +        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,          \
> +                   va_arg (ARG, long long T));               \
> +        break;                                               \
> +                                                             \
> +      case 3:                                                \
> +        if (T (-1) < T (0))                                  \
> +          pp_scalar (PP, "%" GCC_PRISZ F,                    \
> +                     (fmt_size_t) va_arg (ARG, ssize_t));    \
> +        else                                                 \
> +          pp_scalar (PP, "%" GCC_PRISZ F,                    \
> +                     (fmt_size_t) va_arg (ARG, size_t));     \
> +        break;                                               \
> +                                                             \
> +      case 4:                                                \
> +        if (sizeof (ptrdiff_t) <= sizeof (int))              \
> +          pp_scalar (PP, "%" F,                              \
> +                     (int) va_arg (ARG, ptrdiff_t));         \
> +        else if (sizeof (ptrdiff_t) <= sizeof (long))        \
> +          pp_scalar (PP, "%l" F,                             \
> +                     (long int) va_arg (ARG, ptrdiff_t));    \
> +        else                                                 \
> +          pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,        \
> +                     (long long int)                         \
> +                     va_arg (ARG, ptrdiff_t));               \
>          break;                                               \
>                                                               \
>        default:                                               \
> @@ -1237,6 +1260,8 @@ on_end_quote (pretty_printer *pp,
>     %ld, %li, %lo, %lu, %lx: long versions of the above.
>     %lld, %lli, %llo, %llu, %llx: long long versions.
>     %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
> +   %zd, %zi, %zo, %zu, %zx: size_t versions.
> +   %td, %ti, %to, %tu, %tx: ptrdiff_t versions.
>     %f: double
>     %c: character.
>     %s: string.
> @@ -1422,7 +1447,7 @@ pp_format (pretty_printer *pp,
>           obstack_1grow (&buffer->chunk_obstack, *p);
>           p++;
>         }
> -      while (strchr ("qwl+#", p[-1]));
> +      while (strchr ("qwlzt+#", p[-1]));
>
>        if (p[-1] == '.')
>         {
> @@ -1524,6 +1549,16 @@ pp_format (pretty_printer *pp,
>               wide = true;
>               continue;
>
> +           case 'z':
> +             gcc_assert (!precision);
> +             precision = 3;
> +             continue;
> +
> +           case 't':
> +             gcc_assert (!precision);
> +             precision = 4;
> +             continue;
> +
>             case 'l':
>               /* We don't support precision beyond that of "long long".  */
>               gcc_assert (precision < 2);
> @@ -1570,8 +1605,8 @@ pp_format (pretty_printer *pp,
>           if (wide)
>             pp_wide_integer (pp, va_arg (*text->m_args_ptr, HOST_WIDE_INT));
>           else
> -           pp_integer_with_precision
> -             (pp, *text->m_args_ptr, precision, int, "d");
> +           pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                                      int, "d");
>           break;
>
>         case 'o':
> @@ -1579,8 +1614,8 @@ pp_format (pretty_printer *pp,
>             pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
>                        va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>           else
> -           pp_integer_with_precision
> -             (pp, *text->m_args_ptr, precision, unsigned, "o");
> +           pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                                      unsigned, "o");
>           break;
>
>         case 's':
> @@ -1599,8 +1634,8 @@ pp_format (pretty_printer *pp,
>             pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
>                        va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>           else
> -           pp_integer_with_precision
> -             (pp, *text->m_args_ptr, precision, unsigned, "u");
> +           pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                                      unsigned, "u");
>           break;
>
>         case 'f':
> @@ -1629,8 +1664,8 @@ pp_format (pretty_printer *pp,
>             pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
>                        va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
>           else
> -           pp_integer_with_precision
> -             (pp, *text->m_args_ptr, precision, unsigned, "x");
> +           pp_integer_with_precision (pp, *text->m_args_ptr, precision,
> +                                      unsigned, "x");
>           break;
>
>         case '.':
> @@ -2774,6 +2809,18 @@ test_pp_format ()
>    ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
>    ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
>                       0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-27 12345678", "%zd %x", (ssize_t)-27, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-5 12345678", "%zi %x", (ssize_t)-5, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("10 12345678", "%zu %x", (size_t)10, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("17 12345678", "%zo %x", (size_t)15, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%zx %x", (size_t)0xcafebabe,
> +                     0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-27 12345678", "%td %x", (ptrdiff_t)-27, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("-5 12345678", "%ti %x", (ptrdiff_t)-5, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("10 12345678", "%tu %x", (ptrdiff_t)10, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("17 12345678", "%to %x", (ptrdiff_t)15, 0x12345678);
> +  ASSERT_PP_FORMAT_2 ("1afebabe 12345678", "%tx %x", (ptrdiff_t)0x1afebabe,
> +                     0x12345678);
>    ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
>    ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
>    ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
>
>         Jakub
>
Jakub Jelinek May 22, 2024, 9:14 a.m. UTC | #4
On Wed, May 22, 2024 at 05:05:30PM +0800, YunQiang Su wrote:
> > --- gcc/gcc.cc.jj       2024-02-09 14:54:09.141489744 +0100
> > +++ gcc/gcc.cc  2024-02-09 22:04:37.655678742 +0100
> > @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
> >               if (*p1++ != '<' || p[-2] != '>')
> >                 fatal_error (input_location,
> >                              "specs %%include syntax malformed after "
> > -                            "%ld characters",
> > -                            (long) (p1 - buffer + 1));
> > +                            "%td characters", p1 - buffer + 1);
> >
> 
> Should we use %td later for gcc itself? Since we may use older
> compiler to build gcc.
> My major workstation is Debian Bookworm, which has GCC 12, and then I
> get some warnings:

That is fine and expected.  During stage1 such warnings are intentionally
not fatal, only in stage2+ when we know it is the same version of gcc
we want those can be fatal.
Otherwise we could never add any new modifies...

	Jakub
YunQiang Su May 22, 2024, 9:23 a.m. UTC | #5
Jakub Jelinek <jakub@redhat.com> 于2024年5月22日周三 17:14写道:
>
> On Wed, May 22, 2024 at 05:05:30PM +0800, YunQiang Su wrote:
> > > --- gcc/gcc.cc.jj       2024-02-09 14:54:09.141489744 +0100
> > > +++ gcc/gcc.cc  2024-02-09 22:04:37.655678742 +0100
> > > @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
> > >               if (*p1++ != '<' || p[-2] != '>')
> > >                 fatal_error (input_location,
> > >                              "specs %%include syntax malformed after "
> > > -                            "%ld characters",
> > > -                            (long) (p1 - buffer + 1));
> > > +                            "%td characters", p1 - buffer + 1);
> > >
> >
> > Should we use %td later for gcc itself? Since we may use older
> > compiler to build gcc.
> > My major workstation is Debian Bookworm, which has GCC 12, and then I
> > get some warnings:
>
> That is fine and expected.  During stage1 such warnings are intentionally
> not fatal, only in stage2+ when we know it is the same version of gcc
> we want those can be fatal.

It may have only 1 stage in some cases.
For example we have a full binutils/libc stack, and just build a cross-gcc.
For all libraries for target, such as libgcc etc, it is OK; while for
host executables
it will be a problem.

> Otherwise we could never add any new modifies...
>
>         Jakub
>
Jakub Jelinek May 22, 2024, 9:33 a.m. UTC | #6
On Wed, May 22, 2024 at 05:23:33PM +0800, YunQiang Su wrote:
> Jakub Jelinek <jakub@redhat.com> 于2024年5月22日周三 17:14写道:
> >
> > On Wed, May 22, 2024 at 05:05:30PM +0800, YunQiang Su wrote:
> > > > --- gcc/gcc.cc.jj       2024-02-09 14:54:09.141489744 +0100
> > > > +++ gcc/gcc.cc  2024-02-09 22:04:37.655678742 +0100
> > > > @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
> > > >               if (*p1++ != '<' || p[-2] != '>')
> > > >                 fatal_error (input_location,
> > > >                              "specs %%include syntax malformed after "
> > > > -                            "%ld characters",
> > > > -                            (long) (p1 - buffer + 1));
> > > > +                            "%td characters", p1 - buffer + 1);
> > > >
> > >
> > > Should we use %td later for gcc itself? Since we may use older
> > > compiler to build gcc.
> > > My major workstation is Debian Bookworm, which has GCC 12, and then I
> > > get some warnings:
> >
> > That is fine and expected.  During stage1 such warnings are intentionally
> > not fatal, only in stage2+ when we know it is the same version of gcc
> > we want those can be fatal.
> 
> It may have only 1 stage in some cases.
> For example we have a full binutils/libc stack, and just build a cross-gcc.
> For all libraries for target, such as libgcc etc, it is OK; while for
> host executables
> it will be a problem.

That is still ok, it is just a warning about unknown gcc format specifiers,
at runtime the code from the compiler being built will be used and that
handles those.  We have added dozens of these over years, %td/%zd certainly
aren't an exception.  Just try to build with some older gcc version, say
4.8.5, and you'll see far more such warnings.
But also as recommended, you shouldn't be building cross-gcc with old
version of gcc, you should use same version of the native compiler to
build the cross compiler.

https://gcc.gnu.org/install/build.html

"To build a cross compiler, we recommend first building and installing a native
compiler. You can then use the native GCC compiler to build the cross
compiler."

	Jakub
YunQiang Su May 22, 2024, 9:43 a.m. UTC | #7
Jakub Jelinek <jakub@redhat.com> 于2024年5月22日周三 17:33写道:
>
> On Wed, May 22, 2024 at 05:23:33PM +0800, YunQiang Su wrote:
> > Jakub Jelinek <jakub@redhat.com> 于2024年5月22日周三 17:14写道:
> > >
> > > On Wed, May 22, 2024 at 05:05:30PM +0800, YunQiang Su wrote:
> > > > > --- gcc/gcc.cc.jj       2024-02-09 14:54:09.141489744 +0100
> > > > > +++ gcc/gcc.cc  2024-02-09 22:04:37.655678742 +0100
> > > > > @@ -2410,8 +2410,7 @@ read_specs (const char *filename, bool m
> > > > >               if (*p1++ != '<' || p[-2] != '>')
> > > > >                 fatal_error (input_location,
> > > > >                              "specs %%include syntax malformed after "
> > > > > -                            "%ld characters",
> > > > > -                            (long) (p1 - buffer + 1));
> > > > > +                            "%td characters", p1 - buffer + 1);
> > > > >
> > > >
> > > > Should we use %td later for gcc itself? Since we may use older
> > > > compiler to build gcc.
> > > > My major workstation is Debian Bookworm, which has GCC 12, and then I
> > > > get some warnings:
> > >
> > > That is fine and expected.  During stage1 such warnings are intentionally
> > > not fatal, only in stage2+ when we know it is the same version of gcc
> > > we want those can be fatal.
> >
> > It may have only 1 stage in some cases.
> > For example we have a full binutils/libc stack, and just build a cross-gcc.
> > For all libraries for target, such as libgcc etc, it is OK; while for
> > host executables
> > it will be a problem.
>
> That is still ok, it is just a warning about unknown gcc format specifiers,
> at runtime the code from the compiler being built will be used and that
> handles those.  We have added dozens of these over years, %td/%zd certainly
> aren't an exception.  Just try to build with some older gcc version, say
> 4.8.5, and you'll see far more such warnings.

Thanks for your explaination. It's OK for me if it can work well at runtime.

> But also as recommended, you shouldn't be building cross-gcc with old
> version of gcc, you should use same version of the native compiler to
> build the cross compiler.
>
> https://gcc.gnu.org/install/build.html
>
> "To build a cross compiler, we recommend first building and installing a native
> compiler. You can then use the native GCC compiler to build the cross
> compiler."
>
>         Jakub
>
diff mbox series

Patch

--- gcc/gcc.cc.jj	2024-02-09 14:54:09.141489744 +0100
+++ gcc/gcc.cc	2024-02-09 22:04:37.655678742 +0100
@@ -2410,8 +2410,7 @@  read_specs (const char *filename, bool m
 	      if (*p1++ != '<' || p[-2] != '>')
 		fatal_error (input_location,
 			     "specs %%include syntax malformed after "
-			     "%ld characters",
-			     (long) (p1 - buffer + 1));
+			     "%td characters", p1 - buffer + 1);
 
 	      p[-2] = '\0';
 	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
@@ -2431,8 +2430,7 @@  read_specs (const char *filename, bool m
 	      if (*p1++ != '<' || p[-2] != '>')
 		fatal_error (input_location,
 			     "specs %%include syntax malformed after "
-			     "%ld characters",
-			     (long) (p1 - buffer + 1));
+			     "%td characters", p1 - buffer + 1);
 
 	      p[-2] = '\0';
 	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
@@ -2458,8 +2456,7 @@  read_specs (const char *filename, bool m
 	      if (! ISALPHA ((unsigned char) *p1))
 		fatal_error (input_location,
 			     "specs %%rename syntax malformed after "
-			     "%ld characters",
-			     (long) (p1 - buffer));
+			     "%td characters", p1 - buffer);
 
 	      p2 = p1;
 	      while (*p2 && !ISSPACE ((unsigned char) *p2))
@@ -2468,8 +2465,7 @@  read_specs (const char *filename, bool m
 	      if (*p2 != ' ' && *p2 != '\t')
 		fatal_error (input_location,
 			     "specs %%rename syntax malformed after "
-			     "%ld characters",
-			     (long) (p2 - buffer));
+			     "%td characters", p2 - buffer);
 
 	      name_len = p2 - p1;
 	      *p2++ = '\0';
@@ -2479,8 +2475,7 @@  read_specs (const char *filename, bool m
 	      if (! ISALPHA ((unsigned char) *p2))
 		fatal_error (input_location,
 			     "specs %%rename syntax malformed after "
-			     "%ld characters",
-			     (long) (p2 - buffer));
+			     "%td characters", p2 - buffer);
 
 	      /* Get new spec name.  */
 	      p3 = p2;
@@ -2490,8 +2485,7 @@  read_specs (const char *filename, bool m
 	      if (p3 != p - 1)
 		fatal_error (input_location,
 			     "specs %%rename syntax malformed after "
-			     "%ld characters",
-			     (long) (p3 - buffer));
+			     "%td characters", p3 - buffer);
 	      *p3 = '\0';
 
 	      for (sl = specs; sl; sl = sl->next)
@@ -2530,8 +2524,8 @@  read_specs (const char *filename, bool m
 	    }
 	  else
 	    fatal_error (input_location,
-			 "specs unknown %% command after %ld characters",
-			 (long) (p1 - buffer));
+			 "specs unknown %% command after %td characters",
+			 p1 - buffer);
 	}
 
       /* Find the colon that should end the suffix.  */
@@ -2542,8 +2536,8 @@  read_specs (const char *filename, bool m
       /* The colon shouldn't be missing.  */
       if (*p1 != ':')
 	fatal_error (input_location,
-		     "specs file malformed after %ld characters",
-		     (long) (p1 - buffer));
+		     "specs file malformed after %td characters",
+		     p1 - buffer);
 
       /* Skip back over trailing whitespace.  */
       p2 = p1;
@@ -2556,8 +2550,8 @@  read_specs (const char *filename, bool m
       p = skip_whitespace (p1 + 1);
       if (p[1] == 0)
 	fatal_error (input_location,
-		     "specs file malformed after %ld characters",
-		     (long) (p - buffer));
+		     "specs file malformed after %td characters",
+		     p - buffer);
 
       p1 = p;
       /* Find next blank line or end of string.  */
--- gcc/c-family/c-format.cc.jj	2024-02-09 14:54:08.958492278 +0100
+++ gcc/c-family/c-format.cc	2024-02-09 22:27:20.021113168 +0100
@@ -512,6 +512,8 @@  static const format_length_info gcc_diag
 {
   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
   { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
+  { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
+  { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
   { NO_FMT, NO_FMT, 0 }
 };
 
@@ -758,9 +760,9 @@  static const format_char_info asm_fprint
    by all pretty_printer instances within GCC.  */
 
 #define PP_FORMAT_CHAR_TABLE \
-  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
-  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
-  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
+  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
+  { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
+  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL }, \
   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL }, \
@@ -833,8 +835,8 @@  static const format_char_info gcc_cxxdia
 static const format_char_info gcc_gfc_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
-  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
+  { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
+  { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  T99_ST,  T99_UPD, BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
 
--- gcc/fortran/error.cc.jj	2024-01-03 12:07:06.006680415 +0100
+++ gcc/fortran/error.cc	2024-02-09 22:40:33.054339955 +0100
@@ -536,7 +536,8 @@  error_print (const char *type, const cha
 {
   enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_UINTEGER,
 	 TYPE_LONGINT, TYPE_ULONGINT, TYPE_LLONGINT, TYPE_ULLONGINT,
-	 TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, NOTYPE };
+	 TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, TYPE_SIZE,
+	 TYPE_SSIZE, TYPE_PTRDIFF, NOTYPE };
   struct
   {
     int type;
@@ -553,6 +554,9 @@  error_print (const char *type, const cha
       unsigned HOST_WIDE_INT hwuintval;
       char charval;
       const char * stringval;
+      size_t sizeval;
+      ssize_t ssizeval;
+      ptrdiff_t ptrdiffval;
     } u;
   } arg[MAX_ARGS], spec[MAX_ARGS];
   /* spec is the array of specifiers, in the same order as they
@@ -662,6 +666,24 @@  error_print (const char *type, const cha
 	      gcc_unreachable ();
 	    break;
 
+	  case 'z':
+	    c = *format++;
+	    if (c == 'u')
+	      arg[pos].type = TYPE_SIZE;
+	    else if (c == 'i' || c == 'd')
+	      arg[pos].type = TYPE_SSIZE;
+	    else
+	      gcc_unreachable ();
+	    break;
+
+	  case 't':
+	    c = *format++;
+	    if (c == 'u' || c == 'i' || c == 'd')
+	      arg[pos].type = TYPE_PTRDIFF;
+	    else
+	      gcc_unreachable ();
+	    break;
+
 	  case 'c':
 	    arg[pos].type = TYPE_CHAR;
 	    break;
@@ -742,6 +764,18 @@  error_print (const char *type, const cha
 	    arg[pos].u.hwuintval = va_arg (argp, unsigned HOST_WIDE_INT);
 	    break;
 
+	  case TYPE_SSIZE:
+	    arg[pos].u.ssizeval = va_arg (argp, ssize_t);
+	    break;
+
+	  case TYPE_SIZE:
+	    arg[pos].u.sizeval = va_arg (argp, size_t);
+	    break;
+
+	  case TYPE_PTRDIFF:
+	    arg[pos].u.ptrdiffval = va_arg (argp, ptrdiff_t);
+	    break;
+
 	  case TYPE_CHAR:
 	    arg[pos].u.charval = (char) va_arg (argp, int);
 	    break;
@@ -839,6 +873,30 @@  error_print (const char *type, const cha
 	  else
 	    error_hwint (spec[n++].u.hwuintval);
 	  break;
+
+	case 'z':
+	  format++;
+	  if (*format == 'u')
+	    error_uinteger (spec[n++].u.sizeval);
+	  else
+	    error_integer (spec[n++].u.ssizeval);
+	  break;
+
+	case 't':
+	  format++;
+	  if (*format == 'u')
+	    {
+	      ptrdiff_t ptrdiffval = spec[n++].u.ptrdiffval;
+	      if (sizeof (ptrdiff_t) == sizeof (int))
+		error_uinteger ((unsigned) ptrdiffval);
+	      else if (sizeof (ptrdiff_t) == sizeof (long))
+		error_uinteger ((unsigned long) ptrdiffval);
+	      else
+		error_uinteger (ptrdiffval);
+	    }
+	  else
+	    error_integer (spec[n++].u.ptrdiffval);
+	  break;
 	}
     }
 
--- gcc/fortran/primary.cc.jj	2024-02-09 14:54:09.102490284 +0100
+++ gcc/fortran/primary.cc	2024-02-09 22:04:37.654678756 +0100
@@ -1190,14 +1190,14 @@  got_delim:
 	{
 	  if (istart < 1)
 	    {
-	      gfc_error ("Substring start index (%ld) at %L below 1",
-			 (long) istart, &e->ref->u.ss.start->where);
+	      gfc_error ("Substring start index (%td) at %L below 1",
+			 istart, &e->ref->u.ss.start->where);
 	      return MATCH_ERROR;
 	    }
 	  if (iend > (ssize_t) length)
 	    {
-	      gfc_error ("Substring end index (%ld) at %L exceeds string "
-			 "length", (long) iend, &e->ref->u.ss.end->where);
+	      gfc_error ("Substring end index (%td) at %L exceeds string "
+			 "length", iend, &e->ref->u.ss.end->where);
 	      return MATCH_ERROR;
 	    }
 	  length = iend - istart + 1;
@@ -3240,8 +3240,8 @@  gfc_convert_to_structure_constructor (gf
 	      if (warn_line_truncation && c < e1)
 		gfc_warning_now (OPT_Wcharacter_truncation,
 				 "CHARACTER expression will be truncated "
-				 "in constructor (%ld/%ld) at %L", (long int) c,
-				 (long int) e1, &actual->expr->where);
+				 "in constructor (%td/%td) at %L", c,
+				 e1, &actual->expr->where);
 	    }
 	}
 
--- gcc/fortran/check.cc.jj	2024-02-09 14:54:09.086490505 +0100
+++ gcc/fortran/check.cc	2024-02-09 22:04:37.653678770 +0100
@@ -6298,8 +6298,8 @@  gfc_check_transfer (gfc_expr *source, gf
   if (source_size < result_size)
     gfc_warning (OPT_Wsurprising,
 		 "Intrinsic TRANSFER at %L has partly undefined result: "
-		 "source size %ld < result size %ld", &source->where,
-		 (long) source_size, (long) result_size);
+		 "source size %zd < result size %zd", &source->where,
+		 source_size, result_size);
 
   return true;
 }
--- gcc/pretty-print.cc.jj	2024-02-09 14:54:09.225488581 +0100
+++ gcc/pretty-print.cc	2024-02-09 22:04:37.652678783 +0100
@@ -769,7 +769,30 @@  output_buffer::~output_buffer ()
         break;                                               \
                                                              \
       case 2:                                                \
-        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T));  \
+        pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,          \
+                   va_arg (ARG, long long T));               \
+        break;                                               \
+                                                             \
+      case 3:                                                \
+        if (T (-1) < T (0))                                  \
+          pp_scalar (PP, "%" GCC_PRISZ F,                    \
+                     (fmt_size_t) va_arg (ARG, ssize_t));    \
+        else                                                 \
+          pp_scalar (PP, "%" GCC_PRISZ F,                    \
+                     (fmt_size_t) va_arg (ARG, size_t));     \
+        break;                                               \
+                                                             \
+      case 4:                                                \
+        if (sizeof (ptrdiff_t) <= sizeof (int))              \
+          pp_scalar (PP, "%" F,                              \
+                     (int) va_arg (ARG, ptrdiff_t));         \
+        else if (sizeof (ptrdiff_t) <= sizeof (long))        \
+          pp_scalar (PP, "%l" F,                             \
+                     (long int) va_arg (ARG, ptrdiff_t));    \
+        else                                                 \
+          pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F,        \
+                     (long long int)                         \
+                     va_arg (ARG, ptrdiff_t));               \
         break;                                               \
                                                              \
       default:                                               \
@@ -1237,6 +1260,8 @@  on_end_quote (pretty_printer *pp,
    %ld, %li, %lo, %lu, %lx: long versions of the above.
    %lld, %lli, %llo, %llu, %llx: long long versions.
    %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
+   %zd, %zi, %zo, %zu, %zx: size_t versions.
+   %td, %ti, %to, %tu, %tx: ptrdiff_t versions.
    %f: double
    %c: character.
    %s: string.
@@ -1422,7 +1447,7 @@  pp_format (pretty_printer *pp,
 	  obstack_1grow (&buffer->chunk_obstack, *p);
 	  p++;
 	}
-      while (strchr ("qwl+#", p[-1]));
+      while (strchr ("qwlzt+#", p[-1]));
 
       if (p[-1] == '.')
 	{
@@ -1524,6 +1549,16 @@  pp_format (pretty_printer *pp,
 	      wide = true;
 	      continue;
 
+	    case 'z':
+	      gcc_assert (!precision);
+	      precision = 3;
+	      continue;
+
+	    case 't':
+	      gcc_assert (!precision);
+	      precision = 4;
+	      continue;
+
 	    case 'l':
 	      /* We don't support precision beyond that of "long long".  */
 	      gcc_assert (precision < 2);
@@ -1570,8 +1605,8 @@  pp_format (pretty_printer *pp,
 	  if (wide)
 	    pp_wide_integer (pp, va_arg (*text->m_args_ptr, HOST_WIDE_INT));
 	  else
-	    pp_integer_with_precision
-	      (pp, *text->m_args_ptr, precision, int, "d");
+	    pp_integer_with_precision (pp, *text->m_args_ptr, precision,
+				       int, "d");
 	  break;
 
 	case 'o':
@@ -1579,8 +1614,8 @@  pp_format (pretty_printer *pp,
 	    pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
 		       va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
 	  else
-	    pp_integer_with_precision
-	      (pp, *text->m_args_ptr, precision, unsigned, "o");
+	    pp_integer_with_precision (pp, *text->m_args_ptr, precision,
+				       unsigned, "o");
 	  break;
 
 	case 's':
@@ -1599,8 +1634,8 @@  pp_format (pretty_printer *pp,
 	    pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
 		       va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
 	  else
-	    pp_integer_with_precision
-	      (pp, *text->m_args_ptr, precision, unsigned, "u");
+	    pp_integer_with_precision (pp, *text->m_args_ptr, precision,
+				       unsigned, "u");
 	  break;
 
 	case 'f':
@@ -1629,8 +1664,8 @@  pp_format (pretty_printer *pp,
 	    pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
 		       va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
 	  else
-	    pp_integer_with_precision
-	      (pp, *text->m_args_ptr, precision, unsigned, "x");
+	    pp_integer_with_precision (pp, *text->m_args_ptr, precision,
+				       unsigned, "x");
 	  break;
 
 	case '.':
@@ -2774,6 +2809,18 @@  test_pp_format ()
   ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
   ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
 		      0x12345678);
+  ASSERT_PP_FORMAT_2 ("-27 12345678", "%zd %x", (ssize_t)-27, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("-5 12345678", "%zi %x", (ssize_t)-5, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("10 12345678", "%zu %x", (size_t)10, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("17 12345678", "%zo %x", (size_t)15, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%zx %x", (size_t)0xcafebabe,
+		      0x12345678);
+  ASSERT_PP_FORMAT_2 ("-27 12345678", "%td %x", (ptrdiff_t)-27, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("-5 12345678", "%ti %x", (ptrdiff_t)-5, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("10 12345678", "%tu %x", (ptrdiff_t)10, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("17 12345678", "%to %x", (ptrdiff_t)15, 0x12345678);
+  ASSERT_PP_FORMAT_2 ("1afebabe 12345678", "%tx %x", (ptrdiff_t)0x1afebabe,
+		      0x12345678);
   ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
   ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
   ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",