public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-1397] libstdc++: Fix filesystem::path comparisons for C++23 Date: Fri, 11 Jun 2021 18:23:57 +0000 (GMT) [thread overview] Message-ID: <20210611182357.97D5A3857C7B@sourceware.org> (raw) https://gcc.gnu.org/g:1e690757d30775ed340a368b9a9463b2ad68de01 commit r12-1397-g1e690757d30775ed340a368b9a9463b2ad68de01 Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Jun 11 19:18:11 2021 +0100 libstdc++: Fix filesystem::path comparisons for C++23 In C++23 there is a basic_string_view(Range&&) constructor, which is constrained to take a range (specifically, a contiguous_range). When the filesystem::path comparison operators call lhs.compare(rhs) the overload taking a string_view is considered, which means checking whether path satisfies the range concept. That satisfaction result changes depending whether path::iterator is complete, which is ill-formed; no diagnostic required. To avoid the problem, this change ensures that the overload resolution is performed in a context where path::iterator is complete and the range concept is satisfied. (The result of overload resolution is always that the compare(const path&) overload is the best match, but we still have to consider the compare(basic_string_view<value_type>) one to decide if it even participates in overload resolution). For std::filesystem::path we can't define the comparison operators later in the file, because they are hidden friends, so a new helper is introduced that gets defined when everything else is complete. For std::experimental::filesystem::path we can just move the definitions of the comparison operators later in the file. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/bits/fs_path.h (operator==, operator<=>): Use new _S_compare function. (path::_S_compare): New function to call path::compare in a context where path::iterator is complete. * include/experimental/bits/fs_path.h (operator<, operator==): Define after path::iterator is complete. * testsuite/27_io/filesystem/path/native/conv_c++23.cc: New test. * testsuite/experimental/filesystem/path/native/conv_c++23.cc: New test. Diff: --- libstdc++-v3/include/bits/fs_path.h | 17 +++++++++++++++-- libstdc++-v3/include/experimental/bits/fs_path.h | 16 ++++++++++++---- .../27_io/filesystem/path/native/conv_c++23.cc | 12 ++++++++++++ .../experimental/filesystem/path/native/conv_c++23.cc | 12 ++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h index ad2518f414c..5e285204527 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -513,13 +513,13 @@ namespace __detail /// Compare paths friend bool operator==(const path& __lhs, const path& __rhs) noexcept - { return __lhs.compare(__rhs) == 0; } + { return path::_S_compare(__lhs, __rhs) == 0; } #if __cpp_lib_three_way_comparison /// Compare paths friend strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept - { return __lhs.compare(__rhs) <=> 0; } + { return path::_S_compare(__lhs, __rhs) <=> 0; } #else /// Compare paths friend bool operator!=(const path& __lhs, const path& __rhs) noexcept @@ -627,6 +627,11 @@ namespace __detail static basic_string<_CharT, _Traits, _Allocator> _S_str_convert(basic_string_view<value_type>, const _Allocator&); + // Returns lhs.compare(rhs), but defined after path::iterator is complete. + __attribute__((__always_inline__)) + static int + _S_compare(const path& __lhs, const path& __rhs) noexcept; + void _M_split_cmpts(); _Type _M_type() const noexcept { return _M_cmpts.type(); } @@ -1330,6 +1335,14 @@ namespace __detail return _M_at_end == __rhs._M_at_end; } + // Define this now that path and path::iterator are complete. + // It needs to consider the string_view(Range&&) constructor during + // overload resolution, which depends on whether range<path> is satisfied, + // which depends on whether path::iterator is complete. + inline int + path::_S_compare(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs); } + /// @} group filesystem _GLIBCXX_END_NAMESPACE_CXX11 } // namespace filesystem diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 1ecf2f3a7bd..1fb84ec1e78 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -551,8 +551,7 @@ namespace __detail size_t hash_value(const path& __p) noexcept; /// Compare paths - inline bool operator<(const path& __lhs, const path& __rhs) noexcept - { return __lhs.compare(__rhs) < 0; } + inline bool operator<(const path& __lhs, const path& __rhs) noexcept; /// Compare paths inline bool operator<=(const path& __lhs, const path& __rhs) noexcept @@ -567,8 +566,7 @@ namespace __detail { return !(__lhs < __rhs); } /// Compare paths - inline bool operator==(const path& __lhs, const path& __rhs) noexcept - { return __lhs.compare(__rhs) == 0; } + inline bool operator==(const path& __lhs, const path& __rhs) noexcept; /// Compare paths inline bool operator!=(const path& __lhs, const path& __rhs) noexcept @@ -1275,6 +1273,16 @@ namespace __detail return _M_at_end == __rhs._M_at_end; } + // Define these now that path and path::iterator are complete. + // They needs to consider the string_view(Range&&) constructor during + // overload resolution, which depends on whether range<path> is satisfied, + // which depends on whether path::iterator is complete. + inline bool operator<(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) < 0; } + + inline bool operator==(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) == 0; } + /// @} group filesystem-ts _GLIBCXX_END_NAMESPACE_CXX11 } // namespace v1 diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/native/conv_c++23.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/native/conv_c++23.cc new file mode 100644 index 00000000000..b4efed2bd47 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/native/conv_c++23.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <filesystem> + +void +test01() +{ + using std::filesystem::path; + path p; + path::string_type s(p); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/native/conv_c++23.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/native/conv_c++23.cc new file mode 100644 index 00000000000..f3c3f884965 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/native/conv_c++23.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <experimental/filesystem> + +void +test01() +{ + using std::experimental::filesystem::path; + path p; + path::string_type s(p); +}
reply other threads:[~2021-06-11 18:23 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210611182357.97D5A3857C7B@sourceware.org \ --to=redi@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).