diff options
Diffstat (limited to 'libstdc++-v3')
26 files changed, 2116 insertions, 366 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a479a1219ff..238e356c843 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,120 @@ +2019-11-30 Jonathan Wakely <jwakely@redhat.com> + + * acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Enable by default for + mingw targets. + * configure: Regenerate. + + * include/bits/fs_path.h (u8path(InputIterator, InputIterator)) + (u8path(const Source&)) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Simplify + conditions. + * include/experimental/bits/fs_path.h [_GLIBCXX_FILESYSTEM_IS_WINDOWS] + (__u8path(const Source&, char)): Add overloads for std::string and + types convertible to std::string. + (_Cvt::_S_wconvert): Add a new overload for char8_t strings and use + codecvt_utf8_utf16 to do the correct conversion. + +2019-11-29 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/fs_path.h (path::operator/=): Change template-head to + use typename instead of class. + * include/experimental/bits/fs_path.h (path::operator/=): Likewise. + * include/std/ostream (operator<<): Likewise. + +2019-11-29 Tom Honermann <tom@honermann.net> + + New tests + * testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc: + New test to validate deleted overloads of character and string + inserters for narrow ostreams. + * testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc: + New test to validate deleted overloads of character and string + inserters for wide ostreams. + * testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc: New test + to validate u8path invocations with sequences of char8_t. + * testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc: + New test to validate u8path invocations with sequences of char8_t. + + Updates to existing tests + * testsuite/experimental/feat-char8_t.cc: Updated the expected + __cpp_lib_char8_t feature test macro value. + * testsuite/27_io/filesystem/path/factory/u8path.cc: Added testing of + u8path invocation with std::string, std::string_view, and iterators + thereof. + * testsuite/experimental/filesystem/path/factory/u8path.cc: Added + testing of u8path invocation with std::string, std::string_view, and + iterators thereof. + + 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 + available for use by u8path. + * include/experimental/bits/fs_path.h: Moved helper utilities out + of std::experimental::filesystem::v1::path into a detail + namespace to make them available for use by u8path. + +2019-11-29 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/91997 + * python/libstdcxx/v6/printers.py (find_type): Fail more gracefully + if we run out of base classes to look at. + (llokup_templ_spec, lookup_node_type): New utilities to find node + types for node-based containers. + (StdListPrinter.children, NodeIteratorPrinter.__init__) + (NodeIteratorPrinter.to_string, StdSlistPrinter.children) + (StdSlistIteratorPrinter.to_string, StdRbtreeIteratorPrinter.__init__) + (StdMapPrinter.children, StdSetPrinter.children) + (StdForwardListPrinter.children): Use lookup_node_type instead of + find_type. + (StdListIteratorPrinter.__init__, StdFwdListIteratorPrinter.__init__): + Pass name of node type to NodeIteratorPrinter constructor. + (Tr1HashtableIterator.__init__): Rename argument. + (StdHashtableIterator.__init__): Likewise. Use lookup_templ_spec + instead of find_type. + * testsuite/libstdc++-prettyprinters/59161.cc: Remove workaround for + _Node typedef not being present in debuginfo. + * testsuite/libstdc++-prettyprinters/91997.cc: New test. + +2019-11-26 François Dumont <fdumont@gcc.gnu.org> + + * include/debug/helper_functions.h (__valid_range_aux): Use C++98 + std::input_iterator_tag default constructor invocation. + + * include/debug/array (array<>::fill): Add C++20 constexpr. + (array<>::swap): Likewise. + + * include/debug/safe_iterator.h + [__cpp_lib_concepts](_Safe_iterator<>::iterator_concept): Define for + C++20. + +2019-11-25 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/iterator_concepts.h (ranges::iter_swap): Fix parameter + types of poison pill overload. Use remove_reference_t when checking + constraints. + * include/bits/stl_iterator.h (move_sentinel): Define for C++20. + (move_iterator): Adjust definitions of nested types for C++20. Add + hidden friends for move_sentinel operations, iter_move and iter_swap. + (common_iterator, counted_iterator): Define for C++20. + * testsuite/24_iterators/move_iterator/cust.cc: New test. + * testsuite/24_iterators/move_iterator/sentinel.cc: New test. + * testsuite/24_iterators/common_iterator/1.cc: New test. + * testsuite/24_iterators/counted_iterator/1.cc: New test. + + PR libstdc++/91786 + * include/bits/fs_path.h (filesystem_error): Move definition before + the use in u8path. + 2019-11-24 François Dumont <fdumont@gcc.gnu.org> * include/debug/functions.h: Remove <bits/move.h> include. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index ad2cb01d94f..73e07e513bc 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -4436,6 +4436,9 @@ AC_DEFUN([GLIBCXX_ENABLE_FILESYSTEM_TS], [ solaris*) enable_libstdcxx_filesystem_ts=yes ;; + mingw*) + enable_libstdcxx_filesystem_ts=yes + ;; *) enable_libstdcxx_filesystem_ts=no ;; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index cb67581206d..e1d24132294 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -74551,6 +74551,9 @@ $as_echo_n "checking whether to build Filesystem TS support... " >&6; } solaris*) enable_libstdcxx_filesystem_ts=yes ;; + mingw*) + enable_libstdcxx_filesystem_ts=yes + ;; *) enable_libstdcxx_filesystem_ts=no ;; 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 e1083acf30f..20ec42da57d 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -63,99 +63,122 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @{ */ - /// A filesystem path. - class path - { - template<typename _CharT> - using __is_encoded_char = __is_one_of<remove_const_t<_CharT>, - char, + class path; + + /// @cond undocumented +namespace __detail +{ + template<typename _CharT> + using __is_encoded_char = __is_one_of<remove_const_t<_CharT>, + char, #ifdef _GLIBCXX_USE_CHAR8_T - char8_t, + char8_t, #endif #if _GLIBCXX_USE_WCHAR_T - wchar_t, + wchar_t, #endif - char16_t, char32_t>; - - template<typename _Iter, - typename _Iter_traits = std::iterator_traits<_Iter>> - using __is_path_iter_src - = __and_<__is_encoded_char<typename _Iter_traits::value_type>, - std::is_base_of<std::input_iterator_tag, - typename _Iter_traits::iterator_category>>; + char16_t, char32_t>; - template<typename _Iter> - static __is_path_iter_src<_Iter> - __is_path_src(_Iter, int); + template<typename _Iter, + typename _Iter_traits = std::iterator_traits<_Iter>> + using __is_path_iter_src + = __and_<__is_encoded_char<typename _Iter_traits::value_type>, + std::is_base_of<std::input_iterator_tag, + typename _Iter_traits::iterator_category>>; - template<typename _CharT, typename _Traits, typename _Alloc> - static __is_encoded_char<_CharT> - __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); + template<typename _Iter> + static __is_path_iter_src<_Iter> + __is_path_src(_Iter, int); - template<typename _CharT, typename _Traits> - static __is_encoded_char<_CharT> - __is_path_src(const basic_string_view<_CharT, _Traits>&, int); + template<typename _CharT, typename _Traits, typename _Alloc> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); - template<typename _Unknown> - static std::false_type - __is_path_src(const _Unknown&, ...); + template<typename _CharT, typename _Traits> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string_view<_CharT, _Traits>&, int); - template<typename _Tp1, typename _Tp2> - struct __constructible_from; + template<typename _Unknown> + static std::false_type + __is_path_src(const _Unknown&, ...); - template<typename _Iter> - struct __constructible_from<_Iter, _Iter> - : __is_path_iter_src<_Iter> - { }; + template<typename _Tp1, typename _Tp2> + struct __constructible_from; - template<typename _Source> - struct __constructible_from<_Source, void> - : decltype(__is_path_src(std::declval<_Source>(), 0)) - { }; + template<typename _Iter> + struct __constructible_from<_Iter, _Iter> + : __is_path_iter_src<_Iter> + { }; - template<typename _Tp1, typename _Tp2 = void> - using _Path = typename - std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>, - __not_<is_void<remove_pointer_t<_Tp1>>>, - __constructible_from<_Tp1, _Tp2>>::value, - path>::type; - - template<typename _Source> - static _Source - _S_range_begin(_Source __begin) { return __begin; } - - struct __null_terminated { }; - - template<typename _Source> - static __null_terminated - _S_range_end(_Source) { return {}; } + template<typename _Source> + struct __constructible_from<_Source, void> + : decltype(__is_path_src(std::declval<_Source>(), 0)) + { }; - template<typename _CharT, typename _Traits, typename _Alloc> - static const _CharT* - _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) - { return __str.data(); } + template<typename _Tp1, typename _Tp2 = void> + using _Path = typename + std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>, + __not_<is_void<remove_pointer_t<_Tp1>>>, + __constructible_from<_Tp1, _Tp2>>::value, + path>::type; - template<typename _CharT, typename _Traits, typename _Alloc> - static const _CharT* - _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) - { return __str.data() + __str.size(); } + template<typename _Source> + static _Source + _S_range_begin(_Source __begin) { return __begin; } - template<typename _CharT, typename _Traits> - static const _CharT* - _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) - { return __str.data(); } + struct __null_terminated { }; - template<typename _CharT, typename _Traits> - static const _CharT* - _S_range_end(const basic_string_view<_CharT, _Traits>& __str) - { return __str.data() + __str.size(); } + template<typename _Source> + static __null_terminated + _S_range_end(_Source) { return {}; } + + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data(); } + + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data() + __str.size(); } + + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data(); } + + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_end(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data() + __str.size(); } + + 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 + = 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>; - template<typename _Tp, - typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), - typename _Val = typename std::iterator_traits<_Iter>::value_type> - using __value_type_is_char - = std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>; +} // namespace __detail + /// @endcond + /// A filesystem path. + class path + { public: #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS using value_type = wchar_t; @@ -193,29 +216,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { _M_split_cmpts(); } template<typename _Source, - typename _Require = _Path<_Source>> + typename _Require = __detail::_Path<_Source>> path(_Source const& __source, format = auto_format) - : _M_pathname(_S_convert(_S_range_begin(__source), - _S_range_end(__source))) + : _M_pathname(_S_convert(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source))) { _M_split_cmpts(); } template<typename _InputIterator, - typename _Require = _Path<_InputIterator, _InputIterator>> + typename _Require = __detail::_Path<_InputIterator, _InputIterator>> path(_InputIterator __first, _InputIterator __last, format = auto_format) : _M_pathname(_S_convert(__first, __last)) { _M_split_cmpts(); } template<typename _Source, - typename _Require = _Path<_Source>, - typename _Require2 = __value_type_is_char<_Source>> + typename _Require = __detail::_Path<_Source>, + typename _Require2 = __detail::__value_type_is_char<_Source>> path(_Source const& __source, const locale& __loc, format = auto_format) - : _M_pathname(_S_convert_loc(_S_range_begin(__source), - _S_range_end(__source), __loc)) + : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source), __loc)) { _M_split_cmpts(); } template<typename _InputIterator, - typename _Require = _Path<_InputIterator, _InputIterator>, - typename _Require2 = __value_type_is_char<_InputIterator>> + typename _Require = __detail::_Path<_InputIterator, _InputIterator>, + typename _Require2 = __detail::__value_type_is_char<_InputIterator>> path(_InputIterator __first, _InputIterator __last, const locale& __loc, format = auto_format) : _M_pathname(_S_convert_loc(__first, __last, __loc)) @@ -231,17 +254,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path& assign(string_type&& __source); template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& operator=(_Source const& __source) { return *this = path(__source); } template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& assign(_Source const& __source) { return *this = path(__source); } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& assign(_InputIterator __first, _InputIterator __last) { return *this = path(__first, __last); } @@ -249,24 +272,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path& operator/=(const path& __p); - template <class _Source> - _Path<_Source>& + template<typename _Source> + __detail::_Path<_Source>& operator/=(_Source const& __source) { - _M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source))); + _M_append(_S_convert(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source))); return *this; } template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& append(_Source const& __source) { - _M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source))); + _M_append(_S_convert(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source))); return *this; } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& append(_InputIterator __first, _InputIterator __last) { _M_append(_S_convert(__first, __last)); @@ -282,23 +307,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path& operator+=(basic_string_view<value_type> __x); template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& operator+=(_Source const& __x) { return concat(__x); } template<typename _CharT> - _Path<_CharT*, _CharT*>& + __detail::_Path<_CharT*, _CharT*>& operator+=(_CharT __x); template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& concat(_Source const& __x) { - _M_concat(_S_convert(_S_range_begin(__x), _S_range_end(__x))); + _M_concat(_S_convert(__detail::_S_range_begin(__x), + __detail::_S_range_end(__x))); return *this; } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& concat(_InputIterator __first, _InputIterator __last) { _M_concat(_S_convert(__first, __last)); @@ -496,11 +522,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct _Cvt; static basic_string_view<value_type> - _S_convert(value_type* __src, __null_terminated) + _S_convert(value_type* __src, __detail::__null_terminated) { return __src; } static basic_string_view<value_type> - _S_convert(const value_type* __src, __null_terminated) + _S_convert(const value_type* __src, __detail::__null_terminated) { return __src; } static basic_string_view<value_type> @@ -522,7 +548,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _InputIterator> static string_type - _S_convert(_InputIterator __src, __null_terminated) + _S_convert(_InputIterator __src, __detail::__null_terminated) { // Read from iterator into basic_string until a null value is seen: auto __s = _S_string_from_iter(__src); @@ -544,7 +570,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _InputIterator> static string_type - _S_convert_loc(_InputIterator __src, __null_terminated, + _S_convert_loc(_InputIterator __src, __detail::__null_terminated, const std::locale& __loc) { const std::string __s = _S_string_from_iter(__src); @@ -622,59 +648,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 size_t hash_value(const path& __p) noexcept; - /// Create a path from a UTF-8-encoded sequence of char - template<typename _InputIterator> - inline auto - u8path(_InputIterator __first, _InputIterator __last) - -> decltype(filesystem::path(__first, __last, std::locale::classic())) - { -#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>) - { - 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))); -#else - // This assumes native normal encoding is UTF-8. - return path{ __first, __last }; -#endif - } - - /// Create a path from a UTF-8-encoded sequence of char - template<typename _Source> - inline auto - u8path(const _Source& __source) - -> decltype(filesystem::path(__source, std::locale::classic())) - { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - 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()); - } -#else - return path{ __source }; -#endif - } - /// @} /// Exception type thrown by the Filesystem library @@ -706,6 +679,78 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 std::__shared_ptr<const _Impl> _M_impl; }; + /** Create a path from a UTF-8-encoded sequence of char + * + * @relates std::filesystem::path + */ + 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 + if constexpr (is_same_v<_CharT, char>) + { + // 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 __p = __u8str.data(); + if (__str_codecvt_in_all(__p, __p + __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))); + } + else + return path{ __first, __last }; +#else + // This assumes native normal encoding is UTF-8. + return path{ __first, __last }; +#endif + } + + /** Create a path from a UTF-8-encoded sequence of char + * + * @relates std::filesystem::path + */ + template<typename _Source, + typename _Require = __detail::_Path<_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_same_v<_CharT, char>) + { + 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()); + } + } + else + return path{ __source }; +#else + return path{ __source }; +#endif + } + /// @cond undocumented struct path::_Cmpt : path @@ -944,7 +989,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } template<typename _CharT> - inline path::_Path<_CharT*, _CharT*>& + inline __detail::_Path<_CharT*, _CharT*>& path::operator+=(_CharT __x) { auto* __addr = std::__addressof(__x); diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index 3843ba5d57f..97aed72e255 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -700,7 +700,7 @@ namespace ranges namespace __cust_iswap { template<typename _It1, typename _It2> - void iter_swap(_It1&, _It2&) = delete; + void iter_swap(_It1, _It2) = delete; template<typename _Tp, typename _Up> concept __adl_iswap @@ -744,7 +744,8 @@ namespace ranges public: template<typename _Tp, typename _Up> requires __adl_iswap<_Tp, _Up> - || (readable<_Tp> && readable<_Up> + || (readable<remove_reference_t<_Tp>> + && readable<remove_reference_t<_Up>> && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>) || (indirectly_movable_storable<_Tp, _Up> && indirectly_movable_storable<_Up, _Tp>) diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a707621c9ed..89cca64438c 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -73,6 +73,11 @@ # define __cpp_lib_array_constexpr 201803 #endif +#if __cplusplus > 201703L +# include <compare> +# include <new> +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -1055,12 +1060,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __it.base(); } #if __cplusplus >= 201103L - /** * @addtogroup iterators * @{ */ +#if __cplusplus > 201703L && __cpp_lib_concepts + template<semiregular _Sent> + class move_sentinel + { + public: + constexpr + move_sentinel() + noexcept(is_nothrow_default_constructible_v<_Sent>) + : _M_last() { } + + constexpr explicit + move_sentinel(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_last(std::move(__s)) { } + + template<typename _S2> requires convertible_to<const _S2&, _Sent> + constexpr + move_sentinel(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_constructible_v<_Sent, const _S2&>) + : _M_last(__s.base()) + { } + + template<typename _S2> requires assignable_from<_Sent&, const _S2&> + constexpr move_sentinel& + operator=(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_assignable_v<_Sent, const _S2&>) + { + _M_last = __s.base(); + return *this; + } + + constexpr _Sent + base() const + noexcept(is_nothrow_copy_constructible_v<_Sent>) + { return _M_last; } + + private: + _Sent _M_last; + }; + + namespace __detail + { + // Weaken iterator_category _Cat to _Limit if it is derived from that, + // otherwise use _Otherwise. + template<typename _Cat, typename _Limit, typename _Otherwise = _Cat> + using __clamp_iter_cat + = conditional_t<derived_from<_Cat, _Limit>, _Limit, _Otherwise>; + } +#endif // C++20 + // 24.4.3 Move iterators /** * Class template move_iterator is an iterator adapter with the same @@ -1073,14 +1127,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Iterator> class move_iterator { - protected: _Iterator _M_current; - typedef iterator_traits<_Iterator> __traits_type; - typedef typename __traits_type::reference __base_ref; + using __traits_type = iterator_traits<_Iterator>; +#if __cplusplus > 201703L && __cpp_lib_concepts + using __base_cat = typename __traits_type::iterator_category; +#else + using __base_ref = typename __traits_type::reference; +#endif public: - typedef _Iterator iterator_type; + using iterator_type = _Iterator; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = input_iterator_tag; + using iterator_category + = __detail::__clamp_iter_cat<__base_cat, random_access_iterator_tag>; + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + using pointer = _Iterator; + using reference = iter_rvalue_reference_t<_Iterator>; +#else typedef typename __traits_type::iterator_category iterator_category; typedef typename __traits_type::value_type value_type; typedef typename __traits_type::difference_type difference_type; @@ -1091,6 +1158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename conditional<is_reference<__base_ref>::value, typename remove_reference<__base_ref>::type&&, __base_ref>::type reference; +#endif _GLIBCXX17_CONSTEXPR move_iterator() @@ -1172,6 +1240,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX17_CONSTEXPR reference operator[](difference_type __n) const { return std::move(_M_current[__n]); } + +#if __cplusplus > 201703L && __cpp_lib_concepts + template<sentinel_for<_Iterator> _Sent> + friend constexpr bool + operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() == __y.base(); } + + template<sized_sentinel_for<_Iterator> _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) + { return __x.base() - __y.base(); } + + template<sized_sentinel_for<_Iterator> _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() - __y.base(); } + + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const move_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + template<indirectly_swappable<_Iterator> _Iter2> + friend constexpr void + iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { return ranges::iter_swap(__x._M_current, __y._M_current); } +#endif // C++20 }; // Note: See __normal_iterator operators note from Gaby to understand @@ -1285,6 +1381,592 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __make_move_if_noexcept_iterator(_Tp* __i) { return _ReturnType(__i); } +#if __cplusplus > 201703L && __cpp_lib_concepts + // [iterators.common] Common iterators + + namespace __detail + { + template<input_or_output_iterator _It> + class _Common_iter_proxy + { + iter_value_t<_It> _M_keep; + + _Common_iter_proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::move(__x)) { } + + template<typename _Iter, typename _Sent> + friend class common_iterator; + + public: + const iter_value_t<_It>* + operator->() const + { return std::__addressof(_M_keep); } + }; + + template<typename _It> + concept __common_iter_has_arrow = readable<const _It> + && (requires(const _It& __it) { __it.operator->(); } + || is_reference_v<iter_reference_t<_It>> + || constructible_from<iter_value_t<_It>, iter_reference_t<_It>>); + + } // namespace __detail + + /// An iterator/sentinel adaptor for representing a non-common range. + template<input_or_output_iterator _It, sentinel_for<_It> _Sent> + requires (!same_as<_It, _Sent>) + class common_iterator + { + template<typename _Tp, typename _Up> + static constexpr bool + _S_noexcept1() + { + if constexpr (is_trivially_default_constructible_v<_Tp>) + return is_nothrow_assignable_v<_Tp, _Up>; + else + return is_nothrow_constructible_v<_Tp, _Up>; + } + + template<typename _It2, typename _Sent2> + static constexpr bool + _S_noexcept() + { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } + + public: + constexpr + common_iterator() + noexcept(is_nothrow_default_constructible_v<_It>) + : _M_it(), _M_index(0) + { } + + constexpr + common_iterator(_It __i) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_it(std::move(__i)), _M_index(0) + { } + + constexpr + common_iterator(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_sent(std::move(__s)), _M_index(1) + { } + + template<typename _It2, typename _Sent2> + requires convertible_to<const _It2&, _It> + && convertible_to<const _Sent2&, _Sent> + constexpr + common_iterator(const common_iterator<_It2, _Sent2>& __x) + noexcept(_S_noexcept<const _It2&, const _Sent2&>()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + constexpr + common_iterator(const common_iterator& __x) + noexcept(_S_noexcept<const _It&, const _Sent&>()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + common_iterator& + operator=(const common_iterator& __x) + noexcept(is_nothrow_copy_assignable_v<_It> + && is_nothrow_copy_assignable_v<_Sent> + && is_nothrow_copy_constructible_v<_It> + && is_nothrow_copy_constructible_v<_Sent>) + { + return this->operator=<_It, _Sent>(__x); + } + + template<typename _It2, typename _Sent2> + requires convertible_to<const _It2&, _It> + && convertible_to<const _Sent2&, _Sent> + && assignable_from<_It&, const _It2&> + && assignable_from<_Sent&, const _Sent2&> + common_iterator& + operator=(const common_iterator<_It2, _Sent2>& __x) + noexcept(is_nothrow_constructible_v<_It, const _It2&> + && is_nothrow_constructible_v<_Sent, const _Sent2&> + && is_nothrow_assignable_v<_It, const _It2&> + && is_nothrow_assignable_v<_Sent, const _Sent2&>) + { + switch(_M_index << 2 | __x._M_index) + { + case 0b0000: + _M_it = __x._M_it; + break; + case 0b0101: + _M_sent = __x._M_sent; + break; + case 0b0001: + _M_it.~_It(); + _M_index = -1; + [[fallthrough]]; + case 0b1001: + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + _M_index = 1; + break; + case 0b0100: + _M_sent.~_Sent(); + _M_index = -1; + [[fallthrough]]; + case 0b1000: + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + _M_index = 0; + break; + default: + __glibcxx_assert(__x._M_has_value()); + __builtin_unreachable(); + } + return *this; + } + + ~common_iterator() + { + switch (_M_index) + { + case 0: + _M_it.~_It(); + break; + case 1: + _M_sent.~_Sent(); + break; + } + } + + decltype(auto) + operator*() + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator*() const requires __detail::__dereferenceable<const _It> + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator->() const requires __detail::__common_iter_has_arrow<_It> + { + __glibcxx_assert(_M_index == 0); + if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); }) + return _M_it; + else if constexpr (is_reference_v<iter_reference_t<_It>>) + { + auto&& __tmp = *_M_it; + return std::__addressof(__tmp); + } + else + return _Common_iter_proxy(*_M_it); + } + + common_iterator& + operator++() + { + __glibcxx_assert(_M_index == 0); + ++_M_it; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_index == 0); + if constexpr (forward_iterator<_It>) + { + common_iterator __tmp = *this; + ++*this; + return __tmp; + } + else + return _M_it++; + } + + template<typename _It2, sentinel_for<_It> _Sent2> + requires sentinel_for<_Sent, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0000: + case 0b0101: + return true; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template<typename _It2, sentinel_for<_It> _Sent2> + requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return true; + case 0b0000: + return __x._M_it == __y._M_it; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template<sized_sentinel_for<_It> _It2, sized_sentinel_for<_It> _Sent2> + requires sized_sentinel_for<_Sent, _It2> + friend iter_difference_t<_It2> + operator-(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return 0; + case 0b0000: + return __x._M_it - __y._M_it; + case 0b0001: + return __x._M_it - __y._M_sent; + case 0b0100: + return __x._M_sent - __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + friend iter_rvalue_reference_t<_It> + iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(std::declval<const _It&>()))) + requires input_iterator<_It> + { + __glibcxx_assert(__i._M_index == 0); + return ranges::iter_move(__i._M_it); + } + + template<indirectly_swappable<_It> _It2, typename _Sent2> + friend void + iter_swap(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + noexcept(noexcept(ranges::iter_swap(std::declval<const _It&>(), + std::declval<const _It2&>()))) + { + __glibcxx_assert(__x._M_index == 0); + __glibcxx_assert(__y._M_index == 0); + return ranges::iter_swap(__x._M_it, __y._M_it); + } + + private: + template<input_or_output_iterator _It2, sentinel_for<_It2> _Sent2> + friend class common_iterator; + + bool _M_has_value() const noexcept { return _M_index < 2; } + + union + { + _It _M_it; + _Sent _M_sent; + unsigned char _M_valueless; + }; + unsigned char _M_index; // 0==_M_it, 1==_M_sent, 2==valueless + }; + + template<typename _It, typename _Sent> + struct incrementable_traits<common_iterator<_It, _Sent>> + { + using difference_type = iter_difference_t<_It>; + }; + + namespace __detail + { + // FIXME: This has to be at namespace-scope because of PR 92078. + template<typename _Iter> + struct __common_iter_ptr + { + using type = void; + }; + + template<typename _Iter> + requires __detail::__common_iter_has_arrow<_Iter> + struct __common_iter_ptr<_Iter> + { + using type = decltype(std::declval<const _Iter&>().operator->()); + }; + } // namespace __detail + + template<input_iterator _It, typename _Sent> + struct iterator_traits<common_iterator<_It, _Sent>> + { + using iterator_concept = conditional_t<forward_iterator<_It>, + forward_iterator_tag, input_iterator_tag>; + using iterator_category = __detail::__clamp_iter_cat< + typename iterator_traits<_It>::iterator_category, + forward_iterator_tag, input_iterator_tag>; + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + using pointer = typename + __detail::__common_iter_ptr<common_iterator<_It, _Sent>>::type; + using reference = iter_reference_t<_It>; + }; + + // [iterators.counted] Counted iterators + + /// An iterator adaptor that keeps track of the distance to the end. + template<input_or_output_iterator _It> + class counted_iterator + { + public: + using iterator_type = _It; + + constexpr counted_iterator() = default; + + constexpr + counted_iterator(_It __i, iter_difference_t<_It> __n) + : _M_current(__i), _M_length(__n) + { __glibcxx_assert(__n >= 0); } + + template<typename _It2> + requires convertible_to<const _It2&, _It> + constexpr + counted_iterator(const counted_iterator<_It2>& __x) + : _M_current(__x._M_current), _M_length(__x._M_length) + { } + + template<typename _It2> + requires assignable_from<_It&, const _It2&> + constexpr counted_iterator& + operator=(const counted_iterator<_It2>& __x) + { + _M_current = __x._M_current; + _M_length = __x._M_length; + return *this; + } + + constexpr _It + base() const & + noexcept(is_nothrow_copy_constructible_v<_It>) + requires copy_constructible<_It> + { return _M_current; } + + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + constexpr iter_difference_t<_It> + count() const noexcept { return _M_length; } + + constexpr decltype(auto) + operator*() + noexcept(noexcept(*_M_current)) + { return *_M_current; } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(*_M_current)) + requires __detail::__dereferenceable<const _It> + { return *_M_current; } + + constexpr counted_iterator& + operator++() + { + __glibcxx_assert(_M_length > 0); + ++_M_current; + --_M_length; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_length > 0); + --_M_length; + __try + { + return _M_current++; + } __catch(...) { + ++_M_length; + throw; + } + + } + + constexpr counted_iterator + operator++(int) requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr counted_iterator& + operator--() requires bidirectional_iterator<_It> + { + --_M_current; + ++_M_length; + return *this; + } + + constexpr counted_iterator + operator--(int) requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr counted_iterator + operator+(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current + __n, _M_length - __n); } + + friend constexpr counted_iterator + operator+(iter_difference_t<_It> __n, const counted_iterator& __x) + requires random_access_iterator<_It> + { return __x + __n; } + + constexpr counted_iterator& + operator+=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n <= _M_length); + _M_current += __n; + _M_length -= __n; + return *this; + } + + constexpr counted_iterator + operator-(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current - __n, _M_length + __n); } + + template<common_with<_It> _It2> + friend constexpr iter_difference_t<_It2> + operator-(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length - __x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(const counted_iterator& __x, default_sentinel_t) + { return -__x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(default_sentinel_t, const counted_iterator& __y) + { return __y._M_length; } + + constexpr counted_iterator& + operator-=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(-__n <= _M_length); + _M_current -= __n; + _M_length += __n; + return *this; + } + + constexpr decltype(auto) + operator[](iter_difference_t<_It> __n) const + noexcept(noexcept(_M_current[__n])) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n < _M_length); + return _M_current[__n]; + } + + template<common_with<_It> _It2> + friend constexpr bool + operator==(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __x._M_length == __y._M_length; } + + friend constexpr bool + operator==(const counted_iterator& __x, default_sentinel_t) + { return __x._M_length == 0; } + + template<common_with<_It> _It2> + friend constexpr strong_ordering + operator<=>(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length <=> __x._M_length; } + + friend constexpr iter_rvalue_reference_t<_It> + iter_move(const counted_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + requires input_iterator<_It> + { return ranges::iter_move(__i._M_current); } + + template<indirectly_swappable<_It> _It2> + friend constexpr void + iter_swap(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { ranges::iter_swap(__x._M_current, __y._M_current); } + + private: + template<input_or_output_iterator _It2> friend class counted_iterator; + + _It _M_current = _It(); + iter_difference_t<_It> _M_length = 0; + }; + + template<typename _It> + struct incrementable_traits<counted_iterator<_It>> + { + using difference_type = iter_difference_t<_It>; + }; + + template<input_iterator _It> + struct iterator_traits<counted_iterator<_It>> : iterator_traits<_It> + { + using pointer = void; + }; +#endif // C++20 + // @} group iterators template<typename _Iterator> @@ -1332,8 +2014,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __iter_to_alloc_t = pair<add_const_t<__iter_key_t<_InputIterator>>, __iter_val_t<_InputIterator>>; - -#endif +#endif // __cpp_deduction_guides _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 5566a087f9a..4e0fac8daac 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -80,11 +80,11 @@ namespace __debug // No explicit construct/copy/destroy for aggregate type. // DR 776. - void + _GLIBCXX20_CONSTEXPR void fill(const value_type& __u) { std::fill_n(begin(), size(), __u); } - void + _GLIBCXX20_CONSTEXPR void swap(array& __other) noexcept(_AT_Type::_Is_nothrow_swappable::value) { std::swap_ranges(begin(), end(), __other.begin()); } @@ -282,6 +282,7 @@ namespace __debug #endif template<typename _Tp, std::size_t _Nm> + _GLIBCXX20_CONSTEXPR inline void swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) noexcept(noexcept(__one.swap(__two))) diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h index ac93ee04720..0344f27143b 100644 --- a/libstdc++-v3/include/debug/helper_functions.h +++ b/libstdc++-v3/include/debug/helper_functions.h @@ -168,7 +168,7 @@ namespace __gnu_debug std::random_access_iterator_tag) { return - __valid_range_aux(__first, __last, std::input_iterator_tag{}) + __valid_range_aux(__first, __last, std::input_iterator_tag()) && __first <= __last; } @@ -192,7 +192,7 @@ namespace __gnu_debug typename _Distance_traits<_InputIterator>::__type& __dist, std::__false_type) { - if (!__valid_range_aux(__first, __last, std::input_iterator_tag{})) + if (!__valid_range_aux(__first, __last, std::input_iterator_tag())) return false; __dist = __get_distance(__first, __last); diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 6700eafca0b..fa0d03f39dc 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -140,6 +140,10 @@ namespace __gnu_debug typedef typename _Traits::reference reference; typedef typename _Traits::pointer pointer; +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = std::__detail::__iter_concept<_Iterator>; +#endif + /// @post the iterator is singular and unattached _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index a3655f616f2..5ce012eec81 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -71,111 +71,129 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 using std::basic_string_view; #endif - /** - * @addtogroup filesystem-ts - * @{ + /** @addtogroup filesystem-ts + * @{ */ - /// A filesystem path. - class path - { - template<typename _CharT, - typename _Ch = typename remove_const<_CharT>::type> - using __is_encoded_char - = __or_<is_same<_Ch, char>, - is_same<_Ch, wchar_t>, + /// @cond undocumented +namespace __detail +{ + template<typename _CharT, + typename _Ch = typename remove_const<_CharT>::type> + using __is_encoded_char + = __or_<is_same<_Ch, char>, + is_same<_Ch, wchar_t>, #ifdef _GLIBCXX_USE_CHAR8_T - is_same<_Ch, char8_t>, + is_same<_Ch, char8_t>, #endif - is_same<_Ch, char16_t>, - is_same<_Ch, char32_t>>; + is_same<_Ch, char16_t>, + is_same<_Ch, char32_t>>; - template<typename _Iter, - typename _Iter_traits = std::iterator_traits<_Iter>> - using __is_path_iter_src - = __and_<__is_encoded_char<typename _Iter_traits::value_type>, - std::is_base_of<std::input_iterator_tag, - typename _Iter_traits::iterator_category>>; + template<typename _Iter, + typename _Iter_traits = std::iterator_traits<_Iter>> + using __is_path_iter_src + = __and_<__is_encoded_char<typename _Iter_traits::value_type>, + std::is_base_of<std::input_iterator_tag, + typename _Iter_traits::iterator_category>>; - template<typename _Iter> - static __is_path_iter_src<_Iter> - __is_path_src(_Iter, int); + template<typename _Iter> + static __is_path_iter_src<_Iter> + __is_path_src(_Iter, int); - template<typename _CharT, typename _Traits, typename _Alloc> - static __is_encoded_char<_CharT> - __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); + template<typename _CharT, typename _Traits, typename _Alloc> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); #if __cplusplus >= 201402L - template<typename _CharT, typename _Traits> - static __is_encoded_char<_CharT> - __is_path_src(const basic_string_view<_CharT, _Traits>&, int); + template<typename _CharT, typename _Traits> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string_view<_CharT, _Traits>&, int); #endif - template<typename _Unknown> - static std::false_type - __is_path_src(const _Unknown&, ...); + template<typename _Unknown> + static std::false_type + __is_path_src(const _Unknown&, ...); - template<typename _Tp1, typename _Tp2> - struct __constructible_from; + template<typename _Tp1, typename _Tp2> + struct __constructible_from; - template<typename _Iter> - struct __constructible_from<_Iter, _Iter> - : __is_path_iter_src<_Iter> - { }; + template<typename _Iter> + struct __constructible_from<_Iter, _Iter> + : __is_path_iter_src<_Iter> + { }; - template<typename _Source> - struct __constructible_from<_Source, void> - : decltype(__is_path_src(std::declval<_Source>(), 0)) - { }; - - template<typename _Tp1, typename _Tp2 = void, - typename _Tp1_nocv = typename remove_cv<_Tp1>::type, - typename _Tp1_noptr = typename remove_pointer<_Tp1>::type> - using _Path = typename - std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>, - __not_<is_void<_Tp1_noptr>>, - __constructible_from<_Tp1, _Tp2>>::value, - path>::type; + template<typename _Source> + struct __constructible_from<_Source, void> + : decltype(__is_path_src(std::declval<_Source>(), 0)) + { }; + + template<typename _Tp1, typename _Tp2 = void, + typename _Tp1_nocv = typename remove_cv<_Tp1>::type, + typename _Tp1_noptr = typename remove_pointer<_Tp1>::type> + using _Path = typename + std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>, + __not_<is_void<_Tp1_noptr>>, + __constructible_from<_Tp1, _Tp2>>::value, + path>::type; - template<typename _Source> - static _Source - _S_range_begin(_Source __begin) { return __begin; } + template<typename _Source> + static _Source + _S_range_begin(_Source __begin) { return __begin; } - struct __null_terminated { }; + struct __null_terminated { }; - template<typename _Source> - static __null_terminated - _S_range_end(_Source) { return {}; } + template<typename _Source> + static __null_terminated + _S_range_end(_Source) { return {}; } - template<typename _CharT, typename _Traits, typename _Alloc> - static const _CharT* - _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) - { return __str.data(); } + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data(); } - template<typename _CharT, typename _Traits, typename _Alloc> - static const _CharT* - _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) - { return __str.data() + __str.size(); } + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data() + __str.size(); } #if __cplusplus >= 201402L - template<typename _CharT, typename _Traits> - static const _CharT* - _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) - { return __str.data(); } - - template<typename _CharT, typename _Traits> - static const _CharT* - _S_range_end(const basic_string_view<_CharT, _Traits>& __str) - { return __str.data() + __str.size(); } + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data(); } + + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_end(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data() + __str.size(); } +#endif + + 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 = typename std::enable_if< + 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; - template<typename _Tp, - typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), - typename _Val = typename std::iterator_traits<_Iter>::value_type> - using __value_type_is_char = typename std::enable_if< - std::is_same<typename std::remove_const<_Val>::type, char>::value - >::type; +} // namespace __detail + /// @endcond + /// A filesystem path. + class path + { public: #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS typedef wchar_t value_type; @@ -205,29 +223,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { _M_split_cmpts(); } template<typename _Source, - typename _Require = _Path<_Source>> + typename _Require = __detail::_Path<_Source>> path(_Source const& __source) - : _M_pathname(_S_convert(_S_range_begin(__source), - _S_range_end(__source))) + : _M_pathname(_S_convert(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source))) { _M_split_cmpts(); } template<typename _InputIterator, - typename _Require = _Path<_InputIterator, _InputIterator>> + typename _Require = __detail::_Path<_InputIterator, _InputIterator>> path(_InputIterator __first, _InputIterator __last) : _M_pathname(_S_convert(__first, __last)) { _M_split_cmpts(); } template<typename _Source, - typename _Require = _Path<_Source>, - typename _Require2 = __value_type_is_char<_Source>> + typename _Require = __detail::_Path<_Source>, + typename _Require2 = __detail::__value_type_is_char<_Source>> path(_Source const& __source, const locale& __loc) - : _M_pathname(_S_convert_loc(_S_range_begin(__source), - _S_range_end(__source), __loc)) + : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source), __loc)) { _M_split_cmpts(); } template<typename _InputIterator, - typename _Require = _Path<_InputIterator, _InputIterator>, - typename _Require2 = __value_type_is_char<_InputIterator>> + typename _Require = __detail::_Path<_InputIterator, _InputIterator>, + typename _Require2 = __detail::__value_type_is_char<_InputIterator>> path(_InputIterator __first, _InputIterator __last, const locale& __loc) : _M_pathname(_S_convert_loc(__first, __last, __loc)) { _M_split_cmpts(); } @@ -242,17 +260,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path& assign(string_type&& __source); template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& operator=(_Source const& __source) { return *this = path(__source); } template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& assign(_Source const& __source) { return *this = path(__source); } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& assign(_InputIterator __first, _InputIterator __last) { return *this = path(__first, __last); } @@ -260,21 +278,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path& operator/=(const path& __p) { return _M_append(__p._M_pathname); } - template <class _Source> - _Path<_Source>& + template<typename _Source> + __detail::_Path<_Source>& operator/=(_Source const& __source) { return append(__source); } template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& append(_Source const& __source) { - return _M_append(_S_convert(_S_range_begin(__source), - _S_range_end(__source))); + return _M_append(_S_convert(__detail::_S_range_begin(__source), + __detail::_S_range_end(__source))); } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& append(_InputIterator __first, _InputIterator __last) { return _M_append(_S_convert(__first, __last)); } @@ -289,20 +307,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& operator+=(_Source const& __x) { return concat(__x); } template<typename _CharT> - _Path<_CharT*, _CharT*>& + __detail::_Path<_CharT*, _CharT*>& operator+=(_CharT __x); template<typename _Source> - _Path<_Source>& + __detail::_Path<_Source>& concat(_Source const& __x) - { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); } + { + return *this += _S_convert(__detail::_S_range_begin(__x), + __detail::_S_range_end(__x)); + } template<typename _InputIterator> - _Path<_InputIterator, _InputIterator>& + __detail::_Path<_InputIterator, _InputIterator>& concat(_InputIterator __first, _InputIterator __last) { return *this += _S_convert(__first, __last); } @@ -446,11 +467,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct _Cvt; static string_type - _S_convert(value_type* __src, __null_terminated) + _S_convert(value_type* __src, __detail::__null_terminated) { return string_type(__src); } static string_type - _S_convert(const value_type* __src, __null_terminated) + _S_convert(const value_type* __src, __detail::__null_terminated) { return string_type(__src); } template<typename _Iter> @@ -464,7 +485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _InputIterator> static string_type - _S_convert(_InputIterator __src, __null_terminated) + _S_convert(_InputIterator __src, __detail::__null_terminated) { auto __s = _S_string_from_iter(__src); return _S_convert(__s.c_str(), __s.c_str() + __s.size()); @@ -484,7 +505,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _InputIterator> static string_type - _S_convert_loc(_InputIterator __src, __null_terminated, + _S_convert_loc(_InputIterator __src, __detail::__null_terminated, const std::locale& __loc) { const std::string __s = _S_string_from_iter(__src); @@ -580,12 +601,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } /// Create a path from a UTF-8-encoded sequence of char - // TODO constrain with _Path<InputIterator, InputIterator> and __value_type_is_char +#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; @@ -596,20 +616,75 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _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 - // TODO constrain with _Path<Source> and __value_type_is_char +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + inline path + __u8path(const string& __s, char) + { + return filesystem::u8path(__s.data(), __s.data() + __s.size()); + } + + template<typename _Source> + inline __enable_if_t<is_convertible<const _Source&, string>::value, path> + __u8path(const _Source& __source, char) + { + std::string __s = __source; + return filesystem::u8path(__s.data(), __s.data() + __s.size()); + } + + template<typename _Source> + inline __enable_if_t<!is_convertible<const _Source&, string>::value, 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 _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 @@ -672,8 +747,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct path::_Cvt { #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS +#ifdef _GLIBCXX_USE_CHAR8_T + static string_type + _S_wconvert(const char8_t* __f, const char8_t* __l, const char8_t*) + { + const char* __f2 = (const char*)__f; + const char* __l2 = (const char*)__l; + std::wstring __wstr; + std::codecvt_utf8_utf16<wchar_t> __wcvt; + if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt)) + return __wstr; + } +#endif + static string_type - _S_wconvert(const char* __f, const char* __l, true_type) + _S_wconvert(const char* __f, const char* __l, const char*) { using _Cvt = std::codecvt<wchar_t, char, mbstate_t>; const auto& __cvt = std::use_facet<_Cvt>(std::locale{}); @@ -686,36 +774,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } static string_type - _S_wconvert(const _CharT* __f, const _CharT* __l, false_type) + _S_wconvert(const _CharT* __f, const _CharT* __l, const void*) { -#ifdef _GLIBCXX_USE_CHAR8_T - if constexpr (is_same<_CharT, char8_t>::value) - return _S_wconvert((const char*)__f, (const char*)__l, true_type()); - else -#endif + struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> + { } __cvt; + std::string __str; + if (__str_codecvt_out_all(__f, __l, __str, __cvt)) { - struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> - { } __cvt; - std::string __str; - if (__str_codecvt_out_all(__f, __l, __str, __cvt)) - { - const char* __f2 = __str.data(); - const char* __l2 = __f2 + __str.size(); - std::codecvt_utf8_utf16<wchar_t> __wcvt; - std::wstring __wstr; - if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt)) - return __wstr; - } - _GLIBCXX_THROW_OR_ABORT(filesystem_error( - "Cannot convert character sequence", - std::make_error_code(errc::illegal_byte_sequence))); + const char* __f2 = __str.data(); + const char* __l2 = __f2 + __str.size(); + std::codecvt_utf8_utf16<wchar_t> __wcvt; + std::wstring __wstr; + if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt)) + return __wstr; } + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); } static string_type _S_convert(const _CharT* __f, const _CharT* __l) { - return _S_wconvert(__f, __l, is_same<_CharT, char>{}); + return _S_wconvert(__f, __l, (const _CharT*)nullptr); } #else static string_type @@ -725,19 +806,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 if constexpr (is_same<_CharT, char8_t>::value) return string_type(__f, __l); else - { #endif + { struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> { } __cvt; std::string __str; if (__str_codecvt_out_all(__f, __l, __str, __cvt)) return __str; -#ifdef _GLIBCXX_USE_CHAR8_T + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); } -#endif - _GLIBCXX_THROW_OR_ABORT(filesystem_error( - "Cannot convert character sequence", - std::make_error_code(errc::illegal_byte_sequence))); } #endif @@ -872,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif template<typename _CharT> - inline path::_Path<_CharT*, _CharT*>& + inline __detail::_Path<_CharT*, _CharT*>& path::operator+=(_CharT __x) { auto* __addr = std::__addressof(__x); diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 2541d978886..895e4d7ab4e 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -512,21 +512,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return (__out << __out.widen(__c)); } // Specialization - template <class _Traits> + template<typename _Traits> inline basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& __out, char __c) { return __ostream_insert(__out, &__c, 1); } // Signed and unsigned - template<class _Traits> + template<typename _Traits> inline basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& __out, signed char __c) { return (__out << static_cast<char>(__c)); } - template<class _Traits> + template<typename _Traits> 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<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char8_t) = delete; +#endif + + template<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char16_t) = delete; + + template<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, char32_t) = delete; + +#ifdef _GLIBCXX_USE_WCHAR_T +#ifdef _GLIBCXX_USE_CHAR8_T + template<typename _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete; +#endif // _GLIBCXX_USE_CHAR8_T + + template<typename _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete; + + template<typename _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete; +#endif // _GLIBCXX_USE_WCHAR_T +#endif // C++20 //@} //@{ @@ -560,7 +601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s); // Partial specializations - template<class _Traits> + template<typename _Traits> inline basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& __out, const char* __s) { @@ -573,15 +614,56 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Signed and unsigned - template<class _Traits> + template<typename _Traits> inline basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s) { return (__out << reinterpret_cast<const char*>(__s)); } - template<class _Traits> + template<typename _Traits> 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<typename _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<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete; +#endif // _GLIBCXX_USE_CHAR8_T + + template<typename _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete; + + template<typename _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<typename _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete; +#endif + + template<typename _Traits> + basic_ostream<wchar_t, _Traits>& + operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete; + + template<typename _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 diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index cd79a1fa6e6..869a8286675 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -94,13 +94,78 @@ def find_type(orig, name): # The type was not found, so try the superclass. We only need # to check the first superclass, so we don't bother with # anything fancier here. - field = typ.fields()[0] - if not field.is_base_class: + fields = typ.fields() + if len(fields) and fields[0].is_base_class: + typ = fields[0].type + else: raise ValueError("Cannot find type %s::%s" % (str(orig), name)) - typ = field.type _versioned_namespace = '__8::' +def lookup_templ_spec(templ, *args): + """ + Lookup template specialization templ<args...> + """ + t = '{}<{}>'.format(templ, ', '.join([str(a) for a in args])) + try: + return gdb.lookup_type(t) + except gdb.error as e: + # Type not found, try again in versioned namespace. + global _versioned_namespace + if _versioned_namespace and _versioned_namespace not in templ: + t = t.replace('::', '::' + _versioned_namespace, 1) + try: + return gdb.lookup_type(t) + except gdb.error: + # If that also fails, rethrow the original exception + pass + raise e + +# Use this to find container node types instead of find_type, +# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91997 for details. +def lookup_node_type(nodename, containertype): + """ + Lookup specialization of template NODENAME corresponding to CONTAINERTYPE. + e.g. if NODENAME is '_List_node' and CONTAINERTYPE is std::list<int> + then return the type std::_List_node<int>. + Returns None if not found. + """ + # If nodename is unqualified, assume it's in namespace std. + if '::' not in nodename: + nodename = 'std::' + nodename + try: + valtype = find_type(containertype, 'value_type') + except: + valtype = containertype.template_argument(0) + valtype = valtype.strip_typedefs() + try: + return lookup_templ_spec(nodename, valtype) + except gdb.error as e: + # For debug mode containers the node is in std::__cxx1998. + if is_member_of_namespace(nodename, 'std'): + if is_member_of_namespace(containertype, 'std::__cxx1998', + 'std::__debug', '__gnu_debug'): + nodename = nodename.replace('::', '::__cxx1998::', 1) + return lookup_templ_spec(nodename, valtype) + try: + return lookup_templ_spec(nodename, valtype) + except gdb.error: + pass + return None + +def is_member_of_namespace(typ, *namespaces): + """ + Test whether a type is a member of one of the specified namespaces. + The type can be specified as a string or a gdb.Type object. + """ + if type(typ) is gdb.Type: + typ = str(typ) + typ = strip_versioned_namespace(typ) + for namespace in namespaces: + if typ.startswith(namespace + '::'): + return True + return False + def is_specialization_of(x, template_name): "Test if a type is a given template instantiation." global _versioned_namespace @@ -253,40 +318,40 @@ class StdListPrinter: self.val = val def children(self): - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() + nodetype = lookup_node_type('_List_node', self.val.type).pointer() return self._iterator(nodetype, self.val['_M_impl']['_M_node']) def to_string(self): - if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: + headnode = self.val['_M_impl']['_M_node'] + if headnode['_M_next'] == headnode.address: return 'empty %s' % (self.typename) return '%s' % (self.typename) class NodeIteratorPrinter: - def __init__(self, typename, val, contname): + def __init__(self, typename, val, contname, nodename): self.val = val self.typename = typename self.contname = contname + self.nodetype = lookup_node_type(nodename, val.type) def to_string(self): if not self.val['_M_node']: return 'non-dereferenceable iterator for std::%s' % (self.contname) - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() - node = self.val['_M_node'].cast(nodetype).dereference() + node = self.val['_M_node'].cast(self.nodetype.pointer()).dereference() return str(get_value_from_list_node(node)) class StdListIteratorPrinter(NodeIteratorPrinter): "Print std::list::iterator" def __init__(self, typename, val): - NodeIteratorPrinter.__init__(self, typename, val, 'list') + NodeIteratorPrinter.__init__(self, typename, val, 'list', '_List_node') class StdFwdListIteratorPrinter(NodeIteratorPrinter): "Print std::forward_list::iterator" def __init__(self, typename, val): - NodeIteratorPrinter.__init__(self, typename, val, 'forward_list') + NodeIteratorPrinter.__init__(self, typename, val, 'forward_list', + '_Fwd_list_node') class StdSlistPrinter: "Print a __gnu_cxx::slist" @@ -313,9 +378,8 @@ class StdSlistPrinter: self.val = val def children(self): - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() - return self._iterator(nodetype, self.val) + nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type) + return self._iterator(nodetype.pointer(), self.val) def to_string(self): if self.val['_M_head']['_M_next'] == 0: @@ -331,8 +395,7 @@ class StdSlistIteratorPrinter: def to_string(self): if not self.val['_M_node']: return 'non-dereferenceable iterator for __gnu_cxx::slist' - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() + nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type).pointer() return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data']) class StdVectorPrinter: @@ -583,12 +646,8 @@ class StdRbtreeIteratorPrinter: def __init__ (self, typename, val): self.val = val - valtype = self.val.type.template_argument(0).strip_typedefs() - nodetype = '_Rb_tree_node<' + str(valtype) + '>' - if _versioned_namespace and typename.startswith('std::' + _versioned_namespace): - nodetype = _versioned_namespace + nodetype - nodetype = gdb.lookup_type('std::' + nodetype) - self.link_type = nodetype.strip_typedefs().pointer() + nodetype = lookup_node_type('_Rb_tree_node', self.val.type) + self.link_type = nodetype.pointer() def to_string (self): if not self.val['_M_node']: @@ -653,9 +712,7 @@ class StdMapPrinter: num_elements(len(RbtreeIterator (self.val)))) def children (self): - rep_type = find_type(self.val.type, '_Rep_type') - node = find_type(rep_type, '_Link_type') - node = node.strip_typedefs() + node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() return self._iter (RbtreeIterator (self.val), node) def display_hint (self): @@ -693,9 +750,7 @@ class StdSetPrinter: num_elements(len(RbtreeIterator (self.val)))) def children (self): - rep_type = find_type(self.val.type, '_Rep_type') - node = find_type(rep_type, '_Link_type') - node = node.strip_typedefs() + node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() return self._iter (RbtreeIterator (self.val), node) class StdBitsetPrinter: @@ -853,11 +908,11 @@ class StdStringPrinter: return 'string' class Tr1HashtableIterator(Iterator): - def __init__ (self, hash): - self.buckets = hash['_M_buckets'] + def __init__ (self, hashtable): + self.buckets = hashtable['_M_buckets'] self.bucket = 0 - self.bucket_count = hash['_M_bucket_count'] - self.node_type = find_type(hash.type, '_Node').pointer() + self.bucket_count = hashtable['_M_bucket_count'] + self.node_type = find_type(hashtable.type, '_Node').pointer() self.node = 0 while self.bucket != self.bucket_count: self.node = self.buckets[self.bucket] @@ -884,9 +939,13 @@ class Tr1HashtableIterator(Iterator): return result class StdHashtableIterator(Iterator): - def __init__(self, hash): - self.node = hash['_M_before_begin']['_M_nxt'] - self.node_type = find_type(hash.type, '__node_type').pointer() + def __init__(self, hashtable): + self.node = hashtable['_M_before_begin']['_M_nxt'] + valtype = hashtable.type.template_argument(1) + cached = hashtable.type.template_argument(9).template_argument(0) + node_type = lookup_templ_spec('std::__detail::_Hash_node', str(valtype), + 'true' if cached else 'false') + self.node_type = node_type.pointer() def __iter__(self): return self @@ -901,7 +960,7 @@ class StdHashtableIterator(Iterator): return valptr.dereference() class Tr1UnorderedSetPrinter: - "Print a tr1::unordered_set" + "Print a std::unordered_set or tr1::unordered_set" def __init__ (self, typename, val): self.typename = strip_versioned_namespace(typename) @@ -927,7 +986,7 @@ class Tr1UnorderedSetPrinter: return izip (counter, StdHashtableIterator (self.hashtable())) class Tr1UnorderedMapPrinter: - "Print a tr1::unordered_map" + "Print a std::unordered_map or tr1::unordered_map" def __init__ (self, typename, val): self.typename = strip_versioned_namespace(typename) @@ -998,8 +1057,7 @@ class StdForwardListPrinter: self.typename = strip_versioned_namespace(typename) def children(self): - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() + nodetype = lookup_node_type('_Fwd_list_node', self.val.type).pointer() return self._iterator(nodetype, self.val['_M_impl']['_M_head']) def to_string(self): diff --git a/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc new file mode 100644 index 00000000000..275ef53fe6a --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc @@ -0,0 +1,160 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + using I = std::common_iterator<int*, const int*>; + static_assert( std::is_default_constructible_v<I> ); + static_assert( std::is_copy_constructible_v<I> ); + static_assert( std::is_copy_assignable_v<I> ); + static_assert( std::is_constructible_v<I, int*> ); + static_assert( std::is_constructible_v<I, const int*> ); + + struct sentinel { operator int*() const { return nullptr; } }; + using K = std::common_iterator<int*, sentinel>; + static_assert( std::is_constructible_v<I, const K&> ); + static_assert( std::is_assignable_v<I, const K&> ); + + struct sentinel2 + { + const int* p; + sentinel2(const int* p = 0) : p(p) { } + bool operator==(const int* p) const { return p == this->p; } + }; + + using J = std::common_iterator<const int*, sentinel2>; + static_assert( std::is_constructible_v<J, const I&> ); + static_assert( std::is_convertible_v<const I&, J> ); +} + +void +test02() +{ + struct sentinel { int limit; }; + + struct iterator + { + using iterator_category = std::input_iterator_tag; + using value_type = int; + using difference_type = std::ptrdiff_t; + using reference = const int&; + + const int& operator*() const { return counter; } + + iterator& operator++() { ++counter; return *this; } + + iterator operator++(int) { auto i = *this; ++counter; return i; } + + bool operator==(sentinel s) const { return counter == s.limit; } + + int counter = 0; + }; + + static_assert( std::sentinel_for<sentinel, iterator> ); + + int out[5] = { }; + std::common_iterator<int*, const int*> obegin = std::begin(out); + std::common_iterator<int*, const int*> oend = std::cend(out); + + iterator i; + sentinel s{5}; + std::common_iterator<iterator, sentinel> begin = i, end = s; + while (begin != end) + *obegin++ = *begin++; + + VERIFY(obegin == oend); + for (int& i : out) + VERIFY( i == (&i - out) ); +} + +void +test03() +{ + int arr[2] = { 1, 2 }; + std::common_iterator<int*, const int*> i = std::ranges::begin(arr); + std::common_iterator<int*, const int*> end = std::ranges::cend(arr); + VERIFY( i != end ); + VERIFY( (end - i) == 2 ); + VERIFY( (i - end) == -2 ); + auto j = i; + VERIFY( j == i ); + VERIFY( (j - i) == 0 ); + j = end; + VERIFY( j != i ); + VERIFY( j == end ); + j = std::ranges::next(i); + VERIFY( j != i ); + VERIFY( j != end ); + VERIFY( (end - j) == 1 ); + VERIFY( (j - i) == 1 ); + VERIFY( (i - j) == -1 ); + ++j; + VERIFY( j == end ); + VERIFY( (end - j) == 0 ); + j = i; + VERIFY( j == i ); + VERIFY( (j - end) == -2 ); + VERIFY( (j - i) == 0 ); + + try + { + struct S { operator const int*() const { throw 1; } }; + i = std::common_iterator<int*, S>(S{}); + VERIFY( false ); + } + catch (int) + { + } +} + +void +test04() +{ + struct X + { + X(int i) : i(i) { } + X(X&& x) : i(x.i) { x.i = -1; } + X& operator=(X&& x) { i = x.i; x.i = 0; return *this; } + int i; + }; + + X arr[] = { 1, 2 }; + std::common_iterator<X*, const X*> i(arr), j(arr+1); + std::ranges::iter_swap(i, j); + VERIFY( arr[0].i == 2 ); + VERIFY( arr[1].i == 1 ); + + X x = std::ranges::iter_move(i); + VERIFY( arr[0].i == -1 ); + VERIFY( x.i == 2 ); +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc b/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc new file mode 100644 index 00000000000..b31469cdebf --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc @@ -0,0 +1,101 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + using I = std::counted_iterator<int*>; + static_assert( std::is_default_constructible_v<I> ); + static_assert( std::is_copy_constructible_v<I> ); + static_assert( std::is_copy_assignable_v<I> ); + static_assert( ! std::is_constructible_v<I, int*> ); + static_assert( std::is_constructible_v<I, int*, std::ptrdiff_t> ); + + using J = std::counted_iterator<const int*>; + static_assert( std::is_constructible_v<J, const I&> ); + static_assert( std::is_convertible_v<const I&, J> ); +} + +void +test02() +{ + int in[3] = { 1, 2, 3 }; + std::counted_iterator<const int*> in_iter(std::begin(in), std::ssize(in)); + VERIFY( in_iter.base() == in ); + VERIFY( (std::default_sentinel - in_iter) == 3 ); + VERIFY( (in_iter - std::default_sentinel) == -3 ); + + int out[4] = { }; + std::counted_iterator<int*> out_iter(std::begin(out), std::ssize(out)); + VERIFY( out_iter.base() == out ); + VERIFY( (std::default_sentinel - out_iter) == 4 ); + VERIFY( (out_iter - std::default_sentinel) == -4 ); + + while (in_iter != std::default_sentinel && out_iter != std::default_sentinel) + *out_iter++ = *in_iter++; + + VERIFY(in_iter == std::default_sentinel); + VERIFY(out_iter != std::default_sentinel); + VERIFY( out[0] == 1 ); + VERIFY( out[1] == 2 ); + VERIFY( out[2] == 3 ); + VERIFY( out[3] == 0 ); + + auto out2 = out_iter; + out2 += 1; + VERIFY( out2 == std::default_sentinel ); + VERIFY( (out2 <=> out_iter) == std::strong_ordering::greater ); + out2 -= 3; + VERIFY( (out_iter - out2) == 2 ); + VERIFY( (out2 <=> out_iter) == std::strong_ordering::less ); +} + +void +test03() +{ + struct X + { + X(int i) : i(i) { } + X(X&& x) : i(x.i) { x.i = -1; } + X& operator=(X&& x) { i = x.i; x.i = 0; return *this; } + int i; + }; + + X arr[] = { 1, 2 }; + std::counted_iterator<X*> i(arr, 2), j(arr + 1, 1); + std::ranges::iter_swap(i, j); + VERIFY( arr[0].i == 2 ); + VERIFY( arr[1].i == 1 ); + + X x = std::ranges::iter_move(i); + VERIFY( arr[0].i == -1 ); + VERIFY( x.i == 2 ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc b/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc new file mode 100644 index 00000000000..6d0817dc204 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + struct X + { + X(int i) : i(i) { } + X(X&& x) : i(x.i) { x.i = -1; } + X& operator=(X&& x) { i = x.i; x.i = 0; return *this; } + int i; + }; + + X arr[] = { 1, 2 }; + std::move_iterator<X*> i(arr), j(arr + 1); + std::ranges::iter_swap(i, j); + VERIFY( arr[0].i == 2 ); + VERIFY( arr[1].i == 1 ); + + X x = std::ranges::iter_move(i); + VERIFY( arr[0].i == -1 ); + VERIFY( x.i == 2 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc b/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc new file mode 100644 index 00000000000..875a8fc37c4 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + using S = std::move_sentinel<const int*>; + using M = std::move_iterator<int*>; + + static_assert( std::is_default_constructible_v<S> ); + static_assert( std::is_copy_constructible_v<S> ); + static_assert( std::is_copy_assignable_v<S> ); + static_assert( std::is_constructible_v<S, std::move_sentinel<int*>> ); + static_assert( std::is_assignable_v<S, std::move_sentinel<int*>> ); + + constexpr S s; + static_assert( s.base() == nullptr ); + + constexpr M m; + static_assert( m == s ); + static_assert( s == m ); + static_assert( !(m != s) ); + static_assert( !(s != m) ); + + int i = 0; + M m2(&i); + VERIFY( m2 != s ); + VERIFY( s != m2 ); + VERIFY( !(m2 == s) ); + VERIFY( !(s == m2) ); +} + +void +test02() +{ + struct sentinel { int limit; }; + + struct iterator + { + using iterator_category = std::input_iterator_tag; + using value_type = int; + using difference_type = std::ptrdiff_t; + using reference = const int&; + + const int& operator*() const { return counter; } + + iterator& operator++() { ++counter; return *this; } + + iterator operator++(int) { auto i = *this; ++counter; return i; } + + bool operator==(sentinel s) const { return counter == s.limit; } + + int counter = 0; + }; + + static_assert( std::sentinel_for<sentinel, iterator> ); + + iterator i; + sentinel s{5}; + int count = 0; + for (auto m = std::make_move_iterator(i); m != std::move_sentinel{s}; ++m) + ++count; + VERIFY( count == 5 ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc new file mode 100644 index 00000000000..f2eb538f42e --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// 29.7.2 Header <ostream> synopsys; deleted character inserters. + +// Test character inserters defined as deleted by P1423. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <ostream> + +void test_character_inserters(std::ostream &os) +{ + os << 'x'; // ok. + os << L'x'; // { dg-error "use of deleted function" } + os << u8'x'; // { dg-error "use of deleted function" } + os << u'x'; // { dg-error "use of deleted function" } + os << U'x'; // { dg-error "use of deleted function" } +} + +void test_string_inserters(std::ostream &os) +{ + os << "text"; // ok. + os << L"text"; // { dg-error "use of deleted function" } + os << u8"text"; // { dg-error "use of deleted function" } + os << u"text"; // { dg-error "use of deleted function" } + os << U"text"; // { dg-error "use of deleted function" } +} diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc new file mode 100644 index 00000000000..1422a01aab3 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// 29.7.2 Header <ostream> synopsys; deleted character inserters. + +// Test wide character inserters defined as deleted by P1423. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <ostream> + +void test_character_inserters(std::wostream &os) +{ + os << 'x'; // ok. + os << L'x'; // ok. + os << u8'x'; // { dg-error "use of deleted function" } + os << u'x'; // { dg-error "use of deleted function" } + os << U'x'; // { dg-error "use of deleted function" } +} + +void test_string_inserters(std::wostream &os) +{ + os << "text"; // ok. + os << L"text"; // ok. + os << u8"text"; // { dg-error "use of deleted function" } + os << u"text"; // { dg-error "use of deleted function" } + os << U"text"; // { dg-error "use of deleted function" } +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc new file mode 100644 index 00000000000..867ee5b3856 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++17 -fchar8_t" } +// { dg-do run { target c++17 } } + +#include <filesystem> +#include <string_view> +#include <testsuite_hooks.h> + +namespace fs = std::filesystem; + +void +test01() +{ + fs::path p = fs::u8path(u8""); + VERIFY( p.empty() ); + + p = fs::u8path(u8"filename1"); + VERIFY( p.u8string() == u8"filename1" ); + + p = fs::u8path(u8"\xf0\x9d\x84\x9e"); + VERIFY( p.u8string() == u8"\U0001D11E" ); + + std::u8string s1 = u8"filename2"; + p = fs::u8path(s1); + VERIFY( p.u8string() == u8"filename2" ); + + std::u8string s2 = u8"filename3"; + p = fs::u8path(s2.begin(), s2.end()); + VERIFY( p.u8string() == u8"filename3" ); + + std::u8string_view sv1{ s1 }; + p = fs::u8path(sv1); + VERIFY( p.u8string() == u8"filename2" ); + + std::u8string_view sv2{ s2 }; + p = fs::u8path(sv2.begin(), sv2.end()); + VERIFY( p.u8string() == u8"filename3" ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc index aff722b5867..fb337ce1284 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc @@ -19,6 +19,7 @@ // { dg-do run { target c++17 } } #include <filesystem> +#include <string_view> #include <testsuite_hooks.h> namespace fs = std::filesystem; @@ -34,6 +35,22 @@ test01() p = fs::u8path("\xf0\x9d\x84\x9e"); VERIFY( p.u8string() == u8"\U0001D11E" ); + + std::string s1 = "filename2"; + p = fs::u8path(s1); + VERIFY( p.u8string() == u8"filename2" ); + + std::string s2 = "filename3"; + p = fs::u8path(s2.begin(), s2.end()); + VERIFY( p.u8string() == u8"filename3" ); + + std::string_view sv1{ s1 }; + p = fs::u8path(sv1); + VERIFY( p.u8string() == u8"filename2" ); + + std::string_view sv2{ s2 }; + p = fs::u8path(sv2.begin(), sv2.end()); + VERIFY( p.u8string() == u8"filename3" ); } void diff --git a/libstdc++-v3/testsuite/experimental/feat-char8_t.cc b/libstdc++-v3/testsuite/experimental/feat-char8_t.cc index e843604266c..c9b277a4626 100644 --- a/libstdc++-v3/testsuite/experimental/feat-char8_t.cc +++ b/libstdc++-v3/testsuite/experimental/feat-char8_t.cc @@ -12,6 +12,6 @@ #ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t" -#elif __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t != 201811L" +#elif __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t != 201907L" #endif diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc new file mode 100644 index 00000000000..dc509c3f912 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc @@ -0,0 +1,52 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-lstdc++fs -fchar8_t" } +// { dg-do run { target c++11 } } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + fs::path p = fs::u8path(u8""); + VERIFY( p.empty() ); + + p = fs::u8path(u8"filename1"); + VERIFY( p.u8string() == u8"filename1" ); + + p = fs::u8path(u8"\xf0\x9d\x84\x9e"); + VERIFY( p.u8string() == u8"\U0001D11E" ); + + std::u8string s1 = u8"filename2"; + p = fs::u8path(s1); + VERIFY( p.u8string() == u8"filename2" ); + + std::u8string s2 = u8"filename3"; + p = fs::u8path(s2.begin(), s2.end()); + VERIFY( p.u8string() == u8"filename3" ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc index bdeb3946a15..83219b7ddda 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc @@ -35,6 +35,14 @@ test01() p = fs::u8path("\xf0\x9d\x84\x9e"); VERIFY( p.u8string() == u8"\U0001D11E" ); + + std::string s1 = "filename2"; + p = fs::u8path(s1); + VERIFY( p.u8string() == u8"filename2" ); + + std::string s2 = "filename3"; + p = fs::u8path(s2.begin(), s2.end()); + VERIFY( p.u8string() == u8"filename3" ); } void diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc index 215899f3d2e..af629496b47 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc @@ -45,8 +45,6 @@ int main() std::list<C> l; l.push_back(c); std::list<C>::iterator liter = l.begin(); - // Need to ensure the list<C>::iterator::_Node typedef is in the debuginfo: - int tmp __attribute__((unused)) = (*liter).ref; // { dg-final { regexp-test liter {ref = @0x.*} } } __gnu_cxx::slist<C> sl; diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc new file mode 100644 index 00000000000..393c5680e2e --- /dev/null +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc @@ -0,0 +1,53 @@ +// { dg-options "-std=gnu++17 -g -O0 -Wno-unused" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <forward_list> +#include <list> +#include <set> +#include <map> +#include <string> +#include <any> +#include <iostream> + +int main() +{ + std::list<std::string> list{"a"}; + std::list<std::string>::iterator lit = list.begin(); + // { dg-final { note-test lit {"a"} } } + + std::forward_list<std::string> flist{"b"}; + std::forward_list<std::string>::iterator flit = flist.begin(); + // { dg-final { note-test flit {"b"} } } + + std::map<int, int> m{ {1, 2} }; + auto mit = m.begin(); + // { dg-final { note-test mit {{first = 1, second = 2}} } } + + std::any a = m; + // { dg-final { note-test a {std::any containing std::map with 1 element = {[1] = 2}} } } + + std::set<int> s{1, 2}; + auto sit = s.begin(); + // { dg-final { note-test sit {1} } } + + std::cout << "\n"; + return 0; // Mark SPOT +} +// { dg-final { gdb-test SPOT } } |