[libc++][memory] Applied [[nodiscard]] to smart pointers (#168483)

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

- [x] - `std::unique_ptr`
- [x] - `std::shared_ptr`
- [x] - `std::weak_ptr`

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.

---------

Co-authored-by: Hristo Hristov <zingam@outlook.com>
This commit is contained in:
Hristo Hristov
2025-11-20 04:19:15 +02:00
committed by GitHub
parent fda20d99ae
commit 3f151a3fa6
4 changed files with 198 additions and 52 deletions

View File

@@ -568,37 +568,43 @@ public:
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; }
[[__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; }
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 +675,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 +686,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 +892,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);
}
@@ -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 @@ public:
_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 @@ protected:
_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>

View File

@@ -258,14 +258,17 @@ public:
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 {
@@ -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);
}

View File

@@ -6,19 +6,144 @@
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// UNSUPPORTED: c++03
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
// <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@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_unique<int>(94);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_unique<int[]>(82);
#endif
#if TEST_STD_VER >= 20
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_unique_for_overwrite<int>();
// expected-warning@+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}}
sPtr.unique(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
sPtr.owner_before(std::shared_ptr<int>());
// expected-warning@+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@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared<int>(std::allocator<int>(), 5);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared<int>();
#if TEST_STD_VER >= 20
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared_for_overwrite<int>(std::allocator<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared_for_overwrite<int>();
// Bounded array variants
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared<int[5]>(std::allocator<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared<int[5]>(std::allocator<int>(), 5);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared_for_overwrite<int[5]>(std::allocator<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared<int[5]>();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared<int[5]>(94);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared_for_overwrite<int[5]>();
// Unbounded array variants
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared<int[]>(std::allocator<int>(), 5);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared<int[]>(std::allocator<int>(), 5, 94);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::allocate_shared_for_overwrite<int[]>(std::allocator<int>(), 5);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared<int[]>(5);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared<int[]>(5, 82);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::make_shared_for_overwrite<int[]>(5);
#endif
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::static_pointer_cast<int[]>(sPtr);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::static_pointer_cast<int[]>(std::move(sPtr));
class Empty {};
std::shared_ptr<Empty> dsPtr;
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::dynamic_pointer_cast<Empty>(dsPtr);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::dynamic_pointer_cast<Empty>(std::move(dsPtr));
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::const_pointer_cast<int[]>(sPtr);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::const_pointer_cast<int[]>(std::move(sPtr));
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::reinterpret_pointer_cast<int[]>(sPtr);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::reinterpret_pointer_cast<int[]>(std::move(sPtr));
#if !defined(TEST_HAS_NO_RTTI)
// expected-warning@+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@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
wPtr.owner_before(std::weak_ptr<int>());
// expected-warning@+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}}

View File

@@ -20,5 +20,5 @@
void f() {
const std::shared_ptr<int> p;
p.unique(); // expected-warning {{'unique' is deprecated}}
(void)p.unique(); // expected-warning {{'unique' is deprecated}}
}