https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72858

--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
I came across one subtle case that I think might be better handled differently
than the others.

The type of the expected argument to a %lc directive is wint_t, which is
commonly int, but on some targets long int.  When the promoted type of the
argument is int, the hint suggests to replace the %lc directive with %c (even
when int and long are the same size).  The trouble with the suggestion is that
%lc behaves differently than %c in two ways: 1) it first converts the wint_t
argument to wchar_t and then to a multibyte character sequence as if by
wctomb(), and 2) it produces between zero and MB_CUR_MAX bytes while %c exactly
one.  This is rather subtle and might be missed by people maintaining
internationalization code they're not familiar with, leading them to introduce
bugs.  To minimize the risk, I think it might be better to change the hint to
suggest to cast the %lc argument to wint_t instead on the assumption that the
%lc is likely to be correct.  Another option might be to suppress the %lc
-Wformat warning altogether when the argument's type is an integer with the
same precision as wint_t.

$ cat /build/tmp/t.c &&
/build/sysroot/sparc-sun-solaris2.12/bin/sparc-sun-solaris2.12-gcc -S -Wall
-m32 /build/tmp/t.c
void f (int x)
{
  __builtin_printf ("%lc", x);
}
/build/tmp/t.c: In function 'f':
/build/tmp/t.c:3:24: warning: format '%lc' expects argument of type 'wint_t',
but argument 2 has type 'int' [-Wformat=]
   __builtin_printf ("%lc", x);
                      ~~^
                      %c

Reply via email to