diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-03-21 21:51:07 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-03-21 22:04:48 +0000 |
commit | 9fc985118d9f5014afc1caf32a411ee5803fba61 (patch) | |
tree | 1e6aaade4c304f7f5c240715682adc07cd1d70b3 /libstdc++-v3 | |
parent | dfb25dfe3d34703f6e493664831dfaf53672b07b (diff) |
libstdc++: Fix path::generic_string allocator handling (PR 94242)
It's not possible to construct a path::string_type from an allocator of
a different type. Create the correct specialization of basic_string, and
adjust path::_S_str_convert to use a basic_string_view so that it is
independent of the allocator type.
PR libstdc++/94242
* include/bits/fs_path.h (path::_S_str_convert): Replace first
parameter with basic_string_view so that strings with different
allocators can be accepted.
(path::generic_string<C,T,A>()): Use basic_string object that uses the
right allocator type.
* testsuite/27_io/filesystem/path/generic/94242.cc: New test.
* testsuite/27_io/filesystem/path/generic/generic_string.cc: Improve
test coverage.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 12 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/fs_path.h | 11 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/path/generic/94242.cc | 52 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc | 32 |
4 files changed, 103 insertions, 4 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e58aef733ae..52944dd475c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2020-03-21 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/94242 + * include/bits/fs_path.h (path::_S_str_convert): Replace first + parameter with basic_string_view so that strings with different + allocators can be accepted. + (path::generic_string<C,T,A>()): Use basic_string object that uses the + right allocator type. + * testsuite/27_io/filesystem/path/generic/94242.cc: New test. + * testsuite/27_io/filesystem/path/generic/generic_string.cc: Improve + test coverage. + 2020-03-18 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/94033 diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h index bf1f09929c3..fb6e8a5247f 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -579,7 +579,7 @@ namespace __detail template<typename _CharT, typename _Traits, typename _Allocator> static basic_string<_CharT, _Traits, _Allocator> - _S_str_convert(const string_type&, const _Allocator& __a); + _S_str_convert(basic_string_view<value_type>, const _Allocator&); void _M_split_cmpts(); @@ -1015,7 +1015,8 @@ namespace __detail /// @cond undocumented template<typename _CharT, typename _Traits, typename _Allocator> std::basic_string<_CharT, _Traits, _Allocator> - path::_S_str_convert(const string_type& __str, const _Allocator& __a) + path::_S_str_convert(basic_string_view<value_type> __str, + const _Allocator& __a) { static_assert(!is_same_v<_CharT, value_type>); @@ -1126,7 +1127,9 @@ namespace __detail #else const value_type __slash = '/'; #endif - string_type __str(__a); + using _Alloc2 = typename allocator_traits<_Allocator>::template + rebind_alloc<value_type>; + basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a); if (_M_type() == _Type::_Root_dir) __str.assign(1, __slash); @@ -1145,7 +1148,7 @@ namespace __detail #endif if (__add_slash) __str += __slash; - __str += __elem._M_pathname; + __str += basic_string_view<value_type>(__elem._M_pathname); __add_slash = __elem._M_type() == _Type::_Filename; } } diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/94242.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/94242.cc new file mode 100644 index 00000000000..c917daed94e --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/94242.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2020 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/>. + +// C++17 30.10.7.4.7 path generic format observers [fs.path.generic.obs] + +#include <filesystem> +#include <testsuite_allocator.h> + +using std::filesystem::path; +using __gnu_test::SimpleAllocator; + +void +test01() +{ + path p = "//foo//bar//."; + using C = path::value_type; + auto g = p.generic_string<C, std::char_traits<C>, SimpleAllocator<C>>(); + VERIFY( g == path("/foo/bar/.").c_str() ); +} + +void +test02() +{ + path p = "//foo//bar//."; + using C = char16_t; + auto g = p.generic_string<C, std::char_traits<C>, SimpleAllocator<C>>(); + VERIFY( g == u"/foo/bar/." ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc index 5caf079ed9b..8554e9f8f63 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc @@ -21,6 +21,7 @@ // C++17 30.10.7.4.7 path generic format observers [fs.path.generic.obs] #include <filesystem> +#include <testsuite_fs.h> #include <testsuite_hooks.h> using std::filesystem::path; @@ -34,11 +35,15 @@ test01() #ifdef __CYGWIN__ VERIFY( path("//a").generic_string() == "//a" ); VERIFY( path("//a/").generic_string() == "//a/" ); + VERIFY( path("//a//").generic_string() == "//a/" ); VERIFY( path("//a/b").generic_string() == "//a/b" ); + VERIFY( path("//a//b").generic_string() == "//a/b" ); #else VERIFY( path("//a").generic_string() == "/a" ); VERIFY( path("//a/").generic_string() == "/a/" ); + VERIFY( path("//a//").generic_string() == "/a/" ); VERIFY( path("//a/b").generic_string() == "/a/b" ); + VERIFY( path("//a//b").generic_string() == "/a/b" ); #endif VERIFY( path("/a//b").generic_string() == "/a/b" ); VERIFY( path("/a//b/").generic_string() == "/a/b/" ); @@ -57,9 +62,36 @@ test02() } } +void +test03() +{ + for (path p : __gnu_test::test_paths) + { + // A path constructed from the generic format string should compare equal + // to the original, because they represent the same path. + VERIFY( path(p.generic_string()) == p ); + VERIFY( path(p.generic_wstring()) == p ); + VERIFY( path(p.generic_u8string()) == p ); + VERIFY( path(p.generic_u16string()) == p ); + VERIFY( path(p.generic_u32string()) == p ); + } + + for (path p : { "a///b//c", "///a//b//c", "a:b//c", "a://b///c" }) + { + // A path constructed from the generic format string should compare equal + // to the original, because they represent the same path. + VERIFY( path(p.generic_string()) == p ); + VERIFY( path(p.generic_wstring()) == p ); + VERIFY( path(p.generic_u8string()) == p ); + VERIFY( path(p.generic_u16string()) == p ); + VERIFY( path(p.generic_u32string()) == p ); + } +} + int main() { test01(); test02(); + test03(); } |