Skip to content

Commit

Permalink
Implement LWG-3656: Inconsistent bit operations returning a count (mi…
Browse files Browse the repository at this point in the history
…crosoft#2880)

Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
2 people authored and fsb4000 committed Aug 13, 2022
1 parent 52d5a3c commit 200b2e5
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 6 deletions.
4 changes: 2 additions & 2 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ _NODISCARD constexpr _Ty bit_floor(const _Ty _Val) noexcept {
}

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_NODISCARD constexpr _Ty bit_width(const _Ty _Val) noexcept {
return static_cast<_Ty>(numeric_limits<_Ty>::digits - _STD countl_zero(_Val));
_NODISCARD constexpr int bit_width(const _Ty _Val) noexcept {
return numeric_limits<_Ty>::digits - _STD countl_zero(_Val);
}

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -2939,7 +2939,7 @@ _NODISCARD _OutputIt _Fmt_write(
// Add 3 to the bit width so we always round up on the division.
// Divide that by the amount of bits a hexit represents (log2(16) = log2(2^4) = 4).
// Add 2 for the 0x prefix.
_Width = static_cast<int>(2 + (_STD bit_width(reinterpret_cast<uintptr_t>(_Value)) + 3) / 4);
_Width = 2 + (_STD bit_width(reinterpret_cast<uintptr_t>(_Value)) + 3) / 4;
}

return _Write_aligned(_STD move(_Out), _Width, _Specs, _Fmt_align::_Right,
Expand Down
3 changes: 3 additions & 0 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@ std/utilities/charconv/charconv.msvc/test.pass.cpp FAIL
std/ranges/range.adaptors/range.transform/end.pass.cpp FAIL
std/ranges/range.adaptors/range.transform/iterator/base.pass.cpp FAIL

# libc++ doesn't yet implement LWG-3656 (https://reviews.llvm.org/D120444)
std/numerics/bit/bit.pow.two/bit_width.pass.cpp FAIL

# MaybePOCCAAllocator doesn't meet the allocator requirements
std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp FAIL

Expand Down
3 changes: 3 additions & 0 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@ utilities\charconv\charconv.msvc\test.pass.cpp
ranges\range.adaptors\range.transform\end.pass.cpp
ranges\range.adaptors\range.transform\iterator\base.pass.cpp

# libc++ doesn't yet implement LWG-3656 (https://reviews.llvm.org/D120444)
numerics\bit\bit.pow.two\bit_width.pass.cpp

# MaybePOCCAAllocator doesn't meet the allocator requirements
containers\sequences\vector\vector.cons\assign_copy.pass.cpp

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <bit>
#include <cassert>
#include <limits>
#include <type_traits>
#include <utility>

using namespace std;
Expand Down Expand Up @@ -76,12 +77,16 @@ constexpr bool test_bit_floor() {
template <typename T>
constexpr bool test_bit_width() {
constexpr int digits = numeric_limits<T>::digits;
assert(bit_width(T{0}) == T{0});
assert(bit_width(T{0}) == 0);
assert(bit_width(numeric_limits<T>::max()) == digits);
assert(bit_width(T{1}) == T{1});
assert(bit_width(T{1}) == 1);
for (int i = 1; i < digits; ++i) {
assert(bit_width(static_cast<T>(T{1} << i)) == static_cast<T>(i + 1));
assert(bit_width(static_cast<T>(T{1} << i)) == i + 1);
}

// LWG-3656: bit_width returns int
static_assert(is_same_v<decltype(bit_width(T{0})), int>);

return true;
}

Expand Down

0 comments on commit 200b2e5

Please sign in to comment.