Thanks for the review. I attached the updated patch.

Can you commit this for me or point me to what I should do next? This is my 
first contribution here.

Best,
Moritz

Am 03.03.21 um 19:02 schrieb Patrick Palka:
On Wed, 3 Mar 2021, Moritz Sichert via Libstdc++ wrote:

std::ranges::reverse_view uses make_reverse_iterator in its
implementation as described in [range.reverse.view]. This accidentally
allows ADL as an unqualified name is used in the call. According to
[contents], however, this should be treated as a qualified lookup into
the std namespace.

This leads to errors due to ambiguous name lookups when another
make_reverse_iterator function is found via ADL.

I found this as llvm has its own implementation of ranges which also has
llvm::make_reverse_iterator. This lead to a compile error with
std::vector<llvm::Value*> | std::ranges::views::reverse.

Thanks for the patch!  It looks good to me.  Some very minor comments
below.


Best,
Moritz


libstdc++-v3/Changelog:

        * include/std/ranges: Avoid accidental ADL when calling
         make_reverse_iterator.
         * testsuite/std/ranges/adaptors/reverse_no_adl.cc: New test.
         Test that views::reverse works when make_reverse_iterator is
         defined in a namespace that could be found via ADL.
---
  libstdc++-v3/include/std/ranges               | 12 +++---
  .../std/ranges/adaptors/reverse_no_adl.cc     | 39 +++++++++++++++++++
  2 files changed, 45 insertions(+), 6 deletions(-)
  create mode 100644 
libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 1be74beb860..adbc6d7b274 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -2958,29 +2958,29 @@ namespace views
        {
        if constexpr (_S_needs_cached_begin)
          if (_M_cached_begin._M_has_value())
-           return make_reverse_iterator(_M_cached_begin._M_get(_M_base));
+           return std::make_reverse_iterator(_M_cached_begin._M_get(_M_base));
auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base));
        if constexpr (_S_needs_cached_begin)
          _M_cached_begin._M_set(_M_base, __it);
-       return make_reverse_iterator(std::move(__it));
+       return std::make_reverse_iterator(std::move(__it));
        }
constexpr auto
        begin() requires common_range<_Vp>
-      { return make_reverse_iterator(ranges::end(_M_base)); }
+      { return std::make_reverse_iterator(ranges::end(_M_base)); }
constexpr auto
        begin() const requires common_range<const _Vp>
-      { return make_reverse_iterator(ranges::end(_M_base)); }
+      { return std::make_reverse_iterator(ranges::end(_M_base)); }
constexpr reverse_iterator<iterator_t<_Vp>>
        end()
-      { return make_reverse_iterator(ranges::begin(_M_base)); }
+      { return std::make_reverse_iterator(ranges::begin(_M_base)); }
constexpr auto
        end() const requires common_range<const _Vp>
-      { return make_reverse_iterator(ranges::begin(_M_base)); }
+      { return std::make_reverse_iterator(ranges::begin(_M_base)); }
constexpr auto
        size() requires sized_range<_Vp>
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc 
b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc
new file mode 100644
index 00000000000..9aa96c7d40e
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2020-2021 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 run { target c++2a } }

Since this isn't an execution test, we should use "compile" instead of
"run" here.


+
+#include <ranges>
+
+// This test tests that views::reverse works and does not use ADL which could
+// lead to accidentally finding test_ns::make_reverse_iterator(const A&).
+
+namespace test_ns
+{
+  struct A {};
+  template <typename T>
+  void make_reverse_iterator(T&&) {}
+} // namespace test_ns
+
+void test()
+{
+  test_ns::A as[] = {{}, {}};
+  auto v = as | std::views::reverse;
+  static_assert(std::ranges::view<decltype(v)>);

I suppose we could also check

   static_assert(std::ranges::range<const decltype(v)>)

which'll additionally verify the std:: qualification inside the const
begin()/end() overloads.

+}
+
--
2.30.1


From 9f9858c24519bcea903de477a37b31eed09725c1 Mon Sep 17 00:00:00 2001
From: Moritz Sichert <sich...@in.tum.de>
Date: Wed, 3 Mar 2021 18:14:28 +0100
Subject: [PATCH] libstdc++: Avoid accidental ADL when calling
 make_reverse_iterator

std::ranges::reverse_view uses make_reverse_iterator in its
implementation as described in [range.reverse.view]. This accidentally
allows ADL as an unqualified name is used in the call. According to
[contents], however, this should be treated as a qualified lookup into
the std namespace.

This leads to errors due to ambiguous name lookups when another
make_reverse_iterator function is found via ADL.

libstdc++-v3/Changelog:

	* include/std/ranges: Avoid accidental ADL when calling
        make_reverse_iterator.
        * testsuite/std/ranges/adaptors/reverse_no_adl.cc: New test.
        Test that views::reverse works when make_reverse_iterator is
        defined in a namespace that could be found via ADL.
---
 libstdc++-v3/include/std/ranges               | 12 +++---
 .../std/ranges/adaptors/reverse_no_adl.cc     | 40 +++++++++++++++++++
 2 files changed, 46 insertions(+), 6 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 1be74beb860..adbc6d7b274 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -2958,29 +2958,29 @@ namespace views
       {
 	if constexpr (_S_needs_cached_begin)
 	  if (_M_cached_begin._M_has_value())
-	    return make_reverse_iterator(_M_cached_begin._M_get(_M_base));
+	    return std::make_reverse_iterator(_M_cached_begin._M_get(_M_base));
 
 	auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base));
 	if constexpr (_S_needs_cached_begin)
 	  _M_cached_begin._M_set(_M_base, __it);
-	return make_reverse_iterator(std::move(__it));
+	return std::make_reverse_iterator(std::move(__it));
       }
 
       constexpr auto
       begin() requires common_range<_Vp>
-      { return make_reverse_iterator(ranges::end(_M_base)); }
+      { return std::make_reverse_iterator(ranges::end(_M_base)); }
 
       constexpr auto
       begin() const requires common_range<const _Vp>
-      { return make_reverse_iterator(ranges::end(_M_base)); }
+      { return std::make_reverse_iterator(ranges::end(_M_base)); }
 
       constexpr reverse_iterator<iterator_t<_Vp>>
       end()
-      { return make_reverse_iterator(ranges::begin(_M_base)); }
+      { return std::make_reverse_iterator(ranges::begin(_M_base)); }
 
       constexpr auto
       end() const requires common_range<const _Vp>
-      { return make_reverse_iterator(ranges::begin(_M_base)); }
+      { return std::make_reverse_iterator(ranges::begin(_M_base)); }
 
       constexpr auto
       size() requires sized_range<_Vp>
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc
new file mode 100644
index 00000000000..7d01f5d42a2
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse_no_adl.cc
@@ -0,0 +1,40 @@
+// Copyright (C) 2020-2021 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 <ranges>
+
+// This test tests that views::reverse works and does not use ADL which could
+// lead to accidentally finding test_ns::make_reverse_iterator(const A&).
+
+namespace test_ns
+{
+  struct A {};
+  template <typename T>
+  void make_reverse_iterator(T&&) {}
+} // namespace test_ns
+
+void test()
+{
+  test_ns::A as[] = {{}, {}};
+  auto v = as | std::views::reverse;
+  static_assert(std::ranges::view<decltype(v)>);
+  static_assert(std::ranges::view<const decltype(v)>);
+}
+
-- 
2.30.1

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to