diff mbox

vfprintf: Add test case for user-defined types and format specifiers

Message ID a63cc9fe-b07a-3426-c530-46a02230663e@redhat.com
State New
Headers show

Commit Message

Florian Weimer June 29, 2017, 11:34 a.m. UTC
On 06/29/2017 12:51 PM, H.J. Lu wrote:
> On Thu, Jun 29, 2017 at 12:31 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 06/19/2017 03:48 PM, Florian Weimer wrote:
>>> 2017-06-19  Florian Weimer  <fweimer@redhat.com>
>>>
>>>       * stdio-common/tst-vfprintf-user-type.c: New file.
>>>       * stdio-common/Makefile (tests): Add tst-vfprintf-user-type.
>>
>> I am going to commit this soon.
>>
> 
> It fails on i686:
> 
> tst-vfprintf-user-type.c: In function \u2018my_printf_function\u2019:
> tst-vfprintf-user-type.c:58:55: error: format \u2018%c\u2019 expects
> argument of type \u2018int\u2019, but argument 7 has type
> \u2018wchar_t {aka const long int}\u2019 [-Werror=format=]
> tst-vfprintf-user-type.c: In function \u2018my_arginfo_function\u2019:
> tst-vfprintf-user-type.c:112:55: error: format \u2018%c\u2019 expects
> argument of type \u2018int\u2019, but argument 7 has type
> \u2018wchar_t {aka const long int}\u2019 [-Werror=format=]

Please try the attached patch.

The need for the wint_t cast looks like a GCC bug.

Thanks,
Florian

Comments

H.J. Lu June 29, 2017, 12:36 p.m. UTC | #1
On Thu, Jun 29, 2017 at 4:34 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 06/29/2017 12:51 PM, H.J. Lu wrote:
>> On Thu, Jun 29, 2017 at 12:31 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>> On 06/19/2017 03:48 PM, Florian Weimer wrote:
>>>> 2017-06-19  Florian Weimer  <fweimer@redhat.com>
>>>>
>>>>       * stdio-common/tst-vfprintf-user-type.c: New file.
>>>>       * stdio-common/Makefile (tests): Add tst-vfprintf-user-type.
>>>
>>> I am going to commit this soon.
>>>
>>
>> It fails on i686:
>>
>> tst-vfprintf-user-type.c: In function \u2018my_printf_function\u2019:
>> tst-vfprintf-user-type.c:58:55: error: format \u2018%c\u2019 expects
>> argument of type \u2018int\u2019, but argument 7 has type
>> \u2018wchar_t {aka const long int}\u2019 [-Werror=format=]
>> tst-vfprintf-user-type.c: In function \u2018my_arginfo_function\u2019:
>> tst-vfprintf-user-type.c:112:55: error: format \u2018%c\u2019 expects
>> argument of type \u2018int\u2019, but argument 7 has type
>> \u2018wchar_t {aka const long int}\u2019 [-Werror=format=]
>
> Please try the attached patch.
>
> The need for the wint_t cast looks like a GCC bug.
>

Works for me.

Thanks.
Andreas Schwab June 29, 2017, 12:39 p.m. UTC | #2
On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:

> The need for the wint_t cast looks like a GCC bug.

%lc wants wint_t.

Andreas.
Florian Weimer June 29, 2017, 12:42 p.m. UTC | #3
On 06/29/2017 02:39 PM, Andreas Schwab wrote:
> On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:
> 
>> The need for the wint_t cast looks like a GCC bug.
> 
> %lc wants wint_t.

Sure, but why warn about this?  I doubt there are any architectures
which define wchar_t and wint_t in such a way that the variable
arguments promotion diverges.

Thanks,
Florian
Andreas Schwab June 29, 2017, 1:30 p.m. UTC | #4
On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:

> On 06/29/2017 02:39 PM, Andreas Schwab wrote:
>> On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:
>> 
>>> The need for the wint_t cast looks like a GCC bug.
>> 
>> %lc wants wint_t.
>
> Sure, but why warn about this?

Because the standard says so.

> I doubt there are any architectures which define wchar_t and wint_t in
> such a way that the variable arguments promotion diverges.

The standard does not make that distinction.

Andreas.
Joseph Myers June 29, 2017, 2:37 p.m. UTC | #5
On Thu, 29 Jun 2017, Florian Weimer wrote:

