From c7790bdbd97889b39fde3e0249b398a9bf5fb43b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 11 Oct 2018 12:32:29 +0100 Subject: [PATCH] Make ext allocators support heterogeneous equality comparison The Allocator requirements include the ability to compare different specializations of the same allocator class template. This did not work for __gnu_cxx::new_allocator and other extension allocators. This patch replaces the equality operators for those allocators with inline friends that support heterogeneous comparisons. (I'm not changing all ext allocators because some are bit-rotted already). Additionally, the equality operators for comparing two std::allocator objects of the same type are now defined as inline friends. Those overloads don't need to be declared at namespace scope, because they aren't specified in the standard (but they're needed in this implementation to avoid ambiguities caused by the extra overloads defined for the base allocator type). * include/bits/allocator.h (operator==(const allocator<_Tp>&, const allocator<_Tp>)) (operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace with inline friends. * include/ext/debug_allocator.h (operator==, operator!=): Replace with inline friend functions that compare to rebound allocators. * include/ext/malloc_allocator.h (operator==, operator!=): Likewise. * include/ext/new_allocator.h (operator==, operator!=): Likewise. * testsuite/ext/debug_allocator/eq.cc: New test. * testsuite/ext/ext_pointer/alloc_eq.cc: New test. * testsuite/ext/malloc_allocator/eq.cc: New test. * testsuite/ext/new_allocator/eq.cc: New test. From-SVN: r265036 --- libstdc++-v3/ChangeLog | 15 +++++++++ libstdc++-v3/include/bits/allocator.h | 20 +++++------- libstdc++-v3/include/ext/debug_allocator.h | 20 ++++++------ libstdc++-v3/include/ext/malloc_allocator.h | 22 +++++++------ libstdc++-v3/include/ext/new_allocator.h | 22 +++++++------ .../testsuite/ext/debug_allocator/eq.cc | 31 +++++++++++++++++++ .../testsuite/ext/ext_pointer/alloc_eq.cc | 31 +++++++++++++++++++ .../testsuite/ext/malloc_allocator/eq.cc | 31 +++++++++++++++++++ .../testsuite/ext/new_allocator/eq.cc | 31 +++++++++++++++++++ 9 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 libstdc++-v3/testsuite/ext/debug_allocator/eq.cc create mode 100644 libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc create mode 100644 libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc create mode 100644 libstdc++-v3/testsuite/ext/new_allocator/eq.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e334ff18ebb..13698961910 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2018-10-11 Jonathan Wakely + + * include/bits/allocator.h + (operator==(const allocator<_Tp>&, const allocator<_Tp>)) + (operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace + with inline friends. + * include/ext/debug_allocator.h (operator==, operator!=): Replace + with inline friend functions that compare to rebound allocators. + * include/ext/malloc_allocator.h (operator==, operator!=): Likewise. + * include/ext/new_allocator.h (operator==, operator!=): Likewise. + * testsuite/ext/debug_allocator/eq.cc: New test. + * testsuite/ext/ext_pointer/alloc_eq.cc: New test. + * testsuite/ext/malloc_allocator/eq.cc: New test. + * testsuite/ext/new_allocator/eq.cc: New test. + 2018-10-10 Jonathan Wakely PR libstdc++/87544 diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index c4e3a4b9c15..d9d1d26e13a 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -148,6 +148,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~allocator() _GLIBCXX_NOTHROW { } + friend bool + operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return true; } + + friend bool + operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return false; } + // Inherit everything else. }; @@ -157,24 +165,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOTHROW { return true; } - template - inline bool - operator==(const allocator<_Tp>&, const allocator<_Tp>&) - _GLIBCXX_NOTHROW - { return true; } - template inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&) _GLIBCXX_NOTHROW { return false; } - template - inline bool - operator!=(const allocator<_Tp>&, const allocator<_Tp>&) - _GLIBCXX_NOTHROW - { return false; } - // Invalid allocator partial specializations. // allocator_traits::rebind_alloc can be used to form a valid allocator type. template diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h index dce224f05ed..3bc750e473b 100644 --- a/libstdc++-v3/include/ext/debug_allocator.h +++ b/libstdc++-v3/include/ext/debug_allocator.h @@ -174,16 +174,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION max_size() const throw() { return _Traits::max_size(_M_allocator) - _M_extra; } - friend bool - operator==(const debug_allocator& __lhs, const debug_allocator& __rhs) - { return __lhs._M_allocator == __rhs._M_allocator; } - }; + template + friend bool + operator==(const debug_allocator& __lhs, + const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW + { return __lhs._M_allocator == debug_allocator(__rhs)._M_allocator; } - template - inline bool - operator!=(const debug_allocator<_Alloc>& __lhs, - const debug_allocator<_Alloc>& __rhs) - { return !(__lhs == __rhs); } + template + friend bool + operator!=(const debug_allocator& __lhs, + const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW + { return !(__lhs == __rhs); } + }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h index 8eaf5d44cf7..1ae53b11ddb 100644 --- a/libstdc++-v3/include/ext/malloc_allocator.h +++ b/libstdc++-v3/include/ext/malloc_allocator.h @@ -166,17 +166,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void destroy(pointer __p) { __p->~_Tp(); } #endif - }; - template - inline bool - operator==(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&) - { return true; } - - template - inline bool - operator!=(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&) - { return false; } + template + friend bool + operator==(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + + template + friend bool + operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } + }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h index 7c50731736b..83c894ce0a7 100644 --- a/libstdc++-v3/include/ext/new_allocator.h +++ b/libstdc++-v3/include/ext/new_allocator.h @@ -157,18 +157,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void destroy(pointer __p) { __p->~_Tp(); } #endif + + template + friend bool + operator==(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + + template + friend bool + operator!=(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } }; - template - inline bool - operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&) - { return true; } - - template - inline bool - operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&) - { return false; } - _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc b/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc new file mode 100644 index 00000000000..4623fde384e --- /dev/null +++ b/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile } + +#include + +__gnu_cxx::debug_allocator< std::allocator > i; +__gnu_cxx::debug_allocator< std::allocator > f; + +bool b1 = i == i; +bool b2 = f == f; +bool b3 = i == f; + +bool n1 = i != i; +bool n2 = f != f; +bool n3 = i != f; diff --git a/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc b/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc new file mode 100644 index 00000000000..0b846cd6a1f --- /dev/null +++ b/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile } + +#include + +__gnu_cxx::_ExtPtr_allocator i; +__gnu_cxx::_ExtPtr_allocator f; + +bool b1 = i == i; +bool b2 = f == f; +bool b3 = i == f; + +bool n1 = i != i; +bool n2 = f != f; +bool n3 = i != f; diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc new file mode 100644 index 00000000000..12063f1f5eb --- /dev/null +++ b/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile } + +#include + +__gnu_cxx::malloc_allocator i; +__gnu_cxx::malloc_allocator f; + +bool b1 = i == i; +bool b2 = f == f; +bool b3 = i == f; + +bool n1 = i != i; +bool n2 = f != f; +bool n3 = i != f; diff --git a/libstdc++-v3/testsuite/ext/new_allocator/eq.cc b/libstdc++-v3/testsuite/ext/new_allocator/eq.cc new file mode 100644 index 00000000000..6dc60038802 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/eq.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile } + +#include + +__gnu_cxx::new_allocator i; +__gnu_cxx::new_allocator f; + +bool b1 = i == i; +bool b2 = f == f; +bool b3 = i == f; + +bool n1 = i != i; +bool n2 = f != f; +bool n3 = i != f;