From: Moritz Sichert Date: Tue, 23 Mar 2021 15:47:37 +0000 (+0000) Subject: libstdc++: Avoid accidental ADL when calling make_reverse_iterator X-Git-Tag: basepoints/gcc-12~457 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=09f08fef71fb776a1d850a7b854c7ccf8a3d6c11;p=thirdparty%2Fgcc.git 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 (reverse_view::begin, reverse_view::end): Qualify make_reverse_iterator calls to avoid ADL. * testsuite/std/ranges/adaptors/reverse.cc: Test that views::reverse works when make_reverse_iterator is defined in an associated namespace. --- diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 1be74beb860d..adbc6d7b274e 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 - { return make_reverse_iterator(ranges::end(_M_base)); } + { return std::make_reverse_iterator(ranges::end(_M_base)); } constexpr reverse_iterator> 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 - { 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.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc index 593b77e4a37b..47386575192b 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc @@ -131,6 +131,23 @@ test05() VERIFY( test_wrapper::increment_count == 5 ); } +namespace test_ns +{ + struct A {}; + template + void make_reverse_iterator(T&&) {} +} // namespace test_ns + +void test06() +{ + // Check that views::reverse works and does not use ADL which could lead + // to accidentally finding test_ns::make_reverse_iterator(const A&). + test_ns::A as[] = {{}, {}}; + auto v = as | std::views::reverse; + static_assert(std::ranges::view); + static_assert(std::ranges::view); +} + int main() { @@ -139,4 +156,5 @@ main() test03(); test04(); test05(); + test06(); }