]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Replace deduced return type in ranges::iter_move (PR 92894)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 7 May 2020 16:39:56 +0000 (17:39 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 7 May 2020 20:07:09 +0000 (21:07 +0100)
The deduced return type causes the instantiation of the function body,
which can then require the instantiation of std::projected::operator*
which is intentionally not defined.

This patch uses a helper trait to define the return type, so that the
function body doesn't need to be instantiated.

Unlike on the master branch, this backport to gcc-10 does not change the
iter_rvalue_reference_t alias template and __indirectly_readable_impl
concept to use the new trait.

Backport from mainline
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.
* testsuite/24_iterators/customization_points/92894.cc: New test.
* testsuite/24_iterators/indirect_callable/92894.cc: New test.

Co-authored-by: Patrick Palka <ppalka@redhat.com>
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/iterator_concepts.h
libstdc++-v3/testsuite/24_iterators/customization_points/92894.cc [new file with mode: 0644]
libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc [new file with mode: 0644]

index 70e296622e7e72ee27b69d815a9401b5abd29936..55d975b84fc1806afc5d3440c42de18980dc5bed 100644 (file)
@@ -1,3 +1,17 @@
+2020-05-07  Jonathan Wakely  <jwakely@redhat.com>
+
+       Backport from mainline
+       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.
+       * testsuite/24_iterators/customization_points/92894.cc: New test.
+       * testsuite/24_iterators/indirect_callable/92894.cc: New test.
+
 2020-05-07  Release Manager
 
        * GCC 10.1.0 released.
index b598532089e9ce89e171d99832a8a94009b12cea..c5b6247cde7d5254e876aae0b18c7e89b0e2af95 100644 (file)
@@ -89,6 +89,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       struct _IMove
       {
       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;
          }
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 (file)
index 0000000..197268f
--- /dev/null
@@ -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 (file)
index 0000000..3408c76
--- /dev/null
@@ -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; });
+}