aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog117
-rw-r--r--libstdc++-v3/acinclude.m43
-rwxr-xr-xlibstdc++-v3/configure3
-rw-r--r--libstdc++-v3/include/bits/c++config2
-rw-r--r--libstdc++-v3/include/bits/fs_path.h359
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h5
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h695
-rw-r--r--libstdc++-v3/include/debug/array5
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h4
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h4
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_path.h369
-rw-r--r--libstdc++-v3/include/std/ostream94
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py138
-rw-r--r--libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc160
-rw-r--r--libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc101
-rw-r--r--libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc50
-rw-r--r--libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc91
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc43
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc43
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc60
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc17
-rw-r--r--libstdc++-v3/testsuite/experimental/feat-char8_t.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc52
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc8
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc2
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc53
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 } }