[libc++ patch] Make locales (and transitively, std::endl) work reliably with gcc

Nico Weber thakis at chromium.org
Fri May 30 07:04:39 PDT 2014


Hi,

on trunk, libc++ relies on undefined initialization order of global
initializers when using gcc:

1. __start_std_streams in iostream.cpp calls locale::id::_init, which
assigns an id to each locale::facet in an initializer

2. Every facet has a static locale::id id, whose constructor sets the
facet's id to 0*

If 2 runs after 1, it clobbers the facet's assigned consecutive id, causing
exceptions to be thrown when e.g. running code like "cout << endl".

To fix this, the attached patch lets _LIBCPP_CONSTEXPR evaluate to
"constexpr" instead of nothing with gcc. locale::id's constructor is marked
_LIBCPP_CONSTEXPR, which ensures that it won't get an initializer that
could potentially run after the iostream.cpp initializer. (This remains
broken when building with msvc.)

Once _LIBCPP_CONSTEXPR is available, bitset fails to compile since gcc
doesn't define __SIZE_WIDTH__, so switch bitset to use __SIZEOF_SIZE_T__
which both clang and gcc define.

Pair-programmed/debugged with Dana Jansens.

Nico
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140530/c931b350/attachment.html>
-------------- next part --------------
Index: include/__config
===================================================================
--- include/__config	(revision 209887)
+++ include/__config	(working copy)
@@ -368,7 +368,14 @@
 #endif
 
 #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+
+// constexpr was added to GCC in 4.6.
+#if _GNUC_VER < 406
 #define _LIBCPP_HAS_NO_CONSTEXPR
+// Can only use constexpr in c++11 mode.
+#elif !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L
+#define _LIBCPP_HAS_NO_CONSTEXPR
+#endif
 
 #define _NOEXCEPT throw()
 #define _NOEXCEPT_(x)
Index: include/bitset
===================================================================
--- include/bitset	(revision 209887)
+++ include/bitset	(working copy)
@@ -249,9 +249,9 @@
 _LIBCPP_CONSTEXPR
 __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
-#if __SIZE_WIDTH__ == 64
+#if __SIZEOF_SIZE_T__ == 8
     : __first_{__v}
-#elif __SIZE_WIDTH__ == 32
+#elif __SIZEOF_SIZE_T__ == 4
     : __first_{__v, __v >> __bits_per_word}
 #else
 #error This constructor has not been ported to this platform


More information about the cfe-commits mailing list