diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-01-04 14:03:59 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-01-04 14:03:59 +0000 |
commit | 73d968d94561fd521bc6a9af993ed1d1ebba8459 (patch) | |
tree | 367ab721427f3648ac6801f1673f52a761409aa1 /libstdc++-v3/testsuite/27_io/filesystem/path | |
parent | 2d4c371efa1451279764e9768d7efa2edfa02e59 (diff) |
Fix bugs in filesystem::path::lexically_normal()
Using path::_List::erase(const_iterator) to remove a non-final component
in path::lexically_normal() is a bug, because it leaves the following
component with an incorrect _M_pos value.
Instead of providing erase members that allow removing components from
the middle, replace them with pop_back() and
_M_erase_from(const_iterator) which only allow removing elements at the
end. Most uses of erase are unaffected, because they only remove
elements from the end anyway. The one use of erasure from the middle in
lexically_normal() is replaced by calls to pop_back() and/or clearing
the last component to leave it as an empty final filename.
Also replace the "???" comment in lexically_normal() to document when
that branch is taken.
* include/bits/fs_path.h (path::_List::erase): Replace both overloads
with ...
(path::pop_back(), path::_M_erase_from(const_iterator)): New member
functions that will only erase elements at the end.
* src/filesystem/std-path.cc (path::_List::_Impl::pop_back()): Define.
(path::_List::_Impl::_M_erase_from(const_iterator)): Define.
(path::_List::operator=(const _List&)): Use _M_erase_from(p) instead
of erase(p, end()).
(path::_List::pop_back()): Define.
(path::_List::_M_erase_from(const_iterator)): Define.
(path::operator/=(const path&)): Use pop_back to remove last component
and _M_erase_from to remove multiple components.
(path::_M_append(basic_string_view<value_type>)): Likewise.
(path::operator+=(const path&)): Likewise.
(path::_M_concat(basic_string_view<value_type>)): Likewise.
(path::remove_filename()): Likewise.
(path::lexically_normal()): Use _List::_Impl iterators instead of
path::iterator. Use pop_back to remove components from the end. Clear
trailing filename, instead of using erase(const_iterator) to remove
a non-final component.
* testsuite/27_io/filesystem/path/generation/normal.cc: Test
additional cases.
* testsuite/27_io/filesystem/path/generation/normal2.cc: New test.
From-SVN: r267576
Diffstat (limited to 'libstdc++-v3/testsuite/27_io/filesystem/path')
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc | 53 |
2 files changed, 55 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc index 320590ccb15..844168352c8 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc @@ -125,6 +125,8 @@ test03() {"../foo/../foo/.." , ".." }, {"../.f/../f" , "../f" }, {"../f/../.f" , "../.f" }, + {"../.." , "../.." }, + {"../../." , "../.." }, {".././../." , "../.." }, {".././.././" , "../.." }, {"/.." , "/" }, diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc new file mode 100644 index 00000000000..f78f5dd8a9f --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc @@ -0,0 +1,53 @@ +// 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 -lstdc++fs" } +// { dg-do run { target c++17 } } +// { dg-require-filesystem-ts "" } + +#undef _GLIBCXX_USE_CXX11_ABI +#define _GLIBCXX_USE_CXX11_ABI 0 +#include <filesystem> +#include <testsuite_fs.h> + +using std::filesystem::path; + +void +compare_paths(path p, std::string expected) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + for (auto& c : expected) + if (c == '/') + c = '\\'; +#endif + __gnu_test::compare_paths(p, expected); +} + +void +test02() +{ + path p = "./a/b/c/../.././b/c"; + // For the COW string this used to produce incorrect results: + auto norm = p.lexically_normal(); + compare_paths( norm, "a/b/c" ); +} + +int +main() +{ + test02(); +} |