99#ifndef _LIBCPP___FWD_BIT_REFERENCE_H
1010#define _LIBCPP___FWD_BIT_REFERENCE_H
1111
12+ #include < __assert>
1213#include < __config>
1314#include < __type_traits/enable_if.h>
1415#include < __type_traits/is_unsigned.h>
16+ #include < climits>
1517
1618#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1719# pragma GCC system_header
@@ -25,20 +27,18 @@ class __bit_iterator;
2527template <class , class = void >
2628struct __size_difference_type_traits ;
2729
30+ // This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`,
31+ // or `unsigned short`. Casting back to _StorageType is crucial to prevent undefined behavior that can arise
32+ // from integral promotions.
33+ // See https://github.com/llvm/llvm-project/pull/122410
2834template <class _StorageType , __enable_if_t <is_unsigned<_StorageType>::value, int > = 0 >
29- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __leading_mask (unsigned __shift) {
30- return static_cast <_StorageType>(static_cast <_StorageType>(~static_cast <_StorageType>(0 )) << __shift);
31- }
32-
33- template <class _StorageType , __enable_if_t <is_unsigned<_StorageType>::value, int > = 0 >
34- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask (unsigned __shift) {
35- return static_cast <_StorageType>(static_cast <_StorageType>(~static_cast <_StorageType>(0 )) >> __shift);
36- }
37-
38- template <class _StorageType , __enable_if_t <is_unsigned<_StorageType>::value, int > = 0 >
39- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask (unsigned __lshift, unsigned __rshift) {
40- return static_cast <_StorageType>(
41- std::__leading_mask<_StorageType>(__lshift) & std::__trailing_mask<_StorageType>(__rshift));
35+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _StorageType
36+ __fill_range_in_word (_StorageType __word, unsigned __ctz, unsigned __clz, bool __fill_val) {
37+ _LIBCPP_ASSERT_VALID_INPUT_RANGE (
38+ __ctz + __clz < sizeof (_StorageType) * CHAR_BIT, " __fill_range_in_word called with invalid range" );
39+ _StorageType __m = static_cast <_StorageType>(static_cast <_StorageType>(~static_cast <_StorageType>(0 )) << __ctz) &
40+ static_cast <_StorageType>(static_cast <_StorageType>(~static_cast <_StorageType>(0 )) >> __clz);
41+ return __fill_val ? __word | __m : __word & ~__m;
4242}
4343
4444_LIBCPP_END_NAMESPACE_STD
0 commit comments