aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Honermann <tom@honermann.net>2019-11-29 17:43:42 +0000
committerJonathan Wakely <jwakely@redhat.com>2019-11-29 17:43:42 +0000
commit47b96008c50b47a31ac99af95775fe1c1add38a4 (patch)
tree696633db265f9ecfc6fb989121ad0b8f725ffd9f
parent9d07cd16786ee43d5dd637575cc86df453a122a9 (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/ChangeLog11
-rw-r--r--libstdc++-v3/include/bits/c++config2
-rw-r--r--libstdc++-v3/include/bits/fs_path.h82
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_path.h73
-rw-r--r--libstdc++-v3/include/std/ostream82
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