Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -3929,16 +3929,19 @@ namespace ranges {
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_STD move(_First));
const auto _ULast = _Get_unwrapped(_STD move(_Last));
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
if (!_STD is_constant_evaluated()) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_Fill_memset(_UFirst, _Value, _Distance);
_UFirst += _Distance;
_Seek_wrapped(_First, _UFirst);
_Seek_wrapped(_First, _UFirst + _Distance);
return _First;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Value)) {
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_Fill_zero_memset(_UFirst, _Distance);
_Seek_wrapped(_First, _UFirst + _Distance);
return _First;
}
}
}

Expand Down Expand Up @@ -3969,15 +3972,17 @@ namespace ranges {
constexpr _It operator()(_It _First, iter_difference_t<_It> _Count, const _Ty& _Value) const {
if (_Count > 0) {
auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count);
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
if (!_STD is_constant_evaluated()) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
_Fill_memset(_UFirst, _Value, static_cast<size_t>(_Count));
_UFirst += _Count;
_Seek_wrapped(_First, _UFirst); // no need to move since _UFirst is a pointer
_Seek_wrapped(_First, _UFirst + _Count); // no need to move since _UFirst is a pointer
return _First;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Value)) {
_Fill_zero_memset(_UFirst, static_cast<size_t>(_Count));
_Seek_wrapped(_First, _UFirst + _Count); // no need to move since _UFirst is a pointer
return _First;
}
}
}

Expand Down
46 changes: 41 additions & 5 deletions stl/inc/memory
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,17 @@ namespace ranges {

if constexpr (_Fill_memset_is_safe<_It, _Ty>) {
const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast));
const auto _Diff = static_cast<size_t>(_OFinal - _OFirst);
_Fill_memset(_OFirst, _Val, _Diff);
_Fill_memset(_OFirst, _Val, static_cast<size_t>(_OFinal - _OFirst));
return _OFinal;
} else {
if constexpr (_Fill_zero_memset_is_safe<_It, _Ty>) {
if (_Is_all_bits_zero(_Val)) {
const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast));
_Fill_zero_memset(_OFirst, static_cast<size_t>(_OFinal - _OFirst));
return _OFinal;
}
}

_Uninitialized_backout _Backout{_STD move(_OFirst)};

while (_Backout._Last != _OLast) {
Expand All @@ -458,11 +465,19 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw,
}

auto _UFirst = _Get_unwrapped_n(_First, _Count);
if constexpr (_Fill_memset_is_safe<_Unwrapped_n_t<const _NoThrowFwdIt&>, _Tval>) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Tval>) {
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_Count));
_UFirst += _Count;
} else {
_Uninitialized_backout<_Unwrapped_n_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Tval>) {
Comment thread
AdamBucior marked this conversation as resolved.
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_UFirst, static_cast<size_t>(_Count));
_Seek_wrapped(_First, _UFirst + _Count);
return _First;
}
}
Comment thread
CaseyCarter marked this conversation as resolved.

_Uninitialized_backout<decltype(_UFirst)> _Backout{_UFirst};

for (; _Count > 0; --_Count) {
_Backout._Emplace_back(_Val);
Expand Down Expand Up @@ -527,10 +542,18 @@ namespace ranges {
}

auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count);
if constexpr (_Fill_memset_is_safe<_It, _Ty>) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_Count));
_Seek_wrapped(_First, _UFirst + _Count);
} else {
if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_UFirst, static_cast<size_t>(_Count));
_Seek_wrapped(_First, _UFirst + _Count);
return _First;
}
}

_Uninitialized_backout _Backout{_STD move(_UFirst)};

