P0482R5 char8_t: Standard library support
authorTom Honermann <tom@honermann.net>
Tue, 19 Feb 2019 02:54:42 +0000 (02:54 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 19 Feb 2019 02:54:42 +0000 (02:54 +0000)
gcc/cp:

2019-02-19  Tom Honermann  <tom@honermann.net>

* name-lookup.c (get_std_name_hint): Added u8string as a name hint.

libstdc++:

2019-02-19  Tom Honermann  <tom@honermann.net>

P0482R5 char8_t: Standard library support
* 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.

From-SVN: r269004

38 files changed:
gcc/cp/ChangeLog
gcc/cp/name-lookup.c
libstdc++-v3/ChangeLog
libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/include/bits/atomic_base.h
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/bits/c++config
libstdc++-v3/include/bits/char_traits.h
libstdc++-v3/include/bits/codecvt.h
libstdc++-v3/include/bits/cpp_type_traits.h
libstdc++-v3/include/bits/fs_path.h
libstdc++-v3/include/bits/functional_hash.h
libstdc++-v3/include/bits/locale_conv.h
libstdc++-v3/include/bits/locale_facets.h
libstdc++-v3/include/bits/localefwd.h
libstdc++-v3/include/bits/postypes.h
libstdc++-v3/include/bits/stringfwd.h
libstdc++-v3/include/c_global/cstddef
libstdc++-v3/include/experimental/bits/fs_path.h
libstdc++-v3/include/experimental/string
libstdc++-v3/include/experimental/string_view
libstdc++-v3/include/std/atomic
libstdc++-v3/include/std/charconv
libstdc++-v3/include/std/limits
libstdc++-v3/include/std/string
libstdc++-v3/include/std/string_view
libstdc++-v3/include/std/type_traits
libstdc++-v3/libsupc++/atomic_lockfree_defines.h
libstdc++-v3/src/c++11/Makefile.am
libstdc++-v3/src/c++11/Makefile.in
libstdc++-v3/src/c++11/codecvt.cc
libstdc++-v3/src/c++11/limits.cc
libstdc++-v3/src/c++98/Makefile.am
libstdc++-v3/src/c++98/Makefile.in
libstdc++-v3/src/c++98/locale_init.cc
libstdc++-v3/src/c++98/localename.cc
libstdc++-v3/testsuite/util/testsuite_abi.cc

index 5d909ef62ec73f99394c863dfe1cf8903e364a26..e2b9be50ff15c9f030af54438c9a6795fda3cf48 100644 (file)
@@ -1,3 +1,7 @@
+2019-02-19  Tom Honermann  <tom@honermann.net>
+
+       * name-lookup.c (get_std_name_hint): Added u8string as a name hint.
+
 2019-02-18  Jason Merrill  <jason@redhat.com>
 
        PR c++/89336 - multiple stores in constexpr stmt.
index 959f43b0238443dd1c8b1b32273c562f2a913c25..2e1b851341b23d568d2ef433120c7efbba417d71 100644 (file)
@@ -5765,6 +5765,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>.  */
index f2279b9f2ae32769d20c145afc0feafeb3dfc880..dad36d6934da9d81cd73ef000e8740941e2ebfbf 100644 (file)
@@ -1,3 +1,88 @@
+2019-02-19  Tom Honermann  <tom@honermann.net>
+
+       P0482R5 char8_t: Standard library support
+       * 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.
+
 2019-02-18  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * 27_io/filesystem/operations/all.cc: Add dg-require-filesystem-ts.
index d776bf0968769c13784ef5f43f06c7165835d0f0..e6079ad2cf3a97e1f51c525443f62e0122bfd7d2 100644 (file)
@@ -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;
index a0860668b90068d0f539acb7ae15fcba64d72a78..c4f12152147ef6fa8b75a6205bb2490df29ea76a 100644 (file)
@@ -2244,6 +2244,17 @@ GLIBCXX_3.4.26 {
     # _Sp_make_shared_tag::_S_eq
     _ZNSt19_Sp_make_shared_tag5_S_eqERKSt9type_info;
 
+    # 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.
@@ -2535,6 +2546,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 {
 
index 78eb5d6a1d4e09a33524772e0f3ebfe4a25942f4..fd2ea7180154e187b0cbf1bac41c002c88f73801 100644 (file)
@@ -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
index 0a6dd3cbc7149bc1b07df819a743b5070b6d7fff..4d0894be99b1340a85c885ff30c71f9f397c2533 100644 (file)
@@ -6753,6 +6753,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>
@@ -6805,6 +6822,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)
index 97bb6db70b13b9f168a25374dd4f4c10b6b9913c..9993f4b1998b03f244eb8d84e3af2ce3aa477418 100644 (file)
@@ -625,6 +625,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 201811
+#endif
+
 /* Define if __float128 is supported on this host. */
 #if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
 #define _GLIBCXX_USE_FLOAT128
index d91fe84063b3cb15821c26b4d0680a98bc6189cc..21099c36c3b514b7aeaac339a7066cca59fc4fda 100644 (file)
@@ -507,6 +507,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
 
index be54a7b71a9d8df9d751553a3e960949c8fbf6bd..80ec608f2dd45044209bf6eb030b2e7d8175716f 100644 (file)
@@ -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
index 0958c7e7b3add7172e804ed7fbb5d0ee4431f739..d7f8517a6babdd9b782762bdd06cb67b37bfc5f6 100644 (file)
@@ -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>
index 98b8dc08a6eede157e8d3f9a8db63a6bdc81cc12..077045e6c788c9040243b6644033dbd428c17ca2 100644 (file)
@@ -69,8 +69,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>>
@@ -320,7 +325,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 #if _GLIBCXX_USE_WCHAR_T
     std::wstring   wstring() const;
 #endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+    __attribute__((__abi_tag__("__u8")))
+    std::u8string  u8string() const;
+#else
     std::string    u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
     std::u16string u16string() const;
     std::u32string u32string() const;
 
@@ -334,7 +344,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 #if _GLIBCXX_USE_WCHAR_T
     std::wstring   generic_wstring() const;
 #endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+    __attribute__((__abi_tag__("__u8")))
+    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;
 
@@ -735,10 +750,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)));
@@ -938,6 +965,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;
@@ -950,10 +986,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",
@@ -978,6 +1026,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
   {
@@ -996,6 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     return _M_pathname;
 #endif
   }
