From a81c86a90ee7c70cf7dcfe44ead5a43f43e82668 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 26 Oct 2014 22:21:12 +0000 Subject: [PATCH 01/12] Remove use of operator&. Also reactivate operator& for minimal test classes. Apparently I disabled them because of a problem in a type trait, but I'm not seeing that now. Maybe it will appear on other compilers. --- include/boost/unordered/detail/buckets.hpp | 4 ++-- test/objects/minimal.hpp | 17 ++++++++++------- test/unordered/compile_map.cpp | 2 ++ test/unordered/compile_set.cpp | 2 ++ test/unordered/compile_tests.hpp | 20 ++++++++++++++++++++ 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 7de4317b..e7a12855 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -223,7 +223,7 @@ namespace boost { namespace unordered { namespace iterator_detail { } value_type* operator->() const { - return &node_->value(); + return node_->value_ptr(); } iterator& operator++() { @@ -287,7 +287,7 @@ namespace boost { namespace unordered { namespace iterator_detail { } value_type const* operator->() const { - return &node_->value(); + return node_->value_ptr(); } c_iterator& operator++() { diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index af7d0387..a757a035 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -48,6 +48,7 @@ namespace minimal public: destructible(constructor_param const&) {} ~destructible() {} + void dummy_member() const {} private: destructible(destructible const&); destructible& operator=(destructible const&); @@ -59,6 +60,7 @@ namespace minimal copy_constructible(constructor_param const&) {} copy_constructible(copy_constructible const&) {} ~copy_constructible() {} + void dummy_member() const {} private: copy_constructible& operator=(copy_constructible const&); copy_constructible() {} @@ -78,6 +80,7 @@ namespace minimal { } + void dummy_member() const {} private: copy_constructible_equality_comparable& operator=( copy_constructible_equality_comparable const&); @@ -121,6 +124,7 @@ namespace minimal { } + void dummy_member() const {} private: ampersand_operator_used operator&() const { return ampersand_operator_used(); } @@ -133,11 +137,10 @@ namespace minimal assignable(assignable const&) {} assignable& operator=(assignable const&) { return *this; } ~assignable() {} - + void dummy_member() const {} private: assignable() {} - // TODO: This messes up a concept check in the tests. - //ampersand_operator_used operator&() const { return ampersand_operator_used(); } + ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; struct movable_init {}; @@ -153,6 +156,7 @@ namespace minimal movable1(BOOST_RV_REF(movable1)) {} movable1& operator=(BOOST_RV_REF(movable1)) { return *this; } ~movable1() {} + void dummy_member() const {} }; #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -164,6 +168,7 @@ namespace minimal movable2(movable2&&) {} ~movable2() {} movable2& operator=(movable2&&) { return *this; } + void dummy_member() const {} private: movable2() {} movable2(movable2 const&); @@ -289,8 +294,7 @@ namespace minimal bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } private: - // TODO: - //ampersand_operator_used operator&() const { return ampersand_operator_used(); } + ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template @@ -326,8 +330,7 @@ namespace minimal bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } private: - // TODO: - //ampersand_operator_used operator&() const { return ampersand_operator_used(); } + ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template diff --git a/test/unordered/compile_map.cpp b/test/unordered/compile_map.cpp index 317607c7..ebd944ea 100644 --- a/test/unordered/compile_map.cpp +++ b/test/unordered/compile_map.cpp @@ -202,6 +202,7 @@ UNORDERED_AUTO_TEST(test2) unordered_unique_test(map, map_value); unordered_map_test(map, assignable, assignable); unordered_copyable_test(map, assignable, map_value, hash, equal_to); + unordered_map_member_test(map, map_value); boost::unordered_map< test::minimal::assignable, @@ -226,6 +227,7 @@ UNORDERED_AUTO_TEST(test2) unordered_equivalent_test(multimap, map_value); unordered_map_test(multimap, assignable, assignable); unordered_copyable_test(multimap, assignable, map_value, hash, equal_to); + unordered_map_member_test(multimap, map_value); } RUN_TESTS() diff --git a/test/unordered/compile_set.cpp b/test/unordered/compile_set.cpp index f023c797..5c622902 100644 --- a/test/unordered/compile_set.cpp +++ b/test/unordered/compile_set.cpp @@ -183,6 +183,7 @@ UNORDERED_AUTO_TEST(test2) unordered_unique_test(set, assignable); unordered_set_test(set, assignable); unordered_copyable_test(set, assignable, assignable, hash, equal_to); + unordered_set_member_test(set, assignable); std::cout<<"Test unordered_multiset.\n"; @@ -195,6 +196,7 @@ UNORDERED_AUTO_TEST(test2) unordered_equivalent_test(multiset, assignable); unordered_set_test(multiset, assignable); unordered_copyable_test(multiset, assignable, assignable, hash, equal_to); + unordered_set_member_test(multiset, assignable); } UNORDERED_AUTO_TEST(movable1_tests) diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index b48a6efd..38d7dda2 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -554,3 +554,23 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) sink(a8); sink(a10); } + +template +void unordered_set_member_test(X& x, T& t) +{ + X x1(x); + x1.insert(t); + x1.begin()->dummy_member(); + x1.cbegin()->dummy_member(); +} + +template +void unordered_map_member_test(X& x, T& t) +{ + X x1(x); + x1.insert(t); + x1.begin()->first.dummy_member(); + x1.cbegin()->first.dummy_member(); + x1.begin()->second.dummy_member(); + x1.cbegin()->second.dummy_member(); +} From 2c9d209eef75eb970889cc5edc65c643783fb674 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 2 Nov 2014 17:35:05 +0000 Subject: [PATCH 02/12] Remove incorrect changelog note. A minor change that is not actually in this release, will be in the next one. Probably too late to rebuild the documenation. --- doc/changes.qbk | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index f71da60d..a7947b3d 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -257,7 +257,5 @@ C++11 support has resulted in some breaking changes: * Fix the `pointer` typedef in iterators ([ticket 10672]). * Fix Coverity warning ([@https://github.com/boostorg/unordered/pull/2 GitHub #2]). -* Rename private `iterator` typedef in some iterator classes, as it - confuses some traits classes. [endsect] From b4795f414d69581a0fedf268108582a3010a9507 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 8 Nov 2014 22:22:11 +0000 Subject: [PATCH 03/12] Remove unneeded ConstNodePointer template parameters. --- include/boost/unordered/detail/buckets.hpp | 10 +++++----- include/boost/unordered/detail/table.hpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index e7a12855..329435d3 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -45,9 +45,9 @@ namespace boost { namespace unordered { namespace iterator_detail { // all no throw template struct iterator; - template struct c_iterator; + template struct c_iterator; template struct l_iterator; - template + template struct cl_iterator; // Local Iterators @@ -64,7 +64,7 @@ namespace boost { namespace unordered { namespace iterator_detail { typename Node::value_type&> { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template + template friend struct boost::unordered::iterator_detail::cl_iterator; private: #endif @@ -114,7 +114,7 @@ namespace boost { namespace unordered { namespace iterator_detail { } }; - template + template struct cl_iterator : public boost::iterator< std::forward_iterator_tag, @@ -246,7 +246,7 @@ namespace boost { namespace unordered { namespace iterator_detail { } }; - template + template struct c_iterator : public boost::iterator< std::forward_iterator_tag, diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 2bb5d450..ddb1e598 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -191,11 +191,11 @@ namespace boost { namespace unordered { namespace detail { typedef boost::unordered::iterator_detail:: iterator iterator; typedef boost::unordered::iterator_detail:: - c_iterator c_iterator; + c_iterator c_iterator; typedef boost::unordered::iterator_detail:: l_iterator l_iterator; typedef boost::unordered::iterator_detail:: - cl_iterator cl_iterator; + cl_iterator cl_iterator; //////////////////////////////////////////////////////////////////////// // Members From 0cedaf7ad624beaf55db1faa6a036b8297ac0978 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 8 Nov 2014 22:22:11 +0000 Subject: [PATCH 04/12] Rename iterator typedef to n_iterator. --- include/boost/unordered/detail/buckets.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 329435d3..da059f47 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -69,7 +69,7 @@ namespace boost { namespace unordered { namespace iterator_detail { private: #endif typedef typename Node::node_pointer node_pointer; - typedef boost::unordered::iterator_detail::iterator iterator; + typedef boost::unordered::iterator_detail::iterator n_iterator; node_pointer ptr_; std::size_t bucket_; std::size_t bucket_count_; @@ -80,7 +80,7 @@ namespace boost { namespace unordered { namespace iterator_detail { l_iterator() BOOST_NOEXCEPT : ptr_() {} - l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT + l_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT : ptr_(x.node_), bucket_(b), bucket_count_(c) {} value_type& operator*() const { @@ -128,7 +128,7 @@ namespace boost { namespace unordered { namespace iterator_detail { private: typedef typename Node::node_pointer node_pointer; - typedef boost::unordered::iterator_detail::iterator iterator; + typedef boost::unordered::iterator_detail::iterator n_iterator; node_pointer ptr_; std::size_t bucket_; std::size_t bucket_count_; @@ -139,7 +139,7 @@ namespace boost { namespace unordered { namespace iterator_detail { cl_iterator() BOOST_NOEXCEPT : ptr_() {} - cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT : + cl_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT : ptr_(x.node_), bucket_(b), bucket_count_(c) {} cl_iterator(boost::unordered::iterator_detail::l_iterator< @@ -268,7 +268,7 @@ namespace boost { namespace unordered { namespace iterator_detail { private: #endif typedef typename Node::node_pointer node_pointer; - typedef boost::unordered::iterator_detail::iterator iterator; + typedef boost::unordered::iterator_detail::iterator n_iterator; node_pointer node_; public: @@ -280,7 +280,7 @@ namespace boost { namespace unordered { namespace iterator_detail { explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : node_(static_cast(x)) {} - c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {} + c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {} value_type const& operator*() const { return node_->value(); From df5a7538b125e51a9a1e72a3e826800bfd7dea99 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 8 Nov 2014 22:22:12 +0000 Subject: [PATCH 05/12] Changelog --- doc/changes.qbk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index a7947b3d..8797dc90 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -258,4 +258,10 @@ C++11 support has resulted in some breaking changes: * Fix Coverity warning ([@https://github.com/boostorg/unordered/pull/2 GitHub #2]). +[h2 Boost 1.58.0] + +* Remove unnecessary template parameter from const iterators. +* Rename private `iterator` typedef in some iterator classes, as it + confuses some traits classes. + [endsect] From 1d8855da27e610c5041ff2f6d43adc8ae574ee8c Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 9 Nov 2014 13:36:27 +0100 Subject: [PATCH 06/12] Remove template patameters from friend declarations in interator<>. --- include/boost/unordered/detail/buckets.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index da059f47..8a67345c 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -192,11 +192,11 @@ namespace boost { namespace unordered { namespace iterator_detail { typename Node::value_type&> { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template + template friend struct boost::unordered::iterator_detail::c_iterator; template friend struct boost::unordered::iterator_detail::l_iterator; - template + template friend struct boost::unordered::iterator_detail::cl_iterator; template friend struct boost::unordered::detail::table; From 31211a607f1c294f973eed10e54e461a8ef920ba Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 9 Nov 2014 23:34:52 +0000 Subject: [PATCH 07/12] Remove assertion that used moved allocator. Fixes #10777. --- doc/changes.qbk | 2 ++ include/boost/unordered/detail/table.hpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 8797dc90..acc43088 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -263,5 +263,7 @@ C++11 support has resulted in some breaking changes: * Remove unnecessary template parameter from const iterators. * Rename private `iterator` typedef in some iterator classes, as it confuses some traits classes. +* Fix move assignment with stateful, propagate_on_container_move_assign + allocators ([ticket 10777]). [endsect] diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index ddb1e598..87012b5e 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -500,9 +500,11 @@ namespace boost { namespace unordered { namespace detail { op2.commit(); } + // Only call with nodes allocated with the currect allocator, or + // one that is equal to it. (Can't assert because other's + // allocators might have already been moved). void move_buckets_from(table& other) { - BOOST_ASSERT(node_alloc() == other.node_alloc()); BOOST_ASSERT(!buckets_); buckets_ = other.buckets_; bucket_count_ = other.bucket_count_; From 8ccde2e5a168416675c1bd6e73b776d6149ebd1a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 9 Nov 2014 23:36:10 +0000 Subject: [PATCH 08/12] Move the allocators after copying the hash functions. Just in case the hash functions throw. --- doc/changes.qbk | 1 + include/boost/unordered/detail/table.hpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index acc43088..586656e6 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -265,5 +265,6 @@ C++11 support has resulted in some breaking changes: confuses some traits classes. * Fix move assignment with stateful, propagate_on_container_move_assign allocators ([ticket 10777]). +* Fix rare exception safety issue in move assignment. [endsect] diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 87012b5e..172739e3 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -712,15 +712,25 @@ namespace boost { namespace unordered { namespace detail { void move_assign(table& x, true_type) { delete_buckets(); + set_hash_functions new_func_this(*this, x); allocators_.move_assign(x.allocators_); - move_assign_no_alloc(x); + // No throw from here. + mlf_ = x.mlf_; + max_load_ = x.max_load_; + move_buckets_from(x); + new_func_this.commit(); } void move_assign(table& x, false_type) { if (node_alloc() == x.node_alloc()) { delete_buckets(); - move_assign_no_alloc(x); + set_hash_functions new_func_this(*this, x); + // No throw from here. + mlf_ = x.mlf_; + max_load_ = x.max_load_; + move_buckets_from(x); + new_func_this.commit(); } else { set_hash_functions new_func_this(*this, x); @@ -745,16 +755,6 @@ namespace boost { namespace unordered { namespace detail { table_impl::fill_buckets(nodes.begin(), *this, node_creator); } } - - void move_assign_no_alloc(table& x) - { - set_hash_functions new_func_this(*this, x); - // No throw from here. - mlf_ = x.mlf_; - max_load_ = x.max_load_; - move_buckets_from(x); - new_func_this.commit(); - } // Accessors From 9090d87725a60cdc3854491252fd2fd4367fdb80 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 16 Nov 2014 10:01:17 +0000 Subject: [PATCH 09/12] Restore ampersand workaround for Visual C++ 9 --- test/objects/minimal.hpp | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index a757a035..9cb054ad 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -19,6 +19,12 @@ #pragma warning(disable:4100) // unreferenced formal parameter #endif +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500) +#define BOOST_UNORDERED_PRIVATE_AMPERSAND private +#else +#define BOOST_UNORDERED_PRIVATE_AMPERSAND public +#endif + namespace test { namespace minimal @@ -29,7 +35,9 @@ namespace minimal class default_assignable; class assignable; - struct ampersand_operator_used {}; + struct ampersand_operator_used { + ampersand_operator_used() { BOOST_TEST(false); } + }; template class hash; template class equal_to; @@ -85,7 +93,9 @@ namespace minimal copy_constructible_equality_comparable& operator=( copy_constructible_equality_comparable const&); copy_constructible_equality_comparable() {} - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; bool operator==( @@ -125,7 +135,8 @@ namespace minimal } void dummy_member() const {} - private: + + BOOST_UNORDERED_PRIVATE_AMPERSAND: ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; @@ -140,7 +151,9 @@ namespace minimal void dummy_member() const {} private: assignable() {} - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; struct movable_init {}; @@ -189,8 +202,9 @@ namespace minimal ~hash() {} std::size_t operator()(T const&) const { return 0; } - private: - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; template @@ -204,8 +218,9 @@ namespace minimal ~equal_to() {} bool operator()(T const&, T const&) const { return true; } - private: - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; template class ptr; @@ -293,8 +308,9 @@ namespace minimal bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } - private: - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; template @@ -329,8 +345,9 @@ namespace minimal bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } - private: - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; template @@ -390,8 +407,9 @@ namespace minimal #else private: allocator& operator=(allocator const&); #endif - private: - ampersand_operator_used operator&() const { return ampersand_operator_used(); } + BOOST_UNORDERED_PRIVATE_AMPERSAND: + ampersand_operator_used operator&() const { + return ampersand_operator_used(); } }; template From 0273ec59d77da6ea56f775ca1fae45c4d98547e4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 3 Dec 2014 18:28:40 +0000 Subject: [PATCH 10/12] Fix Visual C++ 9.0 workaround. --- test/objects/minimal.hpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index 9cb054ad..85132aa3 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -20,9 +20,9 @@ #endif #if !BOOST_WORKAROUND(BOOST_MSVC, == 1500) -#define BOOST_UNORDERED_PRIVATE_AMPERSAND private +#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1 #else -#define BOOST_UNORDERED_PRIVATE_AMPERSAND public +#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0 #endif namespace test @@ -93,9 +93,10 @@ namespace minimal copy_constructible_equality_comparable& operator=( copy_constructible_equality_comparable const&); copy_constructible_equality_comparable() {} - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; bool operator==( @@ -136,9 +137,10 @@ namespace minimal void dummy_member() const {} - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; class assignable @@ -151,9 +153,10 @@ namespace minimal void dummy_member() const {} private: assignable() {} - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; struct movable_init {}; @@ -202,9 +205,10 @@ namespace minimal ~hash() {} std::size_t operator()(T const&) const { return 0; } - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; template @@ -218,9 +222,10 @@ namespace minimal ~equal_to() {} bool operator()(T const&, T const&) const { return true; } - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; template class ptr; @@ -308,9 +313,10 @@ namespace minimal bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; template @@ -345,9 +351,10 @@ namespace minimal bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; template @@ -407,9 +414,10 @@ namespace minimal #else private: allocator& operator=(allocator const&); #endif - BOOST_UNORDERED_PRIVATE_AMPERSAND: +#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED ampersand_operator_used operator&() const { return ampersand_operator_used(); } +#endif }; template From 3a507b4e39aaccca2511ff77e8318693a77ca54b Mon Sep 17 00:00:00 2001 From: Zoey Greer Date: Mon, 8 Dec 2014 16:38:38 -0500 Subject: [PATCH 11/12] Bounds-check after arithmetic is complete double_to_size can return std::numeric_limitsmax(), so we cannot add 1 to the return value of double_to_size. That addition should be done while still working with a double, as can be seen being done on line 850 of this file. This was uncovered by Coverity, and addresses Coverity issues CID13443 and CID12664 --- include/boost/unordered/detail/table.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 172739e3..b356ca22 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -343,7 +343,7 @@ namespace boost { namespace unordered { namespace detail { return policy::new_bucket_count( boost::unordered::detail::double_to_size(floor( static_cast(size) / - static_cast(mlf_))) + 1); + static_cast(mlf_)) + 1)); } //////////////////////////////////////////////////////////////////////// From f014802eb6d367c91a92788608ed1c76d285b04f Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 22 Feb 2015 15:08:46 +0000 Subject: [PATCH 12/12] Release note for pull request #4. --- doc/changes.qbk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index 586656e6..af8cf0a5 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -266,5 +266,7 @@ C++11 support has resulted in some breaking changes: * Fix move assignment with stateful, propagate_on_container_move_assign allocators ([ticket 10777]). * Fix rare exception safety issue in move assignment. +* Fix potential overflow when calculating number of buckets to allocate + ([@https://github.com/boostorg/unordered/pull/4 GitHub #4]). [endsect]