aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-01-30 23:18:22 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-01-30 23:18:22 +0000
commit9c5365902aaee9033ed781bfc5e8147060e5b130 (patch)
treeadddb8ab176cad6dcdff325584717707152c33ed
parentd1ac2471e7325d3e47d7b1c028c36be998f5747e (diff)
downloadgcc-9c5365902aaee9033ed781bfc5e8147060e5b130.zip
gcc-9c5365902aaee9033ed781bfc5e8147060e5b130.tar.gz
gcc-9c5365902aaee9033ed781bfc5e8147060e5b130.tar.bz2
PR libstdc++/89117 fix path::replace_extension("") case
Previously the operator+=(extension) call would have re-parsed the path and recreated the components with the right extension. Since optimising it to not re-parse the whole string, we need to actually remove the extension from the final filename before appending anything to it, and append the dot to that final component too. PR libstdc++/89117 * src/c++17/fs_path.cc (path::replace_extension): Erase extension from final component as well as from _M_pathname. Append the dot using operator+= instead of only to _M_pathname. (path::_M_find_extension): Reformat slightly. * testsuite/27_io/filesystem/path/modifiers/replace_extension.cc: Add more test cases. From-SVN: r268406
-rw-r--r--libstdc++-v3/ChangeLog10
-rw-r--r--libstdc++-v3/src/c++17/fs_path.cc14
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc9
3 files changed, 26 insertions, 7 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index f30fedf..36fcab9 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,13 @@
+2019-01-30 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/89117
+ * src/c++17/fs_path.cc (path::replace_extension): Erase extension from
+ final component as well as from _M_pathname. Append the dot using
+ operator+= instead of only to _M_pathname.
+ (path::_M_find_extension): Reformat slightly.
+ * testsuite/27_io/filesystem/path/modifiers/replace_extension.cc:
+ Add more test cases.
+
2019-01-30 Ulrich Drepper <drepper@redhat.com>
* doc/xml/manual/status_cxx2020.xml: Update P0600 entry.
diff --git a/libstdc++-v3/src/c++17/fs_path.cc b/libstdc++-v3/src/c++17/fs_path.cc
index 34de52f..db6a1cb 100644
--- a/libstdc++-v3/src/c++17/fs_path.cc
+++ b/libstdc++-v3/src/c++17/fs_path.cc
@@ -1258,17 +1258,16 @@ path::replace_extension(const path& replacement)
_M_pathname.erase(ext.second);
else
{
- const auto& back = _M_cmpts.back();
- if (ext.first != &back._M_pathname)
- _GLIBCXX_THROW_OR_ABORT(
- std::logic_error("path::replace_extension failed"));
+ auto& back = _M_cmpts.back();
+ __glibcxx_assert( ext.first == &back._M_pathname );
+ back._M_pathname.erase(ext.second);
_M_pathname.erase(back._M_pos + ext.second);
}
}
// If replacement is not empty and does not begin with a dot character,
// a dot character is appended
if (!replacement.empty() && replacement.native()[0] != dot)
- _M_pathname += dot;
+ operator+=(".");
operator+=(replacement);
return *this;
}
@@ -1803,8 +1802,9 @@ path::_M_find_extension() const
{
if (sz <= 2 && (*s)[0] == dot)
return { s, string_type::npos };
- const auto pos = s->rfind(dot);
- return { s, pos ? pos : string_type::npos };
+ if (const auto pos = s->rfind(dot))
+ return { s , pos };
+ return { s, string_type::npos };
}
}
return {};
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc
index df4b77a..98f2e6e 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc
@@ -33,6 +33,15 @@ test01()
compare_paths( path("/foo.txt").replace_extension("cpp"), "/foo.cpp" );
compare_paths( path("/foo.txt").replace_extension(".cpp"), "/foo.cpp" );
compare_paths( path("/").replace_extension("bar"), "/.bar" );
+ compare_paths( path("/").replace_extension(".bar"), "/.bar" );
+ compare_paths( path("/dir/").replace_extension("bar"), "/dir/.bar" );
+ compare_paths( path("dir/foo").replace_extension("bar"), "dir/foo.bar" );
+
+ // PR 89117:
+ compare_paths( path("/foo.txt").replace_extension(), "/foo" );
+ compare_paths( path("foo.txt").replace_extension(), "foo" );
+ compare_paths( path("/foo").replace_extension(), "/foo" );
+ compare_paths( path("foo").replace_extension(), "foo" );
}
void