Commit 01eb211b by Jonathan Wakely Committed by Jonathan Wakely

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
parent 838fd641
2019-11-15 Jonathan Wakely <jwakely@redhat.com>
* 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 <stop_token>.
* include/precompiled/stdc++.h: Likewise.
* include/std/stop_token: Fix definition of std::nostopstate.
......
......@@ -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<value_type>;
......@@ -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
......
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment