This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [REVISED PATCH 5/9]: C++ P0482R5 char8_t: Standard library support


Attached is a revised patch that addresses changes in P0482R6. Changes from the prior patch include:
- Updated the value of the __cpp_char8_t feature test macro to 201811.

Tested on x86_64-linux.

gcc/cp/ChangeLog:

2018-11-04  Tom Honermann  <tom@honermann.net>

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

libstdc++-v3/ChangeLog:

2018-11-04  Tom Honermann  <tom@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..f2f52596af3 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 201811
+#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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]