From ac523b2c1eba39f35fcb472c52e16047ac10235d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 18 Dec 2025 15:23:56 +0100 Subject: [PATCH] Add more BOOST_CONTAINER_ATTRIBUTE_NODISCARD attributes and fix warnings triggered by this attribute --- include/boost/container/adaptive_pool.hpp | 12 +++++ include/boost/container/allocator.hpp | 2 +- include/boost/container/allocator_traits.hpp | 3 ++ include/boost/container/new_allocator.hpp | 4 ++ include/boost/container/node_allocator.hpp | 7 +++ .../boost/container/pmr/memory_resource.hpp | 2 + .../pmr/monotonic_buffer_resource.hpp | 1 + .../container/pmr/polymorphic_allocator.hpp | 2 +- include/boost/container/scoped_allocator.hpp | 5 +++ test/allocator_traits_test.cpp | 45 +++++++++++-------- test/global_resource_test.cpp | 9 ++-- test/memory_resource_test.cpp | 3 +- test/monotonic_buffer_resource_test.cpp | 4 +- test/polymorphic_allocator_test.cpp | 3 +- 14 files changed, 76 insertions(+), 26 deletions(-) diff --git a/include/boost/container/adaptive_pool.hpp b/include/boost/container/adaptive_pool.hpp index a6a89fa..f620e6a 100644 --- a/include/boost/container/adaptive_pool.hpp +++ b/include/boost/container/adaptive_pool.hpp @@ -150,11 +150,13 @@ class adaptive_pool //!Returns the number of elements that could be allocated. //!Never throws + BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return size_type(-1)/(2u*sizeof(T)); } //!Allocate memory for an array of count elements. //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * = 0) { if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T)))) @@ -187,6 +189,7 @@ class adaptive_pool } } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command(allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, @@ -206,6 +209,7 @@ class adaptive_pool //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate_one() { typedef dtl::shared_adaptive_node_pool @@ -317,11 +321,13 @@ class adaptive_pool //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } @@ -466,11 +472,13 @@ class private_adaptive_pool //!Returns the number of elements that could be allocated. //!Never throws + BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return size_type(-1)/(2u*sizeof(T)); } //!Allocate memory for an array of count elements. //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * = 0) { if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T)))) @@ -497,6 +505,7 @@ class private_adaptive_pool } } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command(allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, @@ -516,6 +525,7 @@ class private_adaptive_pool //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate_one() { return (pointer)m_pool.allocate_node(); @@ -583,11 +593,13 @@ class private_adaptive_pool //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator==(const private_adaptive_pool &, const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator!=(const private_adaptive_pool &, const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } diff --git a/include/boost/container/allocator.hpp b/include/boost/container/allocator.hpp index ddb96be..da19e0b 100644 --- a/include/boost/container/allocator.hpp +++ b/include/boost/container/allocator.hpp @@ -197,7 +197,7 @@ class allocator //!Returns the maximum number of elements that could be allocated. //!Never throws - inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return size_type(-1)/(2u*sizeof(T)); } //!Swaps two allocators, does nothing diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index 7aad7b1..f32a3d0 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -423,6 +423,7 @@ struct allocator_traits //! Returns: a.allocate(n) //! + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline static pointer allocate(Allocator &a, size_type n) { return a.allocate(n); } @@ -434,6 +435,7 @@ struct allocator_traits //! Effects: calls a.allocate(n, p) if that call is well-formed; //! otherwise, invokes a.allocate(n) + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline static pointer allocate(Allocator &a, size_type n, const_void_pointer p) { const bool value = boost::container::dtl:: @@ -458,6 +460,7 @@ struct allocator_traits //! Returns: a.max_size() if that expression is well-formed; otherwise, //! numeric_limits::max(). + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW { const bool value = allocator_traits_detail::has_max_size::value; diff --git a/include/boost/container/new_allocator.hpp b/include/boost/container/new_allocator.hpp index e6cbf71..464a7b7 100644 --- a/include/boost/container/new_allocator.hpp +++ b/include/boost/container/new_allocator.hpp @@ -151,6 +151,7 @@ class new_allocator //!Allocates memory for an array of count elements. //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count) { return dtl::operator_new_allocate(count); @@ -165,6 +166,7 @@ class new_allocator //!Returns the maximum number of elements that could be allocated. //!Never throws + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return std::size_t(-1)/(2*sizeof(T)); } @@ -175,11 +177,13 @@ class new_allocator //!An new_allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator==(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An new_allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator!=(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } }; diff --git a/include/boost/container/node_allocator.hpp b/include/boost/container/node_allocator.hpp index 14c3754..71b178b 100644 --- a/include/boost/container/node_allocator.hpp +++ b/include/boost/container/node_allocator.hpp @@ -137,11 +137,13 @@ class node_allocator //!Returns the number of elements that could be allocated. //!Never throws + BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type max_size() const { return size_type(-1)/sizeof(T); } //!Allocate memory for an array of count elements. //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * = 0) { if(BOOST_UNLIKELY(count > this->max_size())) @@ -186,6 +188,7 @@ class node_allocator singleton_t::instance().deallocate_free_blocks(); } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command (allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { @@ -198,6 +201,7 @@ class node_allocator //!Returns maximum the number of objects the previously allocated memory //!pointed by p can hold. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_CONTAINER_STATIC_ASSERT(( Version > 1 )); @@ -207,6 +211,7 @@ class node_allocator //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). //!Throws bad_alloc if there is no enough memory + BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate_one() { BOOST_CONTAINER_STATIC_ASSERT(( Version > 1 )); @@ -307,11 +312,13 @@ class node_allocator //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator==(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } diff --git a/include/boost/container/pmr/memory_resource.hpp b/include/boost/container/pmr/memory_resource.hpp index 3eabc3e..5ca9196 100644 --- a/include/boost/container/pmr/memory_resource.hpp +++ b/include/boost/container/pmr/memory_resource.hpp @@ -62,11 +62,13 @@ class BOOST_CONTAINER_NOVTABLE memory_resource //! Returns: //! `&a == &b || a.is_equal(b)`. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT { return &a == &b || a.is_equal(b); } //! Returns: //! !(a == b). + BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT { return !(a == b); } diff --git a/include/boost/container/pmr/monotonic_buffer_resource.hpp b/include/boost/container/pmr/monotonic_buffer_resource.hpp index a52bbf8..c5e1c93 100644 --- a/include/boost/container/pmr/monotonic_buffer_resource.hpp +++ b/include/boost/container/pmr/monotonic_buffer_resource.hpp @@ -112,6 +112,7 @@ class BOOST_CONTAINER_DECL monotonic_buffer_resource ~monotonic_buffer_resource() BOOST_OVERRIDE; //! Effects: `upstream_resource()->deallocate()` as necessary to release all allocated memory. + //! Resets *this to its initial state at construction. //! [Note: memory is released back to `upstream_resource()` even if some blocks that were allocated //! from this have not been deallocated from this. - end note] void release() BOOST_NOEXCEPT; diff --git a/include/boost/container/pmr/polymorphic_allocator.hpp b/include/boost/container/pmr/polymorphic_allocator.hpp index e2ac7c4..cad9de2 100644 --- a/include/boost/container/pmr/polymorphic_allocator.hpp +++ b/include/boost/container/pmr/polymorphic_allocator.hpp @@ -78,7 +78,7 @@ class polymorphic_allocator //! Returns: Equivalent to //! `static_cast(m_resource->allocate(n * sizeof(T), alignof(T)))`. - T* allocate(size_t n) + BOOST_CONTAINER_ATTRIBUTE_NODISCARD T* allocate(size_t n) { return static_cast(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of::value)); } //! Requires: p was allocated from a memory resource, x, equal to *m_resource, diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index 90e3406..0e51036 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -734,6 +734,7 @@ class scoped_allocator_adaptor //! Returns: //! allocator_traits:: max_size(outer_allocator()). + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return outer_traits_type::max_size(this->outer_allocator()); } @@ -748,11 +749,13 @@ class scoped_allocator_adaptor //! Returns: //! allocator_traits::allocate(outer_allocator(), n). + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline pointer allocate(size_type n) { return outer_traits_type::allocate(this->outer_allocator(), n); } //! Returns: //! allocator_traits::allocate(outer_allocator(), n, hint). + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline pointer allocate(size_type n, const_void_pointer hint) { return outer_traits_type::allocate(this->outer_allocator(), n, hint); } @@ -880,6 +883,7 @@ struct scoped_allocator_operator_equal /// @endcond template +BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool operator==(const scoped_allocator_adaptor& a ,const scoped_allocator_adaptor& b) { @@ -894,6 +898,7 @@ inline bool operator==(const scoped_allocator_adaptor +BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool operator!=(const scoped_allocator_adaptor& a ,const scoped_allocator_adaptor& b) { return !(a == b); } diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 89cd714..e4ffc03 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -320,27 +320,36 @@ int main() CAlloc c_alloc; SAlloc s_alloc; - //allocate - CAllocTraits::allocate(c_alloc, 1); - BOOST_TEST(c_alloc.allocate_called()); + //allocate/deallocate + { + CAllocTraits::pointer p = CAllocTraits::allocate(c_alloc, 1); + BOOST_TEST(c_alloc.allocate_called()); - SAllocTraits::allocate(s_alloc, 1); - BOOST_TEST(s_alloc.allocate_called()); + CAllocTraits::deallocate(c_alloc, p, 1); + BOOST_TEST(c_alloc.deallocate_called()); + } + { + SAllocTraits::pointer p = SAllocTraits::allocate(s_alloc, 1); + BOOST_TEST(s_alloc.allocate_called()); - //deallocate - CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1); - BOOST_TEST(c_alloc.deallocate_called()); - - SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1); - BOOST_TEST(s_alloc.deallocate_called()); + SAllocTraits::deallocate(s_alloc, p, 1); + BOOST_TEST(s_alloc.deallocate_called()); + } //allocate with hint - CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer()); - BOOST_TEST(c_alloc.allocate_hint_called()); - - s_alloc.allocate_called_ = false; - SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer()); - BOOST_TEST(s_alloc.allocate_called()); + { + CAllocTraits::pointer p = CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer()); + BOOST_TEST(c_alloc.allocate_hint_called()); + CAllocTraits::deallocate(c_alloc, p, 1); + BOOST_TEST(c_alloc.deallocate_called()); + } + { + s_alloc.allocate_called_ = false; + SAllocTraits::pointer p = SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer()); + BOOST_TEST(s_alloc.allocate_called()); + SAllocTraits::deallocate(s_alloc, p, 1); + BOOST_TEST(s_alloc.deallocate_called()); + } //destroy float dummy; @@ -350,7 +359,7 @@ int main() SAllocTraits::destroy(s_alloc, &dummy); //max_size - CAllocTraits::max_size(c_alloc); + BOOST_TEST(0 != CAllocTraits::max_size(c_alloc)); BOOST_TEST(c_alloc.max_size_called()); BOOST_TEST(SAllocTraits::size_type(-1)/sizeof(SAllocTraits::value_type) == SAllocTraits::max_size(s_alloc)); diff --git a/test/global_resource_test.cpp b/test/global_resource_test.cpp index 8535e09..0230d55 100644 --- a/test/global_resource_test.cpp +++ b/test/global_resource_test.cpp @@ -24,7 +24,7 @@ using namespace boost::container::pmr; #pragma warning (disable : 4290) #endif -#if __cplusplus >= 201103L +#if BOOST_CXX_VERSION >= 201103L #define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER #define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER noexcept #else @@ -71,7 +71,7 @@ void test_new_delete_resource() #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL BOOST_TEST(memcount == allocation_count); #endif - void *addr = mr->allocate(16, 1); + void *const addr = mr->allocate(16, 1); #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL BOOST_TEST((allocation_count - memcount) == 1); #endif @@ -90,8 +90,9 @@ void test_null_memory_resource() #if !defined(BOOST_NO_EXCEPTIONS) bool bad_allocexception_thrown = false; + void *p = 0; BOOST_CONTAINER_TRY{ - mr->allocate(1, 1); + p = mr->allocate(1, 1); } BOOST_CONTAINER_CATCH(std::bad_alloc&) { bad_allocexception_thrown = true; @@ -101,6 +102,8 @@ void test_null_memory_resource() BOOST_CONTAINER_CATCH_END BOOST_TEST(bad_allocexception_thrown == true); + if(p) + mr->deallocate(p, 1, 1); #endif //BOOST_NO_EXCEPTIONS } diff --git a/test/memory_resource_test.cpp b/test/memory_resource_test.cpp index aad394a..0695b78 100644 --- a/test/memory_resource_test.cpp +++ b/test/memory_resource_test.cpp @@ -26,10 +26,11 @@ void test_allocate() BOOST_TEST(d.do_allocate_bytes == 0); BOOST_TEST(d.do_allocate_alignment == 0); - mr.allocate(2, 4); + void *const p = mr.allocate(2, 4); BOOST_TEST(d.do_allocate_called == true); BOOST_TEST(d.do_allocate_bytes == 2); BOOST_TEST(d.do_allocate_alignment == 4); + mr.deallocate(p, 2, 4); } void test_deallocate() diff --git a/test/monotonic_buffer_resource_test.cpp b/test/monotonic_buffer_resource_test.cpp index 4923e24..33e3a7b 100644 --- a/test/monotonic_buffer_resource_test.cpp +++ b/test/monotonic_buffer_resource_test.cpp @@ -431,8 +431,10 @@ void test_release() memory_resource &mr = monr; BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf)); //Allocate all remaining storage - mr.allocate(monr.remaining_storage(1u), 1u); + const std::size_t sz = monr.remaining_storage(1u); + void *const p = mr.allocate(sz, 1u); BOOST_TEST(monr.current_buffer() == ((char*)&buf + sizeof(buf))); + mr.deallocate(p, sz, 1u); //No new allocation should have occurred BOOST_TEST(monr.remaining_storage(1u) == 0u); //Release and check memory was released and the original buffer is back diff --git a/test/polymorphic_allocator_test.cpp b/test/polymorphic_allocator_test.cpp index 36f99c8..f66d143 100644 --- a/test/polymorphic_allocator_test.cpp +++ b/test/polymorphic_allocator_test.cpp @@ -55,12 +55,13 @@ void test_allocate() polymorphic_allocator p(&d); d.reset(); d.do_allocate_return = &dummy; - p.allocate(2); + int *const ptr = p.allocate(2); BOOST_TEST(d.do_allocate_called == true); BOOST_TEST(d.do_allocate_return == &dummy); //It shall allocate 2*sizeof(int), alignment_of BOOST_TEST(d.do_allocate_bytes == 2*sizeof(int)); BOOST_TEST(d.do_allocate_alignment == dtl::alignment_of::value); + p.deallocate(ptr, 2); //To make [[nodiscard]] happy } void test_deallocate()