diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-11-28 15:27:11 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-11-28 15:27:11 +0000 |
commit | 24d9b090fb4b9a260fedb4489392ebd509e93202 (patch) | |
tree | 7ddbccf4a6ee351ff8e14101617b9248b3e46049 /libstdc++-v3/src | |
parent | 2b4be50093f6b2afb337bc7dded0274b46ce9b31 (diff) |
PR libstdc++/83306 make filesystem_error no-throw copyable
The class API provides no way to modify the members, so we can share
them between copies of the same object. Copying becomes a simple
reference count update, which doesn't throw.
Also adjust the what() string to allow distinguishing between an empty
path passed to the constructor, and no path.
PR libstdc++/83306
* include/bits/fs_path.h (filesystem_error): Move data members into
pimpl class owned by shared_ptr. Remove inline definitions of member
functions.
* src/filesystem/std-path.cc (filesystem_error::_Impl): Define.
(filesystem_error): Define member functions.
* testsuite/27_io/filesystem/filesystem_error/cons.cc: New test.
* testsuite/27_io/filesystem/filesystem_error/copy.cc: New test.
From-SVN: r266565
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/filesystem/std-path.cc | 108 |
1 files changed, 71 insertions, 37 deletions
diff --git a/libstdc++-v3/src/filesystem/std-path.cc b/libstdc++-v3/src/filesystem/std-path.cc index f382eb3759a..fb8898d9040 100644 --- a/libstdc++-v3/src/filesystem/std-path.cc +++ b/libstdc++-v3/src/filesystem/std-path.cc @@ -34,8 +34,6 @@ namespace fs = std::filesystem; using fs::path; -fs::filesystem_error::~filesystem_error() = default; - constexpr path::value_type path::preferred_separator; #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS @@ -741,47 +739,83 @@ fs::hash_value(const path& p) noexcept return seed; } -namespace std +struct fs::filesystem_error::_Impl { -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace filesystem -{ - string - fs_err_concat(const string& __what, const string& __path1, - const string& __path2) + _Impl(const string& what_arg, const path& p1, const path& p2) + : path1(p1), path2(p2), what(make_what(what_arg, &p1, &p2)) + { } + + _Impl(const string& what_arg, const path& p1) + : path1(p1), path2(), what(make_what(what_arg, &p1, nullptr)) + { } + + _Impl(const string& what_arg) + : what(make_what(what_arg, nullptr, nullptr)) + { } + + static std::string + make_what(const std::string& s, const path* p1, const path* p2) { - const size_t __len = 18 + __what.length() - + (__path1.length() ? __path1.length() + 3 : 0) - + (__path2.length() ? __path2.length() + 3 : 0); - string __ret; - __ret.reserve(__len); - __ret = "filesystem error: "; - __ret += __what; - if (!__path1.empty()) - { - __ret += " ["; - __ret += __path1; - __ret += ']'; - } - if (!__path2.empty()) + const std::string pstr1 = p1 ? p1->u8string() : std::string{}; + const std::string pstr2 = p2 ? p2->u8string() : std::string{}; + const size_t len = 18 + s.length() + + (pstr1.length() ? pstr1.length() + 3 : 0) + + (pstr2.length() ? pstr2.length() + 3 : 0); + std::string w; + w.reserve(len); + w = "filesystem error: "; + w += s; + if (p1) { - __ret += " ["; - __ret += __path2; - __ret += ']'; + w += " ["; + w += pstr1; + w += ']'; + if (p2) + { + w += " ["; + w += pstr2; + w += ']'; + } } - return __ret; + return w; } -_GLIBCXX_BEGIN_NAMESPACE_CXX11 + path path1; + path path2; + std::string what; +}; - std::string filesystem_error::_M_gen_what() - { - return fs_err_concat(system_error::what(), _M_path1.u8string(), - _M_path2.u8string()); - } +template class std::__shared_ptr<const fs::filesystem_error::_Impl>; + +fs::filesystem_error:: +filesystem_error(const string& what_arg, error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg)) +{ } + +fs::filesystem_error:: +filesystem_error(const string& what_arg, const path& p1, error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg, p1)) +{ } + +fs::filesystem_error:: +filesystem_error(const string& what_arg, const path& p1, const path& p2, + error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg, p1, p2)) +{ } + +fs::filesystem_error::~filesystem_error() = default; + +const fs::path& +fs::filesystem_error::path1() const noexcept +{ return _M_impl->path1; } -_GLIBCXX_END_NAMESPACE_CXX11 +const fs::path& +fs::filesystem_error::path2() const noexcept +{ return _M_impl->path2; } -} // filesystem -_GLIBCXX_END_NAMESPACE_VERSION -} // std +const char* +fs::filesystem_error::what() const noexcept +{ return _M_impl->what.c_str(); } |