From 7d3bba5e2fe677d04614bf4ba02a55ee3da4ec02 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Tue, 13 Jun 2023 07:57:26 -0700 Subject: [PATCH] [libc++] Add [[nodiscard]] extensions to the functions in Reviewed By: #libc, ldionne, Mordante Spies: Mordante, ldionne, libcxx-commits Differential Revision: https://reviews.llvm.org/D152653 --- libcxx/docs/UsingLibcxx.rst | 10 +++++++ libcxx/include/__bit/bit_ceil.h | 2 +- libcxx/include/__bit/bit_floor.h | 2 +- libcxx/include/__bit/bit_width.h | 2 +- libcxx/include/__bit/byteswap.h | 2 +- libcxx/include/__bit/countl.h | 10 +++---- libcxx/include/__bit/countr.h | 10 +++---- libcxx/include/__bit/has_single_bit.h | 2 +- libcxx/include/__bit/popcount.h | 2 +- libcxx/include/__bit/rotate.h | 4 +-- .../bit.nodiscard_extensions.compile.pass.cpp | 34 ++++++++++++++++++++++ .../bit.nodiscard_extensions.verify.cpp | 31 ++++++++++++++++++++ .../nodiscard_extensions.compile.pass.cpp | 4 --- .../diagnostics/nodiscard_extensions.verify.cpp | 5 ---- .../numerics/bit/bitops.rot/nodiscard.verify.cpp | 18 ++++++++++++ 15 files changed, 111 insertions(+), 27 deletions(-) create mode 100644 libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.compile.pass.cpp create mode 100644 libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.verify.cpp create mode 100644 libcxx/test/std/numerics/bit/bitops.rot/nodiscard.verify.cpp diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index 3b22ac8..27a8361 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -383,12 +383,20 @@ which no dialect declares as such (See the second form described above). * ``as_const`` * ``binary_search`` * ``bit_cast`` +* ``bit_ceil`` +* ``bit_floor`` +* ``bit_width`` +* ``byteswap`` * ``cbrt`` * ``ceil`` * ``clamp`` * ``copysign`` * ``count_if`` * ``count`` +* ``countl_zero`` +* ``countl_one`` +* ``countr_zero`` +* ``countr_one`` * ``equal_range`` * ``equal`` * ``fabs`` @@ -403,6 +411,7 @@ which no dialect declares as such (See the second form described above). * ``forward`` * ``fpclassify`` * ``get_temporary_buffer`` +* ``has_single_bit`` * ``identity::operator()`` * ``includes`` * ``is_heap_until`` @@ -437,6 +446,7 @@ which no dialect declares as such (See the second form described above). * ``move`` * ``nearbyint`` * ``none_of`` +* ``popcount`` * ``ranges::adjacent_find`` * ``ranges::all_of`` * ``ranges::any_of`` diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h index 1332900..f6bcb351 100644 --- a/libcxx/include/__bit/bit_ceil.h +++ b/libcxx/include/__bit/bit_ceil.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #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 index b2e3809..cf5cf58 100644 --- a/libcxx/include/__bit/bit_floor.h +++ b/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #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 index 4381f22..a2020a0 100644 --- 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 index b290e80..a1e1b53 100644 --- a/libcxx/include/__bit/byteswap.h +++ b/libcxx/include/__bit/byteswap.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #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 index 86eaee0..5d5744a 100644 --- a/libcxx/include/__bit/countl.h +++ b/libcxx/include/__bit/countl.h @@ -24,13 +24,13 @@ _LIBCPP_PUSH_MACROS _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 @@ int __countl_zero(_Tp __t) _NOEXCEPT #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 index d3ca5b6..66ca5e7 100644 --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -23,19 +23,19 @@ _LIBCPP_PUSH_MACROS _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 @@ _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { } 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 index b89f599..a4e1780 100644 --- a/libcxx/include/__bit/has_single_bit.h +++ b/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _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 index 33b94cf..62f4786 100644 --- a/libcxx/include/__bit/popcount.h +++ b/libcxx/include/__bit/popcount.h @@ -35,7 +35,7 @@ int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popco #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 index 5aa7518..e9f4c8d 100644 --- a/libcxx/include/__bit/rotate.h +++ b/libcxx/include/__bit/rotate.h @@ -34,7 +34,7 @@ _Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT #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 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { } 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 index 0000000..a140033 --- /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 index 0000000..79cb56a --- /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 index 0cc86e2..e9fab0c 100644 --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp @@ -173,10 +173,6 @@ void test_nontemplate_cast_wrappers() 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 index 3d0dd2a..d7a26d9 100644 --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.verify.cpp @@ -337,11 +337,6 @@ void test_nontemplate_cast_wrappers() 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 index 0000000..885534a --- /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}} +} -- 2.7.4