From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1984) id 9504339DD805; Fri, 17 Jul 2020 14:48:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9504339DD805 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1594997332; bh=lJ2AkDjVST4wiqz4iZdnOMaUhcx8OauVaFKqWwRjPaw=; h=From:To:Subject:Date:From; b=fA/hDSRuzx9IyszXqUXH9RJL7ssDGeyqqdX0EdYvlpuWdIELRSiIzcKNDpKhryJMc 7jbjlTsmN5BrcW1dTGIta0y0lqpBRL56TaoaJpxONwmsK0MB3Bmllv+tjPbfYmb75W gzos8NEfhvDsYsDO2DvVQOKBTPiSlBXgt/HnHDZc= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Tamar Christina 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 X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/vendors/ARM/heads/arm-perf-staging X-Git-Oldrev: 0e665f256b4ac8c5f78713ebd4e9378fd4ecf5a8 X-Git-Newrev: 87841658d4fa5174d1797ee0abc73b3b3f11cad4 Message-Id: <20200717144852.9504339DD805@sourceware.org> Date: Fri, 17 Jul 2020 14:48:52 +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, 17 Jul 2020 14:48:52 -0000 https://gcc.gnu.org/g:87841658d4fa5174d1797ee0abc73b3b3f11cad4 commit 87841658d4fa5174d1797ee0abc73b3b3f11cad4 Author: Jonathan Wakely 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 + * 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 - 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 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include +#include +#include + +void +test01() +{ + using V = std::vector; + static_assert( std::totally_ordered ); + static_assert( std::three_way_comparable ); + using C = std::compare_three_way_result_t; + static_assert( std::same_as ); + + static_assert( std::random_access_iterator ); + static_assert( std::random_access_iterator ); +} + +// User-defined pointer type that supports operator< but not operator<=> +template +struct Pointer : __gnu_test::PointerBase, T> +{ + using __gnu_test::PointerBase, 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 +template +struct Alloc +{ + typedef T value_type; + typedef Pointer pointer; + + Alloc() = default; + template + Alloc(const Alloc&) { } + + pointer allocate(std::size_t n) + { return pointer(std::allocator().allocate(n)); } + + void deallocate(pointer p, std::size_t n) + { std::allocator().deallocate(p.operator->(), n); } +}; + +void +test02() +{ + using V = std::vector>; + static_assert( std::totally_ordered ); + static_assert( std::three_way_comparable ); + using C = std::compare_three_way_result_t; + static_assert( std::same_as ); + + static_assert( std::random_access_iterator ); + static_assert( std::random_access_iterator ); +} + +void +test03() +{ + struct P : Pointer { + bool operator<(const P&) const = delete; + }; + + struct C { + using pointer = P; + }; + + using I = __gnu_cxx::__normal_iterator; + static_assert( ! std::totally_ordered ); + static_assert( ! std::three_way_comparable ); +}