for (; _Count > 0; --_Count) {
Expand Down Expand Up @@ -2386,6 +2409,12 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size,
} else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) {
_Fill_memset(_Out, _Val, _Size);
} else {
if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty>) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_Out, _Size);
return;
}
}
_Uninitialized_rev_destroying_backout _Backout{_Out};
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) {
_Backout._Emplace_back(_Val);
Expand Down Expand Up @@ -2730,6 +2759,13 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si
} else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) {
_Fill_memset(_Out, _Val, _Size);
} else {
if constexpr (_Fill_zero_memset_is_safe<_Ty*,
_Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_Out, _Size);
return;
}
}
_Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al};
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) {
_Backout._Emplace_back(_Val);
Expand Down
12 changes: 12 additions & 0 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1737,6 +1737,12 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(
_Fill_memset(_Unfancy(_First), _Val, static_cast<size_t>(_Count));
return _First + _Count;
} else {
if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_Unfancy(_First), static_cast<size_t>(_Count));
return _First + _Count;
}
}
_Uninitialized_backout_al<_Alloc> _Backout{_First, _Al};
for (; 0 < _Count; --_Count) {
_Backout._Emplace_back(_Val);
Expand Down Expand Up @@ -1787,6 +1793,12 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c
if constexpr (_Fill_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
} else {
if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_UFirst, static_cast<size_t>(_ULast - _UFirst));
return;
}
}
_Uninitialized_backout<_Unwrapped_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
while (_Backout._Last != _ULast) {
_Backout._Emplace_back(_Val);
Expand Down
51 changes: 39 additions & 12 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -1485,10 +1485,6 @@ _NODISCARD constexpr _Ty* _Get_unwrapped_n(_Ty* const _Src, _Diff) {
}
#endif // _HAS_IF_CONSTEXPR

template <class _Iter>
using _Unwrapped_n_t =
_Remove_cvref_t<decltype(_Get_unwrapped_n(_STD declval<_Iter>(), _Iter_diff_t<_Remove_cvref_t<_Iter>>{}))>;

// FUNCTION TEMPLATE _Seek_wrapped
template <class _Iter, class _UIter, class = void>
_INLINE_VAR constexpr bool _Wrapped_seekable_v = false;
Expand Down Expand Up @@ -4813,12 +4809,33 @@ _INLINE_VAR constexpr bool _Fill_memset_is_safe = conjunction_v<is_scalar<_Ty>,
template <class _FwdIt, class _Ty>
_INLINE_VAR constexpr bool _Fill_memset_is_safe<_FwdIt, _Ty, false> = false;

template <class _FwdIt, class _Ty, bool = is_pointer_v<_FwdIt>>
_INLINE_VAR constexpr bool _Fill_zero_memset_is_safe =
conjunction_v<is_scalar<_Ty>, is_scalar<_Iter_value_t<_FwdIt>>, negation<is_member_pointer<_Iter_value_t<_FwdIt>>>,
negation<is_volatile<remove_reference_t<_Iter_ref_t<_FwdIt>>>>, is_assignable<_Iter_ref_t<_FwdIt>, const _Ty&>>;

template <class _FwdIt, class _Ty>
_INLINE_VAR constexpr bool _Fill_zero_memset_is_safe<_FwdIt, _Ty, false> = false;

template <class _DestTy, class _Ty>
void _Fill_memset(_DestTy* const _Dest, const _Ty _Val, const size_t _Count) {
_DestTy _Dest_val = _Val; // implicitly convert (a cast would suppress warnings); also handles _DestTy being bool
_CSTD memset(_Dest, static_cast<unsigned char>(_Dest_val), _Count);
}

template <class _DestTy>
void _Fill_zero_memset(_DestTy* const _Dest, const size_t _Count) {
_CSTD memset(_Dest, 0, _Count * sizeof(_DestTy));
}

template <class _Ty>
_NODISCARD bool _Is_all_bits_zero(const _Ty& _Val) {
// checks if scalar type has all bits set to zero
_STL_INTERNAL_STATIC_ASSERT(is_scalar_v<_Ty> && !is_member_pointer_v<_Ty>);
constexpr _Ty _Zero{};
return _CSTD memcmp(&_Val, &_Zero, sizeof(_Ty)) == 0;
}

#if _HAS_IF_CONSTEXPR
template <class _FwdIt, class _Ty>
_CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) {
Expand All @@ -4829,13 +4846,18 @@ _CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val)
} else {
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
{
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
return;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_UFirst, static_cast<size_t>(_ULast - _UFirst));
return;
}
}
}

