diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 20e5bc7d5695b..00bbc4100ddb9 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -139,7 +139,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT { return static_cast(*__seg_ & __mask_); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT { return !static_cast(*this); } diff --git a/libcxx/include/bitset b/libcxx/include/bitset index 3453c2fcde71e..271e63b8f5764 100644 --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -675,53 +675,62 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset& set(size_t __pos, bool __val = true); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset& reset() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset& reset(size_t __pos); - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator~() const _NOEXCEPT; + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator~() const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset& flip() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset& flip(size_t __pos); // element access: # ifdef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator[](size_t __p) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator[](size_t __p) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p < _Size, "bitset::operator[] index out of bounds"); return __base::__make_ref(__p); } # else - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __const_reference operator[](size_t __p) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __const_reference operator[](size_t __p) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p < _Size, "bitset::operator[] index out of bounds"); return __base::__make_ref(__p); } # endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 reference operator[](size_t __p) { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 reference operator[](size_t __p) { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p < _Size, "bitset::operator[] index out of bounds"); return __base::__make_ref(__p); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return __base::to_ulong(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { + return __base::to_ulong(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return __base::to_ullong(); } template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator> + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator> to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const; template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, allocator<_CharT> > + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, allocator<_CharT> > to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const; template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string, allocator > + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string, allocator > to_string(char __zero = '0', char __one = '1') const; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 size_t count() const _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_t size() const _NOEXCEPT { return _Size; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 size_t count() const _NOEXCEPT; + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_t size() const _NOEXCEPT { return _Size; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const bitset& __rhs) const _NOEXCEPT; # if _LIBCPP_STD_VER <= 17 _LIBCPP_HIDE_FROM_ABI bool operator!=(const bitset& __rhs) const _NOEXCEPT; # endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool test(size_t __pos) const; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return __base::all(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT { return __base::any(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool none() const _NOEXCEPT { return !any(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator<<(size_t __pos) const _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator>>(size_t __pos) const _NOEXCEPT; + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool test(size_t __pos) const; + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { + return __base::all(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT { + return __base::any(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool none() const _NOEXCEPT { return !any(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator<<(size_t __pos) const _NOEXCEPT; + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator>>(size_t __pos) const _NOEXCEPT; private: template @@ -919,7 +928,7 @@ bitset<_Size>::operator>>(size_t __pos) const _NOEXCEPT { } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> operator&(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { bitset<_Size> __r = __x; __r &= __y; @@ -927,7 +936,7 @@ operator&(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> operator|(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { bitset<_Size> __r = __x; __r |= __y; @@ -935,7 +944,7 @@ operator|(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size> operator^(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { bitset<_Size> __r = __x; __r ^= __y; @@ -944,7 +953,9 @@ operator^(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT { template struct hash > : public __unary_function, size_t> { - _LIBCPP_HIDE_FROM_ABI size_t operator()(const bitset<_Size>& __bs) const _NOEXCEPT { return __bs.__hash_code(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t operator()(const bitset<_Size>& __bs) const _NOEXCEPT { + return __bs.__hash_code(); + } }; template diff --git a/libcxx/test/libcxx/utilities/template.bitset/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/template.bitset/nodiscard.verify.cpp new file mode 100644 index 0000000000000..b13fafe2edfc6 --- /dev/null +++ b/libcxx/test/libcxx/utilities/template.bitset/nodiscard.verify.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Check that functions are marked [[nodiscard]] + +#include + +#include "test_macros.h" +#include "test_allocator.h" + +void test() { + std::bitset<11> bs; + const std::bitset<11> cbs; + + // std::bitset<>::reference operator~() const noexcept; + ~bs[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + ~bs; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + bs[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + cbs[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_ulong(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_ullong(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + struct CharTraits : public std::char_traits {}; + + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_string >(); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_string(); +#if !defined(TEST_HAS_NO_WIDE_CHARACTERS) + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_string(); +#endif + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.to_string(); + + bs.count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.test(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.all(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.any(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs.none(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs << 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs >> 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + bs & bs; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs | bs; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + bs ^ bs; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + std::hash > hash; + + hash(bs); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +}