From 01eb211bade92275e39254cc5a0dc21834dbcac4 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 15 Nov 2019 19:58:15 +0000 Subject: [PATCH] libstdc++: Implement LWG 3070 in path::lexically_relative * src/c++17/fs_path.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] (is_disk_designator): New helper function. (path::_Parser::root_path()): Use is_disk_designator. (path::lexically_relative(const path&)): Implement resolution of LWG 3070. * testsuite/27_io/filesystem/path/generation/relative.cc: Check with path components that look like a root-name. From-SVN: r278313 --- libstdc++-v3/ChangeLog | 8 +++++++ libstdc++-v3/src/c++17/fs_path.cc | 22 ++++++++++++++++++- .../filesystem/path/generation/relative.cc | 16 ++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 53f3b2961c8..e6094bd7a72 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,13 @@ 2019-11-15 Jonathan Wakely + * src/c++17/fs_path.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] + (is_disk_designator): New helper function. + (path::_Parser::root_path()): Use is_disk_designator. + (path::lexically_relative(const path&)): Implement resolution of + LWG 3070. + * testsuite/27_io/filesystem/path/generation/relative.cc: Check with + path components that look like a root-name. + * doc/doxygen/user.cfg.in: Add . * include/precompiled/stdc++.h: Likewise. * include/std/stop_token: Fix definition of std::nostopstate. diff --git a/libstdc++-v3/src/c++17/fs_path.cc b/libstdc++-v3/src/c++17/fs_path.cc index 14842452354..5fba971fef6 100644 --- a/libstdc++-v3/src/c++17/fs_path.cc +++ b/libstdc++-v3/src/c++17/fs_path.cc @@ -47,6 +47,13 @@ static inline bool is_dir_sep(path::value_type ch) #endif } +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS +static inline bool is_disk_designator(std::wstring_view s) +{ + return s.length() == 2 && s[1] == L':'; +} +#endif + struct path::_Parser { using string_view_type = std::basic_string_view; @@ -117,7 +124,7 @@ struct path::_Parser ++pos; } #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - else if (len > 1 && input[1] == L':') + else if (is_disk_designator(input.substr(0, 2))) { // got disk designator root.first.str = input.substr(0, 2); @@ -1747,6 +1754,19 @@ path::lexically_relative(const path& base) const if (!has_root_directory() && base.has_root_directory()) return ret; auto [a, b] = std::mismatch(begin(), end(), base.begin(), base.end()); +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3070. path::lexically_relative causes surprising results if a filename + // can also be a root-name + if (!empty()) + for (auto& p : _M_cmpts) + if (p._M_type() == _Type::_Filename && is_disk_designator(p.native())) + return ret; + if (!base.empty()) + for (auto i = b, end = base.end(); i != end; ++i) + if (i->_M_type() == _Type::_Filename && is_disk_designator(i->native())) + return ret; +#endif if (a == end() && b == base.end()) ret = "."; else diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc index dde08d46f2c..b2ac27293b2 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc @@ -77,10 +77,26 @@ test03() compare_paths( path("/dir/.").lexically_relative("/dir/."), "." ); } +void +test04() +{ +#if defined(__MING32__) || defined(__MINGW64__) + // DR 3070 + compare_paths(path("c:/f:o/bar").lexically_relative("c:/f:o/bar"), "."); + compare_paths(path("c:/foo/bar").lexically_relative("c:/foo/b:r"), "..\\bar"); + compare_paths(path("c:/foo/b:r").lexically_relative("c:/foo/bar"), "..\\b:r"); + compare_paths(path("c:/foo/b:").lexically_relative("c:/foo/b:"), ""); + compare_paths(path("c:/foo/bar").lexically_relative("c:/foo/b:"), ""); + compare_paths(path("c:/f:/bar").lexically_relative("c:/foo/bar"), ""); + compare_paths(path("foo/bar").lexically_relative("foo/b:/bar"), ""); +#endif +} + int main() { test01(); test02(); test03(); + test04(); } -- 2.30.2