Expand Down Expand Up @@ -4890,15 +4912,20 @@ _CONSTEXPR20 _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val
return _Last;
} else {
auto _UDest = _Get_unwrapped_n(_Dest, _Count);
if constexpr (_Fill_memset_is_safe<decltype(_UDest), _Ty>) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
{
if constexpr (_Fill_memset_is_safe<decltype(_UDest), _Ty>) {
_Fill_memset(_UDest, _Val, static_cast<size_t>(_Count));
_UDest += _Count;
_Seek_wrapped(_Dest, _UDest);
_Seek_wrapped(_Dest, _UDest + _Count);
return _Dest;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UDest), _Ty>) {
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_UDest, static_cast<size_t>(_Count));
_Seek_wrapped(_Dest, _UDest + _Count);
return _Dest;
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ void test_make_shared_array_known_bounds() {
test_make_init_destruct_order<ReportAddress[2][2][2]>(); // success multidimensional

test_make_init_destruct_order<ReportAddress[3][3][3]>(); // failure multidimensional

shared_ptr<int[7]> p7 = make_shared<int[7]>(0);
for (int i = 0; i < 7; ++i) {
assert(p7[i] == 0);
}
}

void test_make_shared_array_unknown_bounds() {
Expand Down Expand Up @@ -286,6 +291,11 @@ void test_make_shared_array_unknown_bounds() {
test_make_init_destruct_order<ReportAddress[][2][2]>(2u); // success multidimensional

test_make_init_destruct_order<ReportAddress[][3][3]>(3u); // failure multidimensional

shared_ptr<int[]> p8 = make_shared<int[]>(7u, 0);
for (int i = 0; i < 7; ++i) {
assert(p8[i] == 0);
}
}

int constructCount = 0;
Expand Down Expand Up @@ -506,6 +516,12 @@ void test_allocate_shared_array_known_bounds() {
test_allocate_init_destruct_order<ReportAddress[2][2][2]>(); // success multidimensional

test_allocate_init_destruct_order<ReportAddress[3][3][3]>(); // failure multidimensional

allocator<int> a7;
shared_ptr<int[7]> p7 = allocate_shared<int[7]>(a7, 0);
for (int i = 0; i < 7; ++i) {
assert(p7[i] == 0);
}
}

void test_allocate_shared_array_unknown_bounds() {
Expand Down Expand Up @@ -599,6 +615,12 @@ void test_allocate_shared_array_unknown_bounds() {
test_allocate_init_destruct_order<ReportAddress[][2][2]>(2u); // success multidimensional

test_allocate_init_destruct_order<ReportAddress[][3][3]>(3u); // failure multidimensional

allocator<int> a8;
shared_ptr<int[]> p8 = allocate_shared<int[]>(a8, 7u, 0);
for (int i = 0; i < 7; ++i) {
assert(p8[i] == 0);
}
}

int main() {
Expand Down
10 changes: 9 additions & 1 deletion tests/std/tests/P0896R4_ranges_alg_fill/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ struct instantiator {
}
{ // Validate int is properly converted to bool
bool output[] = {false, true, false};
fill(ranges::begin(output), ranges::end(output), 5);
fill(output, 5);
for (const bool& elem : output) {
assert(elem == true);
}
}
{ // Validate zero-ing
int output[] = {13, 42, 1367};
auto result = fill(output, 0);
for (const auto& elem : output) {
assert(elem == 0);
}
assert(result == ranges::end(output));
}
}
};

Expand Down
8 changes: 8 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_fill_n/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ struct instantiator {
assert(elem == true);
}
}
{ // Validate zero-ing
int output[] = {13, 42, 1367};
auto result = fill_n(ranges::begin(output), ranges::distance(output), 0);
for (const auto& elem : output) {
assert(elem == 0);
}
assert(result == ranges::end(output));
}
}
};

Expand Down
17 changes: 17 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_uninitialized_fill/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,23 @@ struct instantiator {
assert(int_wrapper::constructions == 3);
assert(int_wrapper::destructions == 3);
}

{ // Validate int is properly converted to bool
bool output[] = {false, true, false};
uninitialized_fill(output, 5);
for (const bool& elem : output) {
assert(elem == true);
}
}

{ // Validate zero-ing
int output[] = {13, 42, 1367};
auto result = uninitialized_fill(output, 0);
for (const auto& elem : output) {
assert(elem == 0);
}
assert(result == ranges::end(output));
}
}
};

Expand Down
Loading