https://gcc.gnu.org/g:d5fb86cbec48af24d3ec56519fdf8b0c4133b801

commit r15-7529-gd5fb86cbec48af24d3ec56519fdf8b0c4133b801
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Feb 12 18:30:21 2025 +0000

    libstdc++: Fix use of make_pair that used ADL
    
    _Rb_tree::_M_equal_range calls make_pair unqualified, which means it
    uses ADL. As the new testcase shows, this can find something other than
    std::make_pair. Rather than just changing it to use a qualified call,
    remove the use of make_pair entirely. We don't need to deduce any types
    here, we know exactly what type of std::pair we want to construct, so do
    that explicitly.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/stl_tree.h (_Rb_tree::_M_equal_range): Replace
            unqualified call to make_pair with explicit construction of
            std::pair.
            * testsuite/23_containers/set/operations/equal_range_adl.cc:
            New test.

Diff:
---
 libstdc++-v3/include/bits/stl_tree.h               | 18 ++++++++-------
 .../set/operations/equal_range_adl.cc              | 26 ++++++++++++++++++++++
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_tree.h 
b/libstdc++-v3/include/bits/stl_tree.h
index 7285676f427f..6b35f99a25a3 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -2633,6 +2633,8 @@ namespace __rb_tree
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
     equal_range(const _Key& __k)
     {
+      typedef pair<iterator, iterator> _Ret;
+
       _Base_ptr __x = _M_begin();
       _Base_ptr __y = _M_end();
       while (__x)
@@ -2647,12 +2649,11 @@ namespace __rb_tree
              _Base_ptr __yu(__y);
              __y = __x, __x = _S_left(__x);
              __xu = _S_right(__xu);
-             return make_pair(iterator(_M_lower_bound(__x, __y, __k)),
-                              iterator(_M_upper_bound(__xu, __yu, __k)));
+             return _Ret(iterator(_M_lower_bound(__x, __y, __k)),
+                         iterator(_M_upper_bound(__xu, __yu, __k)));
            }
        }
-      return pair<iterator, iterator>(iterator(__y),
-                                     iterator(__y));
+      return _Ret(iterator(__y), iterator(__y));
     }
 
   template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -2664,6 +2665,8 @@ namespace __rb_tree
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
     equal_range(const _Key& __k) const
     {
+      typedef pair<const_iterator, const_iterator> _Ret;
+
       _Base_ptr __x = _M_begin();
       _Base_ptr __y = _M_end();
       while (__x)
@@ -2678,12 +2681,11 @@ namespace __rb_tree
              _Base_ptr __yu(__y);
              __y = __x, __x = _S_left(__x);
              __xu = _S_right(__xu);
-             return make_pair(const_iterator(_M_lower_bound(__x, __y, __k)),
-                              const_iterator(_M_upper_bound(__xu, __yu, __k)));
+             return _Ret(const_iterator(_M_lower_bound(__x, __y, __k)),
+                         const_iterator(_M_upper_bound(__xu, __yu, __k)));
            }
        }
-      return pair<const_iterator, const_iterator>(const_iterator(__y),
-                                                 const_iterator(__y));
+      return _Ret(const_iterator(__y), const_iterator(__y));
     }
 
   template<typename _Key, typename _Val, typename _KeyOfValue,
diff --git 
a/libstdc++-v3/testsuite/23_containers/set/operations/equal_range_adl.cc 
b/libstdc++-v3/testsuite/23_containers/set/operations/equal_range_adl.cc
new file mode 100644
index 000000000000..38c8f4d21f61
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/operations/equal_range_adl.cc
@@ -0,0 +1,26 @@
+// { dg-do compile }
+
+#include <set>
+
+namespace adl
+{
+#if __cplusplus < 201103L
+  template<typename T> void make_pair(const T&, const T&) { }
+#else
+  template<typename T> void make_pair(T&&, T&&) { }
+#endif
+
+  struct X { bool operator<(const X&) const { return false; } };
+}
+
+typedef std::set<adl::X> Set;
+
+void
+test_equal_range(Set& s, const adl::X& x)
+{
+  // _Rb_tree::_M_equal_range was using make_pair unqualified.
+  (void) s.equal_range(x);
+  const Set& cs = s;
+  // Similarly for the const overload.
+  (void) cs.equal_range(x);
+}

Reply via email to