+#endif // _GLIBCXX_USE_CHAR8_T
 
   inline std::u16string
   path::u16string() const { return string<char16_t>(); }
@@ -1045,9 +1098,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
index 32dc00c5a6f90f720918d6063be8c2aad762a7b3..6a27beed754949ea4185ef11e93a01c01d08bdac 100644 (file)
@@ -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)
 
index 8438fedb5161bdf134973c420aae082a23d1904a..d7510dff80e4c5f8d156d54dbf8c76f4349c7ac1 100644 (file)
@@ -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
index 66ac9c07a5d7e6617609dac4726261bd2014f28f..0db24d53e835336b53d26aa14b20a51fe79c0fc8 100644 (file)
@@ -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
index a8ba24a9661b61234080a22739e42f827c693b87..20a6f006c6772b216fa52165dcd16bf86502063b 100644 (file)
@@ -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;
index 6d4c35190f4cccd7089dbe70144de8fa042f1ebe..17f7d63d829c3438b5817bd2ba69d5555503037e 100644 (file)
@@ -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;
index 9437b61fc5f6e6809780b440cdcb6bb45164daab..0ced16039a4f77ceeebfddb6101192423dfca266 100644 (file)
@@ -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; 
index 4c40737ea63e19c623dca2ac3ee7690b35059414..8c779ec354d84a18d91f1bb4bbb35892d1db2592 100644 (file)
@@ -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; };
index 239776df313eaa353f8e3c1641c797bc846de144..ebd5072fc1ab7762e1e70a2bf1ca95a913845655 100644 (file)
@@ -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>>
@@ -325,7 +330,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 #if _GLIBCXX_USE_WCHAR_T
     std::wstring   wstring() const;
 #endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+    __attribute__((__abi_tag__("__u8")))
+    std::u8string  u8string() const;
+#else
     std::string    u8string() const;
+#endif // _GLIBCXX_USE_CHAR8_T
     std::u16string u16string() const;
     std::u32string u32string() const;
 
@@ -339,7 +349,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 #if _GLIBCXX_USE_WCHAR_T
     std::wstring   generic_wstring() const;
 #endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+    __attribute__((__abi_tag__("__u8")))
+    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;
 
@@ -674,10 +689,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)));
@@ -867,12 +894,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;
@@ -881,10 +920,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",
@@ -899,6 +950,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 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     return _M_pathname;
 #endif
   }
