This patch adds support to libstdc++ for the P0482R5 standard library
changes. This includes:
- New char8_t based specializations:
- std::numeric_limits<char8_t>
- std::char_traits<char8_t>
- std::hash<u8string>
- std::hash<pmr::u8string>
- std::hash<u8string_view>
- std::codecvt<char16_t, char8_t, std::mbstate_t>
- std::codecvt<char32_t, char8_t, std::mbstate_t>
- std::codecvt_byname<char16_t,char8_t,mbstate_t>
- std::codecvt_byname<char32_t,char8_t,mbstate_t>
- New char8_t overloads:
- u8string operator "" s(const char8_t* str, size_t len);
- u8string_view operator""sv(const char8_t* str, size_t len);
- New type aliases:
- std::u8string
- std::u8string_view
- std::atomic_char8_t
- Changed function signatures:
- filesystem::path::u8string() returns u8string.
- filesystem::path::generic_u8string() returns u8string.
- typeinfo for char8_t.
- New macros:
- __cpp_lib_char8_t
- ATOMIC_CHAR8_T_LOCK_FREE
For types and templates that existed in an experimental form prior to
standardization, both the experimental and standardized variants have
been updated. The updates to the experimental versions are optional.
I'm not very familiar with how ABI versioning is done and I'm not
confident that the changes in the .ver files are correct. In
particular, I'm unsure as to whether a CXXABI_3.0 section may be needed
in gnu-versioned-namespace.ver and whether I'm correct in adding a new
CXXABI_1.3.12 section in gnu.ver. If I'm not mistaken, CXXABI has not
already been bumped for gcc 9, so needs to be, but GLIBCXX has already
been bumped and therefore does not need to be.
gcc/cp/ChangeLog:
2018-11-04 Tom Honermann <t...@honermann.net>
* name-lookup.c (get_std_name_hint): Added u8string as a name hint.
libstdc++-v3/ChangeLog:
2018-11-04 Tom Honermann <t...@honermann.net>
* config/abi/pre/gnu-versioned-namespace.ver (CXXABI_2.0): Add
typeinfo symbols for char8_t.
* config/abi/pre/gnu.ver: Add CXXABI_1.3.12.
(GLIBCXX_3.4.26): Add symbols for specializations of
numeric_limits and codecvt that involve char8_t.
(CXXABI_1.3.12): Add typeinfo symbols for char8_t.
* include/bits/atomic_base.h: Add atomic_char8_t.
* include/bits/basic_string.h: Add std::hash<u8string> and
operator""s(const char8_t*, size_t).
* include/bits/c++config: Define _GLIBCXX_USE_CHAR8_T and
__cpp_lib_char8_t.
* include/bits/char_traits.h: Add char_traits<char8_t>.
* include/bits/codecvt.h: Add
codecvt<char16_t, char8_t, mbstate_t>,
codecvt<char32_t, char8_t, mbstate_t>,
codecvt_byname<char16_t, char8_t, mbstate_t>, and
codecvt_byname<char32_t, char8_t, mbstate_t>.
* include/bits/cpp_type_traits.h: Add __is_integer<char8_t> to
recognize char8_t as an integral type.
* include/bits/fs_path.h: (path::__is_encoded_char): Recognize
char8_t.
(path::u8string): Return std::u8string when char8_t support is
enabled.
(path::generic_u8string): Likewise.
(path::_S_convert): Handle conversion from char8_t input.
(path::_S_str_convert): Likewise.
* include/bits/functional_hash.h: Add hash<char8_t>.
* include/bits/locale_conv.h (__str_codecvt_out): Add overloads for
char8_t.
* include/bits/locale_facets.h (_GLIBCXX_NUM_UNICODE_FACETS): Bump
for new char8_t specializations.
* include/bits/localefwd.h: Add missing declarations of
codecvt<char16_t, char, mbstate_t> and
codecvt<char32_t, char, mbstate_t>. Add char8_t declarations
codecvt<char16_t, char8_t, mbstate_t> and
codecvt<char32_t, char8_t, mbstate_t>.
* include/bits/postypes.h: Add u8streampos
* include/bits/stringfwd.h: Add declarations of
char_traits<char8_t> and u8string.
* include/c_global/cstddef: Add __byte_operand<char8_t>.
* include/experimental/bits/fs_path.h (path::__is_encoded_char):
Recognize char8_t.
(path::u8string): Return std::u8string when char8_t support is
enabled.
(path::generic_u8string): Likewise.
(path::_S_convert): Handle conversion from char8_t input.
(path::_S_str_convert): Likewise.
* include/experimental/string: Add u8string.
* include/experimental/string_view: Add u8string_view,
hash<experimental::u8string_view>, and
operator""sv(const char8_t*, size_t).
* include/std/atomic: Add atomic<char8_t> and atomic_char8_t.
* include/std/charconv (__is_int_to_chars_type): Recognize char8_t
as a character type.
* include/std/limits: Add numeric_limits<char8_t>.
* include/std/string_view: Add u8string_view,
hash<experimental::u8string_view>, and
operator""sv(const char8_t*, size_t).
* include/std/type_traits: Add __is_integral_helper<char8_t>,
__make_unsigned<char8_t>, and __make_signed<char8_t>.
* libsupc++/atomic_lockfree_defines.h: Define
ATOMIC_CHAR8_T_LOCK_FREE.
* src/c++11/Makefile.am: Compile with -fchar8_t when compiling
codecvt.cc and limits.cc so that char8_t specializations of
numeric_limits and codecvt and emitted.
* src/c++11/Makefile.in: Likewise.
* src/c++11/codecvt.cc: Define members of
codecvt<char16_t, char8_t, mbstate_t>,
codecvt<char32_t, char8_t, mbstate_t>,
codecvt_byname<char16_t, char8_t, mbstate_t>, and
codecvt_byname<char32_t, char8_t, mbstate_t>.
* src/c++11/limits.cc: Define members of
numeric_limits<char8_t>.
* src/c++98/Makefile.am: Compile with -fchar8_t when compiling
locale_init.cc and localename.cc.
* src/c++98/Makefile.in: Likewise.
* src/c++98/locale_init.cc: Add initialization for the
codecvt<char16_t, char8_t, mbstate_t> and
codecvt<char32_t, char8_t, mbstate_t> facets.
* src/c++98/localename.cc: Likewise.
* testsuite/util/testsuite_abi.cc: Validate ABI bump.
Tom.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 08632c382b7..5f2f8e865ca 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5543,6 +5543,7 @@ get_std_name_hint (const char *name)
{"basic_string", "<string>", cxx98},
{"string", "<string>", cxx98},
{"wstring", "<string>", cxx98},
+ {"u8string", "<string>", cxx2a},
{"u16string", "<string>", cxx11},
{"u32string", "<string>", cxx11},
/* <string_view>. */
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index c448b813331..b26cf1dc8ac 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -301,6 +301,11 @@ CXXABI_2.0 {
_ZTSN10__cxxabiv120__si_class_type_infoE;
_ZTSN10__cxxabiv121__vmi_class_type_infoE;
+ # typeinfo for char8_t
+ _ZTIDu;
+ _ZTIPDu;
+ _ZTIPKDu;
+
# typeinfo for char16_t and char32_t
_ZTIDs;
_ZTIPDs;
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index e8cd286ef0c..b24ff3bf9ee 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2055,6 +2055,18 @@ GLIBCXX_3.4.26 {
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4openEPKwSt13_Ios_Openmode;
_ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb;
+
+ # numeric_limits<char8_t>
+ _ZNSt14numeric_limitsIDuE[5-9]*;
+ _ZNSt14numeric_limitsIDuE1[0-7][hirt]*;
+ _ZNSt14numeric_limitsIDuE1[0-7]mi*;
+ _ZNSt14numeric_limitsIDuE1[0-7]max_e*;
+
+ # codecvt<char16_t, char8_t, mbstate_t>, codecvt<char32_t, char8_t, mbstate_t>
+ _ZNKSt7codecvtID[is]Du*;
+ _ZNSt7codecvtID[is]Du*;
+ _ZT[ISV]St7codecvtID[is]Du*E;
+
} GLIBCXX_3.4.25;
# Symbols in the support library (libsupc++) have their own tag.
@@ -2346,6 +2358,15 @@ CXXABI_1.3.11 {
} CXXABI_1.3.10;
+CXXABI_1.3.12 {
+
+ # typeinfo for char8_t
+ _ZTIDu;
+ _ZTIPDu;
+ _ZTIPKDu;
+
+} CXXABI_1.3.11;
+
# Symbols in the support library (libsupc++) supporting transactional memory.
CXXABI_TM_1 {
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 7a3354d9e6f..b3c8440491b 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -227,6 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// atomic_ulong unsigned long
// atomic_llong long long
// atomic_ullong unsigned long long
+ // atomic_char8_t char8_t
// atomic_char16_t char16_t
// atomic_char32_t char32_t
// atomic_wchar_t wchar_t
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index ae6530fcdc9..9a62ed2ddb7 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -6676,6 +6676,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// std::hash specialization for u8string.
+ template<>
+ struct hash<u8string>
+ : public __hash_base<size_t, u8string>
+ {
+ size_t
+ operator()(const u8string& __s) const noexcept
+ { return std::_Hash_impl::hash(__s.data(),
+ __s.length() * sizeof(char8_t)); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<u8string>> : std::false_type
+ { };
+#endif
+
/// std::hash specialization for u16string.
template<>
struct hash<u16string>
@@ -6728,6 +6745,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return basic_string<wchar_t>{__str, __len}; }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ _GLIBCXX_DEFAULT_ABI_TAG
+ inline basic_string<char8_t>
+ operator""s(const char8_t* __str, size_t __len)
+ { return basic_string<char8_t>{__str, __len}; }
+#endif
+
_GLIBCXX_DEFAULT_ABI_TAG
inline basic_string<char16_t>
operator""s(const char16_t* __str, size_t __len)
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index d499d32b51e..3c119704566 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -617,6 +617,17 @@ namespace std
# endif
#endif
+// Unless explicitly specified, enable char8_t extensions only if the core
+// language char8_t feature macro is defined.
+#ifndef _GLIBCXX_USE_CHAR8_T
+# ifdef __cpp_char8_t
+# define _GLIBCXX_USE_CHAR8_T 1
+# endif
+#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+# define __cpp_lib_char8_t 201803
+#endif
+
/* Define if __float128 is supported on this host. */
#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
#define _GLIBCXX_USE_FLOAT128
diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h
index 63e810715f8..c5490ac37ec 100644
--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -492,6 +492,115 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#endif //_GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct char_traits<char8_t>
+ {
+ typedef char8_t char_type;
+ typedef unsigned int int_type;
+ typedef u8streampos pos_type;
+ typedef streamoff off_type;
+ typedef mbstate_t state_type;
+
+ static _GLIBCXX17_CONSTEXPR void
+ assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
+ { __c1 = __c2; }
+
+ static _GLIBCXX_CONSTEXPR bool
+ eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
+ { return __c1 == __c2; }
+
+ static _GLIBCXX_CONSTEXPR bool
+ lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
+ { return __c1 < __c2; }
+
+ static _GLIBCXX17_CONSTEXPR int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n)
+ {
+#if __cplusplus > 201402
+ if (__builtin_constant_p(__n)
+ && __constant_char_array_p(__s1, __n)
+ && __constant_char_array_p(__s2, __n))
+ return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
+#endif
+ if (__n == 0)
+ return 0;
+ return __builtin_memcmp(__s1, __s2, __n);
+ }
+
+ static _GLIBCXX17_CONSTEXPR size_t
+ length(const char_type* __s)
+ {
+#if __cplusplus > 201402
+ if (__constant_string_p(__s))
+ return __gnu_cxx::char_traits<char_type>::length(__s);
+#endif
+ size_t __i = 0;
+ while (!eq(__s[__i], char_type()))
+ ++__i;
+ return __i;
+ }
+
+ static _GLIBCXX17_CONSTEXPR const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ {
+#if __cplusplus > 201402
+ if (__builtin_constant_p(__n)
+ && __builtin_constant_p(__a)
+ && __constant_char_array_p(__s, __n))
+ return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
+#endif
+ if (__n == 0)
+ return 0;
+ return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
+ }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ if (__n == 0)
+ return __s1;
+ return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+ }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ if (__n == 0)
+ return __s1;
+ return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+ }
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ {
+ if (__n == 0)
+ return __s;
+ return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+ }
+
+ static _GLIBCXX_CONSTEXPR char_type
+ to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
+ { return char_type(__c); }
+
+ static _GLIBCXX_CONSTEXPR int_type
+ to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
+ { return int_type(__c); }
+
+ static _GLIBCXX_CONSTEXPR bool
+ eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
+ { return __c1 == __c2; }
+
+ static _GLIBCXX_CONSTEXPR int_type
+ eof() _GLIBCXX_NOEXCEPT
+ { return static_cast<int_type>(-1); }
+
+ static _GLIBCXX_CONSTEXPR int_type
+ not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
+ { return eq_int_type(__c, eof()) ? 0 : __c; }
+ };
+#endif //_GLIBCXX_USE_CHAR8_T
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h
index bafa28c3a00..b99d54af2f9 100644
--- a/libstdc++-v3/include/bits/codecvt.h
+++ b/libstdc++-v3/include/bits/codecvt.h
@@ -573,6 +573,122 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
do_max_length() const throw();
};
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /** @brief Class codecvt<char16_t, char8_t, mbstate_t> specialization.
+ *
+ * Converts between UTF-16 and UTF-8.
+ */
+ template<>
+ class codecvt<char16_t, char8_t, mbstate_t>
+ : public __codecvt_abstract_base<char16_t, char8_t, mbstate_t>
+ {
+ public:
+ // Types:
+ typedef char16_t intern_type;
+ typedef char8_t extern_type;
+ typedef mbstate_t state_type;
+
+ public:
+ static locale::id id;
+
+ explicit
+ codecvt(size_t __refs = 0)
+ : __codecvt_abstract_base<char16_t, char8_t, mbstate_t>(__refs) { }
+
+ protected:
+ virtual
+ ~codecvt();
+
+ virtual result
+ do_out(state_type& __state, const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_unshift(state_type& __state,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_in(state_type& __state,
+ const extern_type* __from, const extern_type* __from_end,
+ const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const;
+
+ virtual
+ int do_encoding() const throw();
+
+ virtual
+ bool do_always_noconv() const throw();
+
+ virtual
+ int do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const;
+
+ virtual int
+ do_max_length() const throw();
+ };
+
+ /** @brief Class codecvt<char32_t, char8_t, mbstate_t> specialization.
+ *
+ * Converts between UTF-32 and UTF-8.
+ */
+ template<>
+ class codecvt<char32_t, char8_t, mbstate_t>
+ : public __codecvt_abstract_base<char32_t, char8_t, mbstate_t>
+ {
+ public:
+ // Types:
+ typedef char32_t intern_type;
+ typedef char8_t extern_type;
+ typedef mbstate_t state_type;
+
+ public:
+ static locale::id id;
+
+ explicit
+ codecvt(size_t __refs = 0)
+ : __codecvt_abstract_base<char32_t, char8_t, mbstate_t>(__refs) { }
+
+ protected:
+ virtual
+ ~codecvt();
+
+ virtual result
+ do_out(state_type& __state, const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_unshift(state_type& __state,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_in(state_type& __state,
+ const extern_type* __from, const extern_type* __from_end,
+ const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const;
+
+ virtual
+ int do_encoding() const throw();
+
+ virtual
+ bool do_always_noconv() const throw();
+
+ virtual
+ int do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const;
+
+ virtual int
+ do_max_length() const throw();
+ };
+#endif // _GLIBCXX_USE_CHAR8_T
+
#endif // C++11
/// class codecvt_byname [22.2.1.6].
@@ -639,6 +755,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
virtual
~codecvt_byname() { }
};
+
+#if defined(_GLIBCXX_USE_CHAR8_T)
+ template<>
+ class codecvt_byname<char16_t, char8_t, mbstate_t>
+ : public codecvt<char16_t, char8_t, mbstate_t>
+ {
+ public:
+ explicit
+ codecvt_byname(const char* __s, size_t __refs = 0)
+ : codecvt<char16_t, char8_t, mbstate_t>(__refs) { }
+
+ explicit
+ codecvt_byname(const string& __s, size_t __refs = 0)
+ : codecvt_byname(__s.c_str(), __refs) { }
+
+ protected:
+ virtual
+ ~codecvt_byname() { }
+ };
+
+ template<>
+ class codecvt_byname<char32_t, char8_t, mbstate_t>
+ : public codecvt<char32_t, char8_t, mbstate_t>
+ {
+ public:
+ explicit
+ codecvt_byname(const char* __s, size_t __refs = 0)
+ : codecvt<char32_t, char8_t, mbstate_t>(__refs) { }
+
+ explicit
+ codecvt_byname(const string& __s, size_t __refs = 0)
+ : codecvt_byname(__s.c_str(), __refs) { }
+
+ protected:
+ virtual
+ ~codecvt_byname() { }
+ };
+#endif
+
#endif // C++11
// Inhibit implicit instantiations for required instantiations,
@@ -669,6 +824,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
extern template class codecvt_byname<char16_t, char, mbstate_t>;
extern template class codecvt_byname<char32_t, char, mbstate_t>;
+
+#if defined(_GLIBCXX_USE_CHAR8_T)
+ extern template class codecvt_byname<char16_t, char8_t, mbstate_t>;
+ extern template class codecvt_byname<char32_t, char8_t, mbstate_t>;
+#endif
+
#endif
#endif
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 960d469f412..f4c655bb848 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -48,7 +48,7 @@
// so function return values won't work: We need compile-time entities.
// We're left with types and constant integral expressions.
// Secondly, from the point of view of ease of use, type-based compile-time
-// information is -not- *that* convenient. On has to write lots of
+// information is -not- *that* convenient. One has to write lots of
// overloaded functions and to hope that the compiler will select the right
// one. As a net effect, the overall structure isn't very clear at first
// glance.
@@ -171,6 +171,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
# endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct __is_integer<char8_t>
+ {
+ enum { __value = 1 };
+ typedef __true_type __type;
+ };
+#endif
+
#if __cplusplus >= 201103L
template<>
struct __is_integer<char16_t>
diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h
index e3938d06d59..af6ac59a968 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -67,8 +67,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
template<typename _CharT, typename _Ch = remove_const_t<_CharT>>
using __is_encoded_char
- = __or_<is_same<_Ch, char>, is_same<_Ch, wchar_t>,
- is_same<_Ch, char16_t>, is_same<_Ch, char32_t>>;
+ = __or_<is_same<_Ch, char>,
+#ifdef _GLIBCXX_USE_CHAR8_T
+ is_same<_Ch, char8_t>,
+#endif
+ is_same<_Ch, wchar_t>,
+ is_same<_Ch, char16_t>,
+ is_same<_Ch, char32_t>>;
template<typename _Iter,
typename _Iter_traits = std::iterator_traits<_Iter>>
@@ -301,7 +306,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if _GLIBCXX_USE_WCHAR_T
std::wstring wstring() const;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ std::u8string u8string() const;
+#else
std::string u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
std::u16string u16string() const;
std::u32string u32string() const;
@@ -315,7 +324,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if _GLIBCXX_USE_WCHAR_T
std::wstring generic_wstring() const;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ std::u8string generic_u8string() const;
+#else
std::string generic_u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
std::u16string generic_u16string() const;
std::u32string generic_u32string() const;
@@ -666,10 +679,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static string_type
_S_convert(const _CharT* __f, const _CharT* __l)
{
- std::codecvt_utf8<_CharT> __cvt;
- std::string __str;
- if (__str_codecvt_out(__f, __l, __str, __cvt))
- return __str;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ if constexpr (is_same_v<_CharT, char8_t>)
+ {
+ string_type __str(__f, __l);
+ return __str;
+ }
+ else
+ {
+#endif
+ std::codecvt_utf8<_CharT> __cvt;
+ std::string __str;
+ if (__str_codecvt_out(__f, __l, __str, __cvt))
+ return __str;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ }
+#endif
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
std::make_error_code(errc::illegal_byte_sequence)));
@@ -850,6 +875,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
if constexpr (is_same_v<_CharT, char>)
return __u8str;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ else if constexpr (is_same_v<_CharT, char8_t>)
+ {
+ const char* __f = __u8str.data();
+ const char* __l = __f + __u8str.size();
+ _WString __wstr(__f, __l);
+ return __wstr;
+ }
+#endif
else
{
_WString __wstr;
@@ -862,10 +896,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
}
#else
- codecvt_utf8<_CharT> __cvt;
- basic_string<_CharT, _Traits, _Allocator> __wstr{__a};
- if (__str_codecvt_in(__first, __last, __wstr, __cvt))
- return __wstr;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ if constexpr (is_same_v<_CharT, char8_t>)
+ {
+ basic_string<_CharT, _Traits, _Allocator> __wstr{__first, __last, __a};
+ return __wstr;
+ }
+ else
+ {
+#endif
+ codecvt_utf8<_CharT> __cvt;
+ basic_string<_CharT, _Traits, _Allocator> __wstr{__a};
+ if (__str_codecvt_in(__first, __last, __wstr, __cvt))
+ return __wstr;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ }
+#endif
#endif
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
@@ -899,6 +945,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path::wstring() const { return string<wchar_t>(); }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline std::u8string
+ path::u8string() const { return string<char8_t>(); }
+#else
inline std::string
path::u8string() const
{
@@ -917,6 +967,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
return _M_pathname;
#endif
}
+#endif // _GLIBCXX_USE_CHAR8_T
inline std::u16string
path::u16string() const { return string<char16_t>(); }
@@ -966,9 +1017,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ return generic_string<wchar_t>(); }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline std::u8string
+ path::generic_u8string() const
+ { return generic_string<char8_t>(); }
+#else
inline std::string
path::generic_u8string() const
{ return generic_string(); }
+#endif
inline std::u16string
path::generic_u16string() const
diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h
index 0f20b956b76..658b9606ea1 100644
--- a/libstdc++-v3/include/bits/functional_hash.h
+++ b/libstdc++-v3/include/bits/functional_hash.h
@@ -135,6 +135,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Explicit specialization for wchar_t.
_Cxx_hashtable_define_trivial_hash(wchar_t)
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// Explicit specialization for char8_t.
+ _Cxx_hashtable_define_trivial_hash(char8_t)
+#endif
+
/// Explicit specialization for char16_t.
_Cxx_hashtable_define_trivial_hash(char16_t)
diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h
index e9b684b4f98..a09898a406f 100644
--- a/libstdc++-v3/include/bits/locale_conv.h
+++ b/libstdc++-v3/include/bits/locale_conv.h
@@ -158,6 +158,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __str_codecvt_out(__first, __last, __outstr, __cvt, __state, __n);
}
+#ifdef _GLIBCXX_USE_CHAR8_T
+
+ // Convert wide character string to narrow.
+ template<typename _CharT, typename _Traits, typename _Alloc, typename _State>
+ inline bool
+ __str_codecvt_out(const _CharT* __first, const _CharT* __last,
+ basic_string<char8_t, _Traits, _Alloc>& __outstr,
+ const codecvt<_CharT, char8_t, _State>& __cvt,
+ _State& __state, size_t& __count)
+ {
+ using _Codecvt = codecvt<_CharT, char8_t, _State>;
+ using _ConvFn
+ = codecvt_base::result
+ (_Codecvt::*)(_State&, const _CharT*, const _CharT*, const _CharT*&,
+ char8_t*, char8_t*, char8_t*&) const;
+ _ConvFn __fn = &codecvt<_CharT, char8_t, _State>::out;
+ return __do_str_codecvt(__first, __last, __outstr, __cvt, __state,
+ __count, __fn);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc, typename _State>
+ inline bool
+ __str_codecvt_out(const _CharT* __first, const _CharT* __last,
+ basic_string<char8_t, _Traits, _Alloc>& __outstr,
+ const codecvt<_CharT, char8_t, _State>& __cvt)
+ {
+ _State __state = {};
+ size_t __n;
+ return __str_codecvt_out(__first, __last, __outstr, __cvt, __state, __n);
+ }
+
+#endif // _GLIBCXX_USE_CHAR8_T
+
#ifdef _GLIBCXX_USE_WCHAR_T
_GLIBCXX_BEGIN_NAMESPACE_CXX11
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index f6e0283fec9..a5f53a3defa 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -59,7 +59,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_NUM_FACETS 14
# define _GLIBCXX_NUM_CXX11_FACETS 8
#endif
-#define _GLIBCXX_NUM_UNICODE_FACETS 2
+#ifdef _GLIBCXX_USE_CHAR8_T
+# define _GLIBCXX_NUM_UNICODE_FACETS 4
+#else
+# define _GLIBCXX_NUM_UNICODE_FACETS 2
+#endif
// Convert string to numeric value of type _Tp and store results.
// NB: This is specialized for all required types, there is no
diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h
index e8690638c7a..e2a725f7ef0 100644
--- a/libstdc++-v3/include/bits/localefwd.h
+++ b/libstdc++-v3/include/bits/localefwd.h
@@ -139,6 +139,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<> class codecvt<char, char, mbstate_t>;
#ifdef _GLIBCXX_USE_WCHAR_T
template<> class codecvt<wchar_t, char, mbstate_t>;
+#endif
+#if __cplusplus >= 201103L
+ template<> class codecvt<char16_t, char, mbstate_t>;
+ template<> class codecvt<char32_t, char, mbstate_t>;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<> class codecvt<char16_t, char8_t, mbstate_t>;
+ template<> class codecvt<char32_t, char8_t, mbstate_t>;
+#endif
#endif
template<typename _InternT, typename _ExternT, typename _StateT>
class codecvt_byname;
diff --git a/libstdc++-v3/include/bits/postypes.h b/libstdc++-v3/include/bits/postypes.h
index 8abdbf02322..89ab9e8d548 100644
--- a/libstdc++-v3/include/bits/postypes.h
+++ b/libstdc++-v3/include/bits/postypes.h
@@ -235,6 +235,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// File position for wchar_t streams.
typedef fpos<mbstate_t> wstreampos;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// File position for char8_t streams.
+ typedef fpos<mbstate_t> u8streampos;
+#endif
+
#if __cplusplus >= 201103L
/// File position for char16_t streams.
typedef fpos<mbstate_t> u16streampos;
diff --git a/libstdc++-v3/include/bits/stringfwd.h b/libstdc++-v3/include/bits/stringfwd.h
index 2b7f4612cbc..98f06f98d6b 100644
--- a/libstdc++-v3/include/bits/stringfwd.h
+++ b/libstdc++-v3/include/bits/stringfwd.h
@@ -58,6 +58,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<> struct char_traits<wchar_t>;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<> struct char_traits<char8_t>;
+#endif
+
#if __cplusplus >= 201103L
template<> struct char_traits<char16_t>;
template<> struct char_traits<char32_t>;
@@ -79,6 +83,11 @@ _GLIBCXX_END_NAMESPACE_CXX11
typedef basic_string<wchar_t> wstring;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// A string of @c char8_t
+ typedef basic_string<char8_t> u8string;
+#endif
+
#if __cplusplus >= 201103L
/// A string of @c char16_t
typedef basic_string<char16_t> u16string;
diff --git a/libstdc++-v3/include/c_global/cstddef b/libstdc++-v3/include/c_global/cstddef
index b6d4a13c0b1..a6002236814 100644
--- a/libstdc++-v3/include/c_global/cstddef
+++ b/libstdc++-v3/include/c_global/cstddef
@@ -75,6 +75,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<> struct __byte_operand<unsigned char> { using __type = byte; };
#ifdef _GLIBCXX_USE_WCHAR_T
template<> struct __byte_operand<wchar_t> { using __type = byte; };
+#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<> struct __byte_operand<char8_t> { using __type = byte; };
#endif
template<> struct __byte_operand<char16_t> { using __type = byte; };
template<> struct __byte_operand<char32_t> { using __type = byte; };
diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h
index 653b4a3fe85..ad346065e28 100644
--- a/libstdc++-v3/include/experimental/bits/fs_path.h
+++ b/libstdc++-v3/include/experimental/bits/fs_path.h
@@ -82,8 +82,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _CharT,
typename _Ch = typename remove_const<_CharT>::type>
using __is_encoded_char
- = __or_<is_same<_Ch, char>, is_same<_Ch, wchar_t>,
- is_same<_Ch, char16_t>, is_same<_Ch, char32_t>>;
+ = __or_<is_same<_Ch, char>,
+ is_same<_Ch, wchar_t>,
+#ifdef _GLIBCXX_USE_CHAR8_T
+ is_same<_Ch, char8_t>,
+#endif
+ is_same<_Ch, char16_t>,
+ is_same<_Ch, char32_t>>;
template<typename _Iter,
typename _Iter_traits = std::iterator_traits<_Iter>>
@@ -323,7 +328,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if _GLIBCXX_USE_WCHAR_T
std::wstring wstring() const;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ std::u8string u8string() const;
+#else
std::string u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
std::u16string u16string() const;
std::u32string u32string() const;
@@ -337,7 +346,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if _GLIBCXX_USE_WCHAR_T
std::wstring generic_wstring() const;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ std::u8string generic_u8string() const;
+#else
std::string generic_u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
std::u16string generic_u16string() const;
std::u32string generic_u32string() const;
@@ -672,10 +685,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static string_type
_S_convert(const _CharT* __f, const _CharT* __l)
{
- std::codecvt_utf8<_CharT> __cvt;
- std::string __str;
- if (__str_codecvt_out(__f, __l, __str, __cvt))
- return __str;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ if constexpr (is_same<_CharT, char8_t>::value)
+ {
+ string_type __str(__f, __l);
+ return __str;
+ }
+ else
+ {
+#endif
+ std::codecvt_utf8<_CharT> __cvt;
+ std::string __str;
+ if (__str_codecvt_out(__f, __l, __str, __cvt))
+ return __str;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ }
+#endif
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
std::make_error_code(errc::illegal_byte_sequence)));
@@ -865,12 +890,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_WString*
operator()(const _String& __from, _WString& __to, false_type)
{
- // use codecvt_utf8<_CharT> to convert UTF-8 to wide string
- codecvt_utf8<_CharT> __cvt;
- const char* __f = __from.data();
- const char* __l = __f + __from.size();
- if (__str_codecvt_in(__f, __l, __to, __cvt))
- return std::__addressof(__to);
+#ifdef _GLIBCXX_USE_CHAR8_T
+ if constexpr (is_same<_CharT, char8_t>::value)
+ {
+ __to.assign(__from.begin(), __from.end());
+ return std::__addressof(__to);
+ }
+ else
+ {
+#endif
+ // use codecvt_utf8<_CharT> to convert UTF-8 to wide string
+ codecvt_utf8<_CharT> __cvt;
+ const char* __f = __from.data();
+ const char* __l = __f + __from.size();
+ if (__str_codecvt_in(__f, __l, __to, __cvt))
+ return std::__addressof(__to);
+#ifdef _GLIBCXX_USE_CHAR8_T
+ }
+#endif
return nullptr;
}
} __dispatch;
@@ -879,10 +916,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
return *__p;
}
#else
- codecvt_utf8<_CharT> __cvt;
- basic_string<_CharT, _Traits, _Allocator> __wstr{__a};
- if (__str_codecvt_in(__first, __last, __wstr, __cvt))
- return __wstr;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ if constexpr (is_same<_CharT, char8_t>::value)
+ {
+ basic_string<_CharT, _Traits, _Allocator> __wstr{__first, __last, __a};
+ return __wstr;
+ }
+ else
+ {
+#endif
+ codecvt_utf8<_CharT> __cvt;
+ basic_string<_CharT, _Traits, _Allocator> __wstr{__a};
+ if (__str_codecvt_in(__first, __last, __wstr, __cvt))
+ return __wstr;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ }
+#endif
#endif
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
@@ -897,6 +946,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path::wstring() const { return string<wchar_t>(); }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline std::u8string
+ path::u8string() const { return string<char8_t>(); }
+#else
inline std::string
path::u8string() const
{
@@ -915,6 +968,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
return _M_pathname;
#endif
}
+#endif // _GLIBCXX_USE_CHAR8_T
inline std::u16string
path::u16string() const { return string<char16_t>(); }
@@ -936,8 +990,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path::generic_wstring() const { return wstring(); }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline std::u8string
+ path::generic_u8string() const { return u8string(); }
+#else
inline std::string
path::generic_u8string() const { return u8string(); }
+#endif
inline std::u16string
path::generic_u16string() const { return u16string(); }
diff --git a/libstdc++-v3/include/experimental/string b/libstdc++-v3/include/experimental/string
index 5a96bf78d73..d1ee5d369b3 100644
--- a/libstdc++-v3/include/experimental/string
+++ b/libstdc++-v3/include/experimental/string
@@ -73,6 +73,9 @@ inline namespace fundamentals_v2
// basic_string typedef names using polymorphic allocator in namespace
// std::experimental::pmr
typedef basic_string<char> string;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ typedef basic_string<char8_t> u8string;
+#endif
typedef basic_string<char16_t> u16string;
typedef basic_string<char32_t> u32string;
typedef basic_string<wchar_t> wstring;
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index b3bc1a9fb4f..0cbdb663cca 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -565,6 +565,9 @@ inline namespace fundamentals_v1
using string_view = basic_string_view<char>;
#ifdef _GLIBCXX_USE_WCHAR_T
using wstring_view = basic_string_view<wchar_t>;
+#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ using u8string_view = basic_string_view<char8_t>;
#endif
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
@@ -605,6 +608,21 @@ inline namespace fundamentals_v1
{ };
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct hash<experimental::u8string_view>
+ : public __hash_base<size_t, experimental::u8string_view>
+ {
+ size_t
+ operator()(const experimental::u8string_view& __s) const noexcept
+ { return std::_Hash_impl::hash(__s.data(), __s.length()); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
+ { };
+#endif
+
template<>
struct hash<experimental::u16string_view>
: public __hash_base<size_t, experimental::u16string_view>
@@ -652,6 +670,12 @@ namespace experimental
{ return basic_string_view<wchar_t>{__str, __len}; }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline constexpr basic_string_view<char8_t>
+ operator""sv(const char8_t* __str, size_t __len) noexcept
+ { return basic_string_view<char8_t>{__str, __len}; }
+#endif
+
inline constexpr basic_string_view<char16_t>
operator""sv(const char16_t* __str, size_t __len) noexcept
{ return basic_string_view<char16_t>{__str, __len}; }
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index 002604676cd..fe0c141fe1f 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -904,6 +904,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
};
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// Explicit specialization for char8_t.
+ template<>
+ struct atomic<char8_t> : __atomic_base<char8_t>
+ {
+ typedef char8_t __integral_type;
+ typedef __atomic_base<char8_t> __base_type;
+
+ atomic() noexcept = default;
+ ~atomic() noexcept = default;
+ atomic(const atomic&) = delete;
+ atomic& operator=(const atomic&) = delete;
+ atomic& operator=(const atomic&) volatile = delete;
+
+ constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
+
+ using __base_type::operator __integral_type;
+ using __base_type::operator=;
+
+#if __cplusplus > 201402L
+ static constexpr bool is_always_lock_free = ATOMIC_CHAR8_T_LOCK_FREE == 2;
+#endif
+ };
+#endif
+
/// Explicit specialization for char16_t.
template<>
struct atomic<char16_t> : __atomic_base<char16_t>
@@ -990,6 +1015,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// atomic_wchar_t
typedef atomic<wchar_t> atomic_wchar_t;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// atomic_char8_t
+ typedef atomic<char8_t> atomic_char8_t;
+#endif
+
/// atomic_char16_t
typedef atomic<char16_t> atomic_char16_t;
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv
index 922c2c7e25e..852e8b2b696 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -66,6 +66,9 @@ namespace __detail
__not_<__is_one_of<_Tp, bool, char16_t, char32_t
#if _GLIBCXX_USE_WCHAR_T
, wchar_t
+#endif
+#if _GLIBCXX_USE_CHAR8_T
+ , char8_t
#endif
>>>;
diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits
index e8eb6a1e0c4..0bf635e7b92 100644
--- a/libstdc++-v3/include/std/limits
+++ b/libstdc++-v3/include/std/limits
@@ -374,6 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Now there follow 16 explicit specializations. Yes, 16. Make sure
// you get the count right. (18 in C++11 mode, with char16_t and char32_t.)
+ // (+1 if char8_t is enabled.)
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 184. numeric_limits<bool> wording problems
@@ -725,6 +726,69 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= round_toward_zero;
};
+#if _GLIBCXX_USE_CHAR8_T
+ /// numeric_limits<char8_t> specialization.
+ template<>
+ struct numeric_limits<char8_t>
+ {
+ static constexpr bool is_specialized = true;
+
+ static constexpr char8_t
+ min() noexcept { return __glibcxx_min (char8_t); }
+
+ static constexpr char8_t
+ max() noexcept { return __glibcxx_max (char8_t); }
+
+ static constexpr char8_t
+ lowest() noexcept { return min(); }
+
+ static constexpr int digits = __glibcxx_digits (char8_t);
+ static constexpr int digits10 = __glibcxx_digits10 (char8_t);
+ static constexpr int max_digits10 = 0;
+ static constexpr bool is_signed = __glibcxx_signed (char8_t);
+ static constexpr bool is_integer = true;
+ static constexpr bool is_exact = true;
+ static constexpr int radix = 2;
+
+ static constexpr char8_t
+ epsilon() noexcept { return 0; }
+
+ static constexpr char8_t
+ round_error() noexcept { return 0; }
+
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr bool has_denorm_loss = false;
+
+ static constexpr char8_t
+ infinity() noexcept { return char8_t(); }
+
+ static constexpr char8_t
+ quiet_NaN() noexcept { return char8_t(); }
+
+ static constexpr char8_t
+ signaling_NaN() noexcept { return char8_t(); }
+
+ static constexpr char8_t
+ denorm_min() noexcept { return char8_t(); }
+
+ static constexpr bool is_iec559 = false;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = !is_signed;
+
+ static constexpr bool traps = __glibcxx_integral_traps;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_round_style round_style = round_toward_zero;
+ };
+#endif
+
#if __cplusplus >= 201103L
/// numeric_limits<char16_t> specialization.
template<>
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index dd60df2ba6e..7fd29cc163a 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -62,6 +62,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using basic_string = std::basic_string<_CharT, _Traits,
polymorphic_allocator<_CharT>>;
using string = basic_string<char>;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ using u8string = basic_string<char8_t>;
+#endif
using u16string = basic_string<char16_t>;
using u32string = basic_string<char32_t>;
#ifdef _GLIBCXX_USE_WCHAR_T
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 9e0f6a723e4..b7ee0a586f5 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -555,7 +555,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_USE_WCHAR_T
using wstring_view = basic_string_view<wchar_t>;
#endif
-
+#ifdef _GLIBCXX_USE_CHAR8_T
+ using u8string_view = basic_string_view<char8_t>;
+#endif
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
@@ -593,6 +595,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct hash<u8string_view>
+ : public __hash_base<size_t, u8string_view>
+ {
+ size_t
+ operator()(const u8string_view& __str) const noexcept
+ { return std::_Hash_impl::hash(__str.data(), __str.length()); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<u8string_view>> : std::false_type
+ { };
+#endif
+
template<>
struct hash<u16string_view>
: public __hash_base<size_t, u16string_view>
@@ -637,6 +654,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return basic_string_view<wchar_t>{__str, __len}; }
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ inline constexpr basic_string_view<char8_t>
+ operator""sv(const char8_t* __str, size_t __len) noexcept
+ { return basic_string_view<char8_t>{__str, __len}; }
+#endif
+
inline constexpr basic_string_view<char16_t>
operator""sv(const char16_t* __str, size_t __len) noexcept
{ return basic_string_view<char16_t>{__str, __len}; }
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 86b58ccf225..5a1c2c0e08a 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -234,6 +234,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public true_type { };
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct __is_integral_helper<char8_t>
+ : public true_type { };
+#endif
+
template<>
struct __is_integral_helper<char16_t>
: public true_type { };
@@ -1673,8 +1679,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type;
};
- // wchar_t, char16_t and char32_t are integral types but are neither
- // signed integer types nor unsigned integer types, so must be
+ // wchar_t, char8_t, char16_t and char32_t are integral types but are
+ // neither signed integer types nor unsigned integer types, so must be
// transformed to the unsigned integer type with the smallest rank.
// Use the partial specialization for enumeration types to do that.
#if defined(_GLIBCXX_USE_WCHAR_T)
@@ -1686,6 +1692,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<>
+ struct __make_unsigned<char8_t>
+ {
+ using __type
+ = typename __make_unsigned_selector<char8_t, false, true>::__type;
+ };
+#endif
+
template<>
struct __make_unsigned<char16_t>
{
@@ -1803,6 +1818,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#endif
+#if defined(_GLIBCXX_USE_CHAR8_T)
+ template<>
+ struct __make_signed<char8_t>
+ {
+ using __type
+ = typename __make_signed_selector<char8_t, false, true>::__type;
+ };
+#endif
+
template<>
struct __make_signed<char16_t>
{
diff --git a/libstdc++-v3/libsupc++/atomic_lockfree_defines.h b/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
index 2afa6dffb96..6da15823244 100644
--- a/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
+++ b/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
@@ -49,6 +49,9 @@
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#ifdef _GLIBCXX_USE_CHAR8_T
+#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE
+#endif
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am
index a22258782cb..d926e172973 100644
--- a/libstdc++-v3/src/c++11/Makefile.am
+++ b/libstdc++-v3/src/c++11/Makefile.am
@@ -126,6 +126,16 @@ hashtable_c++0x.lo: hashtable_c++0x.cc
hashtable_c++0x.o: hashtable_c++0x.cc
$(CXXCOMPILE) -fimplicit-templates -c $<
+# Use special rules for source files that require -fchar8_t.
+codecvt.lo: codecvt.cc
+ $(LTCXXCOMPILE) -fchar8_t -c $<
+codecvt.o: codecvt.cc
+ $(CXXCOMPILE) -fchar8_t -c $<
+limits.lo: limits.cc
+ $(LTCXXCOMPILE) -fchar8_t -c $<
+limits.o: limits.cc
+ $(CXXCOMPILE) -fchar8_t -c $<
+
if ENABLE_DUAL_ABI
# Rewrite the type info for __ios_failure.
rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,/_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/'
diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in
index d4c4b72a1ae..cec5bfad8ee 100644
--- a/libstdc++-v3/src/c++11/Makefile.in
+++ b/libstdc++-v3/src/c++11/Makefile.in
@@ -751,6 +751,16 @@ hashtable_c++0x.lo: hashtable_c++0x.cc
hashtable_c++0x.o: hashtable_c++0x.cc
$(CXXCOMPILE) -fimplicit-templates -c $<
+# Use special rules for source files that require -fchar8_t.
+codecvt.lo: codecvt.cc
+ $(LTCXXCOMPILE) -fchar8_t -c $<
+codecvt.o: codecvt.cc
+ $(CXXCOMPILE) -fchar8_t -c $<
+limits.lo: limits.cc
+ $(LTCXXCOMPILE) -fchar8_t -c $<
+limits.o: limits.cc
+ $(CXXCOMPILE) -fchar8_t -c $<
+
@ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure-lt.s: cxx11-ios_failure.cc
@ENABLE_DUAL_ABI_TRUE@ $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s
@ENABLE_DUAL_ABI_TRUE@ -test -f tmp-cxx11-ios_failure-lt.o && mv -f tmp-cxx11-ios_failure-lt.o tmp-cxx11-ios_failure-lt.s
diff --git a/libstdc++-v3/src/c++11/codecvt.cc b/libstdc++-v3/src/c++11/codecvt.cc
index 503f2fe1ff3..fc9fd427ee5 100644
--- a/libstdc++-v3/src/c++11/codecvt.cc
+++ b/libstdc++-v3/src/c++11/codecvt.cc
@@ -193,8 +193,9 @@ namespace
}
// If generate_header is set in mode write out UTF-8 BOM.
+ template<typename C>
bool
- write_utf8_bom(range<char>& to, codecvt_mode mode)
+ write_utf8_bom(range<C>& to, codecvt_mode mode)
{
if (mode & generate_header)
return write_bom(to, utf8_bom);
@@ -218,8 +219,9 @@ namespace
}
// If consume_header is set in mode update from.next to after any BOM.
+ template<typename C>
void
- read_utf8_bom(range<const char>& from, codecvt_mode mode)
+ read_utf8_bom(range<const C>& from, codecvt_mode mode)
{
if (mode & consume_header)
read_bom(from, utf8_bom);
@@ -245,8 +247,9 @@ namespace
// Read a codepoint from a UTF-8 multibyte sequence.
// Updates from.next if the codepoint is not greater than maxcode.
// Returns invalid_mb_sequence, incomplete_mb_character or the code point.
+ template<typename C>
char32_t
- read_utf8_code_point(range<const char>& from, unsigned long maxcode)
+ read_utf8_code_point(range<const C>& from, unsigned long maxcode)
{
const size_t avail = from.size();
if (avail == 0)
@@ -315,8 +318,9 @@ namespace
return invalid_mb_sequence;
}
+ template<typename C>
bool
- write_utf8_code_point(range<char>& to, char32_t code_point)
+ write_utf8_code_point(range<C>& to, char32_t code_point)
{
if (code_point < 0x80)
{
@@ -445,8 +449,9 @@ namespace
}
// utf8 -> ucs4
+ template<typename C>
codecvt_base::result
- ucs4_in(range<const char>& from, range<char32_t>& to,
+ ucs4_in(range<const C>& from, range<char32_t>& to,
unsigned long maxcode = max_code_point, codecvt_mode mode = {})
{
read_utf8_bom(from, mode);
@@ -463,8 +468,9 @@ namespace
}
// ucs4 -> utf8
+ template<typename C>
codecvt_base::result
- ucs4_out(range<const char32_t>& from, range<char>& to,
+ ucs4_out(range<const char32_t>& from, range<C>& to,
unsigned long maxcode = max_code_point, codecvt_mode mode = {})
{
if (!write_utf8_bom(to, mode))
@@ -522,9 +528,9 @@ namespace
enum class surrogates { allowed, disallowed };
// utf8 -> utf16 (or utf8 -> ucs2 if s == surrogates::disallowed)
- template<typename C>
+ template<typename C8, typename C16>
codecvt_base::result
- utf16_in(range<const char>& from, range<C>& to,
+ utf16_in(range<const C8>& from, range<C16>& to,
unsigned long maxcode = max_code_point, codecvt_mode mode = {},
surrogates s = surrogates::allowed)
{
@@ -552,9 +558,9 @@ namespace
}
// utf16 -> utf8 (or ucs2 -> utf8 if s == surrogates::disallowed)
- template<typename C>
+ template<typename C16, typename C8>
codecvt_base::result
- utf16_out(range<const C>& from, range<char>& to,
+ utf16_out(range<const C16>& from, range<C8>& to,
unsigned long maxcode = max_code_point, codecvt_mode mode = {},
surrogates s = surrogates::allowed)
{
@@ -593,11 +599,12 @@ namespace
}
// return pos such that [begin,pos) is valid UTF-16 string no longer than max
- const char*
- utf16_span(const char* begin, const char* end, size_t max,
+ template<typename C>
+ const C*
+ utf16_span(const C* begin, const C* end, size_t max,
char32_t maxcode = max_code_point, codecvt_mode mode = {})
{
- range<const char> from{ begin, end };
+ range<const C> from{ begin, end };
read_utf8_bom(from, mode);
size_t count = 0;
while (count+1 < max)
@@ -615,8 +622,9 @@ namespace
}
// utf8 -> ucs2
+ template<typename C>
codecvt_base::result
- ucs2_in(range<const char>& from, range<char16_t>& to,
+ ucs2_in(range<const C>& from, range<char16_t>& to,
char32_t maxcode = max_code_point, codecvt_mode mode = {})
{
// UCS-2 only supports characters in the BMP, i.e. one UTF-16 code unit:
@@ -625,8 +633,9 @@ namespace
}
// ucs2 -> utf8
+ template<typename C>
codecvt_base::result
- ucs2_out(range<const char16_t>& from, range<char>& to,
+ ucs2_out(range<const char16_t>& from, range<C>& to,
char32_t maxcode = max_code_point, codecvt_mode mode = {})
{
// UCS-2 only supports characters in the BMP, i.e. one UTF-16 code unit:
@@ -687,11 +696,12 @@ namespace
return reinterpret_cast<const char16_t*>(from.next);
}
- const char*
- ucs2_span(const char* begin, const char* end, size_t max,
+ template<typename C>
+ const C*
+ ucs2_span(const C* begin, const C* end, size_t max,
char32_t maxcode, codecvt_mode mode)
{
- range<const char> from{ begin, end };
+ range<const C> from{ begin, end };
read_utf8_bom(from, mode);
// UCS-2 only supports characters in the BMP, i.e. one UTF-16 code unit:
maxcode = std::min(max_single_utf16_unit, maxcode);
@@ -702,11 +712,12 @@ namespace
}
// return pos such that [begin,pos) is valid UCS-4 string no longer than max
- const char*
- ucs4_span(const char* begin, const char* end, size_t max,
+ template<typename C>
+ const C*
+ ucs4_span(const C* begin, const C* end, size_t max,
char32_t maxcode = max_code_point, codecvt_mode mode = {})
{
- range<const char> from{ begin, end };
+ range<const C> from{ begin, end };
read_utf8_bom(from, mode);
char32_t c = 0;
while (max-- && c <= maxcode)
@@ -875,6 +886,156 @@ codecvt<char32_t, char, mbstate_t>::do_max_length() const throw()
return 4;
}
+#if defined(_GLIBCXX_USE_CHAR8_T)
+// Define members of codecvt<char16_t, char8_t, mbstate_t> specialization.
+// Converts from UTF-8 to UTF-16.
+
+locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
+
+codecvt<char16_t, char8_t, mbstate_t>::~codecvt() { }
+
+codecvt_base::result
+codecvt<char16_t, char8_t, mbstate_t>::
+do_out(state_type&,
+ const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const
+{
+ range<const char16_t> from{ __from, __from_end };
+ range<char8_t> to{ __to, __to_end };
+ auto res = utf16_out(from, to);
+ __from_next = from.next;
+ __to_next = to.next;
+ return res;
+}
+
+codecvt_base::result
+codecvt<char16_t, char8_t, mbstate_t>::
+do_unshift(state_type&, extern_type* __to, extern_type*,
+ extern_type*& __to_next) const
+{
+ __to_next = __to;
+ return noconv; // we don't use mbstate_t for the unicode facets
+}
+
+codecvt_base::result
+codecvt<char16_t, char8_t, mbstate_t>::
+do_in(state_type&, const extern_type* __from, const extern_type* __from_end,
+ const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const
+{
+ range<const char8_t> from{ __from, __from_end };
+ range<char16_t> to{ __to, __to_end };
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ codecvt_mode mode = {};
+#else
+ codecvt_mode mode = little_endian;
+#endif
+ auto res = utf16_in(from, to, max_code_point, mode);
+ __from_next = from.next;
+ __to_next = to.next;
+ return res;
+}
+
+int
+codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const throw()
+{ return 0; } // UTF-8 is not a fixed-width encoding
+
+bool
+codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const throw()
+{ return false; }
+
+int
+codecvt<char16_t, char8_t, mbstate_t>::
+do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const
+{
+ __end = utf16_span(__from, __end, __max);
+ return __end - __from;
+}
+
+int
+codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const throw()
+{
+ // A single character (one or two UTF-16 code units) requires
+ // up to four UTF-8 code units.
+ return 4;
+}
+
+// Define members of codecvt<char32_t, char8_t, mbstate_t> specialization.
+// Converts from UTF-8 to UTF-32 (aka UCS-4).
+
+locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
+
+codecvt<char32_t, char8_t, mbstate_t>::~codecvt() { }
+
+codecvt_base::result
+codecvt<char32_t, char8_t, mbstate_t>::
+do_out(state_type&, const intern_type* __from, const intern_type* __from_end,
+ const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const
+{
+ range<const char32_t> from{ __from, __from_end };
+ range<char8_t> to{ __to, __to_end };
+ auto res = ucs4_out(from, to);
+ __from_next = from.next;
+ __to_next = to.next;
+ return res;
+}
+
+codecvt_base::result
+codecvt<char32_t, char8_t, mbstate_t>::
+do_unshift(state_type&, extern_type* __to, extern_type*,
+ extern_type*& __to_next) const
+{
+ __to_next = __to;
+ return noconv;
+}
+
+codecvt_base::result
+codecvt<char32_t, char8_t, mbstate_t>::
+do_in(state_type&, const extern_type* __from, const extern_type* __from_end,
+ const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const
+{
+ range<const char8_t> from{ __from, __from_end };
+ range<char32_t> to{ __to, __to_end };
+ auto res = ucs4_in(from, to);
+ __from_next = from.next;
+ __to_next = to.next;
+ return res;
+}
+
+int
+codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const throw()
+{ return 0; } // UTF-8 is not a fixed-width encoding
+
+bool
+codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const throw()
+{ return false; }
+
+int
+codecvt<char32_t, char8_t, mbstate_t>::
+do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const
+{
+ __end = ucs4_span(__from, __end, __max);
+ return __end - __from;
+}
+
+int
+codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const throw()
+{
+ // A single character (one UTF-32 code unit) requires
+ // up to 4 UTF-8 code units.
+ return 4;
+}
+#endif // _GLIBCXX_USE_CHAR8_T
+
// Define members of codecvt_utf8<char16_t> base class implementation.
// Converts from UTF-8 to UCS-2.
@@ -1636,5 +1797,12 @@ inline template class __codecvt_abstract_base<char32_t, char, mbstate_t>;
template class codecvt_byname<char16_t, char, mbstate_t>;
template class codecvt_byname<char32_t, char, mbstate_t>;
+#if defined(_GLIBCXX_USE_CHAR8_T)
+inline template class __codecvt_abstract_base<char16_t, char8_t, mbstate_t>;
+inline template class __codecvt_abstract_base<char32_t, char8_t, mbstate_t>;
+template class codecvt_byname<char16_t, char8_t, mbstate_t>;
+template class codecvt_byname<char32_t, char8_t, mbstate_t>;
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
}
diff --git a/libstdc++-v3/src/c++11/limits.cc b/libstdc++-v3/src/c++11/limits.cc
index 4d7889f2021..cfb3e5b027e 100644
--- a/libstdc++-v3/src/c++11/limits.cc
+++ b/libstdc++-v3/src/c++11/limits.cc
@@ -525,6 +525,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const bool numeric_limits<long double>::tinyness_before;
const float_round_style numeric_limits<long double>::round_style;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ // char8_t
+ const bool numeric_limits<char8_t>::is_specialized;
+ const int numeric_limits<char8_t>::digits;
+ const int numeric_limits<char8_t>::digits10;
+ const int numeric_limits<char8_t>::max_digits10;
+ const bool numeric_limits<char8_t>::is_signed;
+ const bool numeric_limits<char8_t>::is_integer;
+ const bool numeric_limits<char8_t>::is_exact;
+ const int numeric_limits<char8_t>::radix;
+ const int numeric_limits<char8_t>::min_exponent;
+ const int numeric_limits<char8_t>::min_exponent10;
+ const int numeric_limits<char8_t>::max_exponent;
+ const int numeric_limits<char8_t>::max_exponent10;
+ const bool numeric_limits<char8_t>::has_infinity;
+ const bool numeric_limits<char8_t>::has_quiet_NaN;
+ const bool numeric_limits<char8_t>::has_signaling_NaN;
+ const float_denorm_style numeric_limits<char8_t>::has_denorm;
+ const bool numeric_limits<char8_t>::has_denorm_loss;
+ const bool numeric_limits<char8_t>::is_iec559;
+ const bool numeric_limits<char8_t>::is_bounded;
+ const bool numeric_limits<char8_t>::is_modulo;
+ const bool numeric_limits<char8_t>::traps;
+ const bool numeric_limits<char8_t>::tinyness_before;
+ const float_round_style numeric_limits<char8_t>::round_style;
+#endif // _GLIBCXX_USE_CHAR8_T
+
// char16_t
const bool numeric_limits<char16_t>::is_specialized;
const int numeric_limits<char16_t>::digits;
diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am
index bceaa5b0f40..3545ebbac1b 100644
--- a/libstdc++-v3/src/c++98/Makefile.am
+++ b/libstdc++-v3/src/c++98/Makefile.am
@@ -184,13 +184,13 @@ endif
# XXX TODO move locale_init.cc and localename.cc to src/c++11
locale_init.lo: locale_init.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
locale_init.o: locale_init.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
localename.lo: localename.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
localename.o: localename.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
# Use special rules for the deprecated source files so that they find
# deprecated include files.
diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in
index 33f2ac0f87a..53c8592a6cd 100644
--- a/libstdc++-v3/src/c++98/Makefile.in
+++ b/libstdc++-v3/src/c++98/Makefile.in
@@ -805,13 +805,13 @@ c++locale.o: c++locale.cc
# XXX TODO move locale_init.cc and localename.cc to src/c++11
locale_init.lo: locale_init.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
locale_init.o: locale_init.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
localename.lo: localename.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
localename.o: localename.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $<
strstream.lo: strstream.cc
$(LTCXXCOMPILE) -I$(GLIBCXX_INCLUDE_DIR)/backward -Wno-deprecated -c $<
strstream.o: strstream.cc
diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
index b580a9f9d58..edf4ca8fd8e 100644
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ b/libstdc++-v3/src/c++98/locale_init.cc
@@ -209,6 +209,16 @@ namespace
__attribute__ ((aligned(__alignof__(codecvt<char32_t, char, mbstate_t>))));
fake_codecvt_c32 codecvt_c32;
+#ifdef _GLIBCXX_USE_CHAR8_T
+ typedef char fake_codecvt_c16_c8[sizeof(codecvt<char16_t, char8_t, mbstate_t>)]
+ __attribute__ ((aligned(__alignof__(codecvt<char16_t, char8_t, mbstate_t>))));
+ fake_codecvt_c16_c8 codecvt_c16_c8;
+
+ typedef char fake_codecvt_c32_c8[sizeof(codecvt<char32_t, char8_t, mbstate_t>)]
+ __attribute__ ((aligned(__alignof__(codecvt<char32_t, char8_t, mbstate_t>))));
+ fake_codecvt_c32_c8 codecvt_c32_c8;
+#endif
+
// Storage for "C" locale caches.
typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)]
__attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
@@ -329,6 +339,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _GLIBCXX_NUM_UNICODE_FACETS != 0
&codecvt<char16_t, char, mbstate_t>::id,
&codecvt<char32_t, char, mbstate_t>::id,
+#ifdef _GLIBCXX_USE_CHAR8_T
+ &codecvt<char16_t, char8_t, mbstate_t>::id,
+ &codecvt<char32_t, char8_t, mbstate_t>::id,
+#endif
#endif
0
};
@@ -536,6 +550,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _GLIBCXX_NUM_UNICODE_FACETS != 0
_M_init_facet(new (&codecvt_c16) codecvt<char16_t, char, mbstate_t>(1));
_M_init_facet(new (&codecvt_c32) codecvt<char32_t, char, mbstate_t>(1));
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ _M_init_facet(new (&codecvt_c16_c8) codecvt<char16_t, char8_t, mbstate_t>(1));
+ _M_init_facet(new (&codecvt_c32_c8) codecvt<char32_t, char8_t, mbstate_t>(1));
+#endif
+
#endif
#if _GLIBCXX_USE_DUAL_ABI
diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc
index afb43e5cea9..aa66ae207a3 100644
--- a/libstdc++-v3/src/c++98/localename.cc
+++ b/libstdc++-v3/src/c++98/localename.cc
@@ -272,6 +272,12 @@ const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
#if _GLIBCXX_NUM_UNICODE_FACETS != 0
_M_init_facet(new codecvt<char16_t, char, mbstate_t>);
_M_init_facet(new codecvt<char32_t, char, mbstate_t>);
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ _M_init_facet(new codecvt<char16_t, char8_t, mbstate_t>);
+ _M_init_facet(new codecvt<char32_t, char8_t, mbstate_t>);
+#endif
+
#endif
#if _GLIBCXX_USE_DUAL_ABI
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index c9aaf74133f..f45bcf46fac 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -220,6 +220,7 @@ check_version(symbol& test, bool added)
known_versions.push_back("CXXABI_1.3.9");
known_versions.push_back("CXXABI_1.3.10");
known_versions.push_back("CXXABI_1.3.11");
+ known_versions.push_back("CXXABI_1.3.12");
known_versions.push_back("CXXABI_TM_1");
known_versions.push_back("CXXABI_FLOAT128");
}
@@ -238,7 +239,7 @@ check_version(symbol& test, bool added)
// Check that added symbols are added in the latest pre-release version.
bool latestp = (test.version_name == "GLIBCXX_3.4.26"
- || test.version_name == "CXXABI_1.3.11"
+ || test.version_name == "CXXABI_1.3.12"
|| test.version_name == "CXXABI_FLOAT128"
|| test.version_name == "CXXABI_TM_1");
if (added && !latestp)