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

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

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

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.
  

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",