|
12 | 12 |
|
13 | 13 | #include <__algorithm/copy_n.h> |
14 | 14 | #include <__algorithm/min.h> |
| 15 | +#include <__assert> |
15 | 16 | #include <__bit/countr.h> |
16 | 17 | #include <__compare/ordering.h> |
17 | 18 | #include <__config> |
|
22 | 23 | #include <__memory/construct_at.h> |
23 | 24 | #include <__memory/pointer_traits.h> |
24 | 25 | #include <__type_traits/conditional.h> |
| 26 | +#include <__type_traits/enable_if.h> |
25 | 27 | #include <__type_traits/is_constant_evaluated.h> |
| 28 | +#include <__type_traits/is_unsigned.h> |
26 | 29 | #include <__type_traits/void_t.h> |
27 | 30 | #include <__utility/swap.h> |
| 31 | +#include <climits> |
28 | 32 |
|
29 | 33 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
30 | 34 | # pragma GCC system_header |
@@ -55,6 +59,23 @@ struct __size_difference_type_traits<_Cp, __void_t<typename _Cp::difference_type |
55 | 59 | using size_type = typename _Cp::size_type; |
56 | 60 | }; |
57 | 61 |
|
| 62 | +// This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`, |
| 63 | +// or `unsigned short`. Casting back to _StorageType is crucial to prevent undefined behavior that can arise |
| 64 | +// from integral promotions. |
| 65 | +// See https://github.com/llvm/llvm-project/pull/122410 |
| 66 | +template <class _StorageType, __enable_if_t<is_unsigned<_StorageType>::value, int> > |
| 67 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void |
| 68 | +__fill_masked_range(_StorageType* __word, unsigned __ctz, unsigned __clz, bool __fill_val) { |
| 69 | + _LIBCPP_ASSERT_VALID_INPUT_RANGE( |
| 70 | + __ctz + __clz < sizeof(_StorageType) * CHAR_BIT, "__fill_masked_range called with invalid range"); |
| 71 | + _StorageType __m = static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz) & |
| 72 | + static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz); |
| 73 | + if (__fill_val) |
| 74 | + *__word |= __m; |
| 75 | + else |
| 76 | + *__word &= static_cast<_StorageType>(~__m); |
| 77 | +} |
| 78 | + |
58 | 79 | template <class _Cp, bool = __has_storage_type<_Cp>::value> |
59 | 80 | class __bit_reference { |
60 | 81 | using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; |
|
0 commit comments