diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -381,9 +381,17 @@ * ``all_of`` * ``any_of`` * ``binary_search`` +* ``bit_ceil`` +* ``bit_floor`` +* ``bit_width`` +* ``byteswap`` * ``clamp`` * ``count_if`` * ``count`` +* ``countl_zero`` +* ``countl_one`` +* ``countr_zero`` +* ``countr_one`` * ``equal_range`` * ``equal`` * ``find_end`` @@ -392,6 +400,7 @@ * ``find_if`` * ``find`` * ``get_temporary_buffer`` +* ``has_single_bit`` * ``includes`` * ``is_heap_until`` * ``is_heap`` @@ -409,8 +418,11 @@ * ``minmax`` * ``mismatch`` * ``none_of`` +* ``popcount`` * ``remove_if`` * ``remove`` +* ``rotl`` +* ``rotr`` * ``search_n`` * ``search`` * ``unique`` diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h --- a/libcxx/include/__bit/bit_ceil.h +++ b/libcxx/include/__bit/bit_ceil.h @@ -24,7 +24,7 @@ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); diff --git a/libcxx/include/__bit/bit_floor.h b/libcxx/include/__bit/bit_floor.h --- a/libcxx/include/__bit/bit_floor.h +++ b/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/libcxx/include/__bit/bit_width.h b/libcxx/include/__bit/bit_width.h --- a/libcxx/include/__bit/bit_width.h +++ b/libcxx/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/libcxx/include/__bit/byteswap.h b/libcxx/include/__bit/byteswap.h --- a/libcxx/include/__bit/byteswap.h +++ b/libcxx/include/__bit/byteswap.h @@ -23,7 +23,7 @@ #if _LIBCPP_STD_VER >= 23 template -_LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; diff --git a/libcxx/include/__bit/countl.h b/libcxx/include/__bit/countl.h --- a/libcxx/include/__bit/countl.h +++ b/libcxx/include/__bit/countl.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } # ifndef _LIBCPP_HAS_NO_INT128 @@ -86,12 +86,12 @@ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -23,19 +23,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { if (__t == 0) return numeric_limits<_Tp>::digits; @@ -57,7 +57,7 @@ } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/has_single_bit.h b/libcxx/include/__bit/has_single_bit.h --- a/libcxx/include/__bit/has_single_bit.h +++ b/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/libcxx/include/__bit/popcount.h b/libcxx/include/__bit/popcount.h --- a/libcxx/include/__bit/popcount.h +++ b/libcxx/include/__bit/popcount.h @@ -35,7 +35,7 @@ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { if (sizeof(_Tp) <= sizeof(unsigned int)) return std::__libcpp_popcount(static_cast(__t)); else if (sizeof(_Tp) <= sizeof(unsigned long)) diff --git a/libcxx/include/__bit/rotate.h b/libcxx/include/__bit/rotate.h --- a/libcxx/include/__bit/rotate.h +++ b/libcxx/include/__bit/rotate.h @@ -34,7 +34,7 @@ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { const unsigned int __dig = numeric_limits<_Tp>::digits; if ((__cnt % __dig) == 0) return __t; @@ -42,7 +42,7 @@ } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { return std::__rotr(__t, __cnt); } diff --git a/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.compile.pass.cpp b/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.compile.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_NODISCARD_EXT + +// Check that functions aren't marked [[nodiscard]] when +// _LIBCPP_DISBALE_NODISCARD_EXT is defined + +#include + +#include "test_macros.h" + +void func() { + std::bit_cast(42); + std::bit_ceil(0u); + std::bit_floor(0u); + std::bit_width(0u); +#if TEST_STD_VER >= 23 + std::byteswap(0u); +#endif + std::countl_zero(0u); + std::countl_one(0u); + std::countr_zero(0u); + std::countr_one(0u); + std::has_single_bit(0u); + std::popcount(0u); +} diff --git a/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.verify.cpp b/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.verify.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// check that functions are marked [[nodiscard]] + +#include + +#include "test_macros.h" + +void func() { + std::bit_cast(42); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::bit_ceil(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::bit_floor(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::bit_width(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +#if TEST_STD_VER >= 23 + std::byteswap(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +#endif + std::countl_zero(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::countl_one(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::countr_zero(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::countr_one(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::has_single_bit(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::popcount(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +} diff --git a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp @@ -173,10 +173,6 @@ std::to_integer(b); #endif -#if TEST_STD_VER > 17 - std::bit_cast(42); -#endif - #if TEST_STD_VER > 20 enum E { Apple, Orange } e = Apple; std::to_underlying(e); diff --git a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp @@ -337,11 +337,6 @@ std::to_integer(b); #endif -#if TEST_STD_VER > 17 - // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} - std::bit_cast(42); -#endif - #if TEST_STD_VER > 20 enum E { Apple, Orange } e = Apple; // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} diff --git a/libcxx/test/std/numerics/bit/bitops.rot/nodiscard.verify.cpp b/libcxx/test/std/numerics/bit/bitops.rot/nodiscard.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/numerics/bit/bitops.rot/nodiscard.verify.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// Check that std::rotl and std::rotr are marked [[nodiscard]] + +#include + +void func() { + std::rotl(0u, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::rotr(0u, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +}