[libcxx-commits] [libcxx] [libc++][memory] Applied `[[nodiscard]]` to smart pointers (PR #168483)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 18 10:14:11 PST 2025


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/168483

>From 207b44f595ad590a4d85e67b1bc498acf7f08cfa Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 17 Nov 2025 13:13:44 +0200
Subject: [PATCH 1/7] [libc++][memory] Applied `[[nodiscard]]` to smart
 pointers

Applied `[[nodiscard]]` where relevant to smart pointers and related functions.

See guidelines:
- https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant
- `[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue. For example a locking constructor in unique_lock.
---
 libcxx/include/__memory/shared_ptr.h          | 100 +++++++------
 libcxx/include/__memory/unique_ptr.h          |  25 ++--
 .../utilities/smartptr/nodiscard.verify.cpp   | 134 +++++++++++++++++-
 3 files changed, 204 insertions(+), 55 deletions(-)

diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index ee07efe081e51..a470c673425fa 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -568,16 +568,20 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI shared_ptr {
     shared_ptr(__p, __d, __a).swap(*this);
   }
 
-  _LIBCPP_HIDE_FROM_ABI element_type* get() const _NOEXCEPT { return __ptr_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI element_type* get() const _NOEXCEPT { return __ptr_; }
 
-  _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator*() const _NOEXCEPT { return *__ptr_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator*() const _NOEXCEPT {
+    return *__ptr_;
+  }
 
   _LIBCPP_HIDE_FROM_ABI element_type* operator->() const _NOEXCEPT {
     static_assert(!is_array<_Tp>::value, "std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
     return __ptr_;
   }
 
-  _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __cntrl_ ? __cntrl_->use_count() : 0; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT {
+    return __cntrl_ ? __cntrl_->use_count() : 0;
+  }
 
 #if _LIBCPP_STD_VER < 20 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE)
   _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI bool unique() const _NOEXCEPT { return use_count() == 1; }
@@ -586,19 +590,19 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI shared_ptr {
   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return get() != nullptr; }
 
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT {
     return __cntrl_ < __p.__cntrl_;
   }
 
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT {
     return __cntrl_ < __p.__cntrl_;
   }
 
   _LIBCPP_HIDE_FROM_ABI bool __owner_equivalent(const shared_ptr& __p) const { return __cntrl_ == __p.__cntrl_; }
 
 #if _LIBCPP_STD_VER >= 17
-  _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator[](ptrdiff_t __i) const {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator[](ptrdiff_t __i) const {
     static_assert(is_array<_Tp>::value, "std::shared_ptr<T>::operator[] is only valid when T is an array type.");
     return __ptr_[__i];
   }
@@ -669,7 +673,7 @@ shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>;
 // std::allocate_shared and std::make_shared
 //
 template <class _Tp, class _Alloc, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&&... __args) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&&... __args) {
   using _ControlBlock          = __shared_ptr_emplace<_Tp, _Alloc>;
   using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type;
   __allocation_guard<_ControlBlockAllocator> __guard(__a, 1);
@@ -680,21 +684,21 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&&
 }
 
 template <class _Tp, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(_Args&&... __args) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(_Args&&... __args) {
   return std::allocate_shared<_Tp>(allocator<__remove_cv_t<_Tp> >(), std::forward<_Args>(__args)...);
 }
 
 #if _LIBCPP_STD_VER >= 20
 
 template <class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) {
   using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
   _ForOverwriteAllocator __alloc(__a);
   return std::allocate_shared<_Tp>(__alloc);
 }
 
 template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() {
   return std::allocate_shared_for_overwrite<_Tp>(allocator<__remove_cv_t<_Tp>>());
 }
 
@@ -886,67 +890,69 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Array> __allocate_shared_bounded_array(const _
 
 // bounded array variants
 template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a) {
   return std::__allocate_shared_bounded_array<_Tp>(__a);
 }
 
 template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, const remove_extent_t<_Tp>& __u) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>
+allocate_shared(const _Alloc& __a, const remove_extent_t<_Tp>& __u) {
   return std::__allocate_shared_bounded_array<_Tp>(__a, __u);
 }
 
 template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) {
   using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
   _ForOverwriteAllocator __alloc(__a);
   return std::__allocate_shared_bounded_array<_Tp>(__alloc);
 }
 
 template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared() {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared() {
   return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>());
 }
 
 template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(const remove_extent_t<_Tp>& __u) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(const remove_extent_t<_Tp>& __u) {
   return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __u);
 }
 
 template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() {
   return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>());
 }
 
 // unbounded array variants
 template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n) {
   return std::__allocate_shared_unbounded_array<_Tp>(__a, __n);
 }
 
 template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n, const remove_extent_t<_Tp>& __u) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>
+allocate_shared(const _Alloc& __a, size_t __n, const remove_extent_t<_Tp>& __u) {
   return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __u);
 }
 
 template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) {
   using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
   _ForOverwriteAllocator __alloc(__a);
   return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n);
 }
 
 template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n) {
   return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n);
 }
 
 template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n, const remove_extent_t<_Tp>& __u) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n, const remove_extent_t<_Tp>& __u) {
   return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __u);
 }
 
 template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) {
   return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n);
 }
 
@@ -980,12 +986,14 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator>(const shared_ptr<_Tp>& __x, const sh
 }
 
 template <class _Tp, class _Up>
-inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool
+operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
   return !(__y < __x);
 }
 
 template <class _Tp, class _Up>
-inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool
+operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
   return !(__x < __y);
 }
 
@@ -1075,7 +1083,8 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __
 }
 
 template <class _Tp, class _Up>
-inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>
+static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
   return shared_ptr<_Tp>(__r, static_cast< typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 
@@ -1083,13 +1092,14 @@ inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(const shared_pt
 // We don't backport because it is an evolutionary change.
 #if _LIBCPP_STD_VER >= 20
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
   return shared_ptr<_Tp>(std::move(__r), static_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 #endif
 
 template <class _Tp, class _Up>
-inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
+[[__nodiscard__]] inline
+    _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
   typedef typename shared_ptr<_Tp>::element_type _ET;
   _ET* __p = dynamic_cast<_ET*>(__r.get());
   return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>();
@@ -1099,14 +1109,14 @@ inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(const shared_p
 // We don't backport because it is an evolutionary change.
 #if _LIBCPP_STD_VER >= 20
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
   auto* __p = dynamic_cast<typename shared_ptr<_Tp>::element_type*>(__r.get());
   return __p ? shared_ptr<_Tp>(std::move(__r), __p) : shared_ptr<_Tp>();
 }
 #endif
 
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
   typedef typename shared_ptr<_Tp>::element_type _RTp;
   return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get()));
 }
@@ -1115,13 +1125,13 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>&
 // We don't backport because it is an evolutionary change.
 #if _LIBCPP_STD_VER >= 20
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
   return shared_ptr<_Tp>(std::move(__r), const_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 #endif
 
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT {
   return shared_ptr<_Tp>(__r, reinterpret_cast< typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 
@@ -1129,7 +1139,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<
 // We don't backport because it is an evolutionary change.
 #if _LIBCPP_STD_VER >= 20
 template <class _Tp, class _Up>
-_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept {
   return shared_ptr<_Tp>(std::move(__r), reinterpret_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 #endif
@@ -1137,7 +1147,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&&
 #if _LIBCPP_HAS_RTTI
 
 template <class _Dp, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _Dp* get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _Dp* get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT {
   return __p.template __get_deleter<_Dp>();
 }
 
@@ -1192,15 +1202,19 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI weak_ptr {
   _LIBCPP_HIDE_FROM_ABI void swap(weak_ptr& __r) _NOEXCEPT;
   _LIBCPP_HIDE_FROM_ABI void reset() _NOEXCEPT;
 
-  _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __cntrl_ ? __cntrl_->use_count() : 0; }
-  _LIBCPP_HIDE_FROM_ABI bool expired() const _NOEXCEPT { return __cntrl_ == nullptr || __cntrl_->use_count() == 0; }
-  _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> lock() const _NOEXCEPT;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT {
+    return __cntrl_ ? __cntrl_->use_count() : 0;
+  }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool expired() const _NOEXCEPT {
+    return __cntrl_ == nullptr || __cntrl_->use_count() == 0;
+  }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> lock() const _NOEXCEPT;
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT {
     return __cntrl_ < __r.__cntrl_;
   }
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI bool owner_before(const weak_ptr<_Up>& __r) const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_before(const weak_ptr<_Up>& __r) const _NOEXCEPT {
     return __cntrl_ < __r.__cntrl_;
   }
 
@@ -1384,13 +1398,15 @@ class enable_shared_from_this {
   _LIBCPP_HIDE_FROM_ABI ~enable_shared_from_this() {}
 
 public:
-  _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> shared_from_this() { return shared_ptr<_Tp>(__weak_this_); }
-  _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp const> shared_from_this() const { return shared_ptr<const _Tp>(__weak_this_); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> shared_from_this() { return shared_ptr<_Tp>(__weak_this_); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp const> shared_from_this() const {
+    return shared_ptr<const _Tp>(__weak_this_);
+  }
 
 #if _LIBCPP_STD_VER >= 17
-  _LIBCPP_HIDE_FROM_ABI weak_ptr<_Tp> weak_from_this() _NOEXCEPT { return __weak_this_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI weak_ptr<_Tp> weak_from_this() _NOEXCEPT { return __weak_this_; }
 
-  _LIBCPP_HIDE_FROM_ABI weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT { return __weak_this_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT { return __weak_this_; }
 #endif // _LIBCPP_STD_VER >= 17
 
   template <class _Up>
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 3cf4b97a7f49c..a822c761be203 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -258,14 +258,17 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
     return *this;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const
       _NOEXCEPT_(_NOEXCEPT_(*std::declval<pointer>())) {
     return *__ptr_;
   }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT {
+    return __deleter_;
+  }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type&
+  get_deleter() const _NOEXCEPT {
     return __deleter_;
   }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT {
@@ -672,8 +675,8 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
 #endif
 
 template <class _T1, class _D1>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool
-operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
   return !__x;
 }
 
@@ -748,12 +751,13 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
 #if _LIBCPP_STD_VER >= 14
 
 template <class _Tp, class... _Args, enable_if_t<!is_array<_Tp>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(_Args&&... __args) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(_Args&&... __args) {
   return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
 }
 
 template <class _Tp, enable_if_t<__is_unbounded_array_v<_Tp>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(size_t __n) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(size_t __n) {
   typedef __remove_extent_t<_Tp> _Up;
   return unique_ptr<_Tp>(__private_constructor_tag(), new _Up[__n](), __n);
 }
@@ -766,12 +770,13 @@ void make_unique(_Args&&...) = delete;
 #if _LIBCPP_STD_VER >= 20
 
 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite() {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite() {
   return unique_ptr<_Tp>(new _Tp);
 }
 
 template <class _Tp, enable_if_t<is_unbounded_array_v<_Tp>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite(size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp>
+make_unique_for_overwrite(size_t __n) {
   return unique_ptr<_Tp>(__private_constructor_tag(), new __remove_extent_t<_Tp>[__n], __n);
 }
 
diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
index 57eb4f7cc0bf8..46c3263c79d9f 100644
--- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
@@ -6,19 +6,147 @@
 //
 //===----------------------------------------------------------------------===//
 
-// REQUIRES: std-at-least-c++23
-
 // <memory>
 
 // Check that functions are marked [[nodiscard]]
 
 #include <memory>
+#include <utility>
 
 #include "test_macros.h"
 
 void test() {
+  { // [unique.ptr]
+    std::unique_ptr<int> uPtr;
+
+    *uPtr;              // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    uPtr.get();         // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    uPtr.get_deleter(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    const std::unique_ptr<int> cuPtr;
+    cuPtr.get_deleter(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+#if TEST_STD_VER >= 14
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_unique<int>(94);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_unique<int[]>(82);
+#endif
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_unique_for_overwrite<int>();
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_unique_for_overwrite<int[]>(5);
+#endif
+  }
+  { // [util.sharedptr]
+    std::shared_ptr<int[]> sPtr;
+
+    sPtr.get();       // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    *sPtr;            // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    sPtr.use_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    sPtr.owner_before(std::shared_ptr<int>());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    sPtr.owner_before(std::weak_ptr<int>());
+#if TEST_STD_VER >= 17
+    sPtr[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared<int>(std::allocator<int>(), 5);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared<int>();
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared_for_overwrite<int>(std::allocator<int>());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared_for_overwrite<int>();
+
+    // Bounded array variants
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared<int[5]>(std::allocator<int>());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared<int[5]>(std::allocator<int>(), 5);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared_for_overwrite<int[5]>(std::allocator<int>());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared<int[5]>();
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared<int[5]>(94);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared_for_overwrite<int[5]>();
+
+    // Unbounded array variants
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared<int[]>(std::allocator<int>(), 5);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared<int[]>(std::allocator<int>(), 5, 94);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::allocate_shared_for_overwrite<int[]>(std::allocator<int>(), 5);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared<int[]>(5);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared<int[]>(5, 82);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::make_shared_for_overwrite<int[]>(5);
+#endif
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::static_pointer_cast<int[]>(sPtr);
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::static_pointer_cast<int[]>(std::move(sPtr));
+#endif
+    class Empty {};
+    std::shared_ptr<Empty> dsPtr;
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::dynamic_pointer_cast<Empty>(dsPtr);
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::dynamic_pointer_cast<Empty>(std::move(dsPtr));
+#endif
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::const_pointer_cast<int[]>(sPtr);
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::const_pointer_cast<int[]>(std::move(sPtr));
+#endif
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::reinterpret_pointer_cast<int[]>(sPtr);
+#if TEST_STD_VER >= 20
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::reinterpret_pointer_cast<int[]>(std::move(sPtr));
+#endif
+#if !defined(TEST_HAS_NO_RTTI)
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::get_deleter<int[]>(sPtr);
+#endif
+  }
+  { // [util.smartptr.weak]
+    std::weak_ptr<int> wPtr;
+
+    wPtr.use_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    wPtr.expired();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    wPtr.lock();      // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    wPtr.owner_before(std::weak_ptr<int>());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    wPtr.owner_before(std::shared_ptr<int>());
+  }
+  { // [util.smartptr.enab]
+    class EnableShared : public std::enable_shared_from_this<EnableShared> {};
+    EnableShared es;
+    const EnableShared ces;
+
+    es.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ces.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 17
+    es.weak_from_this();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ces.weak_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+  }
 #if TEST_STD_VER >= 23
-  {
+  { // [smartptr.adapt]
     std::unique_ptr<int> uPtr;
     // [inout.ptr]
     std::inout_ptr(uPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

>From ff03257f60b92710e60bb31fe4a7660a920ff987 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 19:41:26 +0200
Subject: [PATCH 2/7] Addressed review comments

---
 libcxx/include/__memory/shared_ptr.h          | 10 +++---
 libcxx/include/__memory/unique_ptr.h          |  3 +-
 .../utilities/smartptr/nodiscard.verify.cpp   | 35 +++++++++----------
 3 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index a470c673425fa..6eddc4daa4184 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -584,7 +584,9 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI shared_ptr {
   }
 
 #if _LIBCPP_STD_VER < 20 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE)
-  _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI bool unique() const _NOEXCEPT { return use_count() == 1; }
+  [[__nodiscard__]] _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI bool unique() const _NOEXCEPT {
+    return use_count() == 1;
+  }
 #endif
 
   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return get() != nullptr; }
@@ -986,14 +988,12 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator>(const shared_ptr<_Tp>& __x, const sh
 }
 
 template <class _Tp, class _Up>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool
-operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
   return !(__y < __x);
 }
 
 template <class _Tp, class _Up>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool
-operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT {
   return !(__x < __y);
 }
 
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index a822c761be203..b5e2d79a3d1d8 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -675,8 +675,7 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
 #endif
 
 template <class _T1, class _D1>
-inline _LIBCPP_HIDE_FROM_ABI
-_LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
   return !__x;
 }
 
diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
index 46c3263c79d9f..641ffcb01528a 100644
--- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++03
+
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE
+
 // <memory>
 
 // Check that functions are marked [[nodiscard]]
@@ -44,19 +48,22 @@ void test() {
     sPtr.get();       // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     *sPtr;            // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.use_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER <= 20
+    sPtr.unique();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.owner_before(std::shared_ptr<int>());
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.owner_before(std::weak_ptr<int>());
-#if TEST_STD_VER >= 17
+#  if TEST_STD_VER >= 17
     sPtr[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#endif
+#  endif
 
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::allocate_shared<int>(std::allocator<int>(), 5);
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::make_shared<int>();
-#if TEST_STD_VER >= 20
+#  if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::allocate_shared_for_overwrite<int>(std::allocator<int>());
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
@@ -89,38 +96,30 @@ void test() {
     std::make_shared<int[]>(5, 82);
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::make_shared_for_overwrite<int[]>(5);
-#endif
+#  endif
 
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::static_pointer_cast<int[]>(sPtr);
-#if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::static_pointer_cast<int[]>(std::move(sPtr));
-#endif
     class Empty {};
     std::shared_ptr<Empty> dsPtr;
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::dynamic_pointer_cast<Empty>(dsPtr);
-#if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::dynamic_pointer_cast<Empty>(std::move(dsPtr));
-#endif
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::const_pointer_cast<int[]>(sPtr);
-#if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::const_pointer_cast<int[]>(std::move(sPtr));
-#endif
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::reinterpret_pointer_cast<int[]>(sPtr);
-#if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::reinterpret_pointer_cast<int[]>(std::move(sPtr));
-#endif
-#if !defined(TEST_HAS_NO_RTTI)
+#  if !defined(TEST_HAS_NO_RTTI)
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::get_deleter<int[]>(sPtr);
-#endif
+#  endif
   }
   { // [util.smartptr.weak]
     std::weak_ptr<int> wPtr;
@@ -140,12 +139,12 @@ void test() {
 
     es.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     ces.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#if TEST_STD_VER >= 17
+#  if TEST_STD_VER >= 17
     es.weak_from_this();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     ces.weak_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#endif
+#  endif
   }
-#if TEST_STD_VER >= 23
+#  if TEST_STD_VER >= 23
   { // [smartptr.adapt]
     std::unique_ptr<int> uPtr;
     // [inout.ptr]
@@ -153,5 +152,5 @@ void test() {
     // [out.ptr]
     std::out_ptr(uPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   }
-#endif
+#  endif
 }

>From 1fc645d0b154394d6519981739ce9da8280d3283 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 19:50:39 +0200
Subject: [PATCH 3/7] Address comment

---
 libcxx/include/__memory/unique_ptr.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index b5e2d79a3d1d8..b5f469365daed 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -675,7 +675,8 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
 #endif
 
 template <class _T1, class _D1>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool
+operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
   return !__x;
 }
 

>From 94a8b14ae6da2de963e66d16a78d9522f2b5d19f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 19:53:48 +0200
Subject: [PATCH 4/7] Formatting

---
 .../utilities/smartptr/nodiscard.verify.cpp   | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
index 641ffcb01528a..7859b92e577c5 100644
--- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
@@ -49,21 +49,21 @@ void test() {
     *sPtr;            // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.use_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 #if TEST_STD_VER <= 20
-    sPtr.unique();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    sPtr.unique(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 #endif
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.owner_before(std::shared_ptr<int>());
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.owner_before(std::weak_ptr<int>());
-#  if TEST_STD_VER >= 17
+#if TEST_STD_VER >= 17
     sPtr[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#  endif
+#endif
 
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::allocate_shared<int>(std::allocator<int>(), 5);
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::make_shared<int>();
-#  if TEST_STD_VER >= 20
+#if TEST_STD_VER >= 20
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::allocate_shared_for_overwrite<int>(std::allocator<int>());
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
@@ -96,7 +96,7 @@ void test() {
     std::make_shared<int[]>(5, 82);
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::make_shared_for_overwrite<int[]>(5);
-#  endif
+#endif
 
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::static_pointer_cast<int[]>(sPtr);
@@ -116,10 +116,10 @@ void test() {
     std::reinterpret_pointer_cast<int[]>(sPtr);
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::reinterpret_pointer_cast<int[]>(std::move(sPtr));
-#  if !defined(TEST_HAS_NO_RTTI)
+#if !defined(TEST_HAS_NO_RTTI)
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     std::get_deleter<int[]>(sPtr);
-#  endif
+#endif
   }
   { // [util.smartptr.weak]
     std::weak_ptr<int> wPtr;
@@ -139,12 +139,12 @@ void test() {
 
     es.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     ces.shared_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#  if TEST_STD_VER >= 17
+#if TEST_STD_VER >= 17
     es.weak_from_this();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     ces.weak_from_this(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#  endif
+#endif
   }
-#  if TEST_STD_VER >= 23
+#if TEST_STD_VER >= 23
   { // [smartptr.adapt]
     std::unique_ptr<int> uPtr;
     // [inout.ptr]
@@ -152,5 +152,5 @@ void test() {
     // [out.ptr]
     std::out_ptr(uPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   }
-#  endif
+#endif
 }

>From 7b15b466cfe35a00291a81e0d7cf869f9e174f97 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 20:08:29 +0200
Subject: [PATCH 5/7] Cleanup

---
 libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
index 7859b92e577c5..e48b017f5a34d 100644
--- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
@@ -48,9 +48,7 @@ void test() {
     sPtr.get();       // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     *sPtr;            // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.use_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#if TEST_STD_VER <= 20
-    sPtr.unique(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#endif
+    sPtr.unique();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
     sPtr.owner_before(std::shared_ptr<int>());
     // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}

>From 5bacb429582e14493647ce564be47b166a44677e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 20:11:20 +0200
Subject: [PATCH 6/7] Fix CI

---
 .../unique.deprecated_in_cxx17.verify.cpp                       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/unique.deprecated_in_cxx17.verify.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/unique.deprecated_in_cxx17.verify.cpp
index eae0f6ec757e3..6bca177899c88 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/unique.deprecated_in_cxx17.verify.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/unique.deprecated_in_cxx17.verify.cpp
@@ -20,5 +20,5 @@
 
 void f() {
   const std::shared_ptr<int> p;
-  p.unique(); // expected-warning {{'unique' is deprecated}}
+  std::ignore = p.unique(); // expected-warning {{'unique' is deprecated}}
 }

>From ad94f635c0759d83d75b0a5be023595500709a44 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 18 Nov 2025 20:13:54 +0200
Subject: [PATCH 7/7] Fix CI

---
 libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
index e48b017f5a34d..66e00d6fa66c0 100644
--- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03
 
-// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
 
 // <memory>
 



More information about the libcxx-commits mailing list