This patch adds support to libstdc++ for the P0482R5 standard library changes. This includes:
- New char8_t based specializations:
  - std::numeric_limits<char8_t>
  - std::char_traits<char8_t>
  - std::hash<u8string>
  - std::hash<pmr::u8string>
  - std::hash<u8string_view>
  - std::codecvt<char16_t, char8_t, std::mbstate_t>
  - std::codecvt<char32_t, char8_t, std::mbstate_t>
  - std::codecvt_byname<char16_t,char8_t,mbstate_t>
  - std::codecvt_byname<char32_t,char8_t,mbstate_t>
- New char8_t overloads:
  - u8string operator "" s(const char8_t* str, size_t len);
  - u8string_view operator""sv(const char8_t* str, size_t len);
- New type aliases:
  - std::u8string
  - std::u8string_view
  - std::atomic_char8_t
- Changed function signatures:
  - filesystem::path::u8string() returns u8string.
  - filesystem::path::generic_u8string() returns u8string.
- typeinfo for char8_t.
- New macros:
  - __cpp_lib_char8_t
  - ATOMIC_CHAR8_T_LOCK_FREE

For types and templates that existed in an experimental form prior to standardization, both the experimental and standardized variants have been updated. The updates to the experimental versions are optional.

I'm not very familiar with how ABI versioning is done and I'm not confident that the changes in the .ver files are correct. In particular, I'm unsure as to whether a CXXABI_3.0 section may be needed in gnu-versioned-namespace.ver and whether I'm correct in adding a new CXXABI_1.3.12 section in gnu.ver. If I'm not mistaken, CXXABI has not already been bumped for gcc 9, so needs to be, but GLIBCXX has already been bumped and therefore does not need to be.

gcc/cp/ChangeLog:

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

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

libstdc++-v3/ChangeLog:

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

     * config/abi/pre/gnu-versioned-namespace.ver (CXXABI_2.0): Add
     typeinfo symbols for char8_t.
     * config/abi/pre/gnu.ver: Add CXXABI_1.3.12.
     (GLIBCXX_3.4.26): Add symbols for specializations of
     numeric_limits and codecvt that involve char8_t.
     (CXXABI_1.3.12): Add typeinfo symbols for char8_t.
     * include/bits/atomic_base.h: Add atomic_char8_t.
     * include/bits/basic_string.h: Add std::hash<u8string> and
     operator""s(const char8_t*, size_t).
     * include/bits/c++config: Define _GLIBCXX_USE_CHAR8_T and
     __cpp_lib_char8_t.
     * include/bits/char_traits.h: Add char_traits<char8_t>.
     * include/bits/codecvt.h: Add
     codecvt<char16_t, char8_t, mbstate_t>,
     codecvt<char32_t, char8_t, mbstate_t>,
     codecvt_byname<char16_t, char8_t, mbstate_t>, and
     codecvt_byname<char32_t, char8_t, mbstate_t>.
     * include/bits/cpp_type_traits.h: Add __is_integer<char8_t> to
     recognize char8_t as an integral type.
     * include/bits/fs_path.h: (path::__is_encoded_char): Recognize
     char8_t.
     (path::u8string): Return std::u8string when char8_t support is
     enabled.
     (path::generic_u8string): Likewise.
     (path::_S_convert): Handle conversion from char8_t input.
     (path::_S_str_convert): Likewise.
     * include/bits/functional_hash.h: Add hash<char8_t>.
     * include/bits/locale_conv.h (__str_codecvt_out): Add overloads for
     char8_t.
     * include/bits/locale_facets.h (_GLIBCXX_NUM_UNICODE_FACETS): Bump
     for new char8_t specializations.
     * include/bits/localefwd.h: Add missing declarations of
     codecvt<char16_t, char, mbstate_t> and
     codecvt<char32_t, char, mbstate_t>.  Add char8_t declarations
     codecvt<char16_t, char8_t, mbstate_t> and
     codecvt<char32_t, char8_t, mbstate_t>.
     * include/bits/postypes.h: Add u8streampos
     * include/bits/stringfwd.h: Add declarations of
     char_traits<char8_t> and u8string.
     * include/c_global/cstddef: Add __byte_operand<char8_t>.
     * include/experimental/bits/fs_path.h (path::__is_encoded_char):
     Recognize char8_t.
     (path::u8string): Return std::u8string when char8_t support is
     enabled.
     (path::generic_u8string): Likewise.
     (path::_S_convert): Handle conversion from char8_t input.
     (path::_S_str_convert): Likewise.
     * include/experimental/string: Add u8string.
     * include/experimental/string_view: Add u8string_view,
     hash<experimental::u8string_view>, and
     operator""sv(const char8_t*, size_t).
     * include/std/atomic: Add atomic<char8_t> and atomic_char8_t.
     * include/std/charconv (__is_int_to_chars_type): Recognize char8_t
     as a character type.
     * include/std/limits: Add numeric_limits<char8_t>.
     * include/std/string_view: Add u8string_view,
     hash<experimental::u8string_view>, and
     operator""sv(const char8_t*, size_t).
     * include/std/type_traits: Add __is_integral_helper<char8_t>,
     __make_unsigned<char8_t>, and __make_signed<char8_t>.
     * libsupc++/atomic_lockfree_defines.h: Define
     ATOMIC_CHAR8_T_LOCK_FREE.
     * src/c++11/Makefile.am: Compile with -fchar8_t when compiling
     codecvt.cc and limits.cc so that char8_t specializations of
     numeric_limits and codecvt and emitted.
     * src/c++11/Makefile.in: Likewise.
     * src/c++11/codecvt.cc: Define members of
     codecvt<char16_t, char8_t, mbstate_t>,
     codecvt<char32_t, char8_t, mbstate_t>,
     codecvt_byname<char16_t, char8_t, mbstate_t>, and
     codecvt_byname<char32_t, char8_t, mbstate_t>.
     * src/c++11/limits.cc: Define members of
     numeric_limits<char8_t>.
     * src/c++98/Makefile.am: Compile with -fchar8_t when compiling
     locale_init.cc and localename.cc.
     * src/c++98/Makefile.in: Likewise.
     * src/c++98/locale_init.cc: Add initialization for the
     codecvt<char16_t, char8_t, mbstate_t> and
     codecvt<char32_t, char8_t, mbstate_t> facets.
     * src/c++98/localename.cc: Likewise.
     * testsuite/util/testsuite_abi.cc: Validate ABI bump.

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

Reply via email to