Add more BOOST_CONTAINER_ATTRIBUTE_NODISCARD attributes and fix warnings triggered by this attribute

This commit is contained in:
Ion Gaztañaga
2025-12-18 15:23:56 +01:00
parent 8ce8b9ee43
commit ac523b2c1e
14 changed files with 76 additions and 26 deletions

View File

@@ -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; }

View File

@@ -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

View File

@@ -423,6 +423,7 @@ struct allocator_traits
//! <b>Returns</b>: <code>a.allocate(n)</code>
//!
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
inline static pointer allocate(Allocator &a, size_type n)
{ return a.allocate(n); }
@@ -434,6 +435,7 @@ struct allocator_traits
//! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
//! otherwise, invokes <code>a.allocate(n)</code>
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
//! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
//! <code>numeric_limits<size_type>::max()</code>.
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<Allocator, size_type (Allocator::*)() const>::value;

View File

@@ -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<T>(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; }
};

View File

@@ -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; }

View File

@@ -62,11 +62,13 @@ class BOOST_CONTAINER_NOVTABLE memory_resource
//! <b>Returns</b>:
//! `&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); }
//! <b>Returns</b>:
//! !(a == b).
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
{ return !(a == b); }

View File

@@ -112,6 +112,7 @@ class BOOST_CONTAINER_DECL monotonic_buffer_resource
~monotonic_buffer_resource() BOOST_OVERRIDE;
//! <b>Effects</b>: `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;

View File

@@ -78,7 +78,7 @@ class polymorphic_allocator
//! <b>Returns</b>: Equivalent to
//! `static_cast<T*>(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<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
//! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,

View File

@@ -734,6 +734,7 @@ class scoped_allocator_adaptor
//! <b>Returns</b>:
//! <code>allocator_traits<OuterAlloc>:: max_size(outer_allocator())</code>.
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
//! <b>Returns</b>:
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
inline pointer allocate(size_type n)
{ return outer_traits_type::allocate(this->outer_allocator(), n); }
//! <b>Returns</b>:
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
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<true>
/// @endcond
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
{
@@ -894,6 +898,7 @@ inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_S
}
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
inline bool operator!=(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
{ return !(a == b); }

View File

@@ -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));

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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

View File

@@ -55,12 +55,13 @@ void test_allocate()
polymorphic_allocator<int> 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<int>
BOOST_TEST(d.do_allocate_bytes == 2*sizeof(int));
BOOST_TEST(d.do_allocate_alignment == dtl::alignment_of<int>::value);
p.deallocate(ptr, 2); //To make [[nodiscard]] happy
}
void test_deallocate()