diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -47,6 +47,7 @@ - P0220R1 - Adopt Library Fundamentals V1 TS Components for C++17 - P0482R6 - char8_t: A type for UTF-8 characters and strings - P2438R2 - ``std::string::substr() &&`` +- P0600R1 - ``nodiscard`` in the library Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx20.rst b/libcxx/docs/Status/Cxx20.rst --- a/libcxx/docs/Status/Cxx20.rst +++ b/libcxx/docs/Status/Cxx20.rst @@ -41,7 +41,6 @@ .. note:: .. [#note-P0591] P0591: The changes in [mem.poly.allocator.mem] are missing. - .. [#note-P0600] P0600: The missing bits in P0600 are in |sect|\ [mem.res.class] and |sect|\ [mem.poly.allocator.class]. .. [#note-P0645] P0645: The paper is implemented but still marked as an incomplete feature (the feature-test macro is not set and the libary is only available when built with ``-fexperimental-library``). Not yet implemented LWG-issues will cause API and ABI breakage. diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -9,7 +9,7 @@ "`P0439R0 `__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|","" "`P0457R2 `__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0" "`P0550R2 `__","LWG","Transformation Trait ``remove_cvref``\ ","Albuquerque","|Complete|","6.0" -"`P0600R1 `__","LWG","nodiscard in the Library","Albuquerque","|In Progress| [#note-P0600]_","7.0" +"`P0600R1 `__","LWG","nodiscard in the Library","Albuquerque","|Complete|","16.0" "`P0616R0 `__","LWG","de-pessimize legacy algorithms with std::move","Albuquerque","|Complete|","12.0" "`P0653R2 `__","LWG","Utility to convert a pointer to a raw pointer","Albuquerque","|Complete|","6.0" "`P0718R2 `__","LWG","Atomic shared_ptr","Albuquerque","","" diff --git a/libcxx/include/__memory_resource/memory_resource.h b/libcxx/include/__memory_resource/memory_resource.h --- a/libcxx/include/__memory_resource/memory_resource.h +++ b/libcxx/include/__memory_resource/memory_resource.h @@ -30,6 +30,7 @@ public: virtual ~memory_resource(); + _LIBCPP_NODISCARD_AFTER_CXX17 [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* allocate(size_t __bytes, size_t __align = __max_align) { return do_allocate(__bytes, __align); diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -54,7 +54,7 @@ // [mem.poly.allocator.mem] - _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { if (__n > __max_size()) { __throw_bad_array_new_length(); } diff --git a/libcxx/test/libcxx/mem/mem.res/nodiscard.verify.cpp b/libcxx/test/libcxx/mem/mem.res/nodiscard.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/mem/mem.res/nodiscard.verify.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// check that functions are marked [[nodiscard]] as an extension in C++17 + +// [[nodiscard]] std::pmr::memory_resource::allocate(size_t, size_t); +// [[nodiscard]] std::pmr::polymorphic_allocator::allocate(size_t, size_t); + +#include + +void f() { + std::pmr::memory_resource* res = nullptr; + res->allocate(0); // expected-warning {{ignoring return value of function}} + res->allocate(0, 1); // expected-warning {{ignoring return value of function}} + + std::pmr::polymorphic_allocator poly; + poly.allocate(0); // expected-warning {{ignoring return value of function}} +} diff --git a/libcxx/test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp b/libcxx/test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp --- a/libcxx/test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp +++ b/libcxx/test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp @@ -24,7 +24,7 @@ std::pmr::monotonic_buffer_resource mono; for (int i = 0; i < 100; ++i) { - mono.allocate(1); + (void)mono.allocate(1); assert(globalMemCounter.last_new_size < 1000000000); mono.release(); assert(globalMemCounter.checkOutstandingNewEq(0)); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp @@ -59,7 +59,7 @@ if (maxSize != sizeTypeMax) { // Test that allocating size_t(~0) throws bad alloc. try { - a.allocate(sizeTypeMax); + (void)a.allocate(sizeTypeMax); assert(false); } catch (const std::exception&) { } @@ -67,7 +67,7 @@ // Test that allocating even one more than the max size does throw. size_t overSize = maxSize + 1; try { - a.allocate(overSize); + (void)a.allocate(overSize); assert(false); } catch (const std::exception&) { } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp @@ -76,7 +76,7 @@ #ifndef TEST_HAS_NO_EXCEPTIONS DisableAllocationGuard g; // null_memory_resource shouldn't allocate. try { - std::pmr::null_memory_resource()->allocate(1); + (void)std::pmr::null_memory_resource()->allocate(1); assert(false); } catch (std::bad_alloc const&) { // do nothing diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp @@ -26,11 +26,11 @@ auto mono1 = std::pmr::monotonic_buffer_resource(initial_buffer_size, std::pmr::new_delete_resource()); assert(globalMemCounter.checkNewCalledEq(0)); - mono1.allocate(1, 1); + (void)mono1.allocate(1, 1); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkNewCalledEq(1)); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkLastNewSizeGe(initial_buffer_size)); - mono1.allocate(initial_buffer_size - 1, 1); + (void)mono1.allocate(initial_buffer_size - 1, 1); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkNewCalledEq(1)); } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp @@ -66,7 +66,7 @@ P2.throw_on_alloc = true; std::pmr::memory_resource& M2 = R2; try { - M2.allocate(42); + (void)M2.allocate(42); assert(false); } catch (TestException const&) { // do nothing. diff --git a/libcxx/test/std/utilities/utility/mem.res/nodiscard.verify.cpp b/libcxx/test/std/utilities/utility/mem.res/nodiscard.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/nodiscard.verify.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// check that functions are marked [[nodiscard]] + +// [[nodiscard]] std::pmr::memory_resource::allocate(size_t, size_t); +// [[nodiscard]] std::pmr::polymorphic_allocator::allocate(size_t, size_t); + +#include + +void f() { + std::pmr::memory_resource* res = nullptr; + res->allocate(0); // expected-warning {{ignoring return value of function}} + res->allocate(0, 1); // expected-warning {{ignoring return value of function}} + + std::pmr::polymorphic_allocator poly; + poly.allocate(0); // expected-warning {{ignoring return value of function}} +}