From 761b111422ce0196cb45bfb3b27d09c4533916e6 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 5 Nov 2025 10:40:47 +0100 Subject: [PATCH] [libc++] Mark string functions as [[nodiscard]] --- libcxx/include/string | 183 ++++++++++-------- .../diagnostics/string.nodiscard.verify.cpp | 115 ++++++++++- .../strings/basic.string/nonnull.verify.cpp | 2 + 3 files changed, 217 insertions(+), 83 deletions(-) diff --git a/libcxx/include/string b/libcxx/include/string index ede42467b99fe..79da203cfdf6f 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1253,45 +1253,55 @@ public: # endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(value_type __c); - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT { return __make_iterator(__get_pointer()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT { return __make_const_iterator(__get_pointer()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT { return __make_iterator(__get_pointer() + size()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT { return __make_const_iterator(__get_pointer() + size()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator + rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT { return begin(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT { return end(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT { + return begin(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT { + return end(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator + crbegin() const _NOEXCEPT { return rbegin(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { + return rend(); + } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { return __is_long() ? __get_long_size() : __get_short_size(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT { return size(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT { + return size(); + } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT { if (size_type __m = __alloc_traits::max_size(__alloc_); __m <= std::numeric_limits::max() / 2) { size_type __res = __m - __alignment; @@ -1309,7 +1319,7 @@ public: } } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { return (__is_long() ? __get_long_cap() : static_cast(__min_cap)) - 1; } @@ -1344,7 +1354,8 @@ public: return size() == 0; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference + operator[](size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); @@ -1352,7 +1363,8 @@ public: return *(data() + __pos); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference + operator[](size_type __pos) _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); @@ -1360,8 +1372,8 @@ public: return *(__get_pointer() + __pos); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; - _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const basic_string& __str) { return append(__str); @@ -1473,22 +1485,22 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back(); - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *__get_pointer(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *data(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } @@ -1761,16 +1773,16 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; # if _LIBCPP_STD_VER <= 20 - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string - substr(size_type __pos = 0, size_type __n = npos) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, __pos, __n); } # else - _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) const& { return basic_string(*this, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) && { return basic_string(std::move(*this), __pos, __n); } # endif @@ -1790,231 +1802,238 @@ public: // [string.ops] // ------------ - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* c_str() const _NOEXCEPT { return data(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* c_str() const _NOEXCEPT { + return data(); + } + + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT { return std::__to_address(__get_pointer()); } # if _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT { return std::__to_address(__get_pointer()); } # endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT { return __alloc_; } // find - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT { return std::__str_find(data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find(data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr"); return std::__str_find(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find(): received nullptr"); return std::__str_find( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT { return std::__str_find(data(), size(), __c, __pos); } // rfind - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT { return std::__str_rfind( data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_rfind(data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT { return std::__str_rfind(data(), size(), __c, __pos); } // find_first_of - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT { return std::__str_find_first_of( data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_of( data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT { return find(__c, __pos); } // find_last_of - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT { return std::__str_find_last_of( data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_of( data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT { return rfind(__c, __pos); } // find_first_not_of - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT { return std::__str_find_first_not_of( data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_not_of( data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT { return std::__str_find_first_not_of(data(), size(), __c, __pos); } // find_last_not_of - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT { return std::__str_find_last_not_of( data(), size(), __str.data(), __pos, __str.size()); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_not_of( data(), size(), __sv.data(), __pos, __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of(data(), size(), __s, __pos, __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of( data(), size(), __s, __pos, traits_type::length(__s)); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT { return std::__str_find_last_not_of(data(), size(), __c, __pos); } // compare - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const basic_string& __str) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int + compare(const basic_string& __str) const _NOEXCEPT { return compare(__self_view(__str)); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT { __self_view __sv = __t; size_t __lhs_sz = size(); size_t __rhs_sz = __sv.size(); @@ -2029,18 +2048,18 @@ public: } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t) const { __self_view __sv = __t; return compare(__pos1, __n1, __sv.data(), __sv.size()); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str) const { return compare(__pos1, __n1, __str.data(), __str.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const { return compare(__pos1, __n1, __self_view(__str), __pos2, __n2); } @@ -2049,53 +2068,56 @@ public: __enable_if_t<__can_be_converted_to_string_view_v<_CharT, _Traits, _Tp> && !is_same<__remove_cvref_t<_Tp>, basic_string>::value, int> = 0> - inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const { __self_view __sv = __t; return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 int + compare(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 int + [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const _LIBCPP_DIAGNOSE_NULLPTR_IF(__n2 != 0 && __s == nullptr, " if n2 is not zero"); // starts_with # if _LIBCPP_STD_VER >= 20 - constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { return __self_view(typename __self_view::__assume_valid(), data(), size()).starts_with(__sv); } - constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept { return !empty() && _Traits::eq(front(), __c); } - constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool + starts_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept { return starts_with(__self_view(__s)); } // ends_with - constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(__self_view __sv) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(__self_view __sv) const noexcept { return __self_view(typename __self_view::__assume_valid(), data(), size()).ends_with(__sv); } - constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept { return !empty() && _Traits::eq(back(), __c); } - constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool + ends_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept { return ends_with(__self_view(__s)); } # endif @@ -2103,15 +2125,16 @@ public: // contains # if _LIBCPP_STD_VER >= 23 - constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { return __self_view(typename __self_view::__assume_valid(), data(), size()).contains(__sv); } - constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept { return __self_view(typename __self_view::__assume_valid(), data(), size()).contains(__c); } - constexpr _LIBCPP_HIDE_FROM_ABI bool contains(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const { + [[__nodiscard__]] constexpr _LIBCPP_HIDE_FROM_ABI bool + contains(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const { return __self_view(typename __self_view::__assume_valid(), data(), size()).contains(__s); } # endif diff --git a/libcxx/test/libcxx/diagnostics/string.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/string.nodiscard.verify.cpp index d421eaf5cb8f1..f020516a2495a 100644 --- a/libcxx/test/libcxx/diagnostics/string.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/string.nodiscard.verify.cpp @@ -11,13 +11,122 @@ // check that functions are marked [[nodiscard]] #include +#include #include "test_macros.h" +std::string prval(); + void test() { - std::string string; - string.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::string str; + const std::string cstr; + std::string_view sv; + + str[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.c_str(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.substr(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + prval().substr(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cstr.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.length(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.find(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.rfind(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.rfind(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.rfind(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.rfind(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.rfind("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + // clang-format off + str.find_first_of(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_of(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_of(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_of(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_of("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.find_last_of(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_of(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_of(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_of(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_of("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.find_first_not_of(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_not_of(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_not_of(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_not_of(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_first_not_of("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.find_last_not_of(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_not_of(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_not_of(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_not_of(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.find_last_not_of("", 0, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.compare(str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, sv, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, str); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, str, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, ""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.compare(0, 0, "", 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // clang-format on + +#if TEST_STD_VER >= 20 + str.starts_with(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.starts_with(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.starts_with(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + str.ends_with(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.ends_with(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.ends_with(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +#endif + +#if TEST_STD_VER >= 23 + str.contains(sv); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.contains(' '); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.contains(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +#endif + #if TEST_STD_VER >= 26 - string.subview(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + str.subview(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} #endif } diff --git a/libcxx/test/libcxx/strings/basic.string/nonnull.verify.cpp b/libcxx/test/libcxx/strings/basic.string/nonnull.verify.cpp index f428c49fd05f4..c9df9f061905e 100644 --- a/libcxx/test/libcxx/strings/basic.string/nonnull.verify.cpp +++ b/libcxx/test/libcxx/strings/basic.string/nonnull.verify.cpp @@ -13,6 +13,8 @@ // Clang 19 and AppleClang don't have diagnose_if with diagnostic flags // UNSUPPORTED: clang-19, apple-clang-17 +// ADDITIONAL_COMPILE_FLAGS: -Wno-unused-result + #include #include "test_macros.h"