From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 3945F386F422; Fri, 11 Jun 2021 22:26:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3945F386F422 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r11-8562] libstdc++: Fix filesystem::path comparisons for C++23 X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-11 X-Git-Oldrev: ef636c00054bc31e45e2d0fc02125fb7613a6c70 X-Git-Newrev: 828cdc64297cf41e467080f0d14358548a78b2e3 Message-Id: <20210611222613.3945F386F422@sourceware.org> Date: Fri, 11 Jun 2021 22:26:13 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Jun 2021 22:26:13 -0000 https://gcc.gnu.org/g:828cdc64297cf41e467080f0d14358548a78b2e3 commit r11-8562-g828cdc64297cf41e467080f0d14358548a78b2e3 Author: Jonathan Wakely 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) 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 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. (cherry picked from commit 1e690757d30775ed340a368b9a9463b2ad68de01) 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, 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 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 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 + +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 + +void +test01() +{ + using std::experimental::filesystem::path; + path p; + path::string_type s(p); +}