summarylogtreecommitdiffstats
path: root/gcc-filesystem.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-filesystem.patch')
-rw-r--r--gcc-filesystem.patch710
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