diff options
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/iterator_concepts.h | 42 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/24_iterators/customization_points/92894.cc | 52 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc | 55 |
4 files changed, 153 insertions, 11 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f699a1bc59e..152c69f843f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,4 +1,19 @@ 2020-05-01 Jonathan Wakely <jwakely@redhat.com> + Patrick Palka <ppalka@redhat.com> + + PR libstdc++/92894 + * include/bits/iterator_concepts.h (ranges::__cust_imove::_IMove): + Add trait to determine return type and an alias for it. + (ranges::__cust_imove::_IMove::operator()): Use __result instead of + deduced return type. + (iter_rvalue_reference_t): Use _IMove::__type instead of checking + the result of ranges::iter_move. + (__detail::__indirectly_readable_impl): Use iter_rvalue_reference_t + instead of checking the result of ranges::iter_move. + * testsuite/24_iterators/customization_points/92894.cc: New test. + * testsuite/24_iterators/indirect_callable/92894.cc: New test. + +2020-05-01 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/94901 * include/std/type_traits (__is_complete_or_unbounded): Replace diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index b598532089e..e221ec70367 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -90,6 +90,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { private: template<typename _Tp> + struct __result + { using type = iter_reference_t<_Tp>; }; + + template<typename _Tp> + requires __adl_imove<_Tp> + struct __result<_Tp> + { using type = decltype(iter_move(std::declval<_Tp>())); }; + + template<typename _Tp> + requires (!__adl_imove<_Tp>) + && is_lvalue_reference_v<iter_reference_t<_Tp>> + struct __result<_Tp> + { using type = remove_reference_t<iter_reference_t<_Tp>>&&; }; + + template<typename _Tp> static constexpr bool _S_noexcept() { @@ -100,16 +115,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } public: - template<typename _Tp> - requires __adl_imove<_Tp> || requires(_Tp& __e) { *__e; } - constexpr decltype(auto) + // The result type of iter_move(std::declval<_Tp>()) + template<std::__detail::__dereferenceable _Tp> + using __type = typename __result<_Tp>::type; + + template<std::__detail::__dereferenceable _Tp> + constexpr __type<_Tp> operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) { if constexpr (__adl_imove<_Tp>) return iter_move(static_cast<_Tp&&>(__e)); - else if constexpr (is_reference_v<iter_reference_t<_Tp>>) - return std::move(*__e); + else if constexpr (is_lvalue_reference_v<iter_reference_t<_Tp>>) + return static_cast<__type<_Tp>>(*__e); else return *__e; } @@ -123,10 +141,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // namespace ranges template<__detail::__dereferenceable _Tp> - requires requires(_Tp& __t) - { { ranges::iter_move(__t) } -> __detail::__can_reference; } + requires __detail:: + __can_reference<ranges::__cust_imove::_IMove::__type<_Tp&>> using iter_rvalue_reference_t - = decltype(ranges::iter_move(std::declval<_Tp&>())); + = ranges::__cust_imove::_IMove::__type<_Tp&>; template<typename> struct incrementable_traits { }; @@ -443,13 +461,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __iter_concept = typename __iter_concept_impl<_Iter>::type; template<typename _In> - concept __indirectly_readable_impl = requires(const _In __in) + concept __indirectly_readable_impl = requires { typename iter_value_t<_In>; typename iter_reference_t<_In>; typename iter_rvalue_reference_t<_In>; - { *__in } -> same_as<iter_reference_t<_In>>; - { ranges::iter_move(__in) } -> same_as<iter_rvalue_reference_t<_In>>; + requires same_as<iter_reference_t<const _In>, + iter_reference_t<_In>>; + requires same_as<iter_rvalue_reference_t<const _In>, + iter_rvalue_reference_t<_In>>; } && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> && common_reference_with<iter_reference_t<_In>&&, diff --git a/libstdc++-v3/testsuite/24_iterators/customization_points/92894.cc b/libstdc++-v3/testsuite/24_iterators/customization_points/92894.cc new file mode 100644 index 00000000000..197268fe5e3 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/customization_points/92894.cc @@ -0,0 +1,52 @@ +// 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> + +using namespace std; + +// Define our own of version of indirectly_readable_impl here, +// to check the use of iter_move even if the real concept in +// <bits/iterator_concepts.h> no longer uses iter_move. +template<class In> +concept indirectly_readable_impl + = requires(const In in) + { + typename iter_value_t<In>; + typename iter_reference_t<In>; + typename iter_rvalue_reference_t<In>; + { *in } -> same_as<iter_reference_t<In>>; + { ranges::iter_move(in) } -> same_as<iter_rvalue_reference_t<In>>; + }; + +template<class T> requires indirectly_readable_impl<projected<T*, identity>> + void algo(T) + { } + +void +test01() +{ + // PR libstdc++/92894 + // Verify that the use of range::iter_move above doesn't cause odr-use of + // projected<local-class-type, identity>::operator* (which is not defined). + struct X { }; + X a; + algo(a); +} diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc new file mode 100644 index 00000000000..3408c76bde1 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc @@ -0,0 +1,55 @@ +// 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> + +using std::projected; +using std::identity; +using std::indirect_unary_predicate; + +template<typename T, + indirect_unary_predicate<projected<T*, identity>> Pred> + constexpr void + all_of(T*, Pred) + { } + +void +test01() +{ + // PR libstdc++/92894 + struct X { }; + X x; + all_of(&x, [](X&) { return false; }); +} + +template<class R, class Proj = identity, + indirect_unary_predicate<projected<R, Proj>> Pred> + constexpr void + find_if(R, Pred, Proj = {}) + { } + +void +test02() +{ + // PR 94241 + struct s { int m; }; + s r[] = { s{0}, s{1}, s{2}, s{3} }; + find_if(r, [](auto const) { return true; }); +} |