@@ -911,6 +911,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
@@ -1248,6 +1248,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 _GLIBCXX_VISIBILITY(default)
+{
+#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++26
+
+#endif // _GLIBCXX_STDBIT_H
@@ -24,6 +24,35 @@
export module std.compat;
export import std;
+#include <stdbit.h>
+
+// <stdbit.h>
+export
+{
+#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
+}
+
#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" }