9
9
#ifndef _LIBCPP___FWD_BIT_REFERENCE_H
10
10
#define _LIBCPP___FWD_BIT_REFERENCE_H
11
11
12
+ #include < __assert>
12
13
#include < __config>
13
14
#include < __type_traits/enable_if.h>
14
15
#include < __type_traits/is_unsigned.h>
16
+ #include < climits>
15
17
16
18
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17
19
# pragma GCC system_header
@@ -25,20 +27,18 @@ class __bit_iterator;
25
27
template <class , class = void >
26
28
struct __size_difference_type_traits ;
27
29
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
28
34
template <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;
42
42
}
43
43
44
44
_LIBCPP_END_NAMESPACE_STD
0 commit comments