diff options
38 files changed, 1099 insertions, 61 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5d909ef..e2b9be5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2019-02-19 Tom Honermann <tom@honermann.net> + + * name-lookup.c (get_std_name_hint): Added u8string as a name hint. + 2019-02-18 Jason Merrill <jason@redhat.com> PR c++/89336 - multiple stores in constexpr stmt. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 959f43b..2e1b851 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -5765,6 +5765,7 @@ get_std_name_hint (const char *name) {"basic_string", "<string>", cxx98}, {"string", "<string>", cxx98}, {"wstring", "<string>", cxx98}, + {"u8string", "<string>", cxx2a}, {"u16string", "<string>", cxx11}, {"u32string", "<string>", cxx11}, /* <string_view>. */ diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f2279b9..dad36d6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,88 @@ +2019-02-19 Tom Honermann <tom@honermann.net> + + P0482R5 char8_t: Standard library support + * config/abi/pre/gnu-versioned-namespace.ver (CXXABI_2.0): Add + typeinfo symbols for char8_t. + * config/abi/pre/gnu.ver: Add CXXABI_1.3.12. + (GLIBCXX_3.4.26): Add symbols for specializations of + numeric_limits and codecvt that involve char8_t. + (CXXABI_1.3.12): Add typeinfo symbols for char8_t. + * include/bits/atomic_base.h: Add atomic_char8_t. + * include/bits/basic_string.h: Add std::hash<u8string> and + operator""s(const char8_t*, size_t). + * include/bits/c++config: Define _GLIBCXX_USE_CHAR8_T and + __cpp_lib_char8_t. + * include/bits/char_traits.h: Add char_traits<char8_t>. + * include/bits/codecvt.h: Add + codecvt<char16_t, char8_t, mbstate_t>, + codecvt<char32_t, char8_t, mbstate_t>, + codecvt_byname<char16_t, char8_t, mbstate_t>, and + codecvt_byname<char32_t, char8_t, mbstate_t>. + * include/bits/cpp_type_traits.h: Add __is_integer<char8_t> to + recognize char8_t as an integral type. + * include/bits/fs_path.h: (path::__is_encoded_char): Recognize + char8_t. + (path::u8string): Return std::u8string when char8_t support is + enabled. + (path::generic_u8string): Likewise. + (path::_S_convert): Handle conversion from char8_t input. + (path::_S_str_convert): Likewise. + * include/bits/functional_hash.h: Add hash<char8_t>. + * include/bits/locale_conv.h (__str_codecvt_out): Add overloads for + char8_t. + * include/bits/locale_facets.h (_GLIBCXX_NUM_UNICODE_FACETS): Bump + for new char8_t specializations. + * include/bits/localefwd.h: Add missing declarations of + codecvt<char16_t, char, mbstate_t> and + codecvt<char32_t, char, mbstate_t>. Add char8_t declarations + codecvt<char16_t, char8_t, mbstate_t> and + codecvt<char32_t, char8_t, mbstate_t>. + * include/bits/postypes.h: Add u8streampos + * include/bits/stringfwd.h: Add declarations of + char_traits<char8_t> and u8string. + * include/c_global/cstddef: Add __byte_operand<char8_t>. + * include/experimental/bits/fs_path.h (path::__is_encoded_char): + Recognize char8_t. + (path::u8string): Return std::u8string when char8_t support is + enabled. + (path::generic_u8string): Likewise. + (path::_S_convert): Handle conversion from char8_t input. + (path::_S_str_convert): Likewise. + * include/experimental/string: Add u8string. + * include/experimental/string_view: Add u8string_view, + hash<experimental::u8string_view>, and + operator""sv(const char8_t*, size_t). + * include/std/atomic: Add atomic<char8_t> and atomic_char8_t. + * include/std/charconv (__is_int_to_chars_type): Recognize char8_t + as a character type. + * include/std/limits: Add numeric_limits<char8_t>. + * include/std/string_view: Add u8string_view, + hash<experimental::u8string_view>, and + operator""sv(const char8_t*, size_t). + * include/std/type_traits: Add __is_integral_helper<char8_t>, + __make_unsigned<char8_t>, and __make_signed<char8_t>. + * libsupc++/atomic_lockfree_defines.h: Define + ATOMIC_CHAR8_T_LOCK_FREE. + * src/c++11/Makefile.am: Compile with -fchar8_t when compiling + codecvt.cc and limits.cc so that char8_t specializations of + numeric_limits and codecvt and emitted. + * src/c++11/Makefile.in: Likewise. + * src/c++11/codecvt.cc: Define members of + codecvt<char16_t, char8_t, mbstate_t>, + codecvt<char32_t, char8_t, mbstate_t>, + codecvt_byname<char16_t, char8_t, mbstate_t>, and + codecvt_byname<char32_t, char8_t, mbstate_t>. + * src/c++11/limits.cc: Define members of + numeric_limits<char8_t>. + * src/c++98/Makefile.am: Compile with -fchar8_t when compiling + locale_init.cc and localename.cc. + * src/c++98/Makefile.in: Likewise. + * src/c++98/locale_init.cc: Add initialization for the + codecvt<char16_t, char8_t, mbstate_t> and + codecvt<char32_t, char8_t, mbstate_t> facets. + * src/c++98/localename.cc: Likewise. + * testsuite/util/testsuite_abi.cc: Validate ABI bump. + 2019-02-18 Wilco Dijkstra <wdijkstr@arm.com> * 27_io/filesystem/operations/all.cc: Add dg-require-filesystem-ts. diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver index d776bf0..e6079ad 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 a086066..c4f1215 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2244,6 +2244,17 @@ GLIBCXX_3.4.26 { # _Sp_make_shared_tag::_S_eq _ZNSt19_Sp_make_shared_tag5_S_eqERKSt9type_info; + # numeric_limits<char8_t> + _ZNSt14numeric_limitsIDuE[5-9]*; + _ZNSt14numeric_limitsIDuE1[0-7][hirt]*; + _ZNSt14numeric_limitsIDuE1[0-7]mi*; + _ZNSt14numeric_limitsIDuE1[0-7]max_e*; + + # codecvt<char16_t, char8_t, mbstate_t>, codecvt<char32_t, char8_t, mbstate_t> + _ZNKSt7codecvtID[is]Du*; + _ZNSt7codecvtID[is]Du*; + _ZT[ISV]St7codecvtID[is]Du*E; + } GLIBCXX_3.4.25; # Symbols in the support library (libsupc++) have their own tag. @@ -2535,6 +2546,15 @@ CXXABI_1.3.11 { } CXXABI_1.3.10; +CXXABI_1.3.12 { + + # typeinfo for char8_t + _ZTIDu; + _ZTIPDu; + _ZTIPKDu; + +} CXXABI_1.3.11; + # Symbols in the support library (libsupc++) supporting transactional memory. CXXABI_TM_1 { diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 78eb5d6..fd2ea71 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 0a6dd3c..4d0894b 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -6753,6 +6753,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #endif /* _GLIBCXX_COMPATIBILITY_CXX0X */ +#ifdef _GLIBCXX_USE_CHAR8_T + /// std::hash specialization for u8string. + template<> + struct hash<u8string> + : public __hash_base<size_t, u8string> + { + size_t + operator()(const u8string& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char8_t)); } + }; + + template<> + struct __is_fast_hash<hash<u8string>> : std::false_type + { }; +#endif + /// std::hash specialization for u16string. template<> struct hash<u16string> @@ -6805,6 +6822,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return basic_string<wchar_t>{__str, __len}; } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + _GLIBCXX_DEFAULT_ABI_TAG + inline basic_string<char8_t> + operator""s(const char8_t* __str, size_t __len) + { return basic_string<char8_t>{__str, __len}; } +#endif + _GLIBCXX_DEFAULT_ABI_TAG inline basic_string<char16_t> operator""s(const char16_t* __str, size_t __len) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 97bb6db..9993f4b 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -625,6 +625,17 @@ namespace std # endif #endif +// Unless explicitly specified, enable char8_t extensions only if the core +// language char8_t feature macro is defined. +#ifndef _GLIBCXX_USE_CHAR8_T +# ifdef __cpp_char8_t +# define _GLIBCXX_USE_CHAR8_T 1 +# endif +#endif +#ifdef _GLIBCXX_USE_CHAR8_T +# define __cpp_lib_char8_t 201811 +#endif + /* Define if __float128 is supported on this host. */ #if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) #define _GLIBCXX_USE_FLOAT128 diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index d91fe84..21099c3 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -507,6 +507,115 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif //_GLIBCXX_USE_WCHAR_T +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct char_traits<char8_t> + { + typedef char8_t char_type; + typedef unsigned int int_type; + typedef u8streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); +#endif + if (__n == 0) + return 0; + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus > 201402 + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits<char_type>::length(__s); +#endif + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); +#endif + if (__n == 0) + return 0; + return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); + } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); + } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); + } + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; + return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast<int_type>(-1); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCXX_USE_CHAR8_T + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h index be54a7b..80ec608 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 0958c7e..d7f8517 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 98b8dc0..077045e 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -69,8 +69,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { template<typename _CharT, typename _Ch = remove_const_t<_CharT>> using __is_encoded_char - = __or_<is_same<_Ch, char>, is_same<_Ch, wchar_t>, - is_same<_Ch, char16_t>, is_same<_Ch, char32_t>>; + = __or_<is_same<_Ch, char>, +#ifdef _GLIBCXX_USE_CHAR8_T + is_same<_Ch, char8_t>, +#endif + is_same<_Ch, wchar_t>, + is_same<_Ch, char16_t>, + is_same<_Ch, char32_t>>; template<typename _Iter, typename _Iter_traits = std::iterator_traits<_Iter>> @@ -320,7 +325,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_WCHAR_T std::wstring wstring() const; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + __attribute__((__abi_tag__("__u8"))) + std::u8string u8string() const; +#else std::string u8string() const; +#endif // _GLIBCXX_USE_CHAR8_T std::u16string u16string() const; std::u32string u32string() const; @@ -334,7 +344,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_WCHAR_T std::wstring generic_wstring() const; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + __attribute__((__abi_tag__("__u8"))) + std::u8string generic_u8string() const; +#else std::string generic_u8string() const; +#endif // _GLIBCXX_USE_CHAR8_T std::u16string generic_u16string() const; std::u32string generic_u32string() const; @@ -735,10 +750,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 static string_type _S_convert(const _CharT* __f, const _CharT* __l) { - std::codecvt_utf8<_CharT> __cvt; - std::string __str; - if (__str_codecvt_out(__f, __l, __str, __cvt)) - return __str; +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same_v<_CharT, char8_t>) + { + string_type __str(__f, __l); + return __str; + } + else + { +#endif + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + return __str; +#ifdef _GLIBCXX_USE_CHAR8_T + } +#endif _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); @@ -938,6 +965,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { if constexpr (is_same_v<_CharT, char>) return __u8str; +#ifdef _GLIBCXX_USE_CHAR8_T + else if constexpr (is_same_v<_CharT, char8_t>) + { + const char* __f = __u8str.data(); + const char* __l = __f + __u8str.size(); + _WString __wstr(__f, __l); + return __wstr; + } +#endif else { _WString __wstr; @@ -950,10 +986,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } } #else - codecvt_utf8<_CharT> __cvt; - basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; - if (__str_codecvt_in(__first, __last, __wstr, __cvt)) - return __wstr; +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same_v<_CharT, char8_t>) + { + basic_string<_CharT, _Traits, _Allocator> __wstr{__first, __last, __a}; + return __wstr; + } + else + { +#endif + codecvt_utf8<_CharT> __cvt; + basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; + if (__str_codecvt_in(__first, __last, __wstr, __cvt)) + return __wstr; +#ifdef _GLIBCXX_USE_CHAR8_T + } +#endif #endif _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", @@ -978,6 +1026,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path::wstring() const { return string<wchar_t>(); } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + inline std::u8string + path::u8string() const { return string<char8_t>(); } +#else inline std::string path::u8string() const { @@ -996,6 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return _M_pathname; #endif } +#endif // _GLIBCXX_USE_CHAR8_T inline std::u16string path::u16string() const { return string<char16_t>(); } @@ -1045,9 +1098,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return generic_string<wchar_t>(); } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + inline std::u8string + path::generic_u8string() const + { return generic_string<char8_t>(); } +#else inline std::string path::generic_u8string() const { return generic_string(); } +#endif inline std::u16string path::generic_u16string() const diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index 32dc00c..6a27bee 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 8438fed..d7510df 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 66ac9c0..0db24d5 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 a8ba24a..20a6f00 100644 --- a/libstdc++-v3/include/bits/localefwd.h +++ b/libstdc++-v3/include/bits/localefwd.h @@ -140,6 +140,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #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 6d4c351..17f7d63 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 9437b61..0ced160 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 4c40737..8c779ec 100644 --- a/libstdc++-v3/include/c_global/cstddef +++ b/libstdc++-v3/include/c_global/cstddef @@ -76,6 +76,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #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; }; template<> struct __byte_operand<short> { using __type = byte; }; diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 239776d..ebd5072 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>> @@ -325,7 +330,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_WCHAR_T std::wstring wstring() const; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + __attribute__((__abi_tag__("__u8"))) + std::u8string u8string() const; +#else std::string u8string() const; +#endif // _GLIBCXX_USE_CHAR8_T std::u16string u16string() const; std::u32string u32string() const; @@ -339,7 +349,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_WCHAR_T std::wstring generic_wstring() const; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + __attribute__((__abi_tag__("__u8"))) + std::u8string generic_u8string() const; +#else std::string generic_u8string() const; +#endif // _GLIBCXX_USE_CHAR8_T std::u16string generic_u16string() const; std::u32string generic_u32string() const; @@ -674,10 +689,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 static string_type _S_convert(const _CharT* __f, const _CharT* __l) { - std::codecvt_utf8<_CharT> __cvt; - std::string __str; - if (__str_codecvt_out(__f, __l, __str, __cvt)) - return __str; +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same<_CharT, char8_t>::value) + { + string_type __str(__f, __l); + return __str; + } + else + { +#endif + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + return __str; +#ifdef _GLIBCXX_USE_CHAR8_T + } +#endif _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); @@ -867,12 +894,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _WString* operator()(const _String& __from, _WString& __to, false_type) { - // use codecvt_utf8<_CharT> to convert UTF-8 to wide string - codecvt_utf8<_CharT> __cvt; - const char* __f = __from.data(); - const char* __l = __f + __from.size(); - if (__str_codecvt_in(__f, __l, __to, __cvt)) - return std::__addressof(__to); +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same<_CharT, char8_t>::value) + { + __to.assign(__from.begin(), __from.end()); + return std::__addressof(__to); + } + else + { +#endif + // use codecvt_utf8<_CharT> to convert UTF-8 to wide string + codecvt_utf8<_CharT> __cvt; + const char* __f = __from.data(); + const char* __l = __f + __from.size(); + if (__str_codecvt_in(__f, __l, __to, __cvt)) + return std::__addressof(__to); +#ifdef _GLIBCXX_USE_CHAR8_T + } +#endif return nullptr; } } __dispatch; @@ -881,10 +920,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return *__p; } #else - codecvt_utf8<_CharT> __cvt; - basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; - if (__str_codecvt_in(__first, __last, __wstr, __cvt)) - return __wstr; +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same<_CharT, char8_t>::value) + { + basic_string<_CharT, _Traits, _Allocator> __wstr{__first, __last, __a}; + return __wstr; + } + else + { +#endif + codecvt_utf8<_CharT> __cvt; + basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; + if (__str_codecvt_in(__first, __last, __wstr, __cvt)) + return __wstr; +#ifdef _GLIBCXX_USE_CHAR8_T + } +#endif #endif _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", @@ -899,6 +950,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path::wstring() const { return string<wchar_t>(); } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + inline std::u8string + path::u8string() const { return string<char8_t>(); } +#else inline std::string path::u8string() const { @@ -917,6 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return _M_pathname; #endif } +#endif // _GLIBCXX_USE_CHAR8_T inline std::u16string path::u16string() const { return string<char16_t>(); } @@ -938,8 +994,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path::generic_wstring() const { return wstring(); } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + inline std::u8string + path::generic_u8string() const { return u8string(); } +#else inline std::string path::generic_u8string() const { return u8string(); } +#endif inline std::u16string path::generic_u16string() const { return u16string(); } diff --git a/libstdc++-v3/include/experimental/string b/libstdc++-v3/include/experimental/string index a8ab002..65bf2b8 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 8cc0e90..ce2c14c 100644 --- a/libstdc++-v3/include/experimental/string_view +++ b/libstdc++-v3/include/experimental/string_view @@ -566,6 +566,9 @@ inline namespace fundamentals_v1 #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>; } // namespace fundamentals_v1 @@ -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 3217961..7acc246 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 3363247..9f01d4c 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -67,6 +67,9 @@ namespace __detail #if _GLIBCXX_USE_WCHAR_T , wchar_t #endif +#if _GLIBCXX_USE_CHAR8_T + , char8_t +#endif >>>; template<typename _Tp> diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits index 759c495..dbea152 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,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = round_toward_zero; }; +#if _GLIBCXX_USE_CHAR8_T + /// numeric_limits<char8_t> specialization. + template<> + struct numeric_limits<char8_t> + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char8_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + lowest() _GLIBCXX_USE_NOEXCEPT { return min(); } + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t); + static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0; + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char8_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char8_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR char8_t + infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; +#endif + #if __cplusplus >= 201103L /// numeric_limits<char16_t> specialization. template<> diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index caa54c2..100c6c8 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -65,6 +65,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; using string = basic_string<char>; +#ifdef _GLIBCXX_USE_CHAR8_T + using u8string = basic_string<char8_t>; +#endif using u16string = basic_string<char16_t>; using u32string = basic_string<char32_t>; #ifdef _GLIBCXX_USE_WCHAR_T diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index a81e0be..844cfb1 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -583,7 +583,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_USE_WCHAR_T using wstring_view = basic_string_view<wchar_t>; #endif - +#ifdef _GLIBCXX_USE_CHAR8_T + using u8string_view = basic_string_view<char8_t>; +#endif using u16string_view = basic_string_view<char16_t>; using u32string_view = basic_string_view<char32_t>; @@ -621,6 +623,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct hash<u8string_view> + : public __hash_base<size_t, u8string_view> + { + size_t + operator()(const u8string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash<hash<u8string_view>> : std::false_type + { }; +#endif + template<> struct hash<u16string_view> : public __hash_base<size_t, u16string_view> @@ -665,6 +682,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return basic_string_view<wchar_t>{__str, __len}; } #endif +#ifdef _GLIBCXX_USE_CHAR8_T + inline constexpr basic_string_view<char8_t> + operator""sv(const char8_t* __str, size_t __len) noexcept + { return basic_string_view<char8_t>{__str, __len}; } +#endif + inline constexpr basic_string_view<char16_t> operator""sv(const char16_t* __str, size_t __len) noexcept { return basic_string_view<char16_t>{__str, __len}; } diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index bc2250d..9939672 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 { }; @@ -1680,8 +1686,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; }; - // wchar_t, char16_t and char32_t are integral types but are neither - // signed integer types nor unsigned integer types, so must be + // wchar_t, char8_t, char16_t and char32_t are integral types but are + // neither signed integer types nor unsigned integer types, so must be // transformed to the unsigned integer type with the smallest rank. // Use the partial specialization for enumeration types to do that. #if defined(_GLIBCXX_USE_WCHAR_T) @@ -1693,6 +1699,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __make_unsigned<char8_t> + { + using __type + = typename __make_unsigned_selector<char8_t, false, true>::__type; + }; +#endif + template<> struct __make_unsigned<char16_t> { @@ -1810,6 +1825,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif +#if defined(_GLIBCXX_USE_CHAR8_T) + template<> + struct __make_signed<char8_t> + { + using __type + = typename __make_signed_selector<char8_t, false, true>::__type; + }; +#endif + template<> struct __make_signed<char16_t> { diff --git a/libstdc++-v3/libsupc++/atomic_lockfree_defines.h b/libstdc++-v3/libsupc++/atomic_lockfree_defines.h index 24d4fe3..614a84c 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 46d31b9..9fc1866 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 92816c8..a972915 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -834,6 +834,16 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -fimplicit-templates -c $< +# Use special rules for source files that require -fchar8_t. +codecvt.lo: codecvt.cc + $(LTCXXCOMPILE) -fchar8_t -c $< +codecvt.o: codecvt.cc + $(CXXCOMPILE) -fchar8_t -c $< +limits.lo: limits.cc + $(LTCXXCOMPILE) -fchar8_t -c $< +limits.o: limits.cc + $(CXXCOMPILE) -fchar8_t -c $< + @ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure-lt.s: cxx11-ios_failure.cc @ENABLE_DUAL_ABI_TRUE@ $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s @ENABLE_DUAL_ABI_TRUE@ -test -f tmp-cxx11-ios_failure-lt.o && mv -f tmp-cxx11-ios_failure-lt.o tmp-cxx11-ios_failure-lt.s diff --git a/libstdc++-v3/src/c++11/codecvt.cc b/libstdc++-v3/src/c++11/codecvt.cc index b2fa375..372aea2 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 ed7e631..77b652d 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 b9f59ec..ba88f00 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 009cb11..8e89c73 100644 --- a/libstdc++-v3/src/c++98/Makefile.in +++ b/libstdc++-v3/src/c++98/Makefile.in @@ -888,13 +888,13 @@ c++locale.o: c++locale.cc # XXX TODO move locale_init.cc and localename.cc to src/c++11 locale_init.lo: locale_init.cc - $(LTCXXCOMPILE) -std=gnu++11 -c $< + $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $< locale_init.o: locale_init.cc - $(LTCXXCOMPILE) -std=gnu++11 -c $< + $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $< localename.lo: localename.cc - $(LTCXXCOMPILE) -std=gnu++11 -c $< + $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $< localename.o: localename.cc - $(LTCXXCOMPILE) -std=gnu++11 -c $< + $(LTCXXCOMPILE) -std=gnu++11 -fchar8_t -c $< strstream.lo: strstream.cc $(LTCXXCOMPILE) -I$(GLIBCXX_INCLUDE_DIR)/backward -Wno-deprecated -c $< strstream.o: strstream.cc diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc index 0b778de..e5e9d74 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 38290f0..4e9c5e6 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 836b62b..a2d2cab 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) |