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 @@ -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 @@ -35,7 +35,7 @@ #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 { +_LIBCPP_NODISCARD_EXT _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 { +_LIBCPP_NODISCARD_EXT _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,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 + +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_NODISCARD_EXT + +// Check that functions aren't marked [[nodiscard]] when +// _LIBCPP_DISBALE_NODISCARD_EXT is defined + +#include + +void func() { + std::bit_ceil(0u); + std::bit_floor(0u); + std::bit_width(0u); + std::byteswap(0u); + std::countl_zero(0u); + std::countl_one(0u); + std::countr_zero(0u); + std::countr_one(0u); + std::has_single_bit(0u); + std::popcount(0u); + std::rotl(0u, 0); + std::rotr(0u, 0); +} 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,28 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +void func() { + 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}} + std::byteswap(0u); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + 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}} + 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}} +}