public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Tamar Christina <tnfchris@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/arm-perf-staging)] libstdc++: Fix __normal_iterator comparisons for C++20 Date: Fri, 17 Jul 2020 14:48:52 +0000 (GMT) [thread overview] Message-ID: <20200717144852.9504339DD805@sourceware.org> (raw) https://gcc.gnu.org/g:87841658d4fa5174d1797ee0abc73b3b3f11cad4 commit 87841658d4fa5174d1797ee0abc73b3b3f11cad4 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Apr 21 23:43:27 2020 +0100 libstdc++: Fix __normal_iterator comparisons for C++20 This fixes a regression introduced when I replaced __normal_iterator's relational operators with operator<=>. If the wrapped iterator type doesn't define operator<=> then __normal_iterator doesdn't either, which breaks any use of fancy pointers that don't define <=>. The regression was found when trying to build cmcstl2. The solution is to use synth-three-way to define __normal_iterator's spaceship operator, so that it is still defined even if the wrapped type only supports operator<. * include/bits/stl_iterator.h (__normal_iterator): Use synth-three-way to define operator<=>. * testsuite/24_iterators/normal_iterator/cmp_c++20.cc: New test. Diff: --- libstdc++-v3/ChangeLog | 4 + libstdc++-v3/include/bits/stl_iterator.h | 7 +- .../24_iterators/normal_iterator/cmp_c++20.cc | 95 ++++++++++++++++++++++ 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4e0a02fef2d..55df9a31244 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,9 @@ 2020-04-21 Jonathan Wakely <jwakely@redhat.com> + * include/bits/stl_iterator.h (__normal_iterator): Use synth-three-way + to define operator<=>. + * testsuite/24_iterators/normal_iterator/cmp_c++20.cc: New test. + * doc/Makefile.am (xml_sources_manual): Add missing XML files. * doc/Makefile.in: Regenerate. * doc/xml/manual/status_cxx1998.xml: Refer to "this section" instead diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 5bfdce6af2d..652f51c6e7f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1048,12 +1048,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template<typename _IteratorL, typename _IteratorR, typename _Container> - constexpr auto + constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) - noexcept(noexcept(__lhs.base() <=> __rhs.base())) - -> decltype(__lhs.base() <=> __rhs.base()) - { return __lhs.base() <=> __rhs.base(); } + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } #else // Forward iterator requirements template<typename _IteratorL, typename _IteratorR, typename _Container> diff --git a/libstdc++-v3/testsuite/24_iterators/normal_iterator/cmp_c++20.cc b/libstdc++-v3/testsuite/24_iterators/normal_iterator/cmp_c++20.cc new file mode 100644 index 00000000000..a5014e8ae99 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/normal_iterator/cmp_c++20.cc @@ -0,0 +1,95 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <iterator> +#include <vector> +#include <testsuite_allocator.h> + +void +test01() +{ + using V = std::vector<int>; + static_assert( std::totally_ordered<V::iterator> ); + static_assert( std::three_way_comparable<V::iterator> ); + using C = std::compare_three_way_result_t<V::iterator>; + static_assert( std::same_as<C, std::strong_ordering> ); + + static_assert( std::random_access_iterator<V::iterator> ); + static_assert( std::random_access_iterator<V::const_iterator> ); +} + +// User-defined pointer type that supports operator< but not operator<=> +template<typename T> +struct Pointer : __gnu_test::PointerBase<Pointer<T>, T> +{ + using __gnu_test::PointerBase<Pointer<T>, T>::PointerBase; + + friend bool operator<(const Pointer& lhs, const Pointer& rhs) noexcept + { return lhs.value < rhs.value; } + + std::partial_ordering operator<=>(const Pointer&) const = delete; +}; + +// Minimal allocator using Pointer<T> +template<typename T> +struct Alloc +{ + typedef T value_type; + typedef Pointer<T> pointer; + + Alloc() = default; + template<typename U> + Alloc(const Alloc<U>&) { } + + pointer allocate(std::size_t n) + { return pointer(std::allocator<T>().allocate(n)); } + + void deallocate(pointer p, std::size_t n) + { std::allocator<T>().deallocate(p.operator->(), n); } +}; + +void +test02() +{ + using V = std::vector<int, Alloc<int>>; + static_assert( std::totally_ordered<V::iterator> ); + static_assert( std::three_way_comparable<V::iterator> ); + using C = std::compare_three_way_result_t<V::iterator>; + static_assert( std::same_as<C, std::weak_ordering> ); + + static_assert( std::random_access_iterator<V::iterator> ); + static_assert( std::random_access_iterator<V::const_iterator> ); +} + +void +test03() +{ + struct P : Pointer<int> { + bool operator<(const P&) const = delete; + }; + + struct C { + using pointer = P; + }; + + using I = __gnu_cxx::__normal_iterator<P, C>; + static_assert( ! std::totally_ordered<I> ); + static_assert( ! std::three_way_comparable<I> ); +}
reply other threads:[~2020-07-17 14:48 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=20200717144852.9504339DD805@sourceware.org \ --to=tnfchris@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).