diff options
author | Tom Honermann <tom@honermann.net> | 2019-11-29 17:43:42 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2019-11-29 17:43:42 +0000 |
commit | 47b96008c50b47a31ac99af95775fe1c1add38a4 (patch) | |
tree | 696633db265f9ecfc6fb989121ad0b8f725ffd9f | |
parent | 9d07cd16786ee43d5dd637575cc86df453a122a9 (diff) |
libstdc++: P1423R3 char8_t remediation (2/4)
Update feature test macro, add deleted operators, update u8path
This patch increments the __cpp_lib_char8_t feature test macro, adds deleted
operator<< overloads for basic_ostream, and modifies u8path to accept
sequences of char8_t for both the C++17 implementation of std::filesystem, and
the filesystem TS implementation.
The implementation mechanism used for u8path differs between the C++17 and
filesystem TS implementations. The changes to the former take advantage of
C++17 'if constexpr'. The changes to the latter retain C++11 compatibility
and rely on tag dispatching.
2019-11-29 Tom Honermann <tom@honermann.net>
Update feature test macro, add deleted operators, update u8path
* include/bits/c++config: Bumped the value of the __cpp_lib_char8_t
feature test macro.
* include/bits/fs_path.h (u8path): Modified u8path to accept sequences
of char8_t.
* include/experimental/bits/fs_path.h (u8path): Modified u8path to
accept sequences of char8_t.
* include/std/ostream: Added deleted overloads of wchar_t, char8_t,
char16_t, and char32_t for ordinary and wide formatted character and
string inserters.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@278856 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 11 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/c++config | 2 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/fs_path.h | 82 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/bits/fs_path.h | 73 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ostream | 82 |
5 files changed, 216 insertions, 34 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 87c76f9a05c..8233ecdce3c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,16 @@ 2019-11-29 Tom Honermann <tom@honermann.net> + Update feature test macro, add deleted operators, update u8path + * include/bits/c++config: Bumped the value of the __cpp_lib_char8_t + feature test macro. + * include/bits/fs_path.h (u8path): Modified u8path to accept sequences + of char8_t. + * include/experimental/bits/fs_path.h (u8path): Modified u8path to + accept sequences of char8_t. + * include/std/ostream: Added deleted overloads of wchar_t, char8_t, + char16_t, and char32_t for ordinary and wide formatted character and + string inserters. + Decouple constraints for u8path from path constructors * include/bits/fs_path.h: Moved helper utilities out of std::filesystem::path into a detail namespace to make them diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 32db60f39e5..7ccfc5f199d 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -620,7 +620,7 @@ namespace std # endif #endif #ifdef _GLIBCXX_USE_CHAR8_T -# define __cpp_lib_char8_t 201811L +# define __cpp_lib_char8_t 201907L #endif /* Define if __float128 is supported on this host. */ diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h index b4c02327f01..643478292cd 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -154,9 +154,24 @@ namespace __detail template<typename _Tp, typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), - typename _Val = typename std::iterator_traits<_Iter>::value_type> + typename _Val = typename std::iterator_traits<_Iter>::value_type, + typename _UnqualVal = std::remove_const_t<_Val>> using __value_type_is_char - = std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>; + = std::enable_if_t<std::is_same_v<_UnqualVal, char>, + _UnqualVal>; + + template<typename _Tp, + typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), + typename _Val = typename std::iterator_traits<_Iter>::value_type, + typename _UnqualVal = std::remove_const_t<_Val>> + using __value_type_is_char_or_char8_t + = std::enable_if_t<__or_v< + std::is_same<_UnqualVal, char> +#ifdef _GLIBCXX_USE_CHAR8_T + , std::is_same<_UnqualVal, char8_t> +#endif + >, + _UnqualVal>; } // namespace __detail /// @endcond @@ -670,29 +685,41 @@ namespace __detail */ template<typename _InputIterator, typename _Require = __detail::_Path<_InputIterator, _InputIterator>, - typename _Require2 = __detail::__value_type_is_char<_InputIterator>> + typename _CharT + = __detail::__value_type_is_char_or_char8_t<_InputIterator>> inline path u8path(_InputIterator __first, _InputIterator __last) { #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - // XXX This assumes native wide encoding is UTF-16. - std::codecvt_utf8_utf16<path::value_type> __cvt; - path::string_type __tmp; - if constexpr (is_pointer_v<_InputIterator>) +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same_v<_CharT, char8_t>) { - if (__str_codecvt_in_all(__first, __last, __tmp, __cvt)) - return path{ __tmp }; + return path{ __first, __last }; } else { - const std::string __u8str{__first, __last}; - const char* const __ptr = __u8str.data(); - if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt)) - return path{ __tmp }; +#endif + // XXX This assumes native wide encoding is UTF-16. + std::codecvt_utf8_utf16<path::value_type> __cvt; + path::string_type __tmp; + if constexpr (is_pointer_v<_InputIterator>) + { + if (__str_codecvt_in_all(__first, __last, __tmp, __cvt)) + return path{ __tmp }; + } + else + { + const std::string __u8str{__first, __last}; + const char* const __ptr = __u8str.data(); + if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt)) + return path{ __tmp }; + } + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); +#ifdef _GLIBCXX_USE_CHAR8_T } - _GLIBCXX_THROW_OR_ABORT(filesystem_error( - "Cannot convert character sequence", - std::make_error_code(errc::illegal_byte_sequence))); +#endif #else // This assumes native normal encoding is UTF-8. return path{ __first, __last }; @@ -705,21 +732,32 @@ namespace __detail */ template<typename _Source, typename _Require = __detail::_Path<_Source>, - typename _Require2 = __detail::__value_type_is_char<_Source>> + typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>> inline path u8path(const _Source& __source) { #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - if constexpr (is_convertible_v<const _Source&, std::string_view>) +#ifdef _GLIBCXX_USE_CHAR8_T + if constexpr (is_same_v<_CharT, char8_t>) { - const std::string_view __s = __source; - return filesystem::u8path(__s.data(), __s.data() + __s.size()); + return path{ __source }; } else { - std::string __s = path::_S_string_from_iter(__source); - return filesystem::u8path(__s.data(), __s.data() + __s.size()); +#endif + if constexpr (is_convertible_v<const _Source&, std::string_view>) + { + const std::string_view __s = __source; + return filesystem::u8path(__s.data(), __s.data() + __s.size()); + } + else + { + std::string __s = path::_S_string_from_iter(__source); + return filesystem::u8path(__s.data(), __s.data() + __s.size()); + } +#ifdef _GLIBCXX_USE_CHAR8_T } +#endif #else return path{ __source }; #endif diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 075e9a8d125..b924fbfd5f6 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -170,10 +170,23 @@ namespace __detail template<typename _Tp, typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), - typename _Val = typename std::iterator_traits<_Iter>::value_type> + typename _Val = typename std::iterator_traits<_Iter>::value_type, + typename _UnqualVal = typename std::remove_const<_Val>::type> using __value_type_is_char = typename std::enable_if< - std::is_same<typename std::remove_const<_Val>::type, char>::value - >::type; + std::is_same<_UnqualVal, char>::value, + _UnqualVal>::type; + + template<typename _Tp, + typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), + typename _Val = typename std::iterator_traits<_Iter>::value_type, + typename _UnqualVal = typename std::remove_const<_Val>::type> + using __value_type_is_char_or_char8_t = typename std::enable_if< + __or_< + std::is_same<_UnqualVal, char> +#ifdef _GLIBCXX_USE_CHAR8_T + ,std::is_same<_UnqualVal, char8_t> +#endif + >::value, _UnqualVal>::type; } // namespace __detail /// @endcond @@ -588,13 +601,11 @@ namespace __detail } /// Create a path from a UTF-8-encoded sequence of char - template<typename _InputIterator, - typename _Require = __detail::_Path<_InputIterator, _InputIterator>, - typename _Require2 = __detail::__value_type_is_char<_InputIterator>> +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + template<typename _InputIterator> inline path - u8path(_InputIterator __first, _InputIterator __last) + __u8path(_InputIterator __first, _InputIterator __last, char) { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS // XXX This assumes native wide encoding is UTF-16. std::codecvt_utf8_utf16<path::value_type> __cvt; path::string_type __tmp; @@ -605,21 +616,61 @@ namespace __detail _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); + } + +#ifdef _GLIBCXX_USE_CHAR8_T + template<typename _InputIterator> + inline path + __u8path(_InputIterator __first, _InputIterator __last, char8_t) + { + return path{ __first, __last }; + } +#endif // _GLIBCXX_USE_CHAR8_T +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS + + template<typename _InputIterator, + typename _Require = __detail::_Path<_InputIterator, _InputIterator>, + typename _CharT = + __detail::__value_type_is_char_or_char8_t<_InputIterator>> + inline path + u8path(_InputIterator __first, _InputIterator __last) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return __u8path(__first, __last, _CharT{}); #else return path{ __first, __last }; #endif } /// Create a path from a UTF-8-encoded sequence of char +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + template<typename _Source> + inline path + __u8path(const _Source& __source, char) + { + std::string __s = path::_S_string_from_iter(__source); + return filesystem::u8path(__s.data(), __s.data() + __s.size()); + } + +#ifdef _GLIBCXX_USE_CHAR8_T + template<typename _Source> + inline path + __u8path(const _Source& __source, char8_t) + { + return path{ __source }; + } +#endif // _GLIBCXX_USE_CHAR8_T +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS + template<typename _Source, typename _Require = __detail::_Path<_Source>, - typename _Require2 = __detail::__value_type_is_char<_Source>> + typename _CharT = + __detail::__value_type_is_char_or_char8_t<_Source>> inline path u8path(const _Source& __source) { #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - std::string __s = path::_S_string_from_iter(__source); - return filesystem::u8path(__s.data(), __s.data() + __s.size()); + return __u8path(__source, _CharT{}); #else return path{ __source }; #endif diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 2541d978886..771c28db7b7 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -527,6 +527,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c) { return (__out << static_cast<char>(__c)); } + +#if __cplusplus > 201703L + // The following deleted overloads prevent formatting character values as + // numeric values. + +#ifdef _GLIBCXX_USE_WCHAR_T + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char8_t) = delete; +#endif + + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char16_t) = delete; + + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char32_t) = delete; + +#ifdef _GLIBCXX_USE_WCHAR_T +#ifdef _GLIBCXX_USE_CHAR8_T + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete; +#endif // _GLIBCXX_USE_CHAR8_T + + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete; + + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete; +#endif // _GLIBCXX_USE_WCHAR_T +#endif // C++20 //@} //@{ @@ -582,6 +623,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline basic_ostream<char, _Traits> & operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s) { return (__out << reinterpret_cast<const char*>(__s)); } + +#if __cplusplus > 201703L + // The following deleted overloads prevent formatting strings as + // pointer values. + +#ifdef _GLIBCXX_USE_WCHAR_T + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete; +#endif // _GLIBCXX_USE_CHAR8_T + + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete; + + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete; + +#ifdef _GLIBCXX_USE_WCHAR_T +#ifdef _GLIBCXX_USE_CHAR8_T + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete; +#endif + + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete; + + template<class _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete; +#endif // _GLIBCXX_USE_WCHAR_T +#endif // C++20 //@} // Standard basic_ostream manipulators |