[PATCH] Update newlib so that it passes libc++'s tests

JF Bastien jfb@chromium.org
Wed Dec 18 22:25:00 GMT 2013


> A value of 0 as WCHAR_MIN in the unsigned case has the wrong type if
> wchar_t promotes to unsigned int / unsigned long (as opposed to, say, if
> it's unsigned short promoting to signed int).  glibc (2.18 and later) uses
> (L'\0' + 0) (if __WCHAR_MIN__ isn't predefined) in the unsigned case to
> get the correct promoted version of wchar_t, and similar constructs
> involving + L'\0' for WCHAR_MAX to get the right type in those cases as
> well.
>
> In general, you need to make sure these constants have the right type,
> being the promoted version of the type to which the macros refer,
> including int/long differences even when those have the same
> representation and alignment - and, for C++, distinguishing the distinct
> wchar_t type from the type to which it promotes (the latter being the
> right type for such constants) - not just the right value.  In #if
> expressions they need the same value and signedness as in normal C/C++
> code (this means that (L'\0' - 1) is not a correct expression for
> WCHAR_MAX in the unsigned case because in #if expressions it would
> evaluate to UINTMAX_MAX).


Thanks for pointing this out, I wasn't aware of this latest glibc fix.
Here's an updated definition (for both stdint.h and wchar.h). If it
looks good I'll update the patch, assuming the rest of the ongoing
discussion doesn't change this snippet further. To summarize other
discussions, the code first relies on the compiler's own defines
(__WCHAR_{MIN,MAX}__) and stdint.h/wchar.h includes (which could
define WCHAR_{MIN,MAX}) to do the right thing. If that fails then
AFAICT we're stuck with making an educated guess as to what the
"right" value is, and in some cases that guess will necessarily be
wrong because we can't use casts. Newlib's current guess (before my
patch) is 32-bits, so I decided to stick to that and I don't think
going with 16-bits is any better (it's also wrong in some cases, but
now it's also different from what previous newlib versions used to
guess!).

I'm of course open to suggestions here, but I'm not seeing a better
solution and hope someone else sees one.

#ifndef WCHAR_MIN
#ifdef __WCHAR_MIN__
#define WCHAR_MIN __WCHAR_MIN__
#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0)
#define WCHAR_MIN (0 + L'\0')
#else
#define WCHAR_MIN (-0x7fffffff - 1 + L'\0')
#endif
#endif

#ifndef WCHAR_MAX
#ifdef __WCHAR_MAX__
#define WCHAR_MAX __WCHAR_MAX__
#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0)
#define WCHAR_MAX (0xffffffffu + L'\0')
#else
#define WCHAR_MAX (0x7fffffffu + L'\0')
#endif



More information about the Newlib mailing list