> On 06/29/2017 02:39 PM, Andreas Schwab wrote:
> > On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:
> > 
> >> The need for the wint_t cast looks like a GCC bug.
> > 
> > %lc wants wint_t.
> 
> Sure, but why warn about this?  I doubt there are any architectures
> which define wchar_t and wint_t in such a way that the variable
> arguments promotion diverges.

The different signedness can break the ABI, if you pass a negative wchar_t 
(so sign-extended to 64-bit) but the called function expects wint_t 
(zero-extended to 64-bit).  (E.g., the powerpc64 ABI requires such 
zero-extension of an unsigned argument.)
Florian Weimer July 4, 2017, 12:58 p.m. UTC | #6
On 06/29/2017 04:37 PM, Joseph Myers wrote:
> On Thu, 29 Jun 2017, Florian Weimer wrote:
> 
>> On 06/29/2017 02:39 PM, Andreas Schwab wrote:
>>> On Jun 29 2017, Florian Weimer <fweimer@redhat.com> wrote:
>>>
>>>> The need for the wint_t cast looks like a GCC bug.
>>>
>>> %lc wants wint_t.
>>
>> Sure, but why warn about this?  I doubt there are any architectures
>> which define wchar_t and wint_t in such a way that the variable
>> arguments promotion diverges.
> 
> The different signedness can break the ABI, if you pass a negative wchar_t 
> (so sign-extended to 64-bit) but the called function expects wint_t 
> (zero-extended to 64-bit).  (E.g., the powerpc64 ABI requires such 
> zero-extension of an unsigned argument.)

I see.  Based on what is said in the standard, the cast is indeed
required.  That's rather unfortunate from a programmer convenience point
of view.

Florian
diff mbox

Patch

vfprintf: Fix tst-vfprintf-mbs-prec and tst-vfprintf-user-type

2017-06-29  Florian Weimer  <fweimer@redhat.com>

	* stdio-common/tst-vfprintf-user-type.c (my_printf_function):
	Adjust format string.
	* stdio-common/Makefile (tst-vfprintf-mbs-prec.out): Add locale
	dependency.

diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 309d83e..622a85f 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -87,6 +87,7 @@  $(objpfx)tst-grouping.out: $(gen-locales)
 $(objpfx)tst-sprintf.out: $(gen-locales)
 $(objpfx)tst-sscanf.out: $(gen-locales)
 $(objpfx)tst-swprintf.out: $(gen-locales)
+$(objpfx)tst-vfprintf-mbs-prec.out: $(gen-locales)
 endif
 
 tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace
diff --git a/stdio-common/tst-vfprintf-user-type.c b/stdio-common/tst-vfprintf-user-type.c
index e9596c3..91ea02f 100644
--- a/stdio-common/tst-vfprintf-user-type.c
+++ b/stdio-common/tst-vfprintf-user-type.c
@@ -29,6 +29,7 @@ 
 #include <support/check.h>
 #include <support/support.h>
 #include <support/test-driver.h>
+#include <wchar.h>
 
 /* Initialized by do_test using register_printf_type.  */
 static int user_type;
@@ -55,8 +56,9 @@  my_printf_function (FILE *fp, const struct printf_info *info,
                     const void *const *args)
 {
   if (test_verbose > 0)
-    printf ("info: %s (%p, %p, {%p}@%p) called for %%%c (prec %d)\n",
-            __func__, fp, info, args[0], args, info->spec, info->prec);
+    printf ("info: %s (%p, %p, {%p}@%p) called for %%%lc (prec %d)\n",
+            __func__, fp, info, args[0], args, (wint_t) info->spec,
+            info->prec);
 
   TEST_VERIFY (info->spec == 'P');
   size_t nargs;
@@ -109,8 +111,9 @@  my_arginfo_function (const struct printf_info *info,
   if (info->spec != 'P')
     return -1;
   if (test_verbose > 0)
-    printf ("info: %s (%p, %zu, %p, %p) called for %%%c (prec %d)\n",
-            __func__, info, n, argtypes, size, info->spec, info->prec);
+    printf ("info: %s (%p, %zu, %p, %p) called for %%%lc (prec %d)\n",
+            __func__, info, n, argtypes, size, (wint_t) info->spec,
+            info->prec);
 
   TEST_VERIFY_EXIT (n >= 1);
   size_t nargs;