Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Fri, 18 Jan 2013 20:11:33 -0500
From: Rich Felker <>
Subject: Make bits/wchar.h correct for all architectures (bug 15036) (fwd)

Hi all,
I think the same issues apply to musl, and the solution seems very
elegant. Maybe we can apply the same thing. What do you think?


----- Forwarded message from "Joseph S. Myers" <> -----

Comment: DKIM? See
Comment: DomainKeys? See
Date: Fri, 18 Jan 2013 22:41:04 +0000
From: "Joseph S. Myers" <>
Subject: Make bits/wchar.h correct for all architectures (bug 15036)
Message-ID: <>
Mailing-List: contact; run by ezmlm
Delivered-To: mailing list

The standard headers stdint.h and wchar.h define macros WCHAR_MIN and
WCHAR_MAX; they are defined in glibc via bits/wchar.h.  These are the
limits of wchar_t (as an integer type; not necessarily valid character
values) and must have the same type as results from applying the
integer promotions to an object of type wchar_t, as well as being
integer constant expressions usable in #if directives.

The generic bits/wchar.h has definitions that are only correct when
wchar_t is int.  x86, but no other architecture, has its own version
of the header to allow for the type being long rather than int on
32-bit x86.  This leaves the values incorrect when the type is
unsigned int (ARM, AArch64) and the type incorrect but the values
correct when it is long (m68k, hppa, 32-bit powerpc, sh, I think based
on examination of GCC headers).  I've filed by 15036 for this issue.

Since GCC 3.3, a macro __WCHAR_MAX__ has been predefined by GCC, and
since 4.5 a macro __WCHAR_MIN__ has been predefined as well.  These
deal with getting the type and value right in all cases, and so it is
natural to use them in bits/wchar.h when available.

When those predefined macros are not available, it is still possible
to give definitions that are correct for all systems supported by
glibc.  For all such systems, int is 32-bit, and so is wchar_t.  Now
it is possible to determine in the preprocessor whether wchar_t is
signed or unsigned by testing "L'\0' - 1 > 0", and knowing that, we
know what the correct limiting values of 32-bit wchar_t are, and can
ensure the type is correct by adding L'\0'.  This patch implements
such logic to determine the expansions of these macros (using the GCC
macros where available, and logic that's correct for 32-bit int and
wchar_t otherwise), so eliminating the x86-specific version of this

(The construct (L'\0' + 0), rather than just L'\0', for the MIN value
in the unsigned case, is to ensure that for C++ the type is still the
promoted version of wchar_t, rather than wchar_t itself which is a
distinct type in C++.  The reason for (0xffffffffu + L'\0') rather
than just (L'\0' - 1) as the MAX value in the unsigned case is that
(L'\0' - 1) would have the wrong value in preprocessor expressions,
UINTMAX_MAX, because all unsigned types are treated as uintmax_t in
such expressions.)

Tested x86_64 and x86.

2013-01-18  Joseph Myers  <>

	[BZ #15036]
	* bits/wchar.h (__WCHAR_MAX): Define based on __WCHAR_MAX__, or
	based on [L'\0' - 1 > 0] if [!__WCHAR_MAX__].
	(__WCHAR_MIN): Likewise, using __WCHAR_MIN__.
	* sysdeps/unix/sysv/linux/x86/bits/wchar.h: Remove.

diff --git a/bits/wchar.h b/bits/wchar.h
index eb07151..2bbd93c 100644
--- a/bits/wchar.h
+++ b/bits/wchar.h
@@ -19,7 +19,20 @@
 #ifndef _BITS_WCHAR_H
 #define _BITS_WCHAR_H	1
-#define __WCHAR_MIN	(-2147483647 - 1)
-#define __WCHAR_MAX	(2147483647)
+#ifdef __WCHAR_MAX__
+# define __WCHAR_MAX	__WCHAR_MAX__
+#elif L'\0' - 1 > 0
+# define __WCHAR_MAX	(0xffffffffu + L'\0')
+# define __WCHAR_MAX	(0x7fffffff + L'\0')
+#ifdef __WCHAR_MIN__
+# define __WCHAR_MIN	__WCHAR_MIN__
+#elif L'\0' - 1 > 0
+# define __WCHAR_MIN	(L'\0' + 0)
+# define __WCHAR_MIN	(-__WCHAR_MAX - 1)
 #endif	/* bits/wchar.h */
diff --git a/sysdeps/unix/sysv/linux/x86/bits/wchar.h b/sysdeps/unix/sysv/linux/x86/bits/wchar.h
deleted file mode 100644
index 16b8b77..0000000
--- a/sysdeps/unix/sysv/linux/x86/bits/wchar.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* wchar_t type related definitions.  i386/x86-64 version.
-   Copyright (C) 2000-2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   Lesser General Public License for more details.
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <>.  */
-#ifndef _BITS_WCHAR_H
-#define _BITS_WCHAR_H	1
-#include <bits/wordsize.h>
-#if __WORDSIZE == 64
-# define __WCHAR_MIN	(-2147483647 - 1)
-# define __WCHAR_MAX	(2147483647)
-# define __WCHAR_MIN	(-2147483647l - 1l)
-# define __WCHAR_MAX	(2147483647l)
-#endif	/* bits/wchar.h */

Joseph S. Myers

----- End forwarded message -----

Powered by blists - more mailing lists

Your e-mail address:

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.