From 9e4e5b39cc581a2dfec777f2e383aa3b6761bf6b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 21 Nov 2025 10:45:16 +0200 Subject: [PATCH 1/3] [libc++][forward_list] Applied `[[nodiscard]]` `[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant --- libcxx/include/forward_list | 49 ++++++++++--------- .../forward_list.nodiscard.verify.cpp | 25 +++++++++- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 272e52d68f46a..550bacb4ee8d6 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -732,50 +732,52 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v); - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(this->__alloc_); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__base::__before_begin()->__next_); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__base::__before_begin()->__next_); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(nullptr); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { + return iterator(nullptr); + } + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(nullptr); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return const_iterator(__base::__before_begin()->__next_); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return const_iterator(nullptr); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator before_begin() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator before_begin() _NOEXCEPT { return iterator(__base::__before_begin()); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator before_begin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator before_begin() const _NOEXCEPT { return const_iterator(__base::__before_begin()); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbefore_begin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbefore_begin() const _NOEXCEPT { return const_iterator(__base::__before_begin()); } [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __base::__before_begin()->__next_ == nullptr; } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return std::min(__node_traits::max_size(this->__alloc_), numeric_limits::max()); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference front() { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference front() { _LIBCPP_ASSERT_NON_NULL(!empty(), "forward_list::front called on an empty list"); return __base::__before_begin()->__next_->__get_value(); } - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_reference front() const { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_reference front() const { _LIBCPP_ASSERT_NON_NULL(!empty(), "forward_list::front called on an empty list"); return __base::__before_begin()->__next_->__get_value(); } @@ -822,15 +824,15 @@ public: # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_Tp> _Range> - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator - insert_range_after(const_iterator __position, _Range&& __range) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 + _LIBCPP_HIDE_FROM_ABI iterator insert_range_after(const_iterator __position, _Range&& __range) { return __insert_after_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); } # endif template - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator - __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI + iterator __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __p); _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __f, const_iterator __l); @@ -1516,8 +1518,8 @@ operator==(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc> # if _LIBCPP_STD_VER <= 17 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool -operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline + _LIBCPP_HIDE_FROM_ABI bool operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return !(__x == __y); } @@ -1556,15 +1558,16 @@ operator<=>(const forward_list<_Tp, _Allocator>& __x, const forward_list<_Tp, _A # endif // #if _LIBCPP_STD_VER <= 17 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void -swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline + _LIBCPP_HIDE_FROM_ABI void swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } # if _LIBCPP_STD_VER >= 20 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Allocator>::size_type -erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI +typename forward_list<_Tp, _Allocator>::size_type erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { return __c.remove_if(__pred); } diff --git a/libcxx/test/libcxx/diagnostics/forward_list.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/forward_list.nodiscard.verify.cpp index 7594a1d299a50..671c7f71ab2a2 100644 --- a/libcxx/test/libcxx/diagnostics/forward_list.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/forward_list.nodiscard.verify.cpp @@ -13,6 +13,27 @@ #include void test() { - std::forward_list forward_list; - forward_list.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::forward_list fl; + const std::forward_list cfl; + + fl.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + fl.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.before_begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.before_begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.cbefore_begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.cbefore_begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + fl.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fl.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + fl.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cfl.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} } From d93f85dcd33c736053937e1d909a4ac809b2947f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Mon, 24 Nov 2025 12:22:39 +0200 Subject: [PATCH 2/3] Addressed comments --- libcxx/include/forward_list | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 550bacb4ee8d6..8419ea4c0474a 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -1558,16 +1558,15 @@ operator<=>(const forward_list<_Tp, _Allocator>& __x, const forward_list<_Tp, _A # endif // #if _LIBCPP_STD_VER <= 17 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline - _LIBCPP_HIDE_FROM_ABI void swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) - _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void +swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } # if _LIBCPP_STD_VER >= 20 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI -typename forward_list<_Tp, _Allocator>::size_type erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Allocator>::size_type +erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { return __c.remove_if(__pred); } From 1ffab06686037687aa103a4dc1e0e8038e0aa996 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Mon, 24 Nov 2025 12:23:56 +0200 Subject: [PATCH 3/3] Addressed comments --- libcxx/include/forward_list | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 8419ea4c0474a..56c45d0d46575 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -824,15 +824,15 @@ public: # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_Tp> _Range> - _LIBCPP_CONSTEXPR_SINCE_CXX26 - _LIBCPP_HIDE_FROM_ABI iterator insert_range_after(const_iterator __position, _Range&& __range) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator + insert_range_after(const_iterator __position, _Range&& __range) { return __insert_after_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); } # endif template - _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI - iterator __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator + __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __p); _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __f, const_iterator __l); @@ -1518,8 +1518,8 @@ operator==(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc> # if _LIBCPP_STD_VER <= 17 template -_LIBCPP_CONSTEXPR_SINCE_CXX26 inline - _LIBCPP_HIDE_FROM_ABI bool operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool +operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return !(__x == __y); }