For some reason the Filesystem library says that you can construct paths from iterators with value_type that is a possibly const encoded character type. I don't know why we support const value_type in this place, when normally that is bogus (even const_iterators have a non-const value_type, and various algorithms won't compile with const value_type).
Anyway, this fixes path to allow such wonky iterators, and fixes a bug where I was using *iter++ which isn't defined for input iterators. * include/experimental/bits/fs_path.h (path::_S_convert<_Iter>(_Iter, _Iter)): Remove cv-qualifiers from iterator's value_type. (path::_S_convert<_Iter>(_Iter __first, __null_terminated)): Likewise. Do not use operation not supported by input iterators. (path::__is_path_iter_src): Add partial specialization for const encoded character types. * testsuite/experimental/filesystem/path/construct/range.cc: Test construction from input iterators with const value types. Tested powerpc64le-linux, committed to trunk.
commit e8d357aafe250824728fd9e69dcf650871f6a6e6 Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Oct 28 18:07:18 2016 +0100 Fix filesystem::path for iterators with const value_type * include/experimental/bits/fs_path.h (path::_S_convert<_Iter>(_Iter, _Iter)): Remove cv-qualifiers from iterator's value_type. (path::_S_convert<_Iter>(_Iter __first, __null_terminated)): Likewise. Do not use operation not supported by input iterators. (path::__is_path_iter_src): Add partial specialization for const encoded character types. * testsuite/experimental/filesystem/path/construct/range.cc: Test construction from input iterators with const value types. diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 4d7291f..f6a290d 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -385,7 +385,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _S_convert(_Iter __first, _Iter __last) { using __value_type = typename std::iterator_traits<_Iter>::value_type; - return _Cvt<__value_type>::_S_convert(__first, __last); + return _Cvt<remove_cv_t<__value_type>>::_S_convert(__first, __last); } template<typename _InputIterator> @@ -393,10 +393,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _S_convert(_InputIterator __src, __null_terminated) { using _Tp = typename std::iterator_traits<_InputIterator>::value_type; - std::basic_string<_Tp> __tmp; - while (*__src != _Tp{}) - __tmp.push_back(*__src++); - return _S_convert(__tmp.data(), __tmp.data() + __tmp.size()); + std::basic_string<remove_cv_t<_Tp>> __tmp; + for (; *__src != _Tp{}; ++__src) + __tmp.push_back(*__src); + return _S_convert(__tmp.c_str(), __tmp.c_str() + __tmp.size()); } static string_type @@ -571,6 +571,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct path::__is_encoded_char<char32_t> : std::true_type { using value_type = char32_t; }; + template<typename _Tp> + struct path::__is_encoded_char<const _Tp> : __is_encoded_char<_Tp> { }; + struct path::_Cmpt : path { _Cmpt(string_type __s, _Type __t, size_t __pos) diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc index b68e65d..3dfec2f 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc @@ -24,6 +24,7 @@ #include <experimental/filesystem> #include <string> #include <testsuite_fs.h> +#include <testsuite_iterators.h> using std::experimental::filesystem::path; using __gnu_test::compare_paths; @@ -54,6 +55,52 @@ test01() compare_paths(p1, p7); compare_paths(p1, p8); #endif + + using __gnu_test::test_container; + using __gnu_test::input_iterator_wrapper; + // Test with input iterators and const value_types + test_container<char, input_iterator_wrapper> + r1(&s.front(), &s.front() + s.size()); + path p9(r1.begin(), r1.end()); + compare_paths(p1, p9); + + test_container<char, input_iterator_wrapper> + r2(&s.front(), &s.front() + s.size() + 1); // includes null-terminator + path p10(r2.begin()); + compare_paths(p1, p10); + + test_container<const char, input_iterator_wrapper> + r3(s.c_str(), s.c_str() + s.size()); + path p11(r3.begin(), r3.end()); + compare_paths(p1, p11); + + test_container<const char, input_iterator_wrapper> + r4(s.c_str(), s.c_str() + s.size() + 1); // includes null-terminator + path p12(r4.begin()); + compare_paths(p1, p12); + +#if _GLIBCXX_USE_WCHAR_T + // Test with input iterators and const value_types + test_container<wchar_t, input_iterator_wrapper> + r5(&ws.front(), &ws.front() + ws.size()); + path p13(r5.begin(), r5.end()); + compare_paths(p1, p13); + + test_container<wchar_t, input_iterator_wrapper> + r6(&ws.front(), &ws.front() + ws.size() + 1); // includes null-terminator + path p14(r6.begin()); + compare_paths(p1, p14); + + test_container<const wchar_t, input_iterator_wrapper> + r7(ws.c_str(), ws.c_str() + ws.size()); + path p15(r7.begin(), r7.end()); + compare_paths(p1, p15); + + test_container<const wchar_t, input_iterator_wrapper> + r8(ws.c_str(), ws.c_str() + ws.size() + 1); // includes null-terminator + path p16(r8.begin()); + compare_paths(p1, p16); +#endif } }