+#endif // _GLIBCXX_USE_CHAR8_T
 
   inline std::u16string
   path::u16string() const { return string<char16_t>(); }
@@ -938,8 +994,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(); }
index a8ab002d445ac4aef4d3872f9f01b59749117fd9..65bf2b8d0097aeed1eb100be7852f8715ad11e5a 100644 (file)
@@ -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;
index 8cc0e90246b05f7ec5357fc6dd085dc139d9d406..ce2c14cfe361fb6b95c0c4f688fda74b64b5f3e6 100644 (file)
@@ -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}; }
index 32179613d6b79f3cf391ef1255282f8e7916513e..7acc2462bfb5074a8d7cbc3d5915f2db4baa88ab 100644 (file)
@@ -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;
 
index 3363247e11eb57193228255b54a002b43cf74838..9f01d4c0889ddb4dedeceb93714a1fb2be10a4f1 100644 (file)
@@ -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
            >>>;
 
index 759c49568dd62b741e5a72d99c42def9c2920bab..dbea152d0149f39d1b91622b447cd666d258111c 100644 (file)
@@ -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,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        = round_toward_zero;
     };
 
+#if _GLIBCXX_USE_CHAR8_T
+  /// numeric_limits<char8_t> specialization.
+  template<>
+    struct numeric_limits<char8_t>
+    {
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      lowest() _GLIBCXX_USE_NOEXCEPT { return min(); }
+
+      static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t);
+      static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t);
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0;
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t);
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
+
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
+
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
+       = denorm_absent;
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); }
+
+      static _GLIBCXX_CONSTEXPR char8_t
+      denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); }
+
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed;
+
+      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
+       = round_toward_zero;
+    };
+#endif
+
 #if __cplusplus >= 201103L
   /// numeric_limits<char16_t> specialization.
   template<>
index caa54c2410045d051dab6afe47388c22388db175..100c6c84ef604670ffc5b18958125523a4de37d8 100644 (file)
@@ -65,6 +65,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
index a81e0befdd5783d5f73603713b798f68ba04da0e..844cfb148ad60a670b9cecdf2d39b4c49d958273 100644 (file)
@@ -583,7 +583,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>;
 
@@ -621,6 +623,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>
@@ -665,6 +682,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}; }
index bc2250d9dce98ef12ab1d9e011e05796c2647d60..993967244ffbcceac6644d1c19244100fcafd55a 100644 (file)
@@ -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 { };
@@ -1680,8 +1686,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)
@@ -1693,6 +1699,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>
     {
@@ -1810,6 +1825,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>
     {
index 24d4fe3ddda0fd05b0ecbc737a4c5c749b60088e..614a84c1fa8ebf5be73be6489d6fb4ceb525ed08 100644 (file)
@@ -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
index 46d31b9cc646130269d77d9c42a6210afcc7d323..9fc1866270237895d79cb6eb92c434785de10489 100644 (file)
@@ -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/'
index 92816c8cb684fc68801f98a5985e0c4b790ef64d..a972915a2a73da4502e6f2b60b28898e98c58a6b 100644 (file)
@@ -834,6 +834,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
index b2fa375cdf5fccd851e3804cf71c970fcff1630b..372aea289b709aa2672b4ccd473dfa0f7c675d47 100644 (file)
@@ -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
 }
index ed7e631ed8884e023d6670b2f2733042b07abe4f..77b652de42de8faeb78dbb7556578de469445d9e 100644 (file)
@@ -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;
index b9f59ecaa10d4f0aca04d7500b8224bc93bfa6e6..ba88f002389378842368084f412aa309e6e981f4 100644 (file)
@@ -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.
index 009cb1127e426b224e6a4e46ea2de031c466a3c9..8e89c734361805450304e4e5a00256cb6827b666 100644 (file)
@@ -888,13 +888,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
index 0b778de9c408a342086ac82bb3f6ba3880dc9c17..e5e9d74379f5c34ca829b7667b553335abbd2952 100644 (file)
@@ -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
index 38290f0b8fe92a999a6802ddc49ef11cf5aeddb6..4e9c5e6c9881c4ad35f995a02adc1fd6866664a7 100644 (file)
@@ -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
index 836b62b128db55aa2199d1c170658001a9b487ad..a2d2cab36530fe0d26ed48c2312848750a1d964e 100644 (file)
@@ -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)