This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Signedness of wchar_t and wint_t leads to problems with gcc -Wsign-conversion
- From: "Michael Kerrisk (man-pages)" <mtk dot manpages at gmail dot com>
- To: "libc-alpha at sourceware dot org" <libc-alpha at sourceware dot org>
- Cc: Igor Liferenko <igor dot liferenko at gmail dot com>, Michael Kerrisk <mtk dot manpages at gmail dot com>
- Date: Mon, 21 Nov 2016 13:24:13 +0100
- Subject: Signedness of wchar_t and wint_t leads to problems with gcc -Wsign-conversion
- Authentication-results: sourceware.org; auth=none
- Reply-to: mtk dot manpages at gmail dot com
I was looking at a Debian bug report[1] that left me puzzled on a
certain point. At the very least, I want to document a solution to the
reporter's (Igor) problem, but I wonder also if there is an
implementation bug.
The issue concerns iwslower() and simialr functions that take a wint_t argument:
int iswlower(wint_t wc);
Suppose that the argument to be passed is a 'wchar_t' (as is common,
AFAIK). If one compiles with
gcc -Wsign-conversion
then the following warning results:
warning: conversion to ‘wint_t {aka unsigned int}’ from ‘wchar_t {aka
int}’ may change the sign of the result [-Wsign-conversion]
What should one do to remove this warning?
There is an analogous situation with islower() and similar functions,
where the solution is described by an update I recently added for the
upcoming man-pages release:
The standards require that the argument c for these functions is
either EOF or a value that is representable in the type unsigned
char. If the argument c is of type char, it must be cast to
unsigned char, as in the following example:
char c;
...
res = toupper((unsigned char) c);
This is necessary because char may be the equivalent of signed
char, in which case a byte where the top bit is set would be sign
extended when converting to int, yielding a value that is outside
the range of unsigned char.
However, we don't have a similar solution for iswlower(), because
there is no "(unsigned wchar_t)" cast. And casting to (wint_t) seems
incorrect to me, because if wchar_t is a signed type smaller than
wint_t, then sign extension could occur. (POSIX allows wint_t and
wchar_t to be either signed or unsigned integer types.)
I could be wrong, but it seems like an implementation bug that one of
these types is signed and the other is unsigned. (My brief inspection
of some other systems suggests that on those systems, wchar_t and
wint_t have the same signedness.)
Anyone have any insights here, or did I miss something obvious?
Cheers,
Michael
[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=845172
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/