[libcxx-commits] [libcxx] e593dbc - [libc++][memory] Applied `[[nodiscard]]` to more functions (#172131)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jan 8 02:05:47 PST 2026
Author: Hristo Hristov
Date: 2026-01-08T12:05:43+02:00
New Revision: e593dbc184a176bb604d68ccf6f730170840072d
URL: https://github.com/llvm/llvm-project/commit/e593dbc184a176bb604d68ccf6f730170840072d
DIFF: https://github.com/llvm/llvm-project/commit/e593dbc184a176bb604d68ccf6f730170840072d.diff
LOG: [libc++][memory] Applied `[[nodiscard]]` to more functions (#172131)
`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html
- https://wg21.link/allocator.traits
- https://wg21.link/specialized.addressof
- https://wg21.link/ptr.align
- https://timsong-cpp.github.io/cppwp/n4659/depr.default.allocator
- https://timsong-cpp.github.io/cppwp/n4659/depr.storage.iterator
Towards #172124
Added:
Modified:
libcxx/include/__memory/addressof.h
libcxx/include/__memory/allocator.h
libcxx/include/__memory/allocator_traits.h
libcxx/include/__memory/is_sufficiently_aligned.h
libcxx/include/__memory/raw_storage_iterator.h
libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp
Removed:
libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp
################################################################################
diff --git a/libcxx/include/__memory/addressof.h b/libcxx/include/__memory/addressof.h
index 667071dfc6635..52ec94a5299fa 100644
--- a/libcxx/include/__memory/addressof.h
+++ b/libcxx/include/__memory/addressof.h
@@ -19,7 +19,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp* addressof(_Tp& __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp*
+addressof(_Tp& __x) _NOEXCEPT {
return __builtin_addressof(__x);
}
@@ -27,24 +28,25 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp* a
// Objective-C++ Automatic Reference Counting uses qualified pointers
// that require special addressof() signatures.
template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI __strong _Tp* addressof(__strong _Tp& __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __strong _Tp* addressof(__strong _Tp& __x) _NOEXCEPT {
return &__x;
}
# if __has_feature(objc_arc_weak)
template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI __weak _Tp* addressof(__weak _Tp& __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __weak _Tp* addressof(__weak _Tp& __x) _NOEXCEPT {
return &__x;
}
# endif
template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI __autoreleasing _Tp* addressof(__autoreleasing _Tp& __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __autoreleasing _Tp* addressof(__autoreleasing _Tp& __x) _NOEXCEPT {
return &__x;
}
template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI __unsafe_unretained _Tp* addressof(__unsafe_unretained _Tp& __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __unsafe_unretained _Tp*
+addressof(__unsafe_unretained _Tp& __x) _NOEXCEPT {
return &__x;
}
#endif
diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h
index 1c96a2ab64578..609b305a1250f 100644
--- a/libcxx/include/__memory/allocator.h
+++ b/libcxx/include/__memory/allocator.h
@@ -120,10 +120,11 @@ class allocator
typedef allocator<_Up> other;
};
- _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI pointer address(reference __x) const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI pointer address(reference __x) const _NOEXCEPT {
return std::addressof(__x);
}
- _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI const_pointer address(const_reference __x) const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI const_pointer
+ address(const_reference __x) const _NOEXCEPT {
return std::addressof(__x);
}
@@ -131,7 +132,7 @@ class allocator
return allocate(__n);
}
- _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
return size_type(~0) / sizeof(_Tp);
}
diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index 46c247f7040e0..b38d7293a3fd3 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -314,23 +314,25 @@ struct allocator_traits {
}
template <class _Ap = _Alloc, __enable_if_t<__has_max_size_v<const _Ap>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type& __a) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type
+ max_size(const allocator_type& __a) _NOEXCEPT {
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
return __a.max_size();
_LIBCPP_SUPPRESS_DEPRECATED_POP
}
template <class _Ap = _Alloc, __enable_if_t<!__has_max_size_v<const _Ap>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type&) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type
+ max_size(const allocator_type&) _NOEXCEPT {
return numeric_limits<size_type>::max() / sizeof(value_type);
}
template <class _Ap = _Alloc, __enable_if_t<__has_select_on_container_copy_construction_v<const _Ap>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
select_on_container_copy_construction(const allocator_type& __a) {
return __a.select_on_container_copy_construction();
}
template <class _Ap = _Alloc, __enable_if_t<!__has_select_on_container_copy_construction_v<const _Ap>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
select_on_container_copy_construction(const allocator_type& __a) {
return __a;
}
diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h
index 4280920cabb4b..93d24aaf78f0b 100644
--- a/libcxx/include/__memory/is_sufficiently_aligned.h
+++ b/libcxx/include/__memory/is_sufficiently_aligned.h
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 26
template <size_t _Alignment, class _Tp>
-_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
}
diff --git a/libcxx/include/__memory/raw_storage_iterator.h b/libcxx/include/__memory/raw_storage_iterator.h
index d98b3faf48468..dff0fed3b7565 100644
--- a/libcxx/include/__memory/raw_storage_iterator.h
+++ b/libcxx/include/__memory/raw_storage_iterator.h
@@ -46,7 +46,7 @@ class _LIBCPP_DEPRECATED_IN_CXX17 raw_storage_iterator
typedef void reference;
_LIBCPP_HIDE_FROM_ABI explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {}
- _LIBCPP_HIDE_FROM_ABI raw_storage_iterator& operator*() { return *this; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI raw_storage_iterator& operator*() { return *this; }
_LIBCPP_HIDE_FROM_ABI raw_storage_iterator& operator=(const _Tp& __element) {
::new ((void*)std::addressof(*__x_)) _Tp(__element);
return *this;
@@ -67,7 +67,7 @@ class _LIBCPP_DEPRECATED_IN_CXX17 raw_storage_iterator
return __t;
}
# if _LIBCPP_STD_VER >= 14
- _LIBCPP_HIDE_FROM_ABI _OutputIterator base() const { return __x_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _OutputIterator base() const { return __x_; }
# endif
};
diff --git a/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp
index 6410c84e926aa..6bddeceb9951a 100644
--- a/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp
@@ -6,37 +6,122 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03
+// <memory>
-// check that <memory> functions are marked [[nodiscard]]
+// Check that functions are marked [[nodiscard]]
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_TEMPORARY_BUFFER
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
-// clang-format off
-
#include <memory>
#include "test_macros.h"
void test() {
- std::get_temporary_buffer<int>(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
+ int i = 0;
-void test_allocator_traits() {
- std::allocator<int> allocator;
- std::allocator_traits<std::allocator<int>> allocator_traits;
- allocator_traits.allocate(allocator, 1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- allocator_traits.allocate(allocator, 1, nullptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
+ {
+ std::addressof(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::get_temporary_buffer<int>(0);
+#if _LIBCPP_STD_VER >= 26
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::is_sufficiently_aligned<2>(&i);
+#endif
+ }
-void test_allocator() {
- std::allocator<int> allocator;
- allocator.allocate(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#if TEST_STD_VER <= 17
- allocator.allocate(1, nullptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ {
+ struct Alloc {
+ using value_type = int;
+
+ value_type* allocate(std::size_t) { return nullptr; }
+ } allocator;
+ using AllocTraits = std::allocator_traits<Alloc>;
+
+ struct HintedAlloc {
+ using value_type = int;
+ using size_type = std::size_t;
+ using const_void_pointer = const void*;
+
+ value_type* allocate(size_type) { return nullptr; }
+ value_type* allocate(size_type, const_void_pointer) { return nullptr; }
+ } hintedAllocator;
+ using HintedAllocTraits = std::allocator_traits<HintedAlloc>;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ AllocTraits::allocate(allocator, 1);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ HintedAllocTraits::allocate(hintedAllocator, 1, nullptr);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ AllocTraits::allocate(allocator, 1, nullptr);
+
+#if TEST_STD_VER >= 23
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ AllocTraits::allocate_at_least(allocator, 1);
#endif
+
+ struct SizedAlloc {
+ using value_type = int;
+ using size_type = std::size_t;
+
+ value_type* allocate(std::size_t) { return nullptr; }
+ value_type* allocate(std::size_t, const void*) { return nullptr; }
+
+ size_type max_size() const { return 0; }
+ } sizedAllocator;
+ using SizedAllocTraits = std::allocator_traits<SizedAlloc>;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ SizedAllocTraits::max_size(sizedAllocator);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ AllocTraits::max_size(allocator);
+
+ struct SelectAlloc {
+ using value_type = int;
+ using const_void_pointer = const void*;
+
+ value_type* allocate(std::size_t) { return nullptr; }
+ value_type* allocate(std::size_t, const void*) { return nullptr; }
+
+ SelectAlloc select_on_container_copy_construction() const { return SelectAlloc(); };
+ } selectAllocator;
+ using SelectAllocTraits = std::allocator_traits<SelectAlloc>;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ SelectAllocTraits::select_on_container_copy_construction(selectAllocator);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ AllocTraits::select_on_container_copy_construction(allocator);
+ }
+
+ {
+ std::allocator<int> allocator;
+
+ allocator.allocate(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
#if TEST_STD_VER >= 23
- allocator.allocate_at_least(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ allocator.allocate_at_least(1);
+#endif
+
+#if TEST_STD_VER <= 17
+ const int ci = 0;
+
+ allocator.address(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ allocator.address(ci); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ allocator.allocate(1, nullptr);
+ allocator.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+ }
+
+#if TEST_STD_VER >= 14
+ {
+ std::raw_storage_iterator<int*, int> it{nullptr};
+
+ *it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it.base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
#endif
}
diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp
deleted file mode 100644
index adb4d697e1324..0000000000000
--- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class Alloc>
-// struct allocator_traits
-// {
-// static constexpr pointer allocate(allocator_type& a, size_type n);
-// ...
-// };
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <cstddef>
-#include <memory>
-
-template <class T>
-struct A {
- typedef T value_type;
- value_type* allocate(std::size_t n);
- value_type* allocate(std::size_t n, const void* p);
-};
-
-void f() {
- A<int> a;
- std::allocator_traits<A<int> >::allocate(a, 10); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::allocator_traits<A<int> >::allocate(a, 10, nullptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
More information about the libcxx-commits
mailing list