This is the first part of the P3370R1 proposal just approved by the
committee in Wrocław. This adds C++ equivalents of the functions added
to C23 by WG14 N3022.
These functions are in the global namespace, but to avoid collisions
with the same functions defined by other standard library
implementations, this change defines them in namespace __gnu_cxx and
then adds them to the global namespace.
libstdc++-v3/ChangeLog:
* include/Makefile.am: Add stdbit.h.
* include/Makefile.in: Regenerate.
* src/c++23/std.compat.cc.in: Export <stdbit.h> functions.
* include/c_compatibility/stdbit.h: New file.
* testsuite/20_util/stdbit/1.cc: New test.
* testsuite/20_util/stdbit/2_neg.cc: New test.
---
I thought I'd already posted these two patches last week, but apparently
not.
Tested x86_64-linux.
Also available at https://forge.sourceware.org/gcc/gcc-TEST/pulls/28
I suppose an alternative to defining these in __gnu_cxx would be to
define them as always_inline, so that there are no extern symbols
anywhere that could clash. They're all very short one-line functions so
always_inline might make sense anyway.
libstdc++-v3/include/Makefile.am | 1 +
libstdc++-v3/include/Makefile.in | 1 +
libstdc++-v3/include/c_compatibility/stdbit.h | 582 ++++++++++++++++++
libstdc++-v3/src/c++23/std.compat.cc.in | 103 ++++
libstdc++-v3/testsuite/20_util/stdbit/1.cc | 320 ++++++++++
.../testsuite/20_util/stdbit/2_neg.cc | 45 ++
6 files changed, 1052 insertions(+)
create mode 100644 libstdc++-v3/include/c_compatibility/stdbit.h
create mode 100644 libstdc++-v3/testsuite/20_util/stdbit/1.cc
create mode 100644 libstdc++-v3/testsuite/20_util/stdbit/2_neg.cc
@@ -908,6 +908,7 @@ c_compatibility_headers = \
${c_compatibility_srcdir}/tgmath.h \
${c_compatibility_srcdir}/math.h \
${c_compatibility_srcdir}/stdatomic.h \
+ ${c_compatibility_srcdir}/stdbit.h \
${c_compatibility_srcdir}/stdlib.h
endif
@@ -1245,6 +1245,7 @@ c_compatibility_builddir = .
@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/tgmath.h \
@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/math.h \
@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdatomic.h \
+@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdbit.h \
@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdlib.h
@GLIBCXX_C_HEADERS_C_STD_TRUE@c_compatibility_headers =
new file mode 100644
@@ -0,0 +1,582 @@
+// C compatibility header <stdbit.h> -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/stdbit.h
+ * This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_STDBIT_H
+#define _GLIBCXX_STDBIT_H
+
+#if __cplusplus > 202302L
+#include <bit>
+
+#define __STDC_VERSION_STDBIT_H__ 202311L
+
+#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__
+#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__
+#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__
+
+#ifndef _GLIBCXX_DOXYGEN
+// We define these in our own namespace, but let Doxygen think otherwise.
+namespace __gnu_cxx
+{
+#endif
+
+/** Count the number of leading zero bits
+ *
+ * @param __value An unsigned integer.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_leading_zeros(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::countl_zero(__value);
+}
+
+inline unsigned int
+stdc_leading_zeros_uc(unsigned char __value)
+{ return stdc_leading_zeros(__value); }
+
+inline unsigned int
+stdc_leading_zeros_us(unsigned short __value)
+{ return stdc_leading_zeros(__value); }
+
+inline unsigned int
+stdc_leading_zeros_ui(unsigned int __value)
+{ return stdc_leading_zeros(__value); }
+
+inline unsigned int
+stdc_leading_zeros_ul(unsigned long int __value)
+{ return stdc_leading_zeros(__value); }
+
+inline unsigned int
+stdc_leading_zeros_ull(unsigned long long int __value)
+{ return stdc_leading_zeros(__value); }
+/// @}
+
+/** Count the number of leading one bits
+ *
+ * @param __value An unsigned integer.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_leading_ones(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::countl_one(__value);
+}
+
+inline unsigned int
+stdc_leading_ones_uc(unsigned char __value)
+{ return stdc_leading_ones(__value); }
+
+inline unsigned int
+stdc_leading_ones_us(unsigned short __value)
+{ return stdc_leading_ones(__value); }
+
+inline unsigned int
+stdc_leading_ones_ui(unsigned int __value)
+{ return stdc_leading_ones(__value); }
+
+inline unsigned int
+stdc_leading_ones_ul(unsigned long int __value)
+{ return stdc_leading_ones(__value); }
+
+inline unsigned int
+stdc_leading_ones_ull(unsigned long long int __value)
+{ return stdc_leading_ones(__value); }
+/// @}
+
+/** Count the number of trailing zero bits
+ *
+ * @param __value An unsigned integer.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_trailing_zeros(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::countr_zero(__value);
+}
+
+inline unsigned int
+stdc_trailing_zeros_uc(unsigned char __value)
+{ return stdc_trailing_zeros(__value); }
+
+inline unsigned int
+stdc_trailing_zeros_us(unsigned short __value)
+{ return stdc_trailing_zeros(__value); }
+
+inline unsigned int
+stdc_trailing_zeros_ui(unsigned int __value)
+{ return stdc_trailing_zeros(__value); }
+
+inline unsigned int
+stdc_trailing_zeros_ul(unsigned long int __value)
+{ return stdc_trailing_zeros(__value); }
+
+inline unsigned int
+stdc_trailing_zeros_ull(unsigned long long int __value)
+{ return stdc_trailing_zeros(__value); }
+/// @}
+
+/** Count the number of trailing one bits
+ *
+ * @param __value An unsigned integer.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_trailing_ones(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::countr_one(__value);
+}
+
+inline unsigned int
+stdc_trailing_ones_uc(unsigned char __value)
+{ return stdc_trailing_ones(__value); }
+
+inline unsigned int
+stdc_trailing_ones_us(unsigned short __value)
+{ return stdc_trailing_ones(__value); }
+
+inline unsigned int
+stdc_trailing_ones_ui(unsigned int __value)
+{ return stdc_trailing_ones(__value); }
+
+inline unsigned int
+stdc_trailing_ones_ul(unsigned long int __value)
+{ return stdc_trailing_ones(__value); }
+
+inline unsigned int
+stdc_trailing_ones_ull(unsigned long long int __value)
+{ return stdc_trailing_ones(__value); }
+/// @}
+
+/** Find the leftmost (i.e. most significant) zero bit
+ *
+ * @param __value An unsigned integer.
+ * @return The one-based index of the first zero bit counting from the left,
+ * or zero if there are no zero bits.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_first_leading_zero(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return __value == _Tp(-1) ? 0 : 1 + std::countl_one(__value);
+}
+
+inline unsigned int
+stdc_first_leading_zero_uc(unsigned char __value)
+{ return stdc_first_leading_zero(__value); }
+
+inline unsigned int
+stdc_first_leading_zero_us(unsigned short __value)
+{ return stdc_first_leading_zero(__value); }
+
+inline unsigned int
+stdc_first_leading_zero_ui(unsigned int __value)
+{ return stdc_first_leading_zero(__value); }
+
+inline unsigned int
+stdc_first_leading_zero_ul(unsigned long int __value)
+{ return stdc_first_leading_zero(__value); }
+
+inline unsigned int
+stdc_first_leading_zero_ull(unsigned long long int __value)
+{ return stdc_first_leading_zero(__value); }
+/// @}
+
+/** Find the leftmost (i.e. most significant) one bit
+ *
+ * @param __value An unsigned integer.
+ * @return The one-based index of the first one bit counting from the left,
+ * or zero if there are no one bits.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_first_leading_one(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return __value == 0 ? 0 : 1 + std::countl_zero(__value);
+}
+
+inline unsigned int
+stdc_first_leading_one_uc(unsigned char __value)
+{ return stdc_first_leading_one(__value); }
+
+inline unsigned int
+stdc_first_leading_one_us(unsigned short __value)
+{ return stdc_first_leading_one(__value); }
+
+inline unsigned int
+stdc_first_leading_one_ui(unsigned int __value)
+{ return stdc_first_leading_one(__value); }
+
+inline unsigned int
+stdc_first_leading_one_ul(unsigned long int __value)
+{ return stdc_first_leading_one(__value); }
+
+inline unsigned int
+stdc_first_leading_one_ull(unsigned long long int __value)
+{ return stdc_first_leading_one(__value); }
+/// @}
+
+/** Find the rightmost (i.e. least significant) zero bit
+ *
+ * @param __value An unsigned integer.
+ * @return The one-based index of the first zero bit counting from the right,
+ * or zero if there are no zero bits.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_first_trailing_zero(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return __value == _Tp(-1) ? 0 : 1 + std::countr_one(__value);
+}
+
+inline unsigned int
+stdc_first_trailing_zero_uc(unsigned char __value)
+{ return stdc_first_trailing_zero(__value); }
+
+inline unsigned int
+stdc_first_trailing_zero_us(unsigned short __value)
+{ return stdc_first_trailing_zero(__value); }
+
+inline unsigned int
+stdc_first_trailing_zero_ui(unsigned int __value)
+{ return stdc_first_trailing_zero(__value); }
+
+inline unsigned int
+stdc_first_trailing_zero_ul(unsigned long int __value)
+{ return stdc_first_trailing_zero(__value); }
+
+inline unsigned int
+stdc_first_trailing_zero_ull(unsigned long long int __value)
+{ return stdc_first_trailing_zero(__value); }
+/// @}
+
+/** Find the rightmost (i.e. least significant) one bit
+ *
+ * @param __value An unsigned integer.
+ * @return The one-based index of the first one bit counting from the right,
+ * or zero if there are no one bits.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_first_trailing_one(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return __value == 0 ? 0 : 1 + std::countr_zero(__value);
+}
+
+inline unsigned int
+stdc_first_trailing_one_uc(unsigned char __value)
+{ return stdc_first_trailing_one(__value); }
+
+inline unsigned int
+stdc_first_trailing_one_us(unsigned short __value)
+{ return stdc_first_trailing_one(__value); }
+
+inline unsigned int
+stdc_first_trailing_one_ui(unsigned int __value)
+{ return stdc_first_trailing_one(__value); }
+
+inline unsigned int
+stdc_first_trailing_one_ul(unsigned long int __value)
+{ return stdc_first_trailing_one(__value); }
+
+inline unsigned int
+stdc_first_trailing_one_ull(unsigned long long int __value)
+{ return stdc_first_trailing_one(__value); }
+/// @}
+
+/** Count zeros
+ *
+ * @param __value An unsigned integer.
+ * @return The total number of zero bits in `__value`.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_count_zeros(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::popcount(_Tp(~__value));
+}
+
+inline unsigned int
+stdc_count_zeros_uc(unsigned char __value)
+{ return stdc_count_zeros(__value); }
+
+inline unsigned int
+stdc_count_zeros_us(unsigned short __value)
+{ return stdc_count_zeros(__value); }
+
+inline unsigned int
+stdc_count_zeros_ui(unsigned int __value)
+{ return stdc_count_zeros(__value); }
+
+inline unsigned int
+stdc_count_zeros_ul(unsigned long int __value)
+{ return stdc_count_zeros(__value); }
+
+inline unsigned int
+stdc_count_zeros_ull(unsigned long long int __value)
+{ return stdc_count_zeros(__value); }
+/// @}
+
+/** Count ones
+ *
+ * @param __value An unsigned integer.
+ * @return The total number of one bits in `__value`.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_count_ones(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::popcount(__value);
+}
+
+inline unsigned int
+stdc_count_ones_uc(unsigned char __value)
+{ return stdc_count_ones(__value); }
+
+inline unsigned int
+stdc_count_ones_us(unsigned short __value)
+{ return stdc_count_ones(__value); }
+
+inline unsigned int
+stdc_count_ones_ui(unsigned int __value)
+{ return stdc_count_ones(__value); }
+
+inline unsigned int
+stdc_count_ones_ul(unsigned long int __value)
+{ return stdc_count_ones(__value); }
+
+inline unsigned int
+stdc_count_ones_ull(unsigned long long int __value)
+{ return stdc_count_ones(__value); }
+/// @}
+
+/** Power of two check
+ *
+ * @param __value An unsigned integer.
+ * @return True if the value has a single bit set, false otherwise.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline bool
+stdc_has_single_bit(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::has_single_bit(__value);
+}
+
+inline bool
+stdc_has_single_bit_uc(unsigned char __value)
+{ return stdc_has_single_bit(__value); }
+
+inline bool
+stdc_has_single_bit_us(unsigned short __value)
+{ return stdc_has_single_bit(__value); }
+
+inline bool
+stdc_has_single_bit_ui(unsigned int __value)
+{ return stdc_has_single_bit(__value); }
+
+inline bool
+stdc_has_single_bit_ul(unsigned long int __value)
+{ return stdc_has_single_bit(__value); }
+
+inline bool
+stdc_has_single_bit_ull(unsigned long long int __value)
+{ return stdc_has_single_bit(__value); }
+/// @}
+
+/** Bit width
+ *
+ * @param __value An unsigned integer.
+ * @return The minimum number of bits needed to represent `__value`.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline unsigned int
+stdc_bit_width(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::bit_width(__value);
+}
+
+inline unsigned int
+stdc_bit_width_uc(unsigned char __value)
+{ return stdc_bit_width(__value); }
+
+inline unsigned int
+stdc_bit_width_us(unsigned short __value)
+{ return stdc_bit_width(__value); }
+
+inline unsigned int
+stdc_bit_width_ui(unsigned int __value)
+{ return stdc_bit_width(__value); }
+
+inline unsigned int
+stdc_bit_width_ul(unsigned long int __value)
+{ return stdc_bit_width(__value); }
+
+inline unsigned int
+stdc_bit_width_ull(unsigned long long int __value)
+{ return stdc_bit_width(__value); }
+/// @}
+
+/** Bit floor
+ *
+ * @param __value An unsigned integer.
+ * @return The largest power of two that is not greater than `__value`.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline _Tp
+stdc_bit_floor(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ return std::bit_floor(__value);
+}
+
+inline unsigned char
+stdc_bit_floor_uc(unsigned char __value)
+{ return stdc_bit_floor(__value); }
+
+inline unsigned short
+stdc_bit_floor_us(unsigned short __value)
+{ return stdc_bit_floor(__value); }
+
+inline unsigned int
+stdc_bit_floor_ui(unsigned int __value)
+{ return stdc_bit_floor(__value); }
+
+inline unsigned long int
+stdc_bit_floor_ul(unsigned long int __value)
+{ return stdc_bit_floor(__value); }
+
+inline unsigned long long int
+stdc_bit_floor_ull(unsigned long long int __value)
+{ return stdc_bit_floor(__value); }
+/// @}
+
+/** Bit ceiling
+ *
+ * Unlike `std::bit_ceil`, this is defined to return zero for values which
+ * are not representable in the return type.
+ *
+ * @param __value An unsigned integer.
+ * @return The smallest power of two that is not less than `__value`.
+ * @since C++26
+ * @{
+ */
+template<typename _Tp>
+inline _Tp
+stdc_bit_ceil(_Tp __value)
+{
+ static_assert(std::__unsigned_integer<_Tp>);
+ constexpr _Tp __msb = _Tp(1) << (__gnu_cxx::__int_traits<_Tp>::__digits - 1);
+ return (__value & __msb) ? 0 : std::bit_ceil(__value);
+}
+
+inline unsigned char
+stdc_bit_ceil_uc(unsigned char __value)
+{ return stdc_bit_ceil(__value); }
+
+inline unsigned short
+stdc_bit_ceil_us(unsigned short __value)
+{ return stdc_bit_ceil(__value); }
+
+inline unsigned int
+stdc_bit_ceil_ui(unsigned int __value)
+{ return stdc_bit_ceil(__value); }
+
+inline unsigned long int
+stdc_bit_ceil_ul(unsigned long int __value)
+{ return stdc_bit_ceil(__value); }
+
+inline unsigned long long int
+stdc_bit_ceil_ull(unsigned long long int __value)
+{ return stdc_bit_ceil(__value); }
+/// @}
+
+#ifndef _GLIBCXX_DOXYGEN
+} // namespace __gnu_cxx
+#define _GLIBCXX_STDBIT_FUNC(F) \
+ using __gnu_cxx::F ## _uc; \
+ using __gnu_cxx::F ## _us; \
+ using __gnu_cxx::F ## _ui; \
+ using __gnu_cxx::F ## _ul; \
+ using __gnu_cxx::F ## _ull; \
+ using __gnu_cxx::F
+_GLIBCXX_STDBIT_FUNC(stdc_leading_zeros);
+_GLIBCXX_STDBIT_FUNC(stdc_leading_ones);
+_GLIBCXX_STDBIT_FUNC(stdc_trailing_zeros);
+_GLIBCXX_STDBIT_FUNC(stdc_trailing_ones);
+_GLIBCXX_STDBIT_FUNC(stdc_first_leading_zero);
+_GLIBCXX_STDBIT_FUNC(stdc_first_leading_one);
+_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_zero);
+_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_one);
+_GLIBCXX_STDBIT_FUNC(stdc_count_zeros);
+_GLIBCXX_STDBIT_FUNC(stdc_count_ones);
+_GLIBCXX_STDBIT_FUNC(stdc_has_single_bit);
+_GLIBCXX_STDBIT_FUNC(stdc_bit_width);
+_GLIBCXX_STDBIT_FUNC(stdc_bit_floor);
+_GLIBCXX_STDBIT_FUNC(stdc_bit_ceil);
+#undef _GLIBCXX_STDBIT_FUNC
+#endif // !DOXYGEN
+#endif // C++23
+
+#endif // _GLIBCXX_STDBIT_H
@@ -24,6 +24,109 @@
export module std.compat;
export import std;
+#include <stdbit.h>
+
+// <stdbit.h>
+export
+{
+ using __gnu_cxx::stdc_leading_zeros_uc;
+ using __gnu_cxx::stdc_leading_zeros_us;
+ using __gnu_cxx::stdc_leading_zeros_ui;
+ using __gnu_cxx::stdc_leading_zeros_ul;
+ using __gnu_cxx::stdc_leading_zeros_ull;
+ using __gnu_cxx::stdc_leading_zeros;
+
+ using __gnu_cxx::stdc_leading_ones_uc;
+ using __gnu_cxx::stdc_leading_ones_us;
+ using __gnu_cxx::stdc_leading_ones_ui;
+ using __gnu_cxx::stdc_leading_ones_ul;
+ using __gnu_cxx::stdc_leading_ones_ull;
+ using __gnu_cxx::stdc_leading_ones;
+
+ using __gnu_cxx::stdc_trailing_zeros_uc;
+ using __gnu_cxx::stdc_trailing_zeros_us;
+ using __gnu_cxx::stdc_trailing_zeros_ui;
+ using __gnu_cxx::stdc_trailing_zeros_ul;
+ using __gnu_cxx::stdc_trailing_zeros_ull;
+ using __gnu_cxx::stdc_trailing_zeros;
+
+ using __gnu_cxx::stdc_trailing_ones_uc;
+ using __gnu_cxx::stdc_trailing_ones_us;
+ using __gnu_cxx::stdc_trailing_ones_ui;
+ using __gnu_cxx::stdc_trailing_ones_ul;
+ using __gnu_cxx::stdc_trailing_ones_ull;
+ using __gnu_cxx::stdc_trailing_ones;
+
+ using __gnu_cxx::stdc_first_leading_zero_uc;
+ using __gnu_cxx::stdc_first_leading_zero_us;
+ using __gnu_cxx::stdc_first_leading_zero_ui;
+ using __gnu_cxx::stdc_first_leading_zero_ul;
+ using __gnu_cxx::stdc_first_leading_zero_ull;
+ using __gnu_cxx::stdc_first_leading_zero;
+
+ using __gnu_cxx::stdc_first_leading_one_uc;
+ using __gnu_cxx::stdc_first_leading_one_us;
+ using __gnu_cxx::stdc_first_leading_one_ui;
+ using __gnu_cxx::stdc_first_leading_one_ul;
+ using __gnu_cxx::stdc_first_leading_one_ull;
+
+ using __gnu_cxx::stdc_first_trailing_zero_uc;
+ using __gnu_cxx::stdc_first_trailing_zero_us;
+ using __gnu_cxx::stdc_first_trailing_zero_ui;
+ using __gnu_cxx::stdc_first_trailing_zero_ul;
+ using __gnu_cxx::stdc_first_trailing_zero_ull;
+ using __gnu_cxx::stdc_first_trailing_zero;
+
+ using __gnu_cxx::stdc_first_trailing_one_uc;
+ using __gnu_cxx::stdc_first_trailing_one_us;
+ using __gnu_cxx::stdc_first_trailing_one_ui;
+ using __gnu_cxx::stdc_first_trailing_one_ul;
+ using __gnu_cxx::stdc_first_trailing_one_ull;
+ using __gnu_cxx::stdc_first_trailing_one;
+
+ using __gnu_cxx::stdc_count_zeros_uc;
+ using __gnu_cxx::stdc_count_zeros_us;
+ using __gnu_cxx::stdc_count_zeros_ui;
+ using __gnu_cxx::stdc_count_zeros_ul;
+ using __gnu_cxx::stdc_count_zeros_ull;
+ using __gnu_cxx::stdc_count_zeros;
+
+ using __gnu_cxx::stdc_count_ones_uc;
+ using __gnu_cxx::stdc_count_ones_us;
+ using __gnu_cxx::stdc_count_ones_ui;
+ using __gnu_cxx::stdc_count_ones_ul;
+ using __gnu_cxx::stdc_count_ones_ull;
+ using __gnu_cxx::stdc_count_ones;
+
+ using __gnu_cxx::stdc_has_single_bit_uc;
+ using __gnu_cxx::stdc_has_single_bit_us;
+ using __gnu_cxx::stdc_has_single_bit_ui;
+ using __gnu_cxx::stdc_has_single_bit_ul;
+ using __gnu_cxx::stdc_has_single_bit_ull;
+ using __gnu_cxx::stdc_has_single_bit;
+
+ using __gnu_cxx::stdc_bit_width_uc;
+ using __gnu_cxx::stdc_bit_width_us;
+ using __gnu_cxx::stdc_bit_width_ui;
+ using __gnu_cxx::stdc_bit_width_ul;
+ using __gnu_cxx::stdc_bit_width_ull;
+ using __gnu_cxx::stdc_bit_width;
+
+ using __gnu_cxx::stdc_bit_floor_uc;
+ using __gnu_cxx::stdc_bit_floor_us;
+ using __gnu_cxx::stdc_bit_floor_ui;
+ using __gnu_cxx::stdc_bit_floor_ul;
+ using __gnu_cxx::stdc_bit_floor_ull;
+ using __gnu_cxx::stdc_bit_floor;
+
+ using __gnu_cxx::stdc_bit_ceil_uc;
+ using __gnu_cxx::stdc_bit_ceil_us;
+ using __gnu_cxx::stdc_bit_ceil_ui;
+ using __gnu_cxx::stdc_bit_ceil_ul;
+ using __gnu_cxx::stdc_bit_ceil_ull;
+ using __gnu_cxx::stdc_bit_ceil;
+}
+
#define STD_COMPAT 1
// C library exports are appended from std-clib.cc.in.
new file mode 100644
@@ -0,0 +1,320 @@
+// { dg-do run { target c++26 } }
+
+#include <stdbit.h>
+
+#if __STDC_VERSION_STDBIT_H__ != 202311L
+# error "__STDC_VERSION_STDBIT_H__ not defined correctly in <stdbit.h>"
+#endif
+#ifndef __STDC_ENDIAN_BIG__
+# error "__STDC_ENDIAN_BIG__ is not defined in <stdbit.h>"
+#endif
+#ifndef __STDC_ENDIAN_LITTLE__
+# error "__STDC_ENDIAN_LITTLE__ is not defined in <stdbit.h>"
+#endif
+#ifndef __STDC_ENDIAN_NATIVE__
+# error "__STDC_ENDIAN_NATIVE__ is not defined in <stdbit.h>"
+#endif
+
+#include <testsuite_hooks.h>
+#include <limits.h>
+
+void
+test_leading_zeros()
+{
+ VERIFY( stdc_leading_zeros_uc(0) == CHAR_BIT );
+ VERIFY( stdc_leading_zeros_uc(UCHAR_MAX) == 0 );
+ VERIFY( stdc_leading_zeros_uc(CHAR_MAX) == (CHAR_MIN ? 1 : 0) );
+ VERIFY( stdc_leading_zeros_uc(UCHAR_MAX >> 3) == 3 );
+ VERIFY( stdc_leading_zeros_uc((unsigned char)(UCHAR_MAX << 3)) == 0 );
+
+ // TODO: replace __X_WIDTH__ with the standard macros once they're in C++26
+ VERIFY( stdc_leading_zeros_us(0) == __SHRT_WIDTH__ );
+ VERIFY( stdc_leading_zeros_us(USHRT_MAX) == 0 );
+ VERIFY( stdc_leading_zeros_us(USHRT_MAX >> 11) == 11 );
+
+ VERIFY( stdc_leading_zeros_ui(0) == __INT_WIDTH__ );
+ VERIFY( stdc_leading_zeros_ui(UINT_MAX) == 0 );
+ VERIFY( stdc_leading_zeros_ui(UINT_MAX >> 11) == 11 );
+
+ VERIFY( stdc_leading_zeros_ul(0) == __LONG_WIDTH__ );
+ VERIFY( stdc_leading_zeros_ul(ULONG_MAX) == 0 );
+ VERIFY( stdc_leading_zeros_ul(ULONG_MAX >> 19) == 19 );
+
+ VERIFY( stdc_leading_zeros_ull(0) == __LONG_LONG_WIDTH__ );
+ VERIFY( stdc_leading_zeros_ull(ULLONG_MAX) == 0 );
+ VERIFY( stdc_leading_zeros_ull(ULLONG_MAX >> 33) == 33 );
+ VERIFY( stdc_leading_zeros_ull(7) == (__LONG_LONG_WIDTH__ - 3) );
+
+ VERIFY( stdc_leading_zeros(7U) == (__INT_WIDTH__ - 3) );
+ VERIFY( stdc_leading_zeros(7UL) == (__LONG_WIDTH__ - 3) );
+ VERIFY( stdc_leading_zeros(7ULL) == (__LONG_LONG_WIDTH__ - 3) );
+
+ static_assert( std::is_same_v<decltype(stdc_leading_zeros(0UL)), unsigned> );
+}
+
+void
+test_leading_ones()
+{
+ VERIFY( stdc_leading_ones_uc(0) == 0 );
+ VERIFY( stdc_leading_ones_uc(UCHAR_MAX) == CHAR_BIT );
+ VERIFY( stdc_leading_ones_uc(CHAR_MAX) == (CHAR_MIN ? 0 : CHAR_BIT) );
+ VERIFY( stdc_leading_ones_uc(UCHAR_MAX >> 3) == 0 );
+ VERIFY( stdc_leading_ones_uc((unsigned char)(UCHAR_MAX << 3)) == (CHAR_BIT - 3) );
+
+ VERIFY( stdc_leading_ones_us(0) == 0 );
+ VERIFY( stdc_leading_ones_us(USHRT_MAX) == __SHRT_WIDTH__ );
+ VERIFY( stdc_leading_ones_us((unsigned short)(USHRT_MAX << 11)) == (__SHRT_WIDTH__ - 11) );
+ VERIFY( stdc_leading_ones_us(USHRT_MAX >> 11) == 0 );
+
+ VERIFY( stdc_leading_ones_ui(0) == 0 );
+ VERIFY( stdc_leading_ones_ui(UINT_MAX) == __INT_WIDTH__ );
+ VERIFY( stdc_leading_ones_ui(UINT_MAX << 11) == (__INT_WIDTH__ - 11) );
+
+ VERIFY( stdc_leading_ones_ul(0) == 0 );
+ VERIFY( stdc_leading_ones_ul(ULONG_MAX) == __LONG_WIDTH__ );
+ VERIFY( stdc_leading_ones_ul(ULONG_MAX << 19) == (__LONG_WIDTH__ - 19) );
+
+ VERIFY( stdc_leading_ones_ull(0) == 0 );
+ VERIFY( stdc_leading_ones_ull(ULLONG_MAX) == __LONG_LONG_WIDTH__ );
+ VERIFY( stdc_leading_ones_ull(ULLONG_MAX << 33) == (__LONG_LONG_WIDTH__ - 33) );
+
+ VERIFY( stdc_leading_ones(-1U << 2) == (__INT_WIDTH__ - 2) );
+ VERIFY( stdc_leading_ones(-1UL << 3) == (__LONG_WIDTH__ - 3) );
+ VERIFY( stdc_leading_ones(-1ULL << 4) == (__LONG_LONG_WIDTH__ - 4) );
+
+ static_assert( std::is_same_v<decltype(stdc_leading_ones(0UL)), unsigned> );
+}
+
+void
+test_trailing_zeros()
+{
+ VERIFY( stdc_trailing_zeros_uc((unsigned char)(UCHAR_MAX << 5)) == 5 );
+ VERIFY( stdc_trailing_zeros_us((unsigned short)(USHRT_MAX << 5)) == 5 );
+ VERIFY( stdc_trailing_zeros_ui(UINT_MAX << 9) == 9 );
+ VERIFY( stdc_trailing_zeros_ul(ULONG_MAX << 19) == 19 );
+ VERIFY( stdc_trailing_zeros_ull(ULLONG_MAX << 39) == 39 );
+ VERIFY( stdc_trailing_zeros(8U) == 3 );
+
+ static_assert( std::is_same_v<decltype(stdc_trailing_zeros(0UL)), unsigned> );
+}
+
+void
+test_trailing_ones()
+{
+ VERIFY( stdc_trailing_ones_uc((unsigned char)3) == 2 );
+ VERIFY( stdc_trailing_ones_uc((unsigned char)135) == 3 );
+ VERIFY( stdc_trailing_ones_us((unsigned short)7) == 3 );
+ VERIFY( stdc_trailing_ones_us((unsigned short)23) == 3 );
+ VERIFY( stdc_trailing_ones_us((unsigned short)235) == 2 );
+ VERIFY( stdc_trailing_ones_ui(11U) == 2 );
+ VERIFY( stdc_trailing_ones_ui(15U) == 4 );
+ VERIFY( stdc_trailing_ones_ul(ULONG_MAX) == __LONG_WIDTH__ );
+ VERIFY( stdc_trailing_ones_ull(ULLONG_MAX) == __LONG_LONG_WIDTH__ );
+ VERIFY( stdc_trailing_ones(7U) == 3 );
+
+ static_assert( std::is_same_v<decltype(stdc_trailing_ones(0UL)), unsigned> );
+}
+
+void
+test_first_leading_zero()
+{
+ VERIFY( stdc_first_leading_zero_uc(0) == 1 );
+ VERIFY( stdc_first_leading_zero_uc(UCHAR_MAX) == 0 );
+ VERIFY( stdc_first_leading_zero_uc(UCHAR_MAX ^ 0b111) == (CHAR_BIT - 2) );
+ VERIFY( stdc_first_leading_zero_us(USHRT_MAX) == 0 );
+ VERIFY( stdc_first_leading_zero_us(USHRT_MAX ^ 0b111) == (__SHRT_WIDTH__ - 2) );
+ VERIFY( stdc_first_leading_zero_ui(UINT_MAX ^ 0b10111) == (__INT_WIDTH__ - 4) );
+ VERIFY( stdc_first_leading_zero_ul(ULONG_MAX ^ 0b10111) == (__LONG_WIDTH__ - 4) );
+ VERIFY( stdc_first_leading_zero_ull(ULLONG_MAX ^ 0b10111) == (__LONG_LONG_WIDTH__ - 4) );
+
+ VERIFY( stdc_first_leading_zero(0U) == 1 );
+ VERIFY( stdc_first_leading_zero(-1U ^ 0b1111) == (__INT_WIDTH__ - 3) );
+
+ static_assert( std::is_same_v<decltype(stdc_first_leading_zero(0UL)), unsigned> );
+}
+
+void
+test_first_leading_one()
+{
+ VERIFY( stdc_first_leading_one_uc(0) == 0 );
+ VERIFY( stdc_first_leading_one_uc(0b00100) == (CHAR_BIT - 2) );
+ VERIFY( stdc_first_leading_one_ui(0b001100) == (__INT_WIDTH__ - 3) );
+ VERIFY( stdc_first_leading_one_ul(0b101100) == (__LONG_WIDTH__ - 5) );
+ VERIFY( stdc_first_leading_one_ull(0b1110000) == (__LONG_LONG_WIDTH__ - 6) );
+
+ VERIFY( stdc_first_leading_one(0U) == 0 );
+ VERIFY( stdc_first_leading_one(-1U >> 4) == 5 );
+ VERIFY( stdc_first_leading_one(-1ULL >> 43) == 44 );
+
+ static_assert( std::is_same_v<decltype(stdc_first_leading_one(0UL)), unsigned> );
+}
+
+void
+test_first_trailing_zero()
+{
+ VERIFY( stdc_first_trailing_zero_uc(0) == 1 );
+ VERIFY( stdc_first_trailing_zero_uc(1) == 2 );
+ VERIFY( stdc_first_trailing_zero_uc(7) == 4 );
+ VERIFY( stdc_first_trailing_zero_us(15) == 5 );
+ VERIFY( stdc_first_trailing_zero_ui(15) == 5 );
+ VERIFY( stdc_first_trailing_zero_ul(15) == 5 );
+ VERIFY( stdc_first_trailing_zero_ull(15) == 5 );
+
+ VERIFY( stdc_first_trailing_zero(15U) == 5 );
+
+ static_assert( std::is_same_v<decltype(stdc_first_trailing_zero(0UL)), unsigned> );
+}
+
+void
+test_first_trailing_one()
+{
+ VERIFY( stdc_first_trailing_one_uc(0) == 0 );
+ VERIFY( stdc_first_trailing_one_uc(1) == 1 );
+ VERIFY( stdc_first_trailing_one_uc(7) == 1 );
+ VERIFY( stdc_first_trailing_one_us(16) == 5 );
+ VERIFY( stdc_first_trailing_one_ui(16) == 5 );
+ VERIFY( stdc_first_trailing_one_ul(16) == 5 );
+ VERIFY( stdc_first_trailing_one_ull(16) == 5 );
+
+ VERIFY( stdc_first_trailing_one(16U) == 5 );
+ VERIFY( stdc_first_trailing_one(-1ULL << 17) == 18 );
+
+ static_assert( std::is_same_v<decltype(stdc_first_trailing_one(0UL)), unsigned> );
+}
+
+void
+test_count_zeros()
+{
+ VERIFY( stdc_count_zeros_uc(0b101010) == (CHAR_BIT - 3) );
+ VERIFY( stdc_count_zeros_us(0b1010101) == (__SHRT_WIDTH__ - 4) );
+ VERIFY( stdc_count_zeros_ui(0b1010101111) == (__INT_WIDTH__ - 7) );
+ VERIFY( stdc_count_zeros_ul(0b10101011110101) == (__LONG_WIDTH__ - 9) );
+ VERIFY( stdc_count_zeros_ull(0b10101011110101) == (__LONG_LONG_WIDTH__ - 9) );
+
+ VERIFY( stdc_count_zeros(0b111UL) == (__LONG_WIDTH__ - 3) );
+ VERIFY( stdc_count_zeros(0U) == __INT_WIDTH__ );
+
+ // std::popcount returns signed int, stdc_count_zeros_uc returns unsigned int.
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_zeros_uc(0u)), unsigned> );
+}
+
+void
+test_count_ones()
+{
+ VERIFY( stdc_count_ones_uc(0b101010) == 3 );
+ VERIFY( stdc_count_ones_us(0b1010101) == 4 );
+ VERIFY( stdc_count_ones_ui(0b1010101111) == 7 );
+ VERIFY( stdc_count_ones_ul(0b10101011110101) == 9 );
+ VERIFY( stdc_count_ones_ull(0b10101011110101) == 9 );
+
+ VERIFY( stdc_count_ones(0b10101011110101U) == 9 );
+ VERIFY( stdc_count_ones(0U) == 0 );
+
+ // std::popcount returns signed int, stdc_count_ones_uc returns unsigned int.
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_count_ones_uc(0u)), unsigned> );
+}
+
+void
+test_has_single_bit()
+{
+ VERIFY ( ! stdc_has_single_bit_uc(0) );
+ VERIFY ( ! stdc_has_single_bit_uc(41) );
+ VERIFY ( stdc_has_single_bit_uc(1) );
+ VERIFY ( stdc_has_single_bit_uc(64) );
+ VERIFY ( stdc_has_single_bit_us(1 << 7) );
+ VERIFY ( stdc_has_single_bit_ui(1 << 11) );
+ VERIFY ( stdc_has_single_bit_ul(1 << 14) );
+ VERIFY ( stdc_has_single_bit_ull(1 << 24) );
+
+ VERIFY ( stdc_has_single_bit(64U) );
+ VERIFY ( stdc_has_single_bit(128UL) );
+ VERIFY ( ! stdc_has_single_bit(129UL) );
+}
+
+void
+test_bit_width()
+{
+ VERIFY( stdc_bit_width_uc(0) == 0 );
+ VERIFY( stdc_bit_width_uc(7) == 3 );
+ VERIFY( stdc_bit_width_uc(0b10101) == 5 );
+ VERIFY( stdc_bit_width_us(0b101010) == 6 );
+ VERIFY( stdc_bit_width_ui(0b1010101) == 7 );
+ VERIFY( stdc_bit_width_ul(ULONG_MAX) == __LONG_WIDTH__ );
+ VERIFY( stdc_bit_width_ull(ULLONG_MAX >> 2) == (__LONG_LONG_WIDTH__ - 2) );
+
+ VERIFY( stdc_bit_width(0b1010101U) == 7U );
+
+ // std::bit_width returns signed int, stdc_bit_width returns unsigned int.
+ static_assert( std::is_same_v<decltype(stdc_bit_width_uc(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_bit_width_us(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_bit_width_ui(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_bit_width_ul(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_bit_width_ul(0)), unsigned> );
+ static_assert( std::is_same_v<decltype(stdc_bit_width(0u)), unsigned> );
+}
+
+void
+test_bit_floor()
+{
+ VERIFY( stdc_bit_floor_uc(0) == 0 );
+ VERIFY( stdc_bit_floor_uc(7) == 4 );
+ VERIFY( stdc_bit_floor_uc(0b10101) == 0b10000 );
+ VERIFY( stdc_bit_floor_us(0b101010) == 0b100000 );
+ VERIFY( stdc_bit_floor_ui(0b1010101) == 0b1000000 );
+ VERIFY( stdc_bit_floor_ul(ULONG_MAX) == (1ul << (__LONG_WIDTH__ - 1)) );
+ VERIFY( stdc_bit_floor_ull(1000000) == (1ULL << 19) );
+
+ VERIFY( stdc_bit_floor(0b1010101U) == 0b1000000 );
+}
+
+void
+test_bit_ceil()
+{
+ VERIFY( stdc_bit_ceil_uc(0) == 1 );
+ VERIFY( stdc_bit_ceil_uc(1) == 1 );
+ VERIFY( stdc_bit_ceil_uc(2) == 2 );
+ VERIFY( stdc_bit_ceil_uc(3) == 4 );
+ VERIFY( stdc_bit_ceil_us(11) == 16 );
+ VERIFY( stdc_bit_ceil_ui(257) == 512 );
+ VERIFY( stdc_bit_ceil_ul(1048) == 2048 );
+ VERIFY( stdc_bit_ceil_ull(1000000) == (1ULL << 20) );
+
+ VERIFY( stdc_bit_ceil(0b1010101U) == 0b10000000 );
+}
+
+int main()
+{
+ test_leading_zeros();
+ test_leading_ones();
+ test_trailing_zeros();
+ test_trailing_ones();
+ test_first_leading_zero();
+ test_first_leading_one();
+ test_first_trailing_zero();
+ test_first_trailing_one();
+ test_count_zeros();
+ test_count_ones();
+ test_has_single_bit();
+ test_bit_width();
+ test_bit_floor();
+ test_bit_ceil();
+}
+
+#include <bit>
+// The standard doesn't require these values to match,
+// so this is specific to libstdc++.
+#ifdef _GLIBCXX_RELEASE
+static_assert(__STDC_ENDIAN_BIG__ == (int)std::endian::big);
+static_assert(__STDC_ENDIAN_LITTLE__ == (int)std::endian::little);
+static_assert(__STDC_ENDIAN_NATIVE__ == (int)std::endian::native);
+#endif
new file mode 100644
@@ -0,0 +1,45 @@
+// { dg-do compile { target c++26 } }
+
+#include <stdbit.h>
+
+void
+test_mandates()
+{
+ // Mandates: T is an unsigned integer type.
+
+ ::stdc_leading_zeros(1); // { dg-error "here" }
+ ::stdc_leading_ones(1); // { dg-error "here" }
+ ::stdc_trailing_zeros(1); // { dg-error "here" }
+ ::stdc_trailing_ones(1); // { dg-error "here" }
+ ::stdc_first_leading_zero(1); // { dg-error "here" }
+ ::stdc_first_leading_one(1); // { dg-error "here" }
+ ::stdc_first_trailing_zero(1); // { dg-error "here" }
+ ::stdc_first_trailing_one(1); // { dg-error "here" }
+ ::stdc_count_zeros(1); // { dg-error "here" }
+ ::stdc_count_ones(1); // { dg-error "here" }
+ ::stdc_has_single_bit(1); // { dg-error "here" }
+ ::stdc_bit_width(1); // { dg-error "here" }
+ ::stdc_bit_floor(1); // { dg-error "here" }
+ ::stdc_bit_ceil(1); // { dg-error "here" }
+
+ ::stdc_leading_zeros(1.0); // { dg-error "here" }
+ ::stdc_leading_ones(1.0); // { dg-error "here" }
+ ::stdc_trailing_zeros(1.0); // { dg-error "here" }
+ ::stdc_trailing_ones(1.0); // { dg-error "here" }
+ ::stdc_first_leading_zero(1.0); // { dg-error "here" }
+ ::stdc_first_leading_one(1.0); // { dg-error "here" }
+ ::stdc_first_trailing_zero(1.0); // { dg-error "here" }
+ ::stdc_first_trailing_one(1.0); // { dg-error "here" }
+ ::stdc_count_zeros(1.0); // { dg-error "here" }
+ ::stdc_count_ones(1.0); // { dg-error "here" }
+ ::stdc_has_single_bit(1.0); // { dg-error "here" }
+ ::stdc_bit_width(1.0); // { dg-error "here" }
+ ::stdc_bit_floor(1.0); // { dg-error "here" }
+ ::stdc_bit_ceil(1.0); // { dg-error "here" }
+}
+
+// { dg-prune-output "static assertion failed" }
+// { dg-prune-output "no matching function" }
+// { dg-prune-output "wrong type" }
+// { dg-prune-output "invalid operands" }
+// { dg-prune-output "non-integral type" }