diff options
Diffstat (limited to 'gcc-filesystem.patch')
-rw-r--r-- | gcc-filesystem.patch | 710 |
1 files changed, 485 insertions, 225 deletions
diff --git a/gcc-filesystem.patch b/gcc-filesystem.patch index 2371fb334434..41969cf3defc 100644 --- a/gcc-filesystem.patch +++ b/gcc-filesystem.patch @@ -1,14 +1,13 @@ -From e719de0f337b242dda0575130d5b6c0e48609635 Mon Sep 17 00:00:00 2001 +From eda88e06651c9293012212b665ca592c85bef645 Mon Sep 17 00:00:00 2001 From: Liu Hao <lh_mouse@126.com> -Date: Fri, 27 Jul 2018 20:34:19 +0200 -Subject: [PATCH] Backport patches for std::filesystem +Date: Sat, 26 Jan 2019 15:14:38 +0800 +Subject: [PATCH] Backport patches for std::filesystem from master. -The following commits were cherry-picked: +This is done by running the following commands on `gcc-8-branch`: - * 861db1097d3f - * 2fd48392d0a4 - * 70fea18e0bbb - * d4fd5c4964cf + git cherry-pick 861db1097d3f 2fd48392d0a4 70fea18e0bbb d4fd5c4964cf + git checkout master -- libstdc++-v3/src/filesystem/ \ + libstdc++-v3/include/bits/fs_\* libstdc++-v3/include/std/filesystem Testsuites and change logs were discarded to reduce the amount of modification. @@ -16,27 +15,28 @@ modification. Signed-off-by: Liu Hao <lh_mouse@126.com> --- libstdc++-v3/config.h.in | 12 + - libstdc++-v3/config/io/basic_file_stdio.cc | 33 +++ + libstdc++-v3/config/io/basic_file_stdio.cc | 33 ++ libstdc++-v3/config/io/basic_file_stdio.h | 5 + - libstdc++-v3/configure | 35 +++ + libstdc++-v3/configure | 35 ++ libstdc++-v3/configure.ac | 2 + libstdc++-v3/crossconfig.m4 | 1 + - libstdc++-v3/include/bits/fs_path.h | 199 +++++++------- - libstdc++-v3/include/bits/fstream.tcc | 36 +++ - .../include/experimental/bits/fs_path.h | 62 ++--- - libstdc++-v3/include/std/fstream | 119 ++++++++ - libstdc++-v3/src/filesystem/dir-common.h | 56 +++- + libstdc++-v3/include/bits/fs_dir.h | 14 +- + libstdc++-v3/include/bits/fs_path.h | 250 +++++++------- + libstdc++-v3/include/bits/fstream.tcc | 36 ++ + .../include/experimental/bits/fs_path.h | 74 ++-- + libstdc++-v3/include/std/fstream | 119 +++++++ + libstdc++-v3/src/filesystem/dir-common.h | 56 ++- libstdc++-v3/src/filesystem/dir.cc | 5 +- - libstdc++-v3/src/filesystem/ops-common.h | 105 ++++++- - libstdc++-v3/src/filesystem/ops.cc | 154 ++++++----- + libstdc++-v3/src/filesystem/ops-common.h | 105 +++++- + libstdc++-v3/src/filesystem/ops.cc | 186 +++++----- libstdc++-v3/src/filesystem/path.cc | 24 +- libstdc++-v3/src/filesystem/std-dir.cc | 5 +- - libstdc++-v3/src/filesystem/std-ops.cc | 260 ++++++++++++------ - libstdc++-v3/src/filesystem/std-path.cc | 105 +++++-- - 18 files changed, 887 insertions(+), 331 deletions(-) + libstdc++-v3/src/filesystem/std-ops.cc | 318 ++++++++++-------- + libstdc++-v3/src/filesystem/std-path.cc | 123 ++++--- + 19 files changed, 942 insertions(+), 461 deletions(-) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in -index 5a0f0678439..1fc10b511fb 100644 +index 765cedc6edf..3fb685ce9aa 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -264,6 +264,9 @@ @@ -140,7 +140,7 @@ index 58f24f670f6..3c857272c57 100644 sys_open(__c_file* __file, ios_base::openmode); diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure -index fbc9daeb195..3dd63c9631d 100755 +index 5535bfa2b5a..b9883d413f6 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -28127,6 +28127,17 @@ eval as_val=\$$as_ac_var @@ -231,8 +231,40 @@ index cb6e3afff3d..669d87f7602 100644 ;; *-netbsd*) SECTION_FLAGS='-ffunction-sections -fdata-sections' +diff --git a/libstdc++-v3/include/bits/fs_dir.h b/libstdc++-v3/include/bits/fs_dir.h +index 9ee1cb66b61..6b332e171cf 100644 +--- a/libstdc++-v3/include/bits/fs_dir.h ++++ b/libstdc++-v3/include/bits/fs_dir.h +@@ -138,13 +138,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + refresh(__ec); + } + +- void +- refresh() +- { _M_type = symlink_status().type(); } +- +- void +- refresh(error_code& __ec) noexcept +- { _M_type = symlink_status(__ec).type(); } ++ void refresh() { _M_type = symlink_status().type(); } ++ void refresh(error_code& __ec) { _M_type = symlink_status(__ec).type(); } + + // observers + const filesystem::path& path() const noexcept { return _M_path; } +@@ -318,10 +313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + _M_file_type(error_code& __ec) const noexcept + { + if (_M_type != file_type::none && _M_type != file_type::symlink) +- { +- __ec.clear(); +- return _M_type; +- } ++ return _M_type; + return status(__ec).type(); + } + diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h -index 51af2891647..49cd95daa4c 100644 +index fb85d489fd8..e3938d06d59 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -37,11 +37,11 @@ @@ -261,7 +293,17 @@ index 51af2891647..49cd95daa4c 100644 template<typename _Iter, typename _Iter_traits = std::iterator_traits<_Iter>> -@@ -144,7 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -106,8 +108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + + template<typename _Tp1, typename _Tp2 = void> + using _Path = typename +- std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>, +- __not_<is_void<_Tp1>>, ++ std::enable_if<__and_<__not_<is_same<_Tp1, path>>, + __constructible_from<_Tp1, _Tp2>>::value, + path>::type; + +@@ -145,7 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), typename _Val = typename std::iterator_traits<_Iter>::value_type> using __value_type_is_char @@ -270,7 +312,7 @@ index 51af2891647..49cd95daa4c 100644 public: #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -@@ -230,37 +232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -231,37 +232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // appends @@ -309,10 +351,39 @@ index 51af2891647..49cd95daa4c 100644 template <class _Source> _Path<_Source>& -@@ -391,6 +363,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -377,7 +348,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + bool has_filename() const; + bool has_stem() const; + bool has_extension() const; +- bool is_absolute() const { return has_root_directory(); } ++ bool is_absolute() const; + bool is_relative() const { return !is_absolute(); } + + // generation +@@ -392,6 +363,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 iterator begin() const; iterator end() const; ++ /// Write a path to a stream ++ template<typename _CharT, typename _Traits> ++ friend std::basic_ostream<_CharT, _Traits>& ++ operator<<(std::basic_ostream<_CharT, _Traits>& __os, const path& __p) ++ { ++ __os << std::quoted(__p.string<_CharT, _Traits>()); ++ return __os; ++ } ++ ++ /// Read a path from a stream ++ template<typename _CharT, typename _Traits> ++ friend std::basic_istream<_CharT, _Traits>& ++ operator>>(std::basic_istream<_CharT, _Traits>& __is, path& __p) ++ { ++ std::basic_string<_CharT, _Traits> __tmp; ++ if (__is >> std::quoted(__tmp)) ++ __p = std::move(__tmp); ++ return __is; ++ } ++ + // Create a basic_string by reading until a null character. + template<typename _InputIterator, + typename _Traits = std::iterator_traits<_InputIterator>, @@ -330,7 +401,7 @@ index 51af2891647..49cd95daa4c 100644 private: enum class _Type : unsigned char { _Multi, _Root_name, _Root_dir, _Filename -@@ -403,19 +389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -404,19 +409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 enum class _Split { _Stem, _Extension }; @@ -351,7 +422,7 @@ index 51af2891647..49cd95daa4c 100644 pair<const string_type*, size_t> _M_find_extension() const; -@@ -443,11 +417,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -444,11 +437,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 static string_type _S_convert(_InputIterator __src, __null_terminated) { @@ -365,7 +436,7 @@ index 51af2891647..49cd95daa4c 100644 } static string_type -@@ -467,10 +438,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -468,10 +458,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _S_convert_loc(_InputIterator __src, __null_terminated, const std::locale& __loc) { @@ -378,8 +449,8 @@ index 51af2891647..49cd95daa4c 100644 } template<typename _CharT, typename _Traits, typename _Allocator> -@@ -500,25 +469,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 - _Type _M_type = _Type::_Multi; +@@ -501,25 +489,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + _Type _M_type = _Type::_Filename; }; - template<> @@ -404,30 +475,35 @@ index 51af2891647..49cd95daa4c 100644 inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } size_t hash_value(const path& __p) noexcept; -@@ -560,10 +510,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) - { +@@ -556,58 +525,50 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + return __result; + } + +- /// Write a path to a stream +- template<typename _CharT, typename _Traits> +- basic_ostream<_CharT, _Traits>& +- operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) +- { - auto __tmp = __p.string<_CharT, _Traits>(); - using __quoted_string - = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; - __os << __quoted_string{__tmp, '"', '\\'}; -+ __os << std::quoted(__p.string<_CharT, _Traits>()); - return __os; - } - -@@ -573,40 +520,55 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 - operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) - { - basic_string<_CharT, _Traits> __tmp; +- return __os; +- } +- +- /// Read a path from a stream +- template<typename _CharT, typename _Traits> +- basic_istream<_CharT, _Traits>& +- operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) +- { +- basic_string<_CharT, _Traits> __tmp; - using __quoted_string - = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; - if (__is >> __quoted_string{ __tmp, '"', '\\' }) -+ if (__is >> std::quoted(__tmp)) - __p = std::move(__tmp); - return __is; - } - +- __p = std::move(__tmp); +- return __is; +- } +- - template<typename _Source> + template<typename _InputIterator> inline auto @@ -490,7 +566,7 @@ index 51af2891647..49cd95daa4c 100644 #endif } -@@ -915,11 +877,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -916,11 +877,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 path::string(const _Allocator& __a) const { if constexpr (is_same_v<_CharT, value_type>) @@ -509,7 +585,24 @@ index 51af2891647..49cd95daa4c 100644 else return _S_str_convert<_CharT, _Traits>(_M_pathname, __a); } -@@ -1087,6 +1054,38 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -1072,6 +1038,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + return ext.first && ext.second != string_type::npos; + } + ++ inline bool ++ path::is_absolute() const ++ { ++#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS ++ return has_root_name() && has_root_directory(); ++#else ++ return has_root_directory(); ++#endif ++ } ++ + inline path::iterator + path::begin() const + { +@@ -1088,6 +1064,38 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return iterator(this, true); } @@ -596,7 +689,7 @@ index f23ff7af4eb..d9eff00823a 100644 typename basic_filebuf<_CharT, _Traits>::__filebuf_type* basic_filebuf<_CharT, _Traits>:: diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h -index ada7c1791aa..d8e37f64908 100644 +index 088d62f8f43..340cc59d541 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -79,8 +79,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 @@ -613,7 +706,7 @@ index ada7c1791aa..d8e37f64908 100644 template<typename _Iter, typename _Iter_traits = std::iterator_traits<_Iter>> -@@ -161,8 +164,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -163,8 +166,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _Tp, typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), typename _Val = typename std::iterator_traits<_Iter>::value_type> @@ -625,7 +718,16 @@ index ada7c1791aa..d8e37f64908 100644 public: #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -@@ -378,6 +382,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -370,7 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + bool has_filename() const; + bool has_stem() const; + bool has_extension() const; +- bool is_absolute() const { return has_root_directory(); } ++ bool is_absolute() const; + bool is_relative() const { return !is_absolute(); } + + // iterators +@@ -380,6 +384,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 iterator begin() const; iterator end() const; @@ -646,7 +748,7 @@ index ada7c1791aa..d8e37f64908 100644 private: enum class _Type : unsigned char { _Multi, _Root_name, _Root_dir, _Filename -@@ -427,11 +445,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -429,11 +447,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 static string_type _S_convert(_InputIterator __src, __null_terminated) { @@ -660,7 +762,7 @@ index ada7c1791aa..d8e37f64908 100644 } static string_type -@@ -451,10 +466,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -453,10 +468,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _S_convert_loc(_InputIterator __src, __null_terminated, const std::locale& __loc) { @@ -673,7 +775,7 @@ index ada7c1791aa..d8e37f64908 100644 } bool _S_is_dir_sep(value_type __ch) -@@ -524,7 +537,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -526,7 +539,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 auto __tmp = __p.string<_CharT, _Traits>(); using __quoted_string = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; @@ -682,7 +784,7 @@ index ada7c1791aa..d8e37f64908 100644 return __os; } -@@ -536,7 +549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -538,7 +551,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_string<_CharT, _Traits> __tmp; using __quoted_string = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; @@ -691,7 +793,7 @@ index ada7c1791aa..d8e37f64908 100644 __p = std::move(__tmp); return __is; } -@@ -594,25 +607,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -596,25 +609,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 std::string _M_what = _M_gen_what(); }; @@ -717,6 +819,23 @@ index ada7c1791aa..d8e37f64908 100644 struct path::_Cmpt : path { _Cmpt(string_type __s, _Type __t, size_t __pos) +@@ -1001,6 +995,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 + return ext.first && ext.second != string_type::npos; + } + ++ inline bool ++ path::is_absolute() const ++ { ++#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS ++ return has_root_name() && has_root_directory(); ++#else ++ return has_root_directory(); ++#endif ++ } ++ + inline path::iterator + path::begin() const + { diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream index 3a5895d68b0..740d12d3bb6 100644 --- a/libstdc++-v3/include/std/fstream @@ -1195,7 +1314,7 @@ index bc186836bd4..c1b817189a9 100644 else if (S_ISSOCK(st.st_mode)) return file_type::socket; diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc -index 4a9e265d1d6..40cadbf6270 100644 +index de290625e54..40cadbf6270 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -47,20 +47,17 @@ @@ -1277,7 +1396,64 @@ index 4a9e265d1d6..40cadbf6270 100644 { if (!is_not_found_errno(errno)) { -@@ -459,8 +458,8 @@ namespace +@@ -424,19 +423,6 @@ fs::create_directories(const path& p, error_code& ec) noexcept + ec = std::make_error_code(errc::invalid_argument); + return false; + } +- +- file_status st = symlink_status(p, ec); +- if (is_directory(st)) +- return false; +- else if (ec && !status_known(st)) +- return false; +- else if (exists(st)) +- { +- if (!ec) +- ec = std::make_error_code(std::errc::not_a_directory); +- return false; +- } +- + std::stack<path> missing; + path pp = p; + +@@ -445,29 +431,24 @@ fs::create_directories(const path& p, error_code& ec) noexcept + ec.clear(); + const auto& filename = pp.filename(); + if (!is_dot(filename) && !is_dotdot(filename)) +- { +- missing.push(std::move(pp)); +- pp = missing.top().parent_path(); +- } +- else +- pp = pp.parent_path(); ++ missing.push(pp); ++ pp.remove_filename(); + } + + if (ec || missing.empty()) + return false; + +- bool created; + do + { + const path& top = missing.top(); +- created = create_directory(top, ec); +- if (ec) +- return false; ++ create_directory(top, ec); ++ if (ec && is_directory(top)) ++ ec.clear(); + missing.pop(); + } +- while (!missing.empty()); ++ while (!missing.empty() && !ec); + +- return created; ++ return missing.empty(); + } + + namespace +@@ -477,8 +458,8 @@ namespace { bool created = false; #ifdef _GLIBCXX_HAVE_SYS_STAT_H @@ -1288,7 +1464,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { const int err = errno; if (err != EEXIST || !is_directory(p, ec)) -@@ -513,7 +512,7 @@ fs::create_directory(const path& p, const path& attributes, +@@ -531,7 +512,7 @@ fs::create_directory(const path& p, const path& attributes, { #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; @@ -1297,7 +1473,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { ec.assign(errno, std::generic_category()); return false; -@@ -562,11 +561,16 @@ void +@@ -580,11 +561,16 @@ void fs::create_hard_link(const path& to, const path& new_hard_link, error_code& ec) noexcept { @@ -1315,7 +1491,7 @@ index 4a9e265d1d6..40cadbf6270 100644 #else ec = std::make_error_code(std::errc::not_supported); #endif -@@ -586,7 +590,7 @@ void +@@ -604,7 +590,7 @@ void fs::create_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept { @@ -1324,7 +1500,7 @@ index 4a9e265d1d6..40cadbf6270 100644 if (::symlink(to.c_str(), new_symlink.c_str())) ec.assign(errno, std::generic_category()); else -@@ -596,7 +600,6 @@ fs::create_symlink(const path& to, const path& new_symlink, +@@ -614,7 +600,6 @@ fs::create_symlink(const path& to, const path& new_symlink, #endif } @@ -1332,7 +1508,7 @@ index 4a9e265d1d6..40cadbf6270 100644 fs::path fs::current_path() { -@@ -612,8 +615,8 @@ fs::current_path(error_code& ec) +@@ -630,8 +615,8 @@ fs::current_path(error_code& ec) { path p; #ifdef _GLIBCXX_HAVE_UNISTD_H @@ -1343,7 +1519,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { p.assign(cwd.get()); ec.clear(); -@@ -621,6 +624,7 @@ fs::current_path(error_code& ec) +@@ -639,6 +624,7 @@ fs::current_path(error_code& ec) else ec.assign(errno, std::generic_category()); #else @@ -1351,7 +1527,7 @@ index 4a9e265d1d6..40cadbf6270 100644 long path_max = pathconf(".", _PC_PATH_MAX); size_t size; if (path_max == -1) -@@ -629,9 +633,15 @@ fs::current_path(error_code& ec) +@@ -647,9 +633,15 @@ fs::current_path(error_code& ec) size = 10240; else size = path_max; @@ -1368,7 +1544,7 @@ index 4a9e265d1d6..40cadbf6270 100644 if (buf) { if (getcwd(buf.get(), size)) -@@ -671,7 +681,7 @@ void +@@ -689,7 +681,7 @@ void fs::current_path(const path& p, error_code& ec) noexcept { #ifdef _GLIBCXX_HAVE_UNISTD_H @@ -1377,7 +1553,7 @@ index 4a9e265d1d6..40cadbf6270 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -698,14 +708,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept +@@ -716,14 +708,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept int err = 0; file_status s1, s2; stat_type st1, st2; @@ -1394,7 +1570,7 @@ index 4a9e265d1d6..40cadbf6270 100644 s2 = make_file_status(st2); else if (is_not_found_errno(errno)) s2.type(file_type::not_found); -@@ -755,7 +765,7 @@ namespace +@@ -773,7 +765,7 @@ namespace { #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; @@ -1403,7 +1579,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { ec.assign(errno, std::generic_category()); return deflt; -@@ -805,7 +815,7 @@ fs::hard_link_count(const path& p) +@@ -823,7 +815,7 @@ fs::hard_link_count(const path& p) std::uintmax_t fs::hard_link_count(const path& p, error_code& ec) noexcept { @@ -1412,7 +1588,7 @@ index 4a9e265d1d6..40cadbf6270 100644 static_cast<uintmax_t>(-1)); } -@@ -881,11 +891,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)), +@@ -899,11 +891,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)), else ec.clear(); #elif _GLIBCXX_HAVE_UTIME_H @@ -1426,7 +1602,7 @@ index 4a9e265d1d6..40cadbf6270 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -938,7 +948,7 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept +@@ -956,7 +948,7 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept #else if (nofollow && is_symlink(st)) ec = std::make_error_code(std::errc::operation_not_supported); @@ -1435,7 +1611,7 @@ index 4a9e265d1d6..40cadbf6270 100644 err = errno; #endif -@@ -958,10 +968,10 @@ fs::read_symlink(const path& p) +@@ -976,10 +968,10 @@ fs::read_symlink(const path& p) return tgt; } @@ -1448,7 +1624,7 @@ index 4a9e265d1d6..40cadbf6270 100644 stat_type st; if (::lstat(p.c_str(), &st)) { -@@ -1015,6 +1025,19 @@ fs::remove(const path& p) +@@ -1033,6 +1025,19 @@ fs::remove(const path& p) bool fs::remove(const path& p, error_code& ec) noexcept { @@ -1468,7 +1644,7 @@ index 4a9e265d1d6..40cadbf6270 100644 if (::remove(p.c_str()) == 0) { ec.clear(); -@@ -1024,6 +1047,7 @@ fs::remove(const path& p, error_code& ec) noexcept +@@ -1042,6 +1047,7 @@ fs::remove(const path& p, error_code& ec) noexcept ec.clear(); else ec.assign(errno, std::generic_category()); @@ -1476,7 +1652,7 @@ index 4a9e265d1d6..40cadbf6270 100644 return false; } -@@ -1077,7 +1101,7 @@ fs::rename(const path& from, const path& to) +@@ -1095,7 +1101,7 @@ fs::rename(const path& from, const path& to) void fs::rename(const path& from, const path& to, error_code& ec) noexcept { @@ -1485,7 +1661,7 @@ index 4a9e265d1d6..40cadbf6270 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -1098,7 +1122,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept +@@ -1116,7 +1122,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept #ifdef _GLIBCXX_HAVE_UNISTD_H if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max())) ec.assign(EINVAL, std::generic_category()); @@ -1494,7 +1670,7 @@ index 4a9e265d1d6..40cadbf6270 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -1126,23 +1150,14 @@ fs::space(const path& p, error_code& ec) noexcept +@@ -1144,23 +1150,14 @@ fs::space(const path& p, error_code& ec) noexcept static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1) }; @@ -1524,7 +1700,7 @@ index 4a9e265d1d6..40cadbf6270 100644 return info; } -@@ -1152,7 +1167,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept +@@ -1170,7 +1167,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept { file_status status; stat_type st; @@ -1533,7 +1709,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { int err = errno; ec.assign(err, std::generic_category()); -@@ -1176,7 +1191,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept +@@ -1194,7 +1191,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept { file_status status; stat_type st; @@ -1542,7 +1718,7 @@ index 4a9e265d1d6..40cadbf6270 100644 { int err = errno; ec.assign(err, std::generic_category()); -@@ -1251,27 +1266,38 @@ fs::path fs::temp_directory_path() +@@ -1269,27 +1266,38 @@ fs::path fs::temp_directory_path() fs::path fs::temp_directory_path(error_code& ec) { @@ -1699,7 +1875,7 @@ index 98eb22ab920..4c9a287ad80 100644 if (ecptr) ecptr->clear(); diff --git a/libstdc++-v3/src/filesystem/std-ops.cc b/libstdc++-v3/src/filesystem/std-ops.cc -index 74868cd48e6..e266fa6d3f8 100644 +index c0742d73b5c..e266fa6d3f8 100644 --- a/libstdc++-v3/src/filesystem/std-ops.cc +++ b/libstdc++-v3/src/filesystem/std-ops.cc @@ -25,6 +25,7 @@ @@ -1743,29 +1919,27 @@ index 74868cd48e6..e266fa6d3f8 100644 return ret; #else return current_path() / p; -@@ -84,13 +82,37 @@ fs::absolute(const path& p) - fs::path - fs::absolute(const path& p, error_code& ec) - { -+ path ret; -+ if (p.empty()) -+ { -+ ec = make_error_code(std::errc::no_such_file_or_directory); -+ return ret; -+ } - #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -- ec = std::make_error_code(errc::not_supported); -- return {}; +@@ -90,17 +88,28 @@ fs::absolute(const path& p, error_code& ec) + ec = make_error_code(std::errc::no_such_file_or_directory); + return ret; + } +- if (p.is_absolute()) ++#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + const wstring& s = p.native(); + uint32_t len = 1024; + wstring buf; + do -+ { + { +- ec.clear(); +- ret = p; +- return ret; + buf.resize(len); + len = GetFullPathNameW(s.c_str(), len, buf.data(), nullptr); -+ } + } + while (len > buf.size()); -+ + +-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS +- ec = std::make_error_code(errc::not_supported); + if (len == 0) + ec.assign((int)GetLastError(), std::system_category()); + else @@ -1775,16 +1949,13 @@ index 74868cd48e6..e266fa6d3f8 100644 + ret = std::move(buf); + } #else - ec.clear(); -- return current_path() / p; +- ret = current_path(ec); ++ ec.clear(); + ret = current_path(); -+ ret /= p; + ret /= p; #endif -+ return ret; - } - - namespace -@@ -118,7 +140,7 @@ namespace + return ret; +@@ -131,7 +140,7 @@ namespace void operator()(void* p) const { ::free(p); } }; @@ -1793,7 +1964,7 @@ index 74868cd48e6..e266fa6d3f8 100644 } fs::path -@@ -133,7 +155,8 @@ fs::canonical(const path& p, error_code& ec) +@@ -146,7 +155,8 @@ fs::canonical(const path& p, error_code& ec) char_ptr buf{ nullptr }; # if _XOPEN_VERSION < 700 // Not safe to call realpath(path, NULL) @@ -1803,7 +1974,7 @@ index 74868cd48e6..e266fa6d3f8 100644 # endif if (char* rp = ::realpath(pa.c_str(), buf.get())) { -@@ -254,7 +277,7 @@ namespace std::filesystem +@@ -267,7 +277,7 @@ namespace std::filesystem #ifdef _GLIBCXX_HAVE_SYS_STAT_H #ifdef NEED_DO_COPY_FILE bool @@ -1812,7 +1983,7 @@ index 74868cd48e6..e266fa6d3f8 100644 copy_options_existing_file options, stat_type* from_st, stat_type* to_st, std::error_code& ec) noexcept -@@ -264,7 +287,7 @@ fs::do_copy_file(const char* from, const char* to, +@@ -277,7 +287,7 @@ fs::do_copy_file(const char* from, const char* to, if (to_st == nullptr) { @@ -1821,7 +1992,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { const int err = errno; if (!is_not_found_errno(err)) -@@ -286,7 +309,7 @@ fs::do_copy_file(const char* from, const char* to, +@@ -299,7 +309,7 @@ fs::do_copy_file(const char* from, const char* to, if (from_st == nullptr) { @@ -1830,7 +2001,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { ec.assign(errno, std::generic_category()); return false; -@@ -344,12 +367,12 @@ fs::do_copy_file(const char* from, const char* to, +@@ -357,12 +367,12 @@ fs::do_copy_file(const char* from, const char* to, } struct CloseFD { @@ -1846,7 +2017,7 @@ index 74868cd48e6..e266fa6d3f8 100644 if (in.fd == -1) { ec.assign(errno, std::generic_category()); -@@ -360,7 +383,7 @@ fs::do_copy_file(const char* from, const char* to, +@@ -373,7 +383,7 @@ fs::do_copy_file(const char* from, const char* to, oflag |= O_TRUNC; else oflag |= O_EXCL; @@ -1855,7 +2026,7 @@ index 74868cd48e6..e266fa6d3f8 100644 if (out.fd == -1) { if (errno == EEXIST && options.skip) -@@ -370,12 +393,12 @@ fs::do_copy_file(const char* from, const char* to, +@@ -383,12 +393,12 @@ fs::do_copy_file(const char* from, const char* to, return false; } @@ -1871,7 +2042,7 @@ index 74868cd48e6..e266fa6d3f8 100644 #endif { ec.assign(errno, std::generic_category()); -@@ -383,7 +406,7 @@ fs::do_copy_file(const char* from, const char* to, +@@ -396,7 +406,7 @@ fs::do_copy_file(const char* from, const char* to, } size_t count = from_st->st_size; @@ -1880,7 +2051,7 @@ index 74868cd48e6..e266fa6d3f8 100644 off_t offset = 0; ssize_t n = ::sendfile(out.fd, in.fd, &offset, count); if (n < 0 && errno != ENOSYS && errno != EINVAL) -@@ -462,15 +485,15 @@ fs::copy(const path& from, const path& to, copy_options options, +@@ -475,15 +485,15 @@ fs::copy(const path& from, const path& to, copy_options options, // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2681. filesystem::copy() cannot copy symlinks if (use_lstat || copy_symlinks @@ -1900,7 +2071,98 @@ index 74868cd48e6..e266fa6d3f8 100644 { if (!is_not_found_errno(errno)) { -@@ -664,8 +687,9 @@ namespace +@@ -636,74 +646,38 @@ fs::create_directories(const path& p, error_code& ec) + ec = std::make_error_code(errc::invalid_argument); + return false; + } +- +- file_status st = symlink_status(p, ec); +- if (is_directory(st)) +- return false; +- else if (ec && !status_known(st)) +- return false; +- else if (exists(st)) +- { +- if (!ec) +- ec = std::make_error_code(std::errc::not_a_directory); +- return false; +- } +- + std::stack<path> missing; + path pp = p; + +- // Strip any trailing slash +- if (pp.has_relative_path() && !pp.has_filename()) +- pp = pp.parent_path(); +- +- do ++ while (pp.has_filename() && status(pp, ec).type() == file_type::not_found) + { ++ ec.clear(); + const auto& filename = pp.filename(); +- if (is_dot(filename) || is_dotdot(filename)) +- pp = pp.parent_path(); +- else +- { +- missing.push(std::move(pp)); +- if (missing.size() > 1000) // sanity check +- { +- ec = std::make_error_code(std::errc::filename_too_long); +- return false; +- } +- pp = missing.top().parent_path(); +- } ++ if (!is_dot(filename) && !is_dotdot(filename)) ++ missing.push(pp); ++ pp = pp.parent_path(); + +- if (pp.empty()) +- break; +- +- st = status(pp, ec); +- if (exists(st)) ++ if (missing.size() > 1000) // sanity check + { +- if (ec) +- return false; +- if (!is_directory(st)) +- { +- ec = std::make_error_code(std::errc::not_a_directory); +- return false; +- } ++ ec = std::make_error_code(std::errc::filename_too_long); ++ return false; + } +- +- if (ec && exists(st)) +- return false; + } +- while (st.type() == file_type::not_found); + +- bool created; ++ if (ec || missing.empty()) ++ return false; ++ + do + { + const path& top = missing.top(); +- created = create_directory(top, ec); +- if (ec) +- return false; ++ create_directory(top, ec); ++ if (ec && is_directory(top)) ++ ec.clear(); + missing.pop(); + } +- while (!missing.empty()); ++ while (!missing.empty() && !ec); + +- return created; ++ return missing.empty(); + } + + namespace +@@ -713,8 +687,9 @@ namespace { bool created = false; #ifdef _GLIBCXX_HAVE_SYS_STAT_H @@ -1912,7 +2174,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { const int err = errno; if (err != EEXIST || !is_directory(p, ec)) -@@ -718,7 +742,7 @@ fs::create_directory(const path& p, const path& attributes, +@@ -767,7 +742,7 @@ fs::create_directory(const path& p, const path& attributes, { #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; @@ -1921,7 +2183,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { ec.assign(errno, std::generic_category()); return false; -@@ -760,18 +784,23 @@ fs::create_hard_link(const path& to, const path& new_hard_link) +@@ -809,18 +784,23 @@ fs::create_hard_link(const path& to, const path& new_hard_link) create_hard_link(to, new_hard_link, ec); if (ec) _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create hard link", @@ -1947,7 +2209,7 @@ index 74868cd48e6..e266fa6d3f8 100644 #else ec = std::make_error_code(std::errc::not_supported); #endif -@@ -791,7 +820,7 @@ void +@@ -840,7 +820,7 @@ void fs::create_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept { @@ -1956,7 +2218,7 @@ index 74868cd48e6..e266fa6d3f8 100644 if (::symlink(to.c_str(), new_symlink.c_str())) ec.assign(errno, std::generic_category()); else -@@ -817,8 +846,8 @@ fs::current_path(error_code& ec) +@@ -866,8 +846,8 @@ fs::current_path(error_code& ec) { path p; #ifdef _GLIBCXX_HAVE_UNISTD_H @@ -1967,7 +2229,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { p.assign(cwd.get()); ec.clear(); -@@ -826,6 +855,7 @@ fs::current_path(error_code& ec) +@@ -875,6 +855,7 @@ fs::current_path(error_code& ec) else ec.assign(errno, std::generic_category()); #else @@ -1975,7 +2237,7 @@ index 74868cd48e6..e266fa6d3f8 100644 long path_max = pathconf(".", _PC_PATH_MAX); size_t size; if (path_max == -1) -@@ -834,9 +864,15 @@ fs::current_path(error_code& ec) +@@ -883,9 +864,15 @@ fs::current_path(error_code& ec) size = 10240; else size = path_max; @@ -1992,7 +2254,7 @@ index 74868cd48e6..e266fa6d3f8 100644 if (buf) { if (getcwd(buf.get(), size)) -@@ -876,7 +912,7 @@ void +@@ -925,7 +912,7 @@ void fs::current_path(const path& p, error_code& ec) noexcept { #ifdef _GLIBCXX_HAVE_UNISTD_H @@ -2001,7 +2263,7 @@ index 74868cd48e6..e266fa6d3f8 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -903,14 +939,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept +@@ -952,14 +939,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept int err = 0; file_status s1, s2; stat_type st1, st2; @@ -2018,7 +2280,7 @@ index 74868cd48e6..e266fa6d3f8 100644 s2 = make_file_status(st2); else if (is_not_found_errno(errno)) s2.type(file_type::not_found); -@@ -959,8 +995,8 @@ namespace +@@ -1008,8 +995,8 @@ namespace do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt) { #ifdef _GLIBCXX_HAVE_SYS_STAT_H @@ -2029,7 +2291,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { ec.assign(errno, std::generic_category()); return deflt; -@@ -1010,7 +1046,7 @@ fs::hard_link_count(const path& p) +@@ -1059,7 +1046,7 @@ fs::hard_link_count(const path& p) std::uintmax_t fs::hard_link_count(const path& p, error_code& ec) noexcept { @@ -2038,7 +2300,7 @@ index 74868cd48e6..e266fa6d3f8 100644 static_cast<uintmax_t>(-1)); } -@@ -1086,11 +1122,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)), +@@ -1135,11 +1122,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)), else ec.clear(); #elif _GLIBCXX_HAVE_UTIME_H @@ -2052,7 +2314,7 @@ index 74868cd48e6..e266fa6d3f8 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -1145,7 +1181,7 @@ fs::permissions(const path& p, perms prms, perm_options opts, +@@ -1194,7 +1181,7 @@ fs::permissions(const path& p, perms prms, perm_options opts, #else if (nofollow && is_symlink(st)) ec = std::make_error_code(std::errc::operation_not_supported); @@ -2061,7 +2323,7 @@ index 74868cd48e6..e266fa6d3f8 100644 err = errno; #endif -@@ -1185,10 +1221,10 @@ fs::read_symlink(const path& p) +@@ -1234,10 +1221,10 @@ fs::read_symlink(const path& p) return tgt; } @@ -2074,7 +2336,7 @@ index 74868cd48e6..e266fa6d3f8 100644 stat_type st; if (::lstat(p.c_str(), &st)) { -@@ -1261,6 +1297,19 @@ fs::remove(const path& p) +@@ -1310,6 +1297,19 @@ fs::remove(const path& p) bool fs::remove(const path& p, error_code& ec) noexcept { @@ -2094,7 +2356,7 @@ index 74868cd48e6..e266fa6d3f8 100644 if (::remove(p.c_str()) == 0) { ec.clear(); -@@ -1270,6 +1319,7 @@ fs::remove(const path& p, error_code& ec) noexcept +@@ -1319,6 +1319,7 @@ fs::remove(const path& p, error_code& ec) noexcept ec.clear(); else ec.assign(errno, std::generic_category()); @@ -2102,7 +2364,7 @@ index 74868cd48e6..e266fa6d3f8 100644 return false; } -@@ -1323,7 +1373,7 @@ fs::rename(const path& from, const path& to) +@@ -1372,7 +1373,7 @@ fs::rename(const path& from, const path& to) void fs::rename(const path& from, const path& to, error_code& ec) noexcept { @@ -2111,7 +2373,7 @@ index 74868cd48e6..e266fa6d3f8 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -1344,7 +1394,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept +@@ -1393,7 +1394,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept #ifdef _GLIBCXX_HAVE_UNISTD_H if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max())) ec.assign(EINVAL, std::generic_category()); @@ -2120,7 +2382,7 @@ index 74868cd48e6..e266fa6d3f8 100644 ec.assign(errno, std::generic_category()); else ec.clear(); -@@ -1364,31 +1414,67 @@ fs::space(const path& p) +@@ -1413,31 +1414,67 @@ fs::space(const path& p) return s; } @@ -2161,8 +2423,8 @@ index 74868cd48e6..e266fa6d3f8 100644 + if (f.f_bavail != unknown) + available = f.f_bavail * fragment_size; + } -+ ec.clear(); -+ } + ec.clear(); + } +#elif _GLIBCXX_FILESYSTEM_IS_WINDOWS + ULARGE_INTEGER bytes_avail = {}, bytes_total = {}, bytes_free = {}; + if (GetDiskFreeSpaceExW(pathname, &bytes_avail, &bytes_total, &bytes_free)) @@ -2173,8 +2435,8 @@ index 74868cd48e6..e266fa6d3f8 100644 + free = bytes_free.QuadPart; + if (bytes_avail.QuadPart != 0) + available = bytes_avail.QuadPart; - ec.clear(); - } ++ ec.clear(); ++ } + else + ec.assign((int)GetLastError(), std::system_category()); #else @@ -2202,7 +2464,7 @@ index 74868cd48e6..e266fa6d3f8 100644 return info; } -@@ -1398,7 +1484,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept +@@ -1447,7 +1484,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept { file_status status; stat_type st; @@ -2211,7 +2473,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { int err = errno; ec.assign(err, std::generic_category()); -@@ -1422,7 +1508,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept +@@ -1471,7 +1508,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept { file_status status; stat_type st; @@ -2220,7 +2482,7 @@ index 74868cd48e6..e266fa6d3f8 100644 { int err = errno; ec.assign(err, std::generic_category()); -@@ -1469,28 +1555,39 @@ fs::path fs::temp_directory_path() +@@ -1518,28 +1555,39 @@ fs::path fs::temp_directory_path() fs::path fs::temp_directory_path(error_code& ec) { @@ -2273,27 +2535,8 @@ index 74868cd48e6..e266fa6d3f8 100644 } fs::path -@@ -1513,7 +1610,8 @@ fs::weakly_canonical(const path& p) - ++iter; - } - // canonicalize: -- result = canonical(result); -+ if (!result.empty()) -+ result = canonical(result); - // append the non-existing elements: - while (iter != end) - result /= *iter++; -@@ -1551,7 +1649,7 @@ fs::weakly_canonical(const path& p, error_code& ec) - ++iter; - } - // canonicalize: -- if (!ec) -+ if (!ec && !result.empty()) - result = canonical(result, ec); - if (ec) - result.clear(); diff --git a/libstdc++-v3/src/filesystem/std-path.cc b/libstdc++-v3/src/filesystem/std-path.cc -index 6f594cec1d5..f6c0b8bb0f6 100644 +index c5bf8099036..f6c0b8bb0f6 100644 --- a/libstdc++-v3/src/filesystem/std-path.cc +++ b/libstdc++-v3/src/filesystem/std-path.cc @@ -38,6 +38,66 @@ fs::filesystem_error::~filesystem_error() = default; @@ -2363,16 +2606,7 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 path& path::remove_filename() { -@@ -63,8 +123,6 @@ path::remove_filename() - } - else if (_M_type == _Type::_Filename) - clear(); -- if (!empty() && _M_pathname.back() != '/') -- throw 1; - return *this; - } - -@@ -76,6 +134,12 @@ path::replace_filename(const path& replacement) +@@ -74,6 +134,12 @@ path::replace_filename(const path& replacement) return *this; } @@ -2385,7 +2619,18 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 path& path::replace_extension(const path& replacement) { -@@ -96,8 +160,8 @@ path::replace_extension(const path& replacement) +@@ -85,18 +151,17 @@ path::replace_extension(const path& replacement) + _M_pathname.erase(ext.second); + else + { +- auto& back = _M_cmpts.back(); ++ const auto& back = _M_cmpts.back(); + if (ext.first != &back._M_pathname) + _GLIBCXX_THROW_OR_ABORT( + std::logic_error("path::replace_extension failed")); +- 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 @@ -2396,25 +2641,7 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 operator+=(replacement); return *this; } -@@ -292,7 +356,7 @@ path::has_root_path() const - bool - path::has_relative_path() const - { -- if (_M_type == _Type::_Filename) -+ if (_M_type == _Type::_Filename && !_M_pathname.empty()) - return true; - if (!_M_cmpts.empty()) - { -@@ -301,7 +365,7 @@ path::has_relative_path() const - ++__it; - if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) - ++__it; -- if (__it != _M_cmpts.end()) -+ if (__it != _M_cmpts.end() && !__it->_M_pathname.empty()) - return true; - } - return false; -@@ -334,11 +398,7 @@ path::has_filename() const +@@ -333,11 +398,7 @@ path::has_filename() const namespace { @@ -2427,16 +2654,76 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 inline bool is_dot(const fs::path& path) { -@@ -378,7 +438,7 @@ path::lexically_normal() const +@@ -377,7 +438,7 @@ path::lexically_normal() const { #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS // Replace each slash character in the root-name -- if (p.is_root_name()) +- if (p._M_type == _Type::_Root_name || p._M_type == _Type::_Root_dir) + if (p._M_type == _Type::_Root_name) { string_type s = p.native(); std::replace(s.begin(), s.end(), L'/', L'\\'); -@@ -487,7 +547,7 @@ path::lexically_proximate(const path& base) const +@@ -397,8 +458,7 @@ path::lexically_normal() const + } + else if (!ret.has_relative_path()) + { +- // remove a dot-dot filename immediately after root-directory +- if (!ret.has_root_directory()) ++ if (!ret.is_absolute()) + ret /= p; + } + else +@@ -406,30 +466,15 @@ path::lexically_normal() const + // Got a path with a relative path (i.e. at least one non-root + // element) and no filename at the end (i.e. empty last element), + // so must have a trailing slash. See what is before it. +- auto elem = ret._M_cmpts.end() - 2; ++ auto elem = std::prev(ret.end(), 2); + if (elem->has_filename() && !is_dotdot(*elem)) + { + // Remove the filename before the trailing slash + // (equiv. to ret = ret.parent_path().remove_filename()) +- +- if (elem == ret._M_cmpts.begin()) +- ret.clear(); +- else +- { +- ret._M_pathname.erase(elem->_M_pos); +- // Remove empty filename at the end: +- ret._M_cmpts.pop_back(); +- // If we still have a trailing non-root dir separator +- // then leave an empty filename at the end: +- if (std::prev(elem)->_M_type == _Type::_Filename) +- elem->clear(); +- else // remove the component completely: +- ret._M_cmpts.pop_back(); +- } ++ ret._M_pathname.erase(elem._M_cur->_M_pos); ++ ret._M_cmpts.erase(elem._M_cur, ret._M_cmpts.end()); + } +- else +- // Append the ".." to something ending in "../" which happens +- // when normalising paths like ".././.." and "../a/../.." ++ else // ??? + ret /= p; + } + } +@@ -475,12 +520,10 @@ path::lexically_relative(const path& base) const + const path& p = *b; + if (is_dotdot(p)) + --n; +- else if (!p.empty() && !is_dot(p)) ++ else if (!is_dot(p)) + ++n; + } +- if (n == 0 && (a == end() || a->empty())) +- ret = "."; +- else if (n >= 0) ++ if (n >= 0) + { + const path dotdot(".."); + while (n--) +@@ -504,7 +547,7 @@ path::lexically_proximate(const path& base) const std::pair<const path::string_type*, std::size_t> path::_M_find_extension() const { @@ -2445,7 +2732,7 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 if (_M_type == _Type::_Filename) s = &_M_pathname; -@@ -502,9 +562,9 @@ path::_M_find_extension() const +@@ -519,9 +562,9 @@ path::_M_find_extension() const { if (auto sz = s->size()) { @@ -2457,34 +2744,7 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 return { s, pos ? pos : string_type::npos }; } } -@@ -514,11 +574,13 @@ path::_M_find_extension() const - void - path::_M_split_cmpts() - { -- _M_type = _Type::_Multi; - _M_cmpts.clear(); -- - if (_M_pathname.empty()) -- return; -+ { -+ _M_type = _Type::_Filename; -+ return; -+ } -+ _M_type = _Type::_Multi; - - size_t pos = 0; - const size_t len = _M_pathname.size(); -@@ -593,8 +655,7 @@ path::_M_split_cmpts() - // An empty element, if trailing non-root directory-separator present. - if (_M_cmpts.back()._M_type == _Type::_Filename) - { -- const auto& last = _M_cmpts.back(); -- pos = last._M_pos + last._M_pathname.size(); -+ pos = _M_pathname.size(); - _M_cmpts.emplace_back(string_type(), _Type::_Filename, pos); - } - } -@@ -704,8 +765,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 +@@ -722,8 +765,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 std::string filesystem_error::_M_gen_what() { @@ -2496,5 +2756,5 @@ index 6f594cec1d5..f6c0b8bb0f6 100644 _GLIBCXX_END_NAMESPACE_CXX11 -- -2.18.0 +2.20.1 |