On 01/04/2018 01:30 AM, Jakub Jelinek wrote:
On Wed, Jan 03, 2018 at 05:00:41PM -0700, Martin Sebor wrote:
This is an example where having a solution for bug 78014 would
be helpful.  I.e., a -Wformat checker to help enforce the use

No, because %zu isn't portable enough for all the hosts we support.

GCC could mitigate all these portability pitfalls by providing
its own versions of the functions (I suggested gcc_printf the
last time we discussed this subject).  libiberty already does
this for a small subset of the portability problems in some of
the standard functions (including vsprintf), so this would be
a natural extension of that approach.

What we could do is define SIZE_T_PRINT_UNSIGNED and similar macros,
to "%zu" on POSIX compliant targets and something else depending on what we
find out during configure (e.g. using templates to find out if size_t
on the host is unsigned {int,long,long long} or something different
(I hope we don't support msp430 as host where size_t is unsigned __int20).

We could do that, but it would be a far inferior solution to
defining our own printf.  Take another look at what using these
awful macros does to readability:

  fprintf (dump_file, "  Directive %u at offset "
           HOST_WIDE_INT_PRINT_UNSIGNED ": \"%.*s\", "
           "length = " HOST_WIDE_INT_PRINT_UNSIGNED "\n",
           dir.dirno,
           (unsigned HOST_WIDE_INT)(size_t)(dir.beg - info.fmtstr),
           (int)dir.len, dir.beg, dir.len);

With GCC's own fprintf, all this ugliness could go away.  In C++ 11
gcc_fprintf could even be a variadic function template that would
completely obviate the need for length modifiers or even conversion
specifiers.  With it, the above could become as simple as:

  gcc_fprintf (dump_file,
               "  Directive %u at offset %u: \"%.*s\", length = %u \n",
               dir.dirno, dir.beg - info.fmtstr,
               dir.len, dir.beg, dir.len);

regardless of the types of the arguments.

Martin


While in theory GCC could handle some PR78014 cases (but only very early
before any folding) for size_t, HOST_WIDE_INT is a define and I don't see
how GCC could argue about portability there.

of %zu instead of %u or %lu (or an explicit cast from size_t)
even on targets size_t is unsigned or unsigned long, respectively.

        Jakub


Reply via email to