_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. --- Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/bits/stl_tree.h | 18 +++++++------ .../set/operations/equal_range_adl.cc | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/set/operations/equal_range_adl.cc 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); +} -- 